KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > api > persistence > enhancer > meta > JDOMetaDataProperties


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 //JDOMetaDataProperties - Java Source
25

26
27 //***************** package ***********************************************
28

29 package com.sun.jdo.api.persistence.enhancer.meta;
30
31
32 //***************** import ************************************************
33

34 import java.lang.reflect.Modifier JavaDoc;
35
36 import java.util.Comparator JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.Enumeration JavaDoc;
39 import java.util.Map JavaDoc;
40 import java.util.List JavaDoc;
41 import java.util.Collection JavaDoc;
42 import java.util.Collections JavaDoc;
43 import java.util.HashSet JavaDoc;
44 import java.util.HashMap JavaDoc;
45 import java.util.ArrayList JavaDoc;
46 import java.util.Properties JavaDoc;
47 import java.util.StringTokenizer JavaDoc;
48
49 import java.text.MessageFormat JavaDoc;
50
51
52 //#########################################################################
53
/**
54  * This class parses properties containing meta data information
55  * about classes. The syntax of the properties is the following:
56  * <ul> <li>
57  * the keys in the properties file are fully qualified classnames or
58  * fully qualified fieldnames
59  * </li> <li>
60  * a fields is separated by a classname with a hash mark ('#')
61  * (e.g. "test.Test#test1")
62  * </li> <li>
63  * all classnames are given in a natural form (e.g. "java.lang.Integer",
64  * "java.lang.Integer[][]", "int", "test.Test$Test1")
65  * </li> <li>
66  * property keys are classnames and fieldnames
67  * (e.g. "test.Test=...", "test.Test#field1=...") <br>
68  * </li> <li>
69  * Classnames can have the following attributes:
70  * <ul> <li>
71  * jdo:{persistent|transactional}
72  * </li> <li>
73  * super: &#60;classname&#62;
74  * </li> <li>
75  * access: {public|protected|package|private}
76  * </li> </ul> <li>
77  * Fieldnames can have the following attributes:
78  * <ul> <li>
79  * type:&#60;type&#62;
80  * </li> <li>
81  * access: {public|protected|package|private}
82  * </li> <li>
83  * jdo:{persistent|transactional|transient}
84  * </li> <li>
85  * annotation:{pk|dfg|mediated}
86  * </li> </ul>
87  * </li> <li>
88  * the names of the attributes can be ommitted: you can say <br>
89  * test.Test1#field1=jdo:persistent,type:java.lang.String,pk,... <br>
90  * or <br>
91  * test.Test1#field1=persistent,java.lang.String,pk,... <br>
92  * or <br>
93  * test.Test1#field1=jdo:persistent,java.lang.String,pk,... <br>
94  * </li> <li>
95  * in order to find fields of a class, a line for the class has to be
96  * specified in the properties: To find the field
97  * <code>test.Test1#field</code>, the keys <code>test.Test1</code> and
98  * <code>test.Test1#Field</code> have to be present.
99  * </li> </ul>
100  * This class is not thread safe.
101  */

102 //#########################################################################
103

104 public final class JDOMetaDataProperties
105 {
106
107
108     /**
109      * The delimiter of a property key between the class- and fieldname.
110      */

111     private static final char FIELD_DELIMITER = '#';
112
113     /**
114      * A string of delimiter characters between attributes.
115      */

116     private static final String JavaDoc PROPERTY_DELIMITERS = " \t,;";
117
118     /**
119      * A delimiter character between attribute name and attribute value
120      */

121     private static final char PROPERTY_ASSIGNER = ':';
122
123
124     //attribute names for classes and fields
125
private static final String JavaDoc PROPERTY_ACCESS_MODIFIER = "access";
126     private static final String JavaDoc PROPERTY_JDO_MODIFIER = "jdo";
127     private static final String JavaDoc PROPERTY_SUPER_CLASSNAME = "super";
128     private static final String JavaDoc PROPERTY_OID_CLASSNAME = "oid";
129     private static final String JavaDoc PROPERTY_TYPE = "type";
130     private static final String JavaDoc PROPERTY_ANNOTATION_TYPE = "annotation";
131
132     //values of the access attribute of classes and fields.
133
private static final String JavaDoc ACCESS_PRIVATE = "private";
134     private static final String JavaDoc ACCESS_PACKAGE_LOCAL = "package";
135     private static final String JavaDoc ACCESS_PROTECTED = "protected";
136     private static final String JavaDoc ACCESS_PUBLIC = "public";
137
138     //values of the jdo attribute of classes and fields.
139
private static final String JavaDoc JDO_TRANSIENT = "transient";
140     private static final String JavaDoc JDO_PERSISTENT = "persistent";
141     private static final String JavaDoc JDO_TRANSACTIONAL = "transactional";
142
143     //values of the annotation type attribute of fields.
144
private static final String JavaDoc ANNOTATION_TYPE_PK = "pk";
145     private static final String JavaDoc ANNOTATION_TYPE_DFG = "dfg";
146     private static final String JavaDoc ANNOTATION_TYPE_MEDIATED = "mediated";
147
148
149     /**
150      * The properties to parse.
151      */

152     private Properties JavaDoc properties;
153
154
155     /**
156      * A map of already read class properties. The keys are the
157      * classnames, the values are the appropriate
158      * <code>JDOClass</code>-object.
159      */

160     private final Map JavaDoc cachedJDOClasses = new HashMap JavaDoc ();
161
162
163     /**
164      * A constant for the cache indicating that a given classname
165      * if not specified in the properties.
166      */

167     private static final JDOClass NULL = new JDOClass (null);
168
169
170     /**
171      * A temporary vector (this is the reason why the implementation is not
172      * thread safe).
173      */

174     private final List JavaDoc tmpTokens = new ArrayList JavaDoc ();
175
176
177     /**********************************************************************
178      * Creates a new object with the given properties.
179      *
180      * @param props The properties.
181      *
182      * @see #properties
183      *********************************************************************/

184
185     public JDOMetaDataProperties (Properties JavaDoc props)
186     {
187
188         this.properties = props;
189
190     } //JDOMetaDataProperties.<init>
191

192
193     /**********************************************************************
194      * Get the information about the class with the given name.
195      *
196      * @param classname The classname.
197      *
198      * @return The information about the class or <code>null</code> if no
199      * information is given.
200      *
201      * @throws JDOMetaDataUserException If something went wrong parsing
202      * the properties.
203      *********************************************************************/

204
205     public final JDOClass getJDOClass (String JavaDoc classname)
206                           throws JDOMetaDataUserException
207     {
208
209         classname = toCanonicalClassName (classname);
210         JDOClass clazz = (JDOClass) this.cachedJDOClasses.get (classname);
211         if (clazz == NULL) //already searched but not found
212
{
213             return null;
214         }
215         if (clazz != null)
216         {
217             return clazz;
218         }
219
220         //load it from the properties file
221
String JavaDoc s = this.properties.getProperty (classname);
222         if (s == null) //class not defined
223
{
224             this.cachedJDOClasses.put (classname, NULL);
225             return null;
226         }
227
228         //the class could be found in the properties
229
clazz = parseJDOClass (classname, s); //parse the class attributes
230
parseJDOFields (clazz); //parse all fields
231
validateDependencies (clazz); //check dependencies
232
this.cachedJDOClasses.put (clazz.getName (), clazz);
233
234         return clazz;
235
236     } //JDOMetaDataProperties.getJDOClass()
237

238
239     /**********************************************************************
240      * Gets the information about the specified field.
241      *
242      * @param classname The name of the class.
243      * @param fieldname The name of the field of the class.
244      *
245      * @return The information about the field or <code>null</code> if
246      * no information could be found.
247      *
248      * @throws JDOMetaDataUserException If something went wrong parsing
249      * the properties.
250      *********************************************************************/

251
252     public final JDOField getJDOField (String JavaDoc fieldname,
253                                        String JavaDoc classname)
254                           throws JDOMetaDataUserException
255     {
256
257         JDOClass clazz = getJDOClass (classname);
258         return (clazz != null ? clazz.getField (fieldname) : null);
259
260     } //JDOMetaDataProperties.getJDOField()
261

262
263     /**********************************************************************
264      * Gets all classnames in the properties.
265      *
266      * @return All classnames in the properties.
267      *********************************************************************/

268
269     public final String JavaDoc [] getKnownClassNames ()
270     {
271
272         Collection JavaDoc classnames = new HashSet JavaDoc ();
273         for (Enumeration JavaDoc names = this.properties.propertyNames (); names.hasMoreElements ();)
274         {
275             String JavaDoc name = (String JavaDoc) names.nextElement ();
276             if (name.indexOf (FIELD_DELIMITER) < 0)
277             {
278                 classnames.add (fromCanonicalClassName (name));
279             }
280         }
281
282         return (String JavaDoc []) classnames.toArray (new String JavaDoc [classnames.size ()]);
283
284     } //JDOMetaDataProperties.getKnownClassNames()
285

286
287     /**********************************************************************
288      * Converts a classname given in a given VM-similar notation (with slashes)
289      * into a canonical notation (with dots).
290      *
291      * @param The VM-similar notation of the classname.
292      *
293      * @return The canonical classname.
294      *
295      * @see #fromCanonicalClassName
296      *********************************************************************/

297
298     private static final String JavaDoc toCanonicalClassName (String JavaDoc classname)
299     {
300
301         return classname.replace ('/', '.');
302
303     } //JDOMetaDataProperties.toCanonicalClassName()
304

305
306     /**********************************************************************
307      * Converts a classname given in a canonical form (with dots) into
308      * a VM-similar notation (with slashes)
309      *
310      * @param classname The canonical classname.
311      *
312      * @return The VM-similar classname notation.
313      *
314      * @see #toCanonicalClassName
315      *********************************************************************/

316
317     private static final String JavaDoc fromCanonicalClassName (String JavaDoc classname)
318     {
319
320         return classname.replace ('.', '/');
321
322     } //JDOMetaDataProperties.fromCanonicalClassName()
323

324
325     /**********************************************************************
326      * Parses the attributes-string of a class and puts them into a
327      * <code>JDOClass</code>-object.
328      *
329      * @param classname The name of the class.
330      * @param atributes The attribute-string as specified in the properties.
331      *
332      * @return @return The create <code>JDOClass</code>-object.
333      *
334      * @throws JDOMetaDataUserException If something went wrong parsing
335      * the attributes.
336      *********************************************************************/

337
338     private final JDOClass parseJDOClass (String JavaDoc classname,
339                                           String JavaDoc attributes)
340                            throws JDOMetaDataUserException
341     {
342
343         List JavaDoc props = parseProperties (attributes);
344
345         //check each property
346
for (int i = 0; i < props.size (); i++)
347         {
348             Property prop = (Property) props.get (i);
349             validateClassProperty (prop, classname);
350         }
351
352         //check dependencies of all properties
353
checkForDuplicateProperties (props, classname);
354
355         //properties are OK - assign them to the JDOClass object
356
JDOClass clazz = new JDOClass (classname);
357         for (int i = 0; i < props.size (); i++)
358         {
359             Property prop = (Property) props.get (i);
360             if (prop.name.equals (PROPERTY_ACCESS_MODIFIER))
361             {
362                 clazz.modifiers = getModifiers (prop.value);
363             }
364             else if (prop.name.equals (PROPERTY_JDO_MODIFIER))
365             {
366                 clazz.isPersistent = prop.value.equals (JDO_PERSISTENT);
367             }
368             else if (prop.name.equals (PROPERTY_SUPER_CLASSNAME))
369             {
370                 clazz.setSuperClassName (prop.value);
371             }
372             else if (prop.name.equals(PROPERTY_OID_CLASSNAME)) {
373                 clazz.setOidClassName(prop.value);
374             }
375
376         }
377
378         return clazz;
379
380     } //JDOMetaDataProperties.parseJDOClass()
381

382
383     /**********************************************************************
384      * Checks if the given attribute-property of a class is valid.
385      *
386      * @param prop The attribute-property.
387      * @param classname The classname.
388      *
389      * @throws JDOMetaDataUserException If the validation failed.
390      *********************************************************************/

391
392     private static final void validateClassProperty (Property prop,
393                                                      String JavaDoc classname)
394                               throws JDOMetaDataUserException
395     {
396
397         String JavaDoc value = prop.value;
398         if (prop.name == null) //try to guess the property name
399
{
400             //check access modifier
401
if (value.equals (ACCESS_PUBLIC) ||
402                  value.equals (ACCESS_PROTECTED) ||
403                  value.equals (ACCESS_PACKAGE_LOCAL) ||
404                  value.equals (ACCESS_PRIVATE))
405             {
406                 prop.name = PROPERTY_ACCESS_MODIFIER;
407             }
408
409             //check persistence
410
else if (value.equals (JDO_PERSISTENT) ||
411                       value.equals (JDO_TRANSIENT))
412             {
413                 prop.name = PROPERTY_JDO_MODIFIER;
414             }
415
416             //assume the the given value is the superclassname
417
else
418             {
419                 prop.name = PROPERTY_SUPER_CLASSNAME;
420             }
421         }
422         else
423         {
424             //do we have a valid property name?
425
String JavaDoc name = prop.name;
426             checkPropertyName (prop.name, new String JavaDoc []
427                                               {
428                                                 PROPERTY_OID_CLASSNAME,
429                                                 PROPERTY_ACCESS_MODIFIER,
430                                                 PROPERTY_JDO_MODIFIER,
431                                                 PROPERTY_SUPER_CLASSNAME
432                                               }, classname);
433
434             //do we have a valid property value?
435
checkPropertyValue (prop,
436                                 new String JavaDoc []
437                                     {
438                                         ACCESS_PUBLIC,
439                                         ACCESS_PROTECTED,
440                                         ACCESS_PACKAGE_LOCAL,
441                                         ACCESS_PRIVATE
442                                     },
443                                 PROPERTY_ACCESS_MODIFIER,
444                                 classname);
445             checkPropertyValue (prop,
446                                 new String JavaDoc [] { JDO_TRANSIENT, JDO_PERSISTENT },
447                                 PROPERTY_JDO_MODIFIER,
448                                 classname);
449         }
450
451     } //JDOMetaDataProperties.validateClassProperty()
452

453
454     /**********************************************************************
455      * Parses all fields of a given class.
456      *
457      * @param clazz The representation of the class.
458      *
459      * @throws JDOMetaDataUserException If something went wrong parsing
460      * the properties.
461      *********************************************************************/

462
463     private final void parseJDOFields (JDOClass clazz)
464                        throws JDOMetaDataUserException
465     {
466
467         //search for fields of the class
468
for (Enumeration JavaDoc names = this.properties.propertyNames (); names.hasMoreElements ();)
469         {
470             String JavaDoc name = (String JavaDoc) names.nextElement ();
471             if (name.startsWith (clazz.getName () + FIELD_DELIMITER)) //field found
472
{
473                 String JavaDoc fieldname = name.substring (name.indexOf (FIELD_DELIMITER) + 1, name.length ());
474                 validateFieldName (fieldname, clazz.getName ());
475                 clazz.addField (parseJDOField (this.properties.getProperty (name), fieldname, clazz));
476             }
477         }
478         clazz.sortFields ();
479
480     } //JDOMetaDataProperties.parseJDOField()
481

482
483     /**********************************************************************
484      * Parses the attribute-string of a field.
485      *
486      * @param attributes The attribute-string.
487      * @param fieldname The fieldname.
488      * @param clazz The class to field belongs to.
489      *
490      * @throws JDOMetaDataUserException If something went wrong parsing
491      * the attributes.
492      *********************************************************************/

493
494     private final JDOField parseJDOField (String JavaDoc attributes,
495                                           String JavaDoc fieldname,
496                                           JDOClass clazz)
497                            throws JDOMetaDataUserException
498     {
499
500         List JavaDoc props = parseProperties (attributes);
501
502         //check each property
503
for (int i = 0; i < props.size (); i++)
504         {
505             Property prop = (Property) props.get (i);
506             validateFieldProperty (prop, fieldname, clazz.getName ());
507         }
508
509         //check dependencies of all properties
510
checkForDuplicateProperties (props, clazz.getName () + FIELD_DELIMITER + fieldname);
511
512         //properties are OK - assign them to the JDOField object
513
JDOField field = new JDOField (fieldname);
514         for (int i = 0; i < props.size (); i++)
515         {
516             Property prop = (Property) props.get (i);
517             if (prop.name.equals (PROPERTY_ACCESS_MODIFIER))
518             {
519                 field.modifiers = getModifiers (prop.value);
520             }
521             else if (prop.name.equals (PROPERTY_JDO_MODIFIER))
522             {
523                 field.jdoModifier = prop.value;
524             }
525             else if (prop.name.equals (PROPERTY_TYPE))
526             {
527                 field.setType (prop.value);
528             }
529             else if (prop.name.equals (PROPERTY_ANNOTATION_TYPE))
530             {
531                 field.annotationType = prop.value;
532             }
533         }
534
535         return field;
536
537     } //JDOMetaDataProperties.parseJDOField()
538

539
540     /**********************************************************************
541      * Checks if the given attribute-property if valid for a field.
542      *
543      * @param prop The attribute-property.
544      * @param fieldname The fieldname.
545      * @param classname The classname.
546
547      * @throws JDOMetaDataUserException If the check fails.
548      *********************************************************************/

549
550     private final void validateFieldProperty (Property prop,
551                                               String JavaDoc fieldname,
552                                               String JavaDoc classname)
553                        throws JDOMetaDataUserException
554     {
555
556         String JavaDoc value = prop.value;
557         if (prop.name == null) //try to guess the property name
558
{
559             //check access modifier
560
if (value.equals (ACCESS_PUBLIC) ||
561                  value.equals (ACCESS_PROTECTED) ||
562                  value.equals (ACCESS_PACKAGE_LOCAL) ||
563                  value.equals (ACCESS_PRIVATE))
564             {
565                 prop.name = PROPERTY_ACCESS_MODIFIER;
566             }
567
568             //check persistence
569
else if (value.equals (JDO_PERSISTENT) ||
570                       value.equals (JDO_TRANSIENT) ||
571                       value.equals (JDO_TRANSACTIONAL))
572             {
573                 prop.name = PROPERTY_JDO_MODIFIER;
574             }
575
576             //annotation type?
577
else if (value.equals (ANNOTATION_TYPE_PK) ||
578                       value.equals (ANNOTATION_TYPE_DFG) ||
579                       value.equals (ANNOTATION_TYPE_MEDIATED))
580             {
581                 prop.name = PROPERTY_ANNOTATION_TYPE;
582             }
583
584             else
585             {
586                 //assume the the given value is the type
587
prop.name = PROPERTY_TYPE;
588             }
589         }
590         else
591         {
592             String JavaDoc entry = classname + FIELD_DELIMITER + fieldname;
593
594             //do we have a valid property name?
595
checkPropertyName (prop.name,
596                                new String JavaDoc []
597                                    {
598                                        PROPERTY_ACCESS_MODIFIER,
599                                        PROPERTY_JDO_MODIFIER,
600                                        PROPERTY_TYPE,
601                                        PROPERTY_ANNOTATION_TYPE
602                                    },
603                                entry);
604
605             //do we have a valid property value
606
checkPropertyValue (prop,
607                                 new String JavaDoc []
608                                     {
609                                         ACCESS_PUBLIC,
610                                         ACCESS_PROTECTED,
611                                         ACCESS_PACKAGE_LOCAL,
612                                         ACCESS_PRIVATE
613                                     },
614                                 PROPERTY_ACCESS_MODIFIER,
615                                 entry);
616             checkPropertyValue (prop,
617                                 new String JavaDoc []
618                                     {
619                                         JDO_PERSISTENT,
620                                         JDO_TRANSIENT,
621                                         JDO_TRANSACTIONAL
622                                     },
623                                 PROPERTY_JDO_MODIFIER,
624                                 entry);
625             checkPropertyValue (prop,
626                                 new String JavaDoc []
627                                     {
628                                         ANNOTATION_TYPE_PK,
629                                         ANNOTATION_TYPE_DFG,
630                                         ANNOTATION_TYPE_MEDIATED
631                                     },
632                                 PROPERTY_ANNOTATION_TYPE,
633                                 entry);
634         }
635
636     } //JDOMetaDataProperties.validateFieldProperty()
637

638
639     /**********************************************************************
640      * Validates dependencies between a class and its fields and between.
641      *
642      * @param clazz The class.
643      *
644      * @throws JDOMetaDataUserException If the validation fails.
645      *********************************************************************/

646
647     private final void validateDependencies (JDOClass clazz)
648                        throws JDOMetaDataUserException
649     {
650
651         for (int i = clazz.fields.size () - 1; i >= 0; i--)
652         {
653             JDOField field = (JDOField) clazz.fields.get (i);
654
655             //set the jdo field modifier according to the jdo class modifier (if jdo field not set yet)
656
if (field.jdoModifier == null)
657             {
658                 field.jdoModifier = (clazz.isPersistent () ? JDO_PERSISTENT : JDO_TRANSIENT);
659             }
660             //if we have a non-persistent class
661
else if (clazz.isTransient ())
662             {
663                 //non-persistent classes cannot have persistent fields
664
if (field.isPersistent ())
665                 {
666                     throw new JDOMetaDataUserException (getErrorMsg (IErrorMessages.ERR_TRANSIENT_CLASS_WITH_PERSISTENT_FIELD,
667                                                                      new String JavaDoc [] { clazz.getName (), field.getName () }));
668                 }
669                 //non-persistent classes cannot have transactional fields
670
if (field.isTransactional ())
671                 {
672                     throw new JDOMetaDataUserException (getErrorMsg (IErrorMessages.ERR_TRANSIENT_CLASS_WITH_TRANSACTIONAL_FIELD,
673                                                                      new String JavaDoc [] { clazz.getName (), field.getName () }));
674                 }
675             }
676
677             //a non-persistent class cannot have an annotated field
678
if (field.isAnnotated () && clazz.isTransient ())
679             {
680                 throw new JDOMetaDataUserException (getErrorMsg (IErrorMessages.ERR_TRANSIENT_CLASS_WITH_ANNOTATED_FIELD,
681                                                                  new String JavaDoc [] { clazz.getName (), field.getName () }));
682             }
683
684             //a non-persistent field cannot have an annotation type
685
if ( ! field.isPersistent () && field.isAnnotated ())
686             {
687                 field.annotationType = ANNOTATION_TYPE_MEDIATED;
688             }
689
690             //set the annotation type if not done yet
691
if ( ! field.isAnnotated () && clazz.isPersistent ())
692             {
693                 field.annotationType = ANNOTATION_TYPE_MEDIATED;
694             }
695         }
696
697     } //JDOMetaDataProperties.validateDependencies()
698

699
700     /**********************************************************************
701      * Checks if a given fieldname is a valid Java identifier.
702      *
703      * @param fieldname The fieldname.
704      * @param classname The corresponding classname.
705      *
706      * @throws JDOMetaDataUserException If the check fails.
707      *********************************************************************/

708
709     private static final void validateFieldName (String JavaDoc fieldname,
710                                                  String JavaDoc classname)
711                               throws JDOMetaDataUserException
712     {
713
714         if (fieldname.length () == 0)
715         {
716             throw new JDOMetaDataUserException (getErrorMsg (IErrorMessages.ERR_EMPTY_FIELDNAME,
717                                                              new String JavaDoc [] { classname }));
718         }
719         if ( ! Character.isJavaIdentifierStart (fieldname.charAt (0)))
720         {
721             throw new JDOMetaDataUserException (getErrorMsg (IErrorMessages.ERR_INVALID_FIELDNAME,
722                                                              new String JavaDoc [] { classname, fieldname }));
723         }
724         for (int i = fieldname.length () - 1; i >= 0; i--)
725         {
726             final char c = fieldname.charAt (i);
727             if ( ! Character.isJavaIdentifierPart (c))
728             {
729                 throw new JDOMetaDataUserException (getErrorMsg (IErrorMessages.ERR_INVALID_FIELDNAME,
730                                                                  new String JavaDoc [] { classname, fieldname }));
731             }
732         }
733
734     } //JDOMetaDataProperties.checkFieldName()
735

736
737     /**********************************************************************
738      * Checks if an attribute-property was entered twice for a class or field.
739      *
740      * @param props The properties.
741      * @param entry The class- or fieldname.
742      *
743      * @throws JDOMetaDataUserException If the check fails.
744      *********************************************************************/

745
746     private static final void checkForDuplicateProperties (List JavaDoc props,
747                                                            String JavaDoc entry)
748                               throws JDOMetaDataUserException
749     {
750
751         for (int i = 0; i < props.size (); i++)
752         {
753             for (int j = i + 1; j < props.size (); j++)
754             {
755                 Property p1 = (Property) props.get (i);
756                 Property p2 = (Property) props.get (j);
757                 if (p1.name.equals (p2.name) && ! p1.value.equals (p2.value))
758                 {
759                     throw new JDOMetaDataUserException (getErrorMsg (IErrorMessages.ERR_DUPLICATE_PROPERTY_NAME,
760                                                                      new String JavaDoc [] { entry, p1.name, p1.value, p2.value }));
761                 }
762             }
763         }
764
765     } //JDOMetaDataProperties.checkForDuplicateEntries()
766

767
768     /**********************************************************************
769      * Checks if an attribute name is recognized by the parser.
770      *
771      * @param name The name of the attribute.
772      * @param validnames A list of valid names (the attribute name has to
773      * be in this list).
774      * @param entry The class- or fieldname.
775      *
776      * @throws JDOMetaDataUserException If the check fails.
777      *********************************************************************/

778
779     private static final void checkPropertyName (String JavaDoc name,
780                                                  String JavaDoc [] validnames,
781                                                  String JavaDoc entry)
782                               throws JDOMetaDataUserException
783     {
784
785         for (int i = 0; i < validnames.length; i++)
786         {
787             if (name.equals (validnames [i]))
788             {
789                 return;
790             }
791         }
792
793         throw new JDOMetaDataUserException (getErrorMsg (IErrorMessages.ERR_INVALID_PROPERTY_NAME,
794                                                          new String JavaDoc [] { entry, name }));
795
796     } //JDOMetaDataProperties.checkPropertyName()
797

798
799     /**********************************************************************
800      * Checks if the given value of an attribute-property is recognized by
801      * by the parser if that value belongs to a given attribute name.
802      *
803      * @param prop The attribute-property (with name and value).
804      * @param validvalues A list of valid values.
805      * @param name The name of the attribute-property to check.
806      * @param entry The class- or fieldname.
807      *
808      * @throws JDOMetaDataUserException If the check fails.
809      *********************************************************************/

810
811     private static final void checkPropertyValue (Property prop,
812                                                   String JavaDoc [] validvalues,
813                                                   String JavaDoc name,
814                                                   String JavaDoc entry)
815                               throws JDOMetaDataUserException
816     {
817
818         if ( ! prop.name.equals (name))
819         {
820             return;
821         }
822
823         for (int i = 0; i < validvalues.length; i++)
824         {
825             if (prop.value.equals (validvalues [i]))
826             {
827                 return;
828             }
829         }
830
831         throw new JDOMetaDataUserException (getErrorMsg (IErrorMessages.ERR_INVALID_PROPERTY_VALUE,
832                                                          new String JavaDoc [] { entry, name, prop.value }));
833
834     } //JDOMetaDataProperties.checkPropertyValue()
835

836
837     /**********************************************************************
838      * Formats an error message with the given parameters.
839      *
840      * @param msg The message with format strings.
841      * @param params The params to format the message with.
842      *
843      * @return The formatted error message.
844      *********************************************************************/

845
846     static final String JavaDoc getErrorMsg (String JavaDoc msg,
847                                      String JavaDoc [] params)
848     {
849
850         return MessageFormat.format (msg, (Object JavaDoc []) params);
851
852     } //JDOMetaDataProperties.getErrorMsg()
853

854
855     /**********************************************************************
856      * Parses the attribute-string of a class- or fieldname.
857      *
858      * @param attributes The attribute-string.
859      *
860      * @return A list of <code>Propert<</code>-objects for the attributes.
861      *
862      * @exception JDOMetaDataUserException If the parsing fails.
863      *********************************************************************/

864
865     final List JavaDoc parseProperties (String JavaDoc attributes)
866                throws JDOMetaDataUserException
867     {
868
869         this.tmpTokens.clear ();
870         StringTokenizer JavaDoc t = new StringTokenizer JavaDoc (attributes, PROPERTY_DELIMITERS);
871         while (t.hasMoreTokens ())
872         {
873             this.tmpTokens.add (parseProperty (t.nextToken ()));
874         }
875
876         return this.tmpTokens;
877
878     } //JDOMetaDataProperties.getTokens()
879

880
881     /**********************************************************************
882      * Parses the given attribute and splits it into name and value.
883      *
884      * @param attribute The attribute-string.
885      *
886      * @return The <code>Propert</code>-object.
887      *
888      * @exception JDOMetaDataUserException If the parsing fails.
889      *********************************************************************/

890
891     private final Property parseProperty (String JavaDoc attribute)
892                            throws JDOMetaDataUserException
893     {
894
895         Property prop = new Property ();
896         int idx = attribute.indexOf (PROPERTY_ASSIGNER);
897         if (idx < 0)
898         {
899             prop.value = attribute;
900         }
901         else
902         {
903             prop.name = attribute.substring (0, idx);
904             prop.value = attribute.substring (idx + 1, attribute.length ());
905             if (prop.name.length () == 0 || prop.value.length () == 0)
906             {
907                 throw new JDOMetaDataUserException (getErrorMsg (IErrorMessages.ERR_EMPTY_PROPERTY_NAME_OR_VALUE,
908                                                                  new String JavaDoc [] { attribute }));
909             }
910         }
911
912         return prop;
913
914     } //JDOMetaDataProperties.parseProperty()
915

916
917     /**********************************************************************
918      *
919      *********************************************************************/

920
921     private static final int getModifiers (String JavaDoc modifier)
922     {
923
924         if (modifier.equals (ACCESS_PUBLIC))
925         {
926             return Modifier.PUBLIC;
927         }
928         if (modifier.equals (ACCESS_PRIVATE))
929         {
930             return Modifier.PRIVATE;
931         }
932         if (modifier.equals (ACCESS_PROTECTED))
933         {
934             return Modifier.PROTECTED;
935         }
936         return 0;
937
938     } //JDOMetaDataProperties.getModifiers()
939

940
941     /**********************************************************************
942      * A simple test to run from the command line.
943      *
944      * @param argv The command line arguments.
945      *********************************************************************/

946
947 /*
948     public static void main (String [] argv)
949     {
950
951         if (argv.length != 1)
952         {
953             System.err.println ("Error: no property filename specified");
954             return;
955         }
956         Properties p = new Properties ();
957         try
958         {
959             java.io.InputStream in = new java.io.FileInputStream (new java.io.File (argv [0]));
960             p.load (in);
961             in.close ();
962             System.out.println ("PROPERTIES: " + p);
963             System.out.println ("############");
964             JDOMetaDataProperties props = new JDOMetaDataProperties (p);
965             String [] classnames = props.getKnownClassNames ();
966             for (int i = 0; i < classnames.length; i++)
967             {
968                 String classname = classnames [i];
969                 System.out.println (classname + ": " + props.getJDOClass (classname));
970             }
971         }
972         catch (Throwable ex)
973         {
974             ex.printStackTrace (System.err);
975         }
976
977     } //JDOMetaDataProperties.main()
978 */

979
980
981     //#####################################################################
982
/**
983      * The holder-class for the name and the value of a property.
984      */

985     //#####################################################################
986

987     private static final class Property
988     {
989
990
991         /**
992          * The name of the property.
993          */

994         String JavaDoc name = null;
995
996
997         /**
998          * The value of the property.
999          */

1000        String JavaDoc value = null;
1001
1002
1003        /******************************************************************
1004         * Creates a string-representation of this object.
1005         *
1006         * @return The string-representation of this object.
1007         *****************************************************************/

1008
1009        public final String JavaDoc toString ()
1010        {
1011
1012            return '<' + name + ':' + value + '>';
1013
1014        } //Property.toString()
1015

1016
1017    } //Property
1018

1019
1020    //#####################################################################
1021
/**
1022     * Holds all unformatted error messages.
1023     */

1024    //#####################################################################
1025

1026    private static interface IErrorMessages
1027    {
1028
1029
1030        //the unformatted error messages
1031
static final String JavaDoc PREFIX = "Error Parsing meta data properties: ";
1032        static final String JavaDoc ERR_EMPTY_FIELDNAME =
1033                            PREFIX + "The class ''{0}'' may not have an empty fieldname.";
1034        static final String JavaDoc ERR_INVALID_FIELDNAME =
1035                            PREFIX + "The field name ''{1}'' of class ''{0}'' is not valid.";
1036        static final String JavaDoc ERR_EMPTY_PROPERTY_NAME_OR_VALUE =
1037                            PREFIX + "The property name and value may not be empty if a ''" + PROPERTY_ASSIGNER + "'' is specified: ''{0}''.";
1038        static final String JavaDoc ERR_INVALID_PROPERTY_NAME =
1039                            PREFIX + "Invalid property name for entry ''{0}'': ''{1}''.";
1040        static final String JavaDoc ERR_INVALID_PROPERTY_VALUE =
1041                            PREFIX + "Invalid value for property ''{1}'' of entry ''{0}'': ''{2}''.";
1042        static final String JavaDoc ERR_DUPLICATE_PROPERTY_NAME =
1043                            PREFIX + "The property ''{1}'' for the entry ''{0}'' entered twice with values: ''{2}'' and ''{3}''.";
1044        static final String JavaDoc ERR_TRANSIENT_CLASS_WITH_PERSISTENT_FIELD =
1045                            PREFIX + "A non-persistent class cannot have a persistent field (class ''{0}'' with field ''{1})''.";
1046        static final String JavaDoc ERR_TRANSIENT_CLASS_WITH_TRANSACTIONAL_FIELD =
1047                            PREFIX + "A non-persistent class cannot have a transactional field (class ''{0}'' with field ''{1})''.";
1048        static final String JavaDoc ERR_TRANSIENT_CLASS_WITH_ANNOTATED_FIELD =
1049                            PREFIX + "A non-persistent class cannot have an annotated field (''{1}'' of class ''{0}'') can''t have a fetch group.";
1050        static final String JavaDoc ERR_NON_PERSISTENT_ANNOTATED_FIELD =
1051                            PREFIX + "A non-persistent field (''{1}'' of class ''{0}'') can''t be a annotated.";
1052
1053
1054    } //IErrorMessages
1055

1056
1057    //#####################################################################
1058
/**
1059     * A class to hold all parsed attributes of a class.
1060     */

1061    //#####################################################################
1062

1063    static final class JDOClass
1064    {
1065
1066
1067        /**
1068         * The name of the class.
1069         */

1070        private String JavaDoc name;
1071
1072
1073        /**
1074         * The name of the superclass.
1075         */

1076        private String JavaDoc superClassName = null;
1077
1078
1079        /**
1080         * The name of the oid class.
1081         */

1082        private String JavaDoc oidClassName = null;
1083
1084
1085        /**
1086         * The access modifier.
1087         */

1088        private int modifiers = Modifier.PUBLIC;
1089
1090
1091        /**
1092         * Do we have a persistent class?
1093         */

1094        private boolean isPersistent = true;
1095
1096
1097        /**
1098         * A list of all parsed fields.
1099         */

1100        private final List JavaDoc fields = new ArrayList JavaDoc ();
1101
1102
1103        /**
1104         *
1105         */

1106        private String JavaDoc [] managedFieldNames = null;
1107
1108
1109        /**
1110         *
1111         */

1112        private String JavaDoc [] fieldNames = null;
1113
1114
1115        /******************************************************************
1116         * Constructs a new object with the given name.
1117         *
1118         * @param name The name of the class.
1119         *
1120         * @see #name
1121         *****************************************************************/

1122
1123        JDOClass (String JavaDoc name)
1124        {
1125
1126            this.name = name;
1127
1128        } //JDOClass.<init>
1129

1130
1131        /******************************************************************
1132         * Gets the name of the class.
1133         *
1134         * @return The name of the class.
1135         *
1136         * @see #name
1137         *****************************************************************/

1138
1139        public final String JavaDoc getName ()
1140        {
1141
1142            return this.name;
1143
1144        } //JDOClass.getName()
1145

1146
1147        /******************************************************************
1148         *
1149         *****************************************************************/

1150
1151        public final int getModifiers ()
1152        {
1153
1154            return this.modifiers;
1155
1156        } //JDOClass.getModifiers()
1157

1158
1159        /******************************************************************
1160         * Sets the superclassname. The given classname should have a canonical
1161         * form (with dots). It is converted to the CM-similar notation
1162         * (with slashes).
1163         *
1164         * @param classname The superclassname.
1165         *
1166         * @see #superClassName
1167         *****************************************************************/

1168
1169        private final void setSuperClassName (String JavaDoc classname)
1170        {
1171
1172            this.superClassName = fromCanonicalClassName (classname);
1173
1174        } //JDOClass.setSuperClassName()
1175

1176
1177        /******************************************************************
1178         * Gets the superclassname.
1179         *
1180         * @return The superclassname.
1181         *
1182         * @see #superClassName
1183         *****************************************************************/

1184
1185        public final String JavaDoc getSuperClassName ()
1186        {
1187
1188            return this.superClassName;
1189
1190        } //JDOClass.getSuperClassName()
1191

1192
1193        /******************************************************************
1194         * Sets the superclassname. The given classname should have a canonical
1195         * form (with dots). It is converted to the CM-similar notation
1196         * (with slashes).
1197         *
1198         * @param classname The superclassname.
1199         *
1200         * @see #superClassName
1201         *****************************************************************/

1202
1203        public void setOidClassName(String JavaDoc classname)
1204        {
1205            this.oidClassName = fromCanonicalClassName(classname);
1206        }
1207
1208
1209        /******************************************************************
1210         * Gets the oidClassName.
1211         *
1212         * @return The oidClassName.
1213         *
1214         * @see #oidClassName
1215         *****************************************************************/

1216
1217        public String JavaDoc getOidClassName()
1218        {
1219            return oidClassName;
1220        }
1221
1222
1223        /******************************************************************
1224         * Do we have a persistent class.
1225         *
1226         * @return Do we have a persistent class?
1227         *
1228         * @see #isPersistent
1229         *****************************************************************/

1230
1231        public final boolean isPersistent ()
1232        {
1233
1234            return this.isPersistent;
1235
1236        } //JDOMetaClass.isPersistent()
1237

1238
1239        /******************************************************************
1240         * Do we have a transient class.
1241         *
1242         * @return Do we have a transient class?
1243         *
1244         * @see #isPersistent
1245         *****************************************************************/

1246
1247        public final boolean isTransient ()
1248        {
1249
1250            return ! isPersistent ();
1251
1252        } //JDOMetaClass.isTransient()
1253

1254
1255        /******************************************************************
1256         * Adds a new field.
1257         *
1258         * @param field The new field.
1259         *
1260         * @see #fields
1261         *****************************************************************/

1262
1263        private final void addField (JDOField field)
1264        {
1265
1266            this.fields.add (field);
1267
1268        } //JDOClass.addField()
1269

1270
1271        /******************************************************************
1272         * Gets the field with the given name.
1273         *
1274         * @param name The name of the requested field.
1275         *
1276         * @return The field or <code>null</code> if not found.
1277         *
1278         * @see #fields
1279         *****************************************************************/

1280
1281        public final JDOField getField (String JavaDoc name)
1282        {
1283
1284            int idx = getIndexOfField (name);
1285            return (idx > -1 ? (JDOField) this.fields.get (idx) : null);
1286
1287        } //JDOField.getField()
1288

1289
1290        /******************************************************************
1291         * Gets the index of the field with the given name.
1292         *
1293         * @param name The name of the field.
1294         *
1295         * @return The index or <code>-1</code> if the field was not found.
1296         *
1297         * @see #fields
1298         *****************************************************************/

1299
1300        public final int getIndexOfField (String JavaDoc name)
1301        {
1302
1303            for (int i = 0; i < this.fields.size (); i++)
1304            {
1305                JDOField field = (JDOField) this.fields.get (i);
1306                if (field.getName ().equals (name))
1307                {
1308                    return i;
1309                }
1310            }
1311
1312            return -1;
1313
1314        } //JDOClass.getIndexOfField()
1315

1316
1317        /******************************************************************
1318         * Gets all fields of this class.
1319         *
1320         * @return The fields.
1321         *
1322         * @see #fields
1323         *****************************************************************/

1324
1325        public final String JavaDoc [] getFields ()
1326        {
1327
1328            if (this.fieldNames == null)
1329            {
1330                final int n = this.fields.size ();
1331                String JavaDoc [] fields = new String JavaDoc [n];
1332                for (int i = 0; i < n; i++)
1333                {
1334                    fields [i] = ((JDOField) this.fields.get (i)).getName ();
1335                }
1336                this.fieldNames = fields;
1337            }
1338
1339            return this.fieldNames;
1340
1341        } //JDOClass.getFields()
1342

1343
1344        /******************************************************************
1345         * Sorts the fields of this class according to the names. This method
1346         * should be called if all fields are added. It is necessary to
1347         * establish an order on the fields.
1348         *
1349         * @see #fields
1350         *****************************************************************/

1351
1352        private final void sortFields ()
1353        {
1354
1355            Collections.sort (this.fields,
1356                              new Comparator JavaDoc ()
1357                                  {
1358                                      public final int compare (Object JavaDoc f1, Object JavaDoc f2)
1359                                      {
1360                                          JDOField field1 = (JDOField) f1;
1361                                          JDOField field2 = (JDOField) f2;
1362                                          //if we dont have managed fields we dont care
1363
if ( ! (field1.isManaged () && field2.isManaged ()))
1364                                          {
1365                                              return (field1.isManaged () ? -1 : 1);
1366                                          }
1367                                          return (field1).getName ().compareTo (field2.getName ());
1368                                      }
1369                                  });
1370
1371        } //JDOClass.sortFields()
1372

1373
1374        /******************************************************************
1375         * Gets a list of persistent field names of this class.
1376         *
1377         * @return The persistent fieldnames.
1378         *
1379         * @see #fields
1380         *****************************************************************/

1381
1382        public final String JavaDoc [] getManagedFieldNames ()
1383        {
1384
1385            if (this.managedFieldNames == null)
1386            {
1387                final int n = this.fields.size ();
1388                List JavaDoc tmp = new ArrayList JavaDoc (n);
1389                for (int i = 0; i < n; i++)
1390                {
1391                    JDOField field = (JDOField) this.fields.get (i);
1392                    if (field.isManaged ())
1393                    {
1394                        tmp.add (field.getName ());
1395                    }
1396                }
1397                this.managedFieldNames = (String JavaDoc []) tmp.toArray (new String JavaDoc [tmp.size ()]);
1398            }
1399
1400            return this.managedFieldNames;
1401
1402        } //JDOClass.getManagedFieldNames()
1403

1404
1405        /******************************************************************
1406         * Creates a string-representation for this object.
1407         *
1408         * @return The string-representation of this object.
1409         *****************************************************************/

1410
1411        public final String JavaDoc toString ()
1412        {
1413
1414            return '<' + PROPERTY_SUPER_CLASSNAME + ':' + this.superClassName + ',' +
1415                         PROPERTY_ACCESS_MODIFIER + ':' + Modifier.toString (this.modifiers) + ',' +
1416                         PROPERTY_JDO_MODIFIER + ':' + this.isPersistent + ',' +
1417                         "fields:" + this.fields + '>';
1418
1419        } //JDOClass.toString()
1420

1421
1422    } //JDOClass
1423

1424
1425    //#####################################################################
1426
/**
1427     * A class to hold the properties of a field.
1428     */

1429    //#####################################################################
1430

1431    static final class JDOField
1432    {
1433
1434
1435        /**
1436         * The name of the field.
1437         */

1438        private String JavaDoc name;
1439
1440
1441        /**
1442         * The type of the field.
1443         */

1444        private String JavaDoc type = null;
1445
1446
1447        /**
1448         * The access modifier of the field.
1449         */

1450        private int modifiers = Modifier.PRIVATE;
1451
1452
1453        /**
1454         * The JDO modifier of the field.
1455         */

1456        private String JavaDoc jdoModifier = null;
1457
1458
1459        /**
1460         * The annotation type.
1461         */

1462        private String JavaDoc annotationType = null;
1463
1464
1465        /******************************************************************
1466         * Creates a new object with the given name.
1467         *
1468         * @param name The name of the field.
1469         *
1470         * @see #name
1471         *****************************************************************/

1472
1473        JDOField (String JavaDoc name)
1474        {
1475
1476            this.name = name;
1477
1478        } //JDOField.<init>
1479

1480
1481        /******************************************************************
1482         * Gets the name of the field.
1483         *
1484         * @return The name of the field.
1485         *
1486         * @see #name
1487         *****************************************************************/

1488
1489        public final String JavaDoc getName ()
1490        {
1491
1492            return this.name;
1493
1494        } //JDOField.getName()
1495

1496
1497        /******************************************************************
1498         * Sets the type of the field. The given classname should have a
1499         * natural form (with dots) and is converted to a VM-similar
1500         * notation (with slashes).
1501         *
1502         * @param type The natural classname.
1503         *
1504         * @see #type
1505         *****************************************************************/

1506
1507        public final void setType (String JavaDoc type)
1508        {
1509
1510            this.type = fromCanonicalClassName (type);
1511
1512        } //JDOField.setType()
1513

1514
1515        /******************************************************************
1516         * Gets the type of the field.
1517         *
1518         * @return The type of the field.
1519         *
1520         * @see #type
1521         *****************************************************************/

1522
1523        public final String JavaDoc getType ()
1524        {
1525
1526            return this.type;
1527
1528        } //JDOField.getType()
1529

1530
1531        /******************************************************************
1532         *
1533         *****************************************************************/

1534
1535        public final int getModifiers ()
1536        {
1537
1538            return this.modifiers;
1539
1540        } //JDOField.getModifiers()
1541

1542
1543        /******************************************************************
1544         * Do we have an annotated field?
1545         *
1546         * @return Do we have an annotated field?
1547         *
1548         * @see #annotationType
1549         *****************************************************************/

1550
1551        public final boolean isAnnotated ()
1552        {
1553
1554            return this.annotationType != null;
1555
1556        } //JDOField.isAnnotated()
1557

1558
1559        /******************************************************************
1560         * Do we have a primary key?
1561         *
1562         * @return Do we have a primary key?
1563         *
1564         * @see #annotationType
1565         *****************************************************************/

1566
1567        public final boolean isPk ()
1568        {
1569
1570            return (this.annotationType != null && this.annotationType.equals (ANNOTATION_TYPE_PK));
1571
1572        } //JDOField.isPk()
1573

1574
1575        /******************************************************************
1576         * Is the field in the default fetch group?
1577         *
1578         * @return Is the field in the default fetch group?
1579         *
1580         * @see #annotationType
1581         *****************************************************************/

1582
1583        public final boolean isInDefaultFetchGroup ()
1584        {
1585
1586            return (this.annotationType != null && this.annotationType.equals (ANNOTATION_TYPE_DFG));
1587
1588        } //JDOField.isInDefaultFetchGroup()
1589

1590
1591        /******************************************************************
1592         * Returns whether the field is declared transient.
1593         *
1594         * @return true if declared transient field.
1595         * @see #jdoModifier
1596         */

1597        public boolean isKnownTransient()
1598        {
1599            return (jdoModifier != null
1600                && jdoModifier.equals(JDO_TRANSIENT));
1601        }
1602
1603
1604        /******************************************************************
1605         * Do we have a persistent field.
1606         *
1607         * @return Do we have a persistent field.
1608         *
1609         * @see #jdoModifier
1610         *****************************************************************/

1611
1612        public final boolean isPersistent ()
1613        {
1614
1615            return (this.jdoModifier != null && this.jdoModifier.equals (JDO_PERSISTENT));
1616
1617        } //JDOField.isPersistent()
1618

1619
1620        /******************************************************************
1621         * Do we have a transactional field.
1622         *
1623         * @return So we have a transactional field?
1624         *
1625         * @see #jdoModifier
1626         *****************************************************************/

1627
1628        public final boolean isTransactional ()
1629        {
1630
1631            return (this.jdoModifier != null && this.jdoModifier.equals (JDO_TRANSACTIONAL));
1632
1633        } //JDOField.isTransactional()
1634

1635
1636        /******************************************************************
1637         * Do we have a managed field?
1638         *
1639         * @return Do we have a managed field?
1640         *****************************************************************/

1641
1642        public final boolean isManaged ()
1643        {
1644
1645            return (isPersistent () || isTransactional ());
1646
1647        } //JDOField.isManaged()
1648

1649
1650        /******************************************************************
1651         * Creates a string-representation of the object.
1652         *
1653         * @return The string-representation of the object.
1654         *****************************************************************/

1655
1656        public final String JavaDoc toString ()
1657        {
1658
1659            return '<' + "name:" + this.name + ',' +
1660                         PROPERTY_TYPE + ':' + this.type + ',' +
1661                         PROPERTY_ACCESS_MODIFIER + ':' + Modifier.toString (this.modifiers) + ',' +
1662                         PROPERTY_JDO_MODIFIER + ':' + this.jdoModifier + ',' +
1663                         PROPERTY_ANNOTATION_TYPE + ':' + this.annotationType +
1664                   '>';
1665
1666        } //JDOField.toString()
1667

1668
1669    } //JDOField
1670

1671
1672} //JDOMetaDataProperties
1673
Popular Tags