KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > xdoclet > modules > ojb > constraints > CollectionDescriptorConstraints


1 package xdoclet.modules.ojb.constraints;
2
3 import xdoclet.modules.ojb.CommaListIterator;
4 import xdoclet.modules.ojb.model.ClassDescriptorDef;
5 import xdoclet.modules.ojb.model.CollectionDescriptorDef;
6 import xdoclet.modules.ojb.model.FieldDescriptorDef;
7 import xdoclet.modules.ojb.model.ModelDef;
8 import xdoclet.modules.ojb.model.PropertyHelper;
9
10 /* Copyright 2004-2005 The Apache Software Foundation
11  *
12  * Licensed under the Apache License, Version 2.0 (the "License");
13  * you may not use this file except in compliance with the License.
14  * You may obtain a copy of the License at
15  *
16  * http://www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an "AS IS" BASIS,
20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  */

24
25 /**
26  * Checks constraints for collection descriptors. Note that constraints may modify the collection descriptor.
27  * For checks of the relationships (e.g. foreignkey) see ModelConstraints.
28  *
29  * @author <a HREF="mailto:tomdz@users.sourceforge.net">Thomas Dudziak (tomdz@users.sourceforge.net)</a>
30  */

31 public class CollectionDescriptorConstraints extends FeatureDescriptorConstraints
32 {
33     /** The collection interface (this type or subtypes of it can be handled by OJB) */
34     private final static String JavaDoc JAVA_COLLECTION_INTERFACE = "java.util.Collection";
35     /** The interface that user-defined collection classes must implement */
36     private final static String JavaDoc MANAGEABLE_COLLECTION_INTERFACE = "org.apache.ojb.broker.ManageableCollection";
37     /** The interface that user-defined query customizers must implement */
38     private final static String JavaDoc QUERY_CUSTOMIZER_INTERFACE = "org.apache.ojb.broker.accesslayer.QueryCustomizer";
39
40     /**
41      * Checks the given collection descriptor.
42      *
43      * @param collDef The collection descriptor
44      * @param checkLevel The amount of checks to perform
45      * @exception ConstraintException If a constraint has been violated
46      */

47     public void check(CollectionDescriptorDef collDef, String JavaDoc checkLevel) throws ConstraintException
48     {
49         ensureElementClassRef(collDef, checkLevel);
50         checkInheritedForeignkey(collDef, checkLevel);
51         ensureCollectionClass(collDef, checkLevel);
52         checkProxyPrefetchingLimit(collDef, checkLevel);
53         checkOrderby(collDef, checkLevel);
54         checkQueryCustomizer(collDef, checkLevel);
55     }
56
57     /**
58      * Ensures that the given collection descriptor has a valid element-class-ref property.
59      *
60      * @param collDef The collection descriptor
61      * @param checkLevel The current check level (this constraint is checked in basic and strict)
62      * @exception ConstraintException If element-class-ref could not be determined or is invalid
63      */

64     private void ensureElementClassRef(CollectionDescriptorDef collDef, String JavaDoc checkLevel) throws ConstraintException
65     {
66         if (CHECKLEVEL_NONE.equals(checkLevel))
67         {
68             return;
69         }
70
71         String JavaDoc arrayElementClassName = collDef.getProperty(PropertyHelper.OJB_PROPERTY_ARRAY_ELEMENT_CLASS_REF);
72
73         if (!collDef.hasProperty(PropertyHelper.OJB_PROPERTY_ELEMENT_CLASS_REF))
74         {
75             if (arrayElementClassName != null)
76             {
77                 // we use the array element type
78
collDef.setProperty(PropertyHelper.OJB_PROPERTY_ELEMENT_CLASS_REF, arrayElementClassName);
79             }
80             else
81             {
82                 throw new ConstraintException("Collection "+collDef.getName()+" in class "+collDef.getOwner().getName()+" does not specify its element class");
83             }
84         }
85
86         // now checking the element type
87
ModelDef model = (ModelDef)collDef.getOwner().getOwner();
88         String JavaDoc elementClassName = collDef.getProperty(PropertyHelper.OJB_PROPERTY_ELEMENT_CLASS_REF);
89         ClassDescriptorDef elementClassDef = model.getClass(elementClassName);
90
91         if (elementClassDef == null)
92         {
93             throw new ConstraintException("Collection "+collDef.getName()+" in class "+collDef.getOwner().getName()+" references an unknown class "+elementClassName);
94         }
95         if (!elementClassDef.getBooleanProperty(PropertyHelper.OJB_PROPERTY_OJB_PERSISTENT, false))
96         {
97             throw new ConstraintException("The element class "+elementClassName+" of the collection "+collDef.getName()+" in class "+collDef.getOwner().getName()+" is not persistent");
98         }
99         if (CHECKLEVEL_STRICT.equals(checkLevel) && (arrayElementClassName != null))
100         {
101             // specified element class must be a subtype of the element type
102
try
103             {
104                 InheritanceHelper helper = new InheritanceHelper();
105
106                 if (!helper.isSameOrSubTypeOf(elementClassDef, arrayElementClassName, true))
107                 {
108                     throw new ConstraintException("The element class "+elementClassName+" of the collection "+collDef.getName()+" in class "+collDef.getOwner().getName()+" is not the same or a subtype of the array base type "+arrayElementClassName);
109                 }
110             }
111             catch (ClassNotFoundException JavaDoc ex)
112             {
113                 throw new ConstraintException("Could not find the class "+ex.getMessage()+" on the classpath while checking the collection "+collDef.getName()+" in class "+collDef.getOwner().getName());
114             }
115         }
116         // we're adjusting the property to use the classloader-compatible form
117
collDef.setProperty(PropertyHelper.OJB_PROPERTY_ELEMENT_CLASS_REF, elementClassDef.getName());
118     }
119
120     /**
121      * Checks that the foreignkey is not modified in an inherited/nested m:n collection descriptor.
122      *
123      * @param collDef The collection descriptor
124      * @param checkLevel The current check level (this constraint is checked in basic and strict)
125      */

126     private void checkInheritedForeignkey(CollectionDescriptorDef collDef, String JavaDoc checkLevel) throws ConstraintException
127     {
128         if (CHECKLEVEL_NONE.equals(checkLevel))
129         {
130             return;
131         }
132         if (!collDef.isInherited() && !collDef.isNested())
133         {
134             return;
135         }
136         if (!collDef.hasProperty(PropertyHelper.OJB_PROPERTY_INDIRECTION_TABLE))
137         {
138             return;
139         }
140
141         String JavaDoc localFk = collDef.getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY);
142         String JavaDoc inheritedFk = collDef.getOriginal().getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY);
143
144         if (!CommaListIterator.sameLists(localFk, inheritedFk))
145         {
146             throw new ConstraintException("The foreignkey property has been changed for the m:n collection "+collDef.getName()+" in class "+collDef.getOwner().getName());
147         }
148     }
149
150     /**
151      * Ensures that the given collection descriptor has the collection-class property if necessary.
152      *
153      * @param collDef The collection descriptor
154      * @param checkLevel The current check level (this constraint is checked in basic (partly) and strict)
155      * @exception ConstraintException If collection-class is given for an array or if no collection-class is given but required
156      */

157     private void ensureCollectionClass(CollectionDescriptorDef collDef, String JavaDoc checkLevel) throws ConstraintException
158     {
159         if (CHECKLEVEL_NONE.equals(checkLevel))
160         {
161             return;
162         }
163
164         if (collDef.hasProperty(PropertyHelper.OJB_PROPERTY_ARRAY_ELEMENT_CLASS_REF))
165         {
166             // an array cannot have a collection-class specified
167
if (collDef.hasProperty(PropertyHelper.OJB_PROPERTY_COLLECTION_CLASS))
168             {
169                 throw new ConstraintException("Collection "+collDef.getName()+" in class "+collDef.getOwner().getName()+" is an array but does specify collection-class");
170             }
171             else
172             {
173                 // no further processing necessary as its an array
174
return;
175             }
176         }
177
178         if (CHECKLEVEL_STRICT.equals(checkLevel))
179         {
180             InheritanceHelper helper = new InheritanceHelper();
181             ModelDef model = (ModelDef)collDef.getOwner().getOwner();
182             String JavaDoc specifiedClass = collDef.getProperty(PropertyHelper.OJB_PROPERTY_COLLECTION_CLASS);
183             String JavaDoc variableType = collDef.getProperty(PropertyHelper.OJB_PROPERTY_VARIABLE_TYPE);
184     
185             try
186             {
187                 if (specifiedClass != null)
188                 {
189                     // if we have a specified class then it has to implement the manageable collection and be a sub type of the variable type
190
if (!helper.isSameOrSubTypeOf(specifiedClass, variableType))
191                     {
192                         throw new ConstraintException("The type "+specifiedClass+" specified as collection-class of the collection "+collDef.getName()+" in class "+collDef.getOwner().getName()+" is not a sub type of the variable type "+variableType);
193                     }
194                     if (!helper.isSameOrSubTypeOf(specifiedClass, MANAGEABLE_COLLECTION_INTERFACE))
195                     {
196                         throw new ConstraintException("The type "+specifiedClass+" specified as collection-class of the collection "+collDef.getName()+" in class "+collDef.getOwner().getName()+" does not implement "+MANAGEABLE_COLLECTION_INTERFACE);
197                     }
198                 }
199                 else
200                 {
201                     // no collection class specified so the variable type has to be a collection type
202
if (helper.isSameOrSubTypeOf(variableType, MANAGEABLE_COLLECTION_INTERFACE))
203                     {
204                         // we can specify it as a collection-class as it is an manageable collection
205
collDef.setProperty(PropertyHelper.OJB_PROPERTY_COLLECTION_CLASS, variableType);
206                     }
207                     else if (!helper.isSameOrSubTypeOf(variableType, JAVA_COLLECTION_INTERFACE))
208                     {
209                         throw new ConstraintException("The collection "+collDef.getName()+" in class "+collDef.getOwner().getName()+" needs the collection-class attribute as its variable type does not implement "+JAVA_COLLECTION_INTERFACE);
210                     }
211                 }
212             }
213             catch (ClassNotFoundException JavaDoc ex)
214             {
215                 throw new ConstraintException("Could not find the class "+ex.getMessage()+" on the classpath while checking the collection "+collDef.getName()+" in class "+collDef.getOwner().getName());
216             }
217         }
218     }
219
220     /**
221      * Checks the orderby attribute.
222      *
223      * @param collDef The collection descriptor
224      * @param checkLevel The current check level (this constraint is checked in basic and strict)
225      * @exception ConstraintException If the value for orderby is invalid (unknown field or ordering)
226      */

227     private void checkOrderby(CollectionDescriptorDef collDef, String JavaDoc checkLevel) throws ConstraintException
228     {
229         if (CHECKLEVEL_NONE.equals(checkLevel))
230         {
231             return;
232         }
233
234         String JavaDoc orderbySpec = collDef.getProperty(PropertyHelper.OJB_PROPERTY_ORDERBY);
235
236         if ((orderbySpec == null) || (orderbySpec.length() == 0))
237         {
238             return;
239         }
240
241         ClassDescriptorDef ownerClass = (ClassDescriptorDef)collDef.getOwner();
242         String JavaDoc elementClassName = collDef.getProperty(PropertyHelper.OJB_PROPERTY_ELEMENT_CLASS_REF).replace('$', '.');
243         ClassDescriptorDef elementClass = ((ModelDef)ownerClass.getOwner()).getClass(elementClassName);
244         FieldDescriptorDef fieldDef;
245         String JavaDoc token;
246         String JavaDoc fieldName;
247         String JavaDoc ordering;
248         int pos;
249
250         for (CommaListIterator it = new CommaListIterator(orderbySpec); it.hasNext();)
251         {
252             token = it.getNext();
253             pos = token.indexOf('=');
254             if (pos == -1)
255             {
256                 fieldName = token;
257                 ordering = null;
258             }
259             else
260             {
261                 fieldName = token.substring(0, pos);
262                 ordering = token.substring(pos + 1);
263             }
264             fieldDef = elementClass.getField(fieldName);
265             if (fieldDef == null)
266             {
267                 throw new ConstraintException("The field "+fieldName+" specified in the orderby attribute of the collection "+collDef.getName()+" in class "+ownerClass.getName()+" hasn't been found in the element class "+elementClass.getName());
268             }
269             if ((ordering != null) && (ordering.length() > 0) &&
270                 !"ASC".equals(ordering) && !"DESC".equals(ordering))
271             {
272                 throw new ConstraintException("The ordering "+ordering+" specified in the orderby attribute of the collection "+collDef.getName()+" in class "+ownerClass.getName()+" is invalid");
273             }
274         }
275     }
276
277     /**
278      * Checks the query-customizer setting of the given collection descriptor.
279      *
280      * @param collDef The collection descriptor
281      * @param checkLevel The current check level (this constraint is only checked in strict)
282      * @exception ConstraintException If the constraint has been violated
283      */

284     private void checkQueryCustomizer(CollectionDescriptorDef collDef, String JavaDoc checkLevel) throws ConstraintException
285     {
286         if (!CHECKLEVEL_STRICT.equals(checkLevel))
287         {
288             return;
289         }
290         
291         String JavaDoc queryCustomizerName = collDef.getProperty(PropertyHelper.OJB_PROPERTY_QUERY_CUSTOMIZER);
292
293         if (queryCustomizerName == null)
294         {
295             return;
296         }
297
298         try
299         {
300             InheritanceHelper helper = new InheritanceHelper();
301
302             if (!helper.isSameOrSubTypeOf(queryCustomizerName, QUERY_CUSTOMIZER_INTERFACE))
303             {
304                 throw new ConstraintException("The class "+queryCustomizerName+" specified as query-customizer of collection "+collDef.getName()+" in class "+collDef.getOwner().getName()+" does not implement the interface "+QUERY_CUSTOMIZER_INTERFACE);
305             }
306         }
307         catch (ClassNotFoundException JavaDoc ex)
308         {
309             throw new ConstraintException("The class "+ex.getMessage()+" specified as query-customizer of collection "+collDef.getName()+" in class "+collDef.getOwner().getName()+" was not found on the classpath");
310         }
311     }
312 }
313
Popular Tags