001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010:
011: package org.mmbase.datatypes;
012:
013: import java.util.*;
014: import java.io.Serializable;
015:
016: import org.mmbase.bridge.*;
017: import org.mmbase.datatypes.processors.*;
018: import org.mmbase.util.*;
019:
020: /**
021: * A value in MMBase (such as the value of a field, or function parameter) is associated with a
022: * 'datatype'. A DataType is actually an elaborated wrapper around a Class object, but besides
023: * this basic type of the value, it also defines restrictions on the values, a default value,
024: * Processors, and perhaps other properties (e.g. properties which describe indications for edit
025: * tool implementations).
026: *
027: * There are several extensions of DataType which normally add other kinds of restrictions which are
028: * specific for certain classes of values. All implementations of DataType extend from {@link
029: * BasicDataType}, but they can sometimes implement different extensions of DataType at the same time
030: * ('multiple inheritance').
031: *
032: * @author Pierre van Rooden
033: * @author Michiel Meeuwissen
034: * @since MMBase-1.8
035: * @version $Id: DataType.java,v 1.65 2008/02/16 22:13:53 nklasens Exp $
036: * @param <C> Class this DataType
037: */
038:
039: public interface DataType<C> extends Descriptor, Cloneable,
040: Comparable<DataType<C>>, Serializable {
041:
042: /**
043: * The XML Namespace to be used for creating datatype XML
044: */
045: public static final String XMLNS = org.mmbase.datatypes.util.xml.DataTypeReader.NAMESPACE_DATATYPES_1_0;
046:
047: // XXXX MM: I think 'action' must be gone; it is silly.
048: static final int PROCESS_GET = 1;
049: static final int PROCESS_SET = 2;
050:
051: /**
052: * Return value for {@link DataType.Restriction#getEnforceStrength}. This means that the value
053: * must be enforced always, and furthermore, that extensions (based on clone) cannot loosen
054: * it. For example, the absolute maximum for any datatype backed by a integer is
055: * Integer.MAX_VALUE, there is no way you can even store a bigger value in this, so this restriction is 'absolute'.
056: */
057: static final int ENFORCE_ABSOLUTE = Integer.MAX_VALUE;
058:
059: /**
060: * Return value for {@link DataType.Restriction#getEnforceStrength}. This means that the value must be enforced always.
061: */
062: static final int ENFORCE_ALWAYS = 100000;
063:
064: /**
065: * Return value for {@link DataType.Restriction#getEnforceStrength}. This means that the value must be enforced only if it was changed.
066: */
067: static final int ENFORCE_ONCHANGE = 10000;
068:
069: /**
070: * Return value for {@link DataType.Restriction#getEnforceStrength}. This means that the value must be enforced only on creation.
071: */
072: static final int ENFORCE_ONCREATE = 1000;
073:
074: /**
075: * Return value for {@link DataType.Restriction#getEnforceStrength}. This means that the
076: * value must be enforced never, so the restriction serves only as UI indication.
077: */
078: static final int ENFORCE_NEVER = 0;
079:
080: /**
081: * Returned by {@link #validate(Object, Node, Field)} if no errors: an empty (nonmodifiable) Collection.
082: */
083: public static final Collection<LocalizedString> VALID = Collections
084: .emptyList();
085:
086: /**
087: * Return the DataType from which this one inherited, or <code>null</code>
088: * @return inherited DataType
089: */
090: public DataType<?> getOrigin();
091:
092: /**
093: * Return an identifier for the basic type (i.e., 'string', 'int', 'datetime') supported by this datatype.
094: * @return identifier for the basic type
095: */
096: public String getBaseTypeIdentifier();
097:
098: /**
099: * Return the datatype's basic (MMBase) type (i.e., STRING, INTEGER, DATETIME) as definied in the Field interface
100: * Note that in some cases (i.e. with older clouds) this may differ from the basic type of the datatype's field,
101: * which defines in what format the data is stored.
102: * @return identifier of the basic type
103: * @see Field#getType
104: */
105: public int getBaseType();
106:
107: /**
108: * Returns the type of values that this data type accepts.
109: * @return the type as a Class
110: */
111: public Class<C> getTypeAsClass();
112:
113: /**
114: * Checks if the passed object is of the correct class (compatible with the type of this data type),
115: * and throws an IllegalArgumentException if it doesn't.
116: * @param value the value whose type (class) to check
117: * @throws IllegalArgumentException if the type is not compatible
118: */
119: public void checkType(Object value);
120:
121: /**
122: * Tries to 'cast' an object for use with this parameter. E.g. if value is a String, but this
123: * parameter is of type Integer, then the string can be parsed to Integer.
124: *
125: *
126: * @param value The value to be filled in a value with this DataType.
127: * @param node Sometimes a node might be needed.
128: * @param field Sometimes a (or 'the') field might be needed.
129: * @return casted object of Class of this DataType
130: */
131: public C cast(Object value, Node node, Field field);
132:
133: /**
134: * Before actually 'cast' an object to the right type, it may undergo some conversion by the
135: * datatype, e.g. enumerations may get resolved (enumerations have the feature that they can
136: * e.g. resolve java-constants to their values).
137: *
138: * This does not guarantee that the value has the 'proper' type, but only that it now can be
139: * cast to the right type without further problems. ({@link org.mmbase.util.Casting#toType(Class, Object)} should do).
140: *
141: * preCast should not change the actual type of value. It is e.g. used in the
142: * Node#setStringValue, and the processor may expect a String there.
143: * @param value The value to be filled in a value with this DataType.
144: * @param node Sometimes a node might be needed.
145: * @param field Sometimes a (or 'the') field might be needed.
146: * @param <D>
147: * @return converted value to be able to cast to the DataType of the field
148: */
149: public <D> D preCast(D value, Node node, Field field);
150:
151: //public Object preCast(Object value, Node node, Field field);
152:
153: /**
154: * Returns the default value of this data type.
155: * @return the default value
156: */
157: public C getDefaultValue();
158:
159: /**
160: * Set the default value for this DataType
161: * @param def default value
162: */
163: public void setDefaultValue(C def);
164:
165: /**
166: * Unlock a DataType so it can be changed or altered.
167: * @param owner the object to finish datatypes with
168: * @return unlocked DataType
169: */
170: public DataType<C> rewrite(Object owner);
171:
172: /**
173: * Is datatype locked
174: * @return <code>true</code> when datatype is locked
175: */
176: public boolean isFinished();
177:
178: /**
179: * Lock a dataType so it can be changed or altered.
180: * @param owner the object to finish datatypes with
181: */
182: public void finish(Object owner);
183:
184: /**
185: * The maximum enforce strength of all restrictions on this datatype.
186: * See {@link DataType#ENFORCE_ALWAYS}, {@link DataType#ENFORCE_ONCHANGE}, {@link DataType#ENFORCE_NEVER}.
187: * @return maximum enforce strength
188: */
189: public int getEnforceStrength();
190:
191: /**
192: * @see #validate(Object, Node, Field)
193: * @return The error message(s) if the value is not compatible. An empty collection if valid.
194: * @param value the value to be validated
195: */
196: public Collection<LocalizedString> validate(C value);
197:
198: /**
199: * Checks if the passed object obeys the restrictions defined for this type.
200: * @param value the value to validate
201: * @param node the node for which the datatype is checked. If not <code>null</code>, and the
202: * datatype is determined as unique, than uniquness is checked for this value using the passed field.
203: * @param field the field for which the datatype is checked.
204: *
205: * @return The error message(s) if the value is not compatible. An empty collection if the value is valid.
206: */
207: public Collection<LocalizedString> validate(C value, Node node,
208: Field field);
209:
210: /**
211: * Returns whether this field is required (may not be <code>null</code>, or otherwise empty).
212: *
213: * @return <code>true</code> if the field is required
214: */
215: public boolean isRequired();
216:
217: /**
218: * Returns the 'required' restriction, containing the value, error messages, and fixed status of this attribute.
219: * @return the restriction as a {@link DataType.Restriction}
220: */
221: public DataType.Restriction<Boolean> getRequiredRestriction();
222:
223: /**
224: * Sets whether the data type requires a value, which means that it may not remain unfilled.
225: * @param required <code>true</code> if a value is required
226: * @throws IllegalStateException if the datatype was finished (and thus can no longer be changed)
227: */
228: public void setRequired(boolean required);
229:
230: /**
231: * Returns whether this field has a unique restriction.
232: * Uniqueness is generally achieved through association of the datatype with one or more sets of fields.
233: * This is notably different from other datatype properties.
234: *
235: * Note that the MMBase core does not generally enforce uniqueness, but the storage layer might.
236: *
237: * @return <code>true</code> if the field is unique
238: */
239: public boolean isUnique();
240:
241: /**
242: * Returns the 'unique' restriction, containing the value, error messages, and fixed status of this attribute.
243: * @return the restriction as a {@link DataType.Restriction}
244: */
245: public DataType.Restriction<Boolean> getUniqueRestriction();
246:
247: /**
248: * Sets whether the data type requires a value.
249: * @param unique <code>true</code> if a value is unique
250: * @throws IllegalStateException if the datatype was finished (and thus can no longer be changed)
251: */
252: public void setUnique(boolean unique);
253:
254: /**
255: * Returns an iterator over all possible values for this datatype, as {@link java.util.Map.Entry}s, or
256: * <code>null</code> if no enumeration restrictions apply. Every Map entry contains as key the
257: * 'value' for this datatype and as value it contains the description for this value in the
258: * given locale.
259: *
260: * This Iterator skips all entries which are impossible because of other restrictions on this datatype.
261: *
262: * @param locale for which to produce
263: * @param cloud Possibly the possible values depend on a cloud (security)
264: * @param node Possibly the possible values depend on an actual node (this may be, and in the default implementation is, ignored)
265: * @param field Possibly the possible values depend on an actual field (this may be, and in the default implementation is, ignored)
266: * @return iterator over all possible values for this datatype
267: *
268: */
269: public Iterator<Map.Entry<C, String>> getEnumerationValues(
270: Locale locale, Cloud cloud, Node node, Field field);
271:
272: /**
273: * Returns a (gui) value from a list of restricted enumerated values, or
274: * <code>null</code> if no enumeration restrictions apply or teh value cannot be found.
275: *
276: * @param locale for which to produce
277: * @param cloud Possibly the possible values depend on a cloud (security)
278: * @param node Possibly the possible values depend on an actual node (this may be, and in the default implementation is, ignored)
279: * @param field Possibly the possible values depend on an actual field (this may be, and in the default implementation is, ignored)
280: * @param key the key for which to look up the (gui) value
281: * @return a (gui) value from a list of restricted enumerated values
282: */
283: public String getEnumerationValue(Locale locale, Cloud cloud,
284: Node node, Field field, Object key);
285:
286: /**
287: * @return the LocalizedEntryListFactory which will be used to produce the result of {@link
288: * #getEnumerationValues}. Never <code>null</code>. This can be used to add more possible values.
289: */
290: public LocalizedEntryListFactory<C> getEnumerationFactory();
291:
292: /**
293: * The enumeration for this datatype as a {@link Restriction}.
294: * @return enumeration for this datatype
295: */
296: public DataType.Restriction<LocalizedEntryListFactory<C>> getEnumerationRestriction();
297:
298: /**
299: * Return the Commit processor of this datatype
300: * @return Commit processor
301: */
302: public CommitProcessor getCommitProcessor();
303:
304: /**
305: * Set the Commit processor of this datatype
306: * @param cp Commit processor
307: */
308: public void setCommitProcessor(CommitProcessor cp);
309:
310: /**
311: * Returns the default processor for this action
312: * @param action either {@link #PROCESS_GET}, or {@link #PROCESS_SET}
313: * XXX What exactly would be against getGetProcesor(), getSetProcessor() ?
314: * @return the default processor for this action
315: */
316: public Processor getProcessor(int action);
317:
318: /**
319: * Returns the processor for this action and processing type
320: * @param action either {@link #PROCESS_GET}, or {@link #PROCESS_SET}
321: * @param processingType the MMBase type defining the type of value to process
322: * @return the processor for this action and processing type
323: */
324: public Processor getProcessor(int action, int processingType);
325:
326: /**
327: * Sets the processor for this action
328: * @param action either {@link #PROCESS_GET}, or {@link #PROCESS_SET}
329: * @param processor the processor for this action
330: */
331: public void setProcessor(int action, Processor processor);
332:
333: /**
334: * Sets the processor for this action
335: * @param action either {@link #PROCESS_GET}, or {@link #PROCESS_SET}
336: * @param processor the processor for this action and processing type
337: * @param processingType the MMBase type defining the type of value to process
338: */
339: public void setProcessor(int action, Processor processor,
340: int processingType);
341:
342: /**
343: * Returns a cloned instance of this datatype, inheriting all validation rules.
344: * Unlike the original datatype though, the cloned copy is declared unfinished even if the original
345: * was finished. This means that the cloned datatype can be changed.
346: * @return cloned instance
347: */
348: public Object clone();
349:
350: /**
351: * Returns a cloned instance of this datatype, inheriting all validation rules.
352: * Similar to calling clone(), but changes the data type name if one is provided.
353: * @param name the new name of the copied datatype (can be <code>null</code>, in which case the name is not changed).
354: * @return cloned DataType
355: */
356: public DataType<C> clone(String name);
357:
358: /**
359: * Returns a DOM element describing this DataType.
360: * @return a DOM element describing this DataType.
361: * @todo EXPERIMENTAL.
362: */
363: public org.w3c.dom.Element toXml();
364:
365: /**
366: * Fills this datatype in another XML (for example in the xml of {@link #getOrigin}, to make one XML, fully describing the DataType).
367: * The implementation of this method is <em>unfinished</em>!
368: * @todo EXPERIMENTAL
369: * @param element a 'datatype' element.
370: */
371: public void toXml(org.w3c.dom.Element element);
372:
373: /**
374: * A restriction controls (one aspect of) the acceptable values of a DataType. A DataType generally has several restrictions.
375: * @param <D> Type of Value describing the restriction
376: */
377: public interface Restriction<D extends Serializable> extends
378: Serializable {
379:
380: /**
381: * @return Name of datatype
382: */
383: public String getName();
384:
385: /**
386: * A Value describing the restriction, so depending on the semantics of this restriction, it
387: * can have virtually every type (as long as it is Serializable)
388: * @return A Value describing the restriction
389: */
390: public D getValue();
391:
392: /**
393: * Set the Value describing the restriction
394: * @param value The instanc for the Value
395: */
396: public void setValue(D value);
397:
398: /**
399: * If the restriction does not hold, the following error description can be used. On default
400: * these descriptions are searched in a resource bundle based on the name of this
401: * restriction.
402: * @return error description
403: */
404: public LocalizedString getErrorDescription();
405:
406: /**
407: * Set error description for this restriction
408: * @param errorDescription description of error
409: */
410: public void setErrorDescription(LocalizedString errorDescription);
411:
412: /**
413: * This function should contain the actual logic of the restriction. This does not consider
414: * the 'enforceStrength' (that is only used in the containing DataType implementation).
415: *
416: * @param value The value to check the restriction for
417: * @param node Some constrainst may need the Node.
418: * @param field Some constrainst may need the Field.
419: * @return Whether the supplied value is a valid value for this restriction.
420: */
421: public boolean valid(Object value, Node node, Field field);
422:
423: /**
424: * If a restriction is 'fixed', the value and error-description cannot be changed any more.
425: * @param fixed
426: */
427: public void setFixed(boolean fixed);
428:
429: /**
430: * See {@link DataType#ENFORCE_ALWAYS}, {@link DataType#ENFORCE_ONCHANGE}, {@link DataType#ENFORCE_NEVER}.
431: * @return enforce strength
432: */
433: public int getEnforceStrength();
434:
435: /**
436: * Set enforce strength
437: * @param v value of {@link DataType#ENFORCE_ALWAYS}, {@link DataType#ENFORCE_ONCHANGE}, {@link DataType#ENFORCE_NEVER}.
438: */
439: public void setEnforceStrength(int v);
440:
441: }
442:
443: }
|