001: /*
002: * Copyright (c) 2001 - 2005 ivata limited.
003: * All rights reserved.
004: * -----------------------------------------------------------------------------
005: * ivata masks may be redistributed under the GNU General Public
006: * License as published by the Free Software Foundation;
007: * version 2 of the License.
008: *
009: * These programs are free software; you can redistribute them and/or
010: * modify them under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; version 2 of the License.
012: *
013: * These programs are distributed in the hope that they will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: *
017: * See the GNU General Public License in the file LICENSE.txt for more
018: * details.
019: *
020: * If you would like a copy of the GNU General Public License write to
021: *
022: * Free Software Foundation, Inc.
023: * 59 Temple Place - Suite 330
024: * Boston, MA 02111-1307, USA.
025: *
026: *
027: * To arrange commercial support and licensing, contact ivata at
028: * http://www.ivata.com/contact.jsp
029: * -----------------------------------------------------------------------------
030: * $Log: FieldImpl.java,v $
031: * Revision 1.9 2005/10/11 18:55:29 colinmacleod
032: * Fixed some checkstyle and javadoc issues.
033: *
034: * Revision 1.8 2005/10/03 10:17:24 colinmacleod
035: * Fixed some style and javadoc issues.
036: *
037: * Revision 1.7 2005/09/14 12:51:52 colinmacleod
038: * Added serialVersionUID.
039: *
040: * Revision 1.6 2005/04/11 12:27:02 colinmacleod
041: * Added preliminary support for filters.
042: * Added FieldValueConvertor factor interface
043: * to split off value convertors for reuse.
044: *
045: * Revision 1.5 2005/04/09 18:04:15 colinmacleod
046: * Changed copyright text to GPL v2 explicitly.
047: *
048: * Revision 1.4 2005/03/10 10:19:24 colinmacleod
049: * Added getLabelKey().
050: *
051: * Revision 1.3 2005/01/19 12:35:04 colinmacleod
052: * Added hidden fields.
053: *
054: * Revision 1.2 2005/01/06 22:13:21 colinmacleod
055: * Moved up a version number.
056: * Changed copyright notices to 2005.
057: * Updated the documentation:
058: * - started working on multiproject:site docu.
059: * - changed the logo.
060: * Added checkstyle and fixed LOADS of style issues.
061: * Added separate thirdparty subproject.
062: * Added struts (in web), util and webgui (in webtheme) from ivata op.
063: *
064: * Revision 1.1 2004/12/29 20:07:07 colinmacleod
065: * Renamed subproject masks to mask.
066: *
067: * Revision 1.2 2004/11/11 13:31:02 colinmacleod
068: * Added MaskFactory.
069: *
070: * Revision 1.1.1.1 2004/05/16 20:40:31 colinmacleod
071: * Ready for 0.1 release
072: * -----------------------------------------------------------------------------
073: */
074: package com.ivata.mask.field;
075:
076: import org.apache.log4j.Logger;
077:
078: import java.io.Serializable;
079: import java.util.List;
080: import java.util.Properties;
081: import com.ivata.mask.Mask;
082: import com.ivata.mask.MaskFactory;
083:
084: /**
085: * This is the default implementation of an <strong>ivata masks </strong> field.
086: * Don't use this class directly, use the {@link Field}interface.
087: *
088: * @author Colin MacLeod
089: * @since ivata masks 0.1 (2004-05-15) <a
090: * href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com </a>
091: * @see Field
092: */
093: public class FieldImpl implements Field, Serializable {
094: /**
095: * Serialization version (for <code>Serializable</code> interface).
096: */
097: private static final long serialVersionUID = 1L;
098:
099: /**
100: * Logger for this class.
101: */
102: private static final Logger logger = Logger
103: .getLogger(FieldImpl.class);
104:
105: /**
106: * If this field represents a combo (select) type, stores the choices as a
107: * <code>Properties</code> instance.
108: */
109: private Properties choiceProperties;
110: /**
111: * If this field represents a combo (select) type, stores the choice keys as
112: * a <code>List</code> of <code>String</code> instances.
113: */
114: private List choicePropertyKeys;
115: /**
116: * The default value for this field. If no default has been defined for this
117: * field, it is <code>null</code>.
118: */
119: private String defaultValue = null;
120: /**
121: * <copyDoc>Refer to {@link #isDisplayOnly}.</copyDoc>
122: */
123: private boolean displayOnly;
124: /**
125: * The data object class for this field, if appropriate, otherwise
126: * <code>null</code>.
127: */
128: private Class dOClass;
129: /**
130: * <p>
131: * Each field may inherit attributes from one other field. This could either
132: * be as a result of an explicit "extends", or it could be a field with the
133: * same name in a super group.
134: * </p>
135: */
136: private Field extendedField;
137: /**
138: * <code>true</code> if this field is hidden. Otherwise, <code>false</code>.
139: */
140: private boolean hidden = false;
141: /**
142: * <p>
143: * The label key is used to identify a clear text description of the field.
144: * </p>
145: */
146: private String labelKey;
147: /**
148: * <code>true</code> if this field is required and must have a non-
149: * <code>null</code>, non-empty value. Otherwise, <code>false</code>
150: * denotes an optional field.
151: */
152: private boolean mandatory = false;
153: /**
154: * <p>
155: * This mask factory is used to retrieve the mask for this field, if the
156: * field represents a value object.
157: * </p>
158: */
159: private MaskFactory maskFactory;
160: /**
161: * Identifier of this field.
162: */
163: private String name;
164: /**
165: * <copyDoc>Refer to {@link #isOneToOne}.</copyDoc>
166: */
167: private boolean oneToOne;
168: /**
169: * Field which contains this one.
170: */
171: private Field parent;
172: /**
173: * Type of the field, from one of the <code>TYPE_</code> values in the
174: * {@link Field}interface.
175: */
176: private String type;
177:
178: /**
179: * Construct a field with the given parent or inherited field.
180: *
181: * @param parentParam
182: * The field whose characteristics this one inherits, if they
183: * have not been set directly.
184: * @param extendedFieldParam
185: * field defined by an explicit "extends" attribute in the
186: * configuration.
187: * @param maskFactoryParam
188: * This mask factory is used to retrieve the mask for this field,
189: * if the field represents a value object.
190: */
191: public FieldImpl(final Field parentParam,
192: final Field extendedFieldParam,
193: final MaskFactory maskFactoryParam) {
194: this .parent = parentParam;
195: this .extendedField = extendedFieldParam;
196: this .maskFactory = maskFactoryParam;
197: }
198:
199: /**
200: * If this field represents a combo (select) type, returns the choices as a
201: * <code>Properties</code> instance.
202: *
203: * @return <code>Properties</code> instance representing the possible
204: * values.
205: */
206: public final Properties getChoiceProperties() {
207: if ((choiceProperties == null) && (extendedField != null)) {
208: return extendedField.getChoiceProperties();
209: }
210: return choiceProperties;
211: }
212:
213: /**
214: * If this field represents a combo (select) type, returns the choice keys
215: * as a <code>List</code> of <code>String</code> instances.
216: *
217: * @return <code>List</code> of <code>String</code> instances
218: * representing the key values of all choice options.
219: */
220: public final List getChoicePropertyKeys() {
221: if ((choicePropertyKeys == null) && (extendedField != null)) {
222: return extendedField.getChoicePropertyKeys();
223: }
224: return choicePropertyKeys;
225: }
226:
227: /**
228: * Get the default value for this field. If no default has been defined for
229: * this field, is <code>null</code>.
230: *
231: * @return default value for this field, or <code>null</code> if none is
232: * defined.
233: */
234: public final String getDefaultValue() {
235: if ((defaultValue == null) && (extendedField != null)) {
236: return extendedField.getDefaultValue();
237: }
238: return defaultValue;
239: }
240:
241: /**
242: * Get the data object class for this field, if appropriate.
243: *
244: * @return data object class if this field links to a data object, otherwise
245: * <code>null</code>.
246: */
247: public final Class getDOClass() {
248: if ((dOClass == null) && (extendedField != null)) {
249: return extendedField.getDOClass();
250: }
251: return dOClass;
252: }
253:
254: /**
255: * Get the key to used as a field label for this field. This key can be
256: * matched against the application resources messages to get the
257: * text in the correct language for the current locale.
258: *
259: * @return Returns the label message key.
260: */
261: public String getLabelKey() {
262: return labelKey;
263: }
264:
265: /**
266: * Id of just this field - equivalent to the field name.
267: *
268: * @return Id of just this field - equivalent to the field name.
269: */
270: public final String getName() {
271: return name;
272: }
273:
274: /**
275: * <p>
276: * Get the field which contains this one.
277: * </p>
278: *
279: * @return Field which contains this field, or <code>null</code> if this
280: * is a top-level field.
281: */
282: public final Field getParent() {
283: return parent;
284: }
285:
286: /**
287: * <p>
288: * Return the full path to this field, including the ids of parent fields
289: * separated by '.' characters.
290: * </p>
291: *
292: * @return Full path to this field, to uniquely identify it within the
293: * system.
294: */
295: public final String getPath() {
296: if (parent != null) {
297: return parent.getPath() + "." + name;
298: }
299: return name;
300: }
301:
302: /**
303: * Indicates what sort of data this field should hold.
304: *
305: * @return type of the field, from one of the <code>TYPE_</code> values in
306: * the {@link Field}interface.
307: */
308: public final String getType() {
309: if ((type == null) && (extendedField != null)) {
310: return extendedField.getType();
311: }
312: return type;
313: }
314:
315: /**
316: * <p>
317: * If this field represents a value object, get the mask associated with
318: * this value object.
319: * </p>
320: *
321: * @return Mask associated with this value object or <code>null</code> if
322: * this field is not a value object.
323: * @see com.ivata.mask.field.Field#getMask
324: */
325: public final Mask getValueObjectMask() {
326: if (dOClass == null) {
327: return null;
328: }
329: return maskFactory.getMask(this , dOClass);
330: }
331:
332: /**
333: * Get whether or not this field can be amended. Useful for automatically
334: * generated fields such as timestamps.
335: * @return <code>true</code> if the field <u>cannot</u> be manually changed.
336: */
337: public boolean isDisplayOnly() {
338: return displayOnly;
339: }
340:
341: /**
342: * <code>true</code> if this field is hidden. Otherwise, <code>false</code>.
343: *
344: * @return Returns whether or not the field is hidden.
345: */
346: public boolean isHidden() {
347: return hidden;
348: }
349:
350: /**
351: * <p>
352: * Is this field is required or optional?
353: * </p>
354: *
355: * @return <code>true</code> if this field is required and must have a
356: * non- <code>null</code>, non-empty value. Otherwise,
357: * <code>false</code> for an optional field.
358: */
359: public final boolean isMandatory() {
360: return mandatory;
361: }
362:
363: /**
364: * If this field represents another value object, but the relationship with
365: * its container is one-to-one, then it can be included in the parent's
366: * mask directly.
367: *
368: * @return <code>true</code> if this field should be displayed directly
369: * in the mask of the parent field.
370: */
371: public boolean isOneToOne() {
372: return oneToOne;
373: }
374:
375: /**
376: * <copyDoc>Refer to {@link #getChoiceProperties}.</copyDoc>
377: * @param choicePropertiesParam
378: * <copyDoc>Refer to {@link #getChoiceProperties}.</copyDoc>
379: */
380: public void setChoiceProperties(
381: final Properties choicePropertiesParam) {
382: if (logger.isDebugEnabled()) {
383: logger.debug("Setting choiceProperties. Before '"
384: + choiceProperties + "', after '"
385: + choicePropertiesParam + "'");
386: }
387: choiceProperties = choicePropertiesParam;
388: }
389:
390: /**
391: * <copyDoc>Refer to {@link #getChoicePropertyKeys}.</copyDoc>
392: * @param choicePropertyKeysParam
393: * <copyDoc>Refer to {@link #getChoicePropertyKeys}.</copyDoc>
394: */
395: public void setChoicePropertyKeys(final List choicePropertyKeysParam) {
396: if (logger.isDebugEnabled()) {
397: logger.debug("Setting choicePropertyKeys. Before '"
398: + choicePropertyKeys + "', after '"
399: + choicePropertyKeysParam + "'");
400: }
401: choicePropertyKeys = choicePropertyKeysParam;
402: }
403:
404: /**
405: * <copyDoc>Refer to {@link #getDefaultValue}.</copyDoc>
406: * @param defaultValueParam
407: * <copyDoc>Refer to {@link #getDefaultValue}.</copyDoc>
408: */
409: public void setDefaultValue(final String defaultValueParam) {
410: if (logger.isDebugEnabled()) {
411: logger.debug("Setting defaultValue. Before '"
412: + defaultValue + "', after '" + defaultValueParam
413: + "'");
414: }
415: defaultValue = defaultValueParam;
416: }
417:
418: /**
419: * <copyDoc>Refer to {@link #isDisplayOnly}.</copyDoc>
420: * @param displayOnlyParam
421: * <copyDoc>Refer to {@link #isDisplayOnly}.</copyDoc>
422: */
423: public void setDisplayOnly(final boolean displayOnlyParam) {
424: if (logger.isDebugEnabled()) {
425: logger.debug("Setting displayOnly. Before '" + displayOnly
426: + "', after '" + displayOnlyParam + "'");
427: }
428: displayOnly = displayOnlyParam;
429: }
430:
431: /**
432: * <copyDoc>Refer to {@link #getDOClass}.</copyDoc>
433: * @param classParam
434: * <copyDoc>Refer to {@link #getDOClass}.</copyDoc>
435: */
436: public void setDOClass(final Class classParam) {
437: if (logger.isDebugEnabled()) {
438: logger.debug("Setting dOClass. Before '" + dOClass
439: + "', after '" + classParam + "'");
440: }
441: dOClass = classParam;
442: }
443:
444: /**
445: * <copyDoc>Refer to {@link #getHidden}.</copyDoc>
446: * @param hiddenParam
447: * <copyDoc>Refer to {@link #getHidden}.</copyDoc>
448: */
449: public void setHidden(final boolean hiddenParam) {
450: if (logger.isDebugEnabled()) {
451: logger.debug("Setting hidden. Before '" + hidden
452: + "', after '" + hiddenParam + "'");
453: }
454: hidden = hiddenParam;
455: }
456:
457: /**
458: * <copyDoc>Refer to {@link #getLabelKey}.</copyDoc>
459: * @param labelKeyParam <copyDoc>Refer to {@link #getLabelKey}.</copyDoc>
460: */
461: public void setLabelKey(final String labelKeyParam) {
462: if (logger.isDebugEnabled()) {
463: logger.debug("Setting labelKey. Before '" + labelKey
464: + "', after '" + labelKeyParam + "'");
465: }
466: labelKey = labelKeyParam;
467: }
468:
469: /**
470: * <copyDoc>Refer to {@link #getMandatory}.</copyDoc>
471: * @param mandatoryParam <copyDoc>Refer to {@link #getMandatory}.</copyDoc>
472: */
473: public void setMandatory(final boolean mandatoryParam) {
474: if (logger.isDebugEnabled()) {
475: logger.debug("Setting mandatory. Before '" + mandatory
476: + "', after '" + mandatoryParam + "'");
477: }
478: mandatory = mandatoryParam;
479: }
480:
481: /**
482: * <copyDoc>Refer to {@link #getName}.</copyDoc>
483: * @param nameParam <copyDoc>Refer to {@link #getName}.</copyDoc>
484: */
485: public void setName(final String nameParam) {
486: if (logger.isDebugEnabled()) {
487: logger.debug("Setting name. Before '" + name + "', after '"
488: + nameParam + "'");
489: }
490: name = nameParam;
491: }
492:
493: /**
494: * <copyDoc>Refer to {@link #isOneToOne}.</copyDoc>
495: * @param oneToOneParam <copyDoc>Refer to {@link #isOneToOne}.</copyDoc>
496: */
497: public void setOneToOne(final boolean oneToOneParam) {
498: if (logger.isDebugEnabled()) {
499: logger.debug("Setting oneToOne. Before '" + oneToOne
500: + "', after '" + oneToOneParam + "'");
501: }
502: oneToOne = oneToOneParam;
503: }
504:
505: /**
506: * <copyDoc>Refer to {@link #getParent}.</copyDoc>
507: * @param parentParam <copyDoc>Refer to {@link #getParent}.</copyDoc>
508: */
509: public void setParent(final Field parentParam) {
510: if (logger.isDebugEnabled()) {
511: logger.debug("Setting parent. Before '" + parent
512: + "', after '" + parentParam + "'");
513: }
514: parent = parentParam;
515: }
516:
517: /**
518: * <copyDoc>Refer to {@link #getType}.</copyDoc>
519: * @param typeParam <copyDoc>Refer to {@link #getType}.</copyDoc>
520: */
521: public void setType(final String typeParam) {
522: if (logger.isDebugEnabled()) {
523: logger.debug("Setting type. Before '" + type + "', after '"
524: + typeParam + "'");
525: }
526: type = typeParam;
527: }
528:
529: /**
530: * Overridden to return the field name.
531: *
532: * @return the field name.
533: */
534: public final String toString() {
535: return getName();
536: }
537: }
|