KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > datatypes > DataTypeCollector


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10
11 package org.mmbase.datatypes;
12
13 import java.util.*;
14 import org.mmbase.datatypes.util.xml.DataTypeDefinition;
15 import org.mmbase.util.logging.*;
16
17 /**
18  * A DataTypeCollector is a collection of named DataTypes. So, you can add and request DataType
19  * objects from this by a String. It also facilitates 'chaining' because you can add other
20  * DataTypeCollectors to it. It will delegate searching of a datatype to them, if a certain key is
21  * not available.
22  * <br />
23  * This object also knowns how to 'lock' its DataType's using it's 'signature'. I have no idea where
24  * that is good for.
25  *
26  * @author Pierre van Rooden
27  * @since MMBase-1.8
28  * @version $Id: DataTypeCollector.java,v 1.11 2006/04/04 22:54:16 michiel Exp $
29  */

30
31 public final class DataTypeCollector {
32
33     private static final Logger log = Logging.getLoggerInstance(DataTypeCollector.class);
34
35     // Map of datatypes local to this collector
36
private Map dataTypes = new HashMap(); // String -> BasicDataType
37
private Map specializations = new HashMap(); // String -> Set
38
private Set roots = new HashSet(); // All datatypes which did't inherit from another datatype (this should normally be (a subset of) the 'database types' of mmbase)
39

40     // the object to finish datatypes with
41
private Object JavaDoc signature = null;
42
43     // dependent collectors
44
private List collectors = new ArrayList();
45
46     // the DataTypeCollector used to store datatypes accessible throughout the application
47
private static DataTypeCollector systemDataTypeCollector;
48
49     /**
50      * Creates the DataTypeCollector used to store datatypes accessible throughout the application.
51      * Called by the {@link DataTypes} class.
52      */

53     static DataTypeCollector createSystemDataTypeCollector() {
54         if (systemDataTypeCollector == null) {
55             Object JavaDoc signature = new String JavaDoc( "SYSTEM_" + System.currentTimeMillis());
56             systemDataTypeCollector = new DataTypeCollector(signature);
57             return systemDataTypeCollector;
58         } else {
59             throw new SecurityException JavaDoc("System datatype collector already defined, may not be created twice.");
60         }
61     }
62
63     /**
64      * Constructor.
65      * @param signature the object used to finish a data type for this collector.
66      */

67     public DataTypeCollector(Object JavaDoc signature) {
68          this.signature = signature;
69     }
70
71     public DataTypeDefinition getDataTypeDefinition() {
72         return new DataTypeDefinition(this);
73     }
74
75     /**
76      * Adds a datatype collector on which this collector depends.
77      * when trying to obtain a datatype or datatype instance, if
78      * the current collector does not contain the datatype, it tries to obtain
79      * it from any colelctors it depends on.
80      * @param collector the dataType collector to add
81      */

82      public void addCollector(DataTypeCollector collector) {
83          collectors.add(collector);
84      }
85
86     /**
87      * Set local datatypes of the collector
88      * @param dataTypes a <code>Map</code> containing the datatypes
89      */

90     public void setDataTypes(Map dataTypes) {
91         this.dataTypes = dataTypes;
92         if (log.isDebugEnabled()) log.debug("DataTypes for collector with signature " + signature + ":" +dataTypes);
93     }
94
95     /**
96      * Set local datatypes of the collector
97      */

98     public Map getDataTypes() {
99         return dataTypes;
100     }
101
102     /**
103      * Get a datatype defined for this collector.
104      * @param name the name of the datatype to retrieve
105      * @return a {@link DataType} with the given name, as defined for this collector, or <code>null</code>
106      * if no datatype is defined.
107      */

108     public BasicDataType getDataType(String JavaDoc name) {
109         return getDataType(name, false);
110     }
111
112     /**
113      * Adds a datatype to this collector.
114      * The datatype should have a unique id. If it has no id (i.e. getName() returns an empty string), it is not added.
115      * If the datatype overrides an existing datatype, a warning is logged.
116      * @param dataType the datatype to add
117      * @return if applicable, the old (original) datatype with the same id as the dattype that was being added, <code>null</code>
118      * if it is not applicable.
119      */

120     public BasicDataType addDataType(BasicDataType dataType) {
121         String JavaDoc name = dataType.getName();
122         if (name == null || "".equals(name)) {
123             // not a proper id, so do not add
124
return null;
125         } else {
126             DataType origin = dataType.getOrigin();
127             if (origin != null) {
128                 if (origin.equals(getDataType(origin.getName()))) { // origin is also in this collector
129
Set spec = (Set) specializations.get(origin.getName());
130                     // TODO, not sure that this stuff with specializations goes ok when using 'parent' collectors.
131
// Does not matter very much, because you problably want to use this functionlaity mainly on the System Collector
132
if (spec == null) {
133                         spec = new HashSet();
134                         specializations.put(origin.getName(), spec);
135                     }
136                     spec.add(dataType);
137                 } else {
138                     roots.add(dataType);
139                 }
140             } else {
141                 roots.add(dataType);
142             }
143             BasicDataType old = (BasicDataType) dataTypes.put(name, dataType);
144             if (old != null && old != dataType) {
145                 log.warn("Replaced " + name + " " + old + " with " + dataType);
146             }
147             return old;
148         }
149     }
150
151     /**
152      * Returns a set of all DataTypes in this collector which are directly inherited from the one with given name
153      */

154     public Collection getSpecializations(String JavaDoc name) {
155         // TODO: see in addDataType
156
Set set = (Set) specializations.get(name);
157         return set == null ? Collections.EMPTY_SET : Collections.unmodifiableSet(set);
158     }
159
160     /**
161      * Recursively calls {@link #getSpecializations(String)} so that you can easily iterate also all indirectly specializaed versions of a certain DataType in this collector
162      */

163     public Iterator getAllSpecializations(String JavaDoc name) {
164         final Iterator i = getSpecializations(name).iterator();
165         return new Iterator() {
166             DataType next = i.hasNext() ? (DataType) i.next() : null;
167             Iterator subIterator = null;
168             public boolean hasNext() {
169                 return next != null || subIterator != null;
170             }
171             public Object JavaDoc next() {
172                 if (subIterator != null) {
173                     Object JavaDoc n = subIterator.next();
174                     if (! subIterator.hasNext()) subIterator = null;
175                     return n;
176                 }
177                 if (next != null) {
178                     subIterator = getAllSpecializations(next.getName());
179                     if (! subIterator.hasNext()) subIterator = null;
180                     Object JavaDoc n = next;
181                     if (i.hasNext()) {
182                         next = (DataType) i.next();
183                     } else {
184                         next = null;
185                     }
186                     return n;
187                 }
188                 throw new NoSuchElementException();
189             }
190             public void remove() {
191                 throw new UnsupportedOperationException JavaDoc();
192             }
193         };
194     }
195     /**
196      * Returns all DataTypes in this Collector which did not have an origina DataType (in this Collector).
197      */

198     public Set getRoots() {
199         // TODO: see in addDataType
200
return Collections.unmodifiableSet(roots);
201     }
202
203     /**
204      * Get a datatype defined for this collector, and possibly any collectors it depends on.
205      * The collector first searches among datatypes defined in its own set.
206      * If that fails, it tries ot get it from any of the other collectors it may depend on, and eventually
207      * from the main repository.
208      * @param name the name of the datatype to retrieve
209      * @param recursive if <code>true</code>, the datatype is also searched in collectors it depends on.
210      * @return a {@link DataType} with the given name, as defined for this collector, or <code>null</code>
211      * if no datatype is defined.
212      */

213     public BasicDataType getDataType(String JavaDoc name, boolean recursive) {
214         BasicDataType dataType = (BasicDataType) dataTypes.get(name);
215         if (this != systemDataTypeCollector && dataType == null && recursive) {
216             for (Iterator i = collectors.iterator(); dataType == null && i.hasNext();) {
217                 DataTypeCollector collector = (DataTypeCollector) i.next();
218                 dataType = collector.getDataType(name, true);
219             }
220             if (dataType == null) {
221                 dataType = systemDataTypeCollector.getDataType(name, false);
222             }
223         }
224         return dataType;
225     }
226
227     /**
228      * Get a datatype instance through this collector.
229      * The collector first searches among datatypes defined in its own set.
230      * If that fails, it tries to get it from any of the other collectors it may depend on, and eventually
231      * from the main repository.
232      * If that fails too, it creates one itself based on the passed base datatype (if given).
233      * @param name the name of the datatype to retrieve
234      * @param baseDataType the datatype to base a new datatype on if it is not yet defined. Can be <code>null</code>.
235      * @return a {@link DataType} with the given name, as defined for this collector, or <code>null</code>
236      * if no datatype is defined and no base datatype was passed.
237      */

238     public BasicDataType getDataTypeInstance(String JavaDoc name, BasicDataType baseDataType) {
239         BasicDataType dataType = getDataType(name, true);
240         if (dataType == null && baseDataType == null) {
241             return null;
242         } else if (dataType == null) {
243             return (BasicDataType)baseDataType.clone(name);
244         } else {
245             return (BasicDataType)dataType.clone();
246         }
247     }
248
249     /**
250      * Returns whether the dataType with the given name is part of the current collection.
251      */

252     public boolean contains(String JavaDoc name) {
253         return dataTypes.containsKey(name);
254     }
255
256     /**
257      * Returns whether the dataType is part of the current collection.
258      */

259     public boolean contains(DataType dataType) {
260         return dataTypes.containsValue(dataType);
261     }
262
263     /**
264      * Unlock a dataType so it can be changed or latered.
265      * This will likely fail if the datatype is not part of this collector.
266      */

267     public void rewrite(DataType dataType) {
268         dataType.rewrite(signature);
269     }
270
271     /**
272      * Lock a dataType so it can be changed or latered.
273      * This will likely fail if the datatype is not part of this collector.
274      */

275     public void finish(DataType dataType) {
276         dataType.finish(signature);
277     }
278
279     public String JavaDoc toString() {
280         return signature + ": " + dataTypes.values() + " " + collectors;
281     }
282
283 }
284
285
Popular Tags