0001: package xdoclet.modules.ojb.model;
0002:
0003: /* Copyright 2004-2005 The Apache Software Foundation
0004: *
0005: * Licensed under the Apache License, Version 2.0 (the "License");
0006: * you may not use this file except in compliance with the License.
0007: * You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: import java.util.*;
0019:
0020: import xdoclet.modules.ojb.CommaListIterator;
0021: import xdoclet.modules.ojb.LogHelper;
0022: import xdoclet.modules.ojb.constraints.*;
0023: import xjavadoc.XClass;
0024:
0025: /**
0026: * Definition of a class for the ojb repository file.
0027: *
0028: * @author <a href="mailto:tomdz@apache.org">Thomas Dudziak</a>
0029: */
0030: public class ClassDescriptorDef extends DefBase {
0031: /** The original class */
0032: private XClass _origin;
0033: /** The direct base types (available after this class has been processed */
0034: private HashMap _directBaseTypes = new HashMap();
0035: /** Sub class defs */
0036: private ArrayList _extents = new ArrayList();
0037: /** Fields */
0038: private ArrayList _fields = new ArrayList();
0039: /** References */
0040: private ArrayList _references = new ArrayList();
0041: /** Collections */
0042: private ArrayList _collections = new ArrayList();
0043: /** Nested objects */
0044: private ArrayList _nested = new ArrayList();
0045: /** Contains modifications to inherited fields/references/collections
0046: * (key = name, value = Properties object with the modifications) */
0047: private HashMap _modifications = new HashMap();
0048: /** Index descriptors */
0049: private ArrayList _indexDescriptors = new ArrayList();
0050: /** The object cache */
0051: private ObjectCacheDef _objectCache = null;
0052: /** The procedures */
0053: private SortedMap _procedures = new TreeMap();
0054: /** The procedure arguments */
0055: private HashMap _procedureArguments = new HashMap();
0056: /** Whether this class descriptor has been processed */
0057: private boolean _hasBeenProcessed = false;
0058:
0059: /**
0060: * Creates a new class definition object.
0061: *
0062: * @param origin The original class
0063: */
0064: public ClassDescriptorDef(XClass origin) {
0065: super (origin.getTransformedQualifiedName());
0066: _origin = origin;
0067: }
0068:
0069: /**
0070: * Returns the original class.
0071: *
0072: * @return The original XDoclet class object
0073: */
0074: public XClass getOriginalClass() {
0075: return _origin;
0076: }
0077:
0078: /**
0079: * Returns the qualified name of this class as per Java spec.
0080: *
0081: * @return The qualified name
0082: */
0083: public String getQualifiedName() {
0084: return getName().replace('$', '.');
0085: }
0086:
0087: /**
0088: * Returns the default table name for this class which is the unqualified class name.
0089: *
0090: * @return The default table name
0091: */
0092: public String getDefaultTableName() {
0093: String name = getName();
0094: int lastDotPos = name.lastIndexOf('.');
0095: int lastDollarPos = name.lastIndexOf('$');
0096:
0097: return lastDollarPos > lastDotPos ? name
0098: .substring(lastDollarPos + 1) : name
0099: .substring(lastDotPos + 1);
0100: }
0101:
0102: /**
0103: * Determines whether this class descriptor has been processed.
0104: *
0105: * @return <code>true</code> if this class descriptor has been processed
0106: */
0107: boolean hasBeenProcessed() {
0108: return _hasBeenProcessed;
0109: }
0110:
0111: /**
0112: * Processes theis class (ensures that all base types are processed, copies their features to this class, and applies
0113: * modifications (removes ignored features, changes declarations).
0114: *
0115: * @throws ConstraintException If a constraint has been violated
0116: */
0117: public void process() throws ConstraintException {
0118: ClassDescriptorDef otherClassDef;
0119:
0120: for (Iterator it = getDirectBaseTypes(); it.hasNext();) {
0121: otherClassDef = (ClassDescriptorDef) it.next();
0122: if (!otherClassDef.hasBeenProcessed()) {
0123: otherClassDef.process();
0124: }
0125: }
0126: for (Iterator it = getNested(); it.hasNext();) {
0127: otherClassDef = ((NestedDef) it.next()).getNestedType();
0128: if (!otherClassDef.hasBeenProcessed()) {
0129: otherClassDef.process();
0130: }
0131: }
0132:
0133: ArrayList newFields = new ArrayList();
0134: ArrayList newReferences = new ArrayList();
0135: ArrayList newCollections = new ArrayList();
0136: FieldDescriptorDef newFieldDef;
0137: ReferenceDescriptorDef newRefDef;
0138: CollectionDescriptorDef newCollDef;
0139:
0140: // adding base features
0141: if (getBooleanProperty(
0142: PropertyHelper.OJB_PROPERTY_INCLUDE_INHERITED, true)) {
0143: ArrayList baseTypes = new ArrayList();
0144: DefBase featureDef;
0145:
0146: addRelevantBaseTypes(this , baseTypes);
0147: for (Iterator it = baseTypes.iterator(); it.hasNext();) {
0148: cloneInheritedFeatures((ClassDescriptorDef) it.next(),
0149: newFields, newReferences, newCollections);
0150: }
0151:
0152: for (Iterator it = newFields.iterator(); it.hasNext();) {
0153: newFieldDef = (FieldDescriptorDef) it.next();
0154: featureDef = getFeature(newFieldDef.getName());
0155: if (featureDef != null) {
0156: if (!getBooleanProperty(
0157: PropertyHelper.OJB_PROPERTY_IGNORE, false)) {
0158: // we have the implicit constraint that an anonymous field cannot redefine/be redefined
0159: // except if it is ignored
0160: if ("anonymous"
0161: .equals(featureDef
0162: .getProperty(PropertyHelper.OJB_PROPERTY_ACCESS))) {
0163: throw new ConstraintException(
0164: "The anonymous field "
0165: + featureDef.getName()
0166: + " in class "
0167: + getName()
0168: + " overrides an inherited field");
0169: }
0170: if ("anonymous"
0171: .equals(newFieldDef
0172: .getProperty(PropertyHelper.OJB_PROPERTY_ACCESS))) {
0173: throw new ConstraintException(
0174: "The inherited anonymous field "
0175: + newFieldDef.getName()
0176: + " is overriden in class "
0177: + getName());
0178: }
0179: }
0180: LogHelper.warn(true, ClassDescriptorDef.class,
0181: "process", "Class " + getName()
0182: + " redefines the inherited field "
0183: + newFieldDef.getName());
0184: it.remove();
0185: }
0186: }
0187: for (Iterator it = newReferences.iterator(); it.hasNext();) {
0188: newRefDef = (ReferenceDescriptorDef) it.next();
0189: if ("super".equals(newRefDef.getName())) {
0190: // we don't inherit super-references
0191: it.remove();
0192: } else if (hasFeature(newRefDef.getName())) {
0193: LogHelper
0194: .warn(
0195: true,
0196: ClassDescriptorDef.class,
0197: "process",
0198: "Class "
0199: + getName()
0200: + " redefines the inherited reference "
0201: + newRefDef.getName());
0202: it.remove();
0203: }
0204: }
0205: for (Iterator it = newCollections.iterator(); it.hasNext();) {
0206: newCollDef = (CollectionDescriptorDef) it.next();
0207: if (hasFeature(newCollDef.getName())) {
0208: LogHelper
0209: .warn(
0210: true,
0211: ClassDescriptorDef.class,
0212: "process",
0213: "Class "
0214: + getName()
0215: + " redefines the inherited collection "
0216: + newCollDef.getName());
0217: it.remove();
0218: }
0219: }
0220: }
0221: // adding nested features
0222: for (Iterator it = getNested(); it.hasNext();) {
0223: cloneNestedFeatures((NestedDef) it.next(), newFields,
0224: newReferences, newCollections);
0225: }
0226: _fields.addAll(0, newFields);
0227: _references.addAll(0, newReferences);
0228: _collections.addAll(0, newCollections);
0229: sortFields();
0230: _hasBeenProcessed = true;
0231: }
0232:
0233: /**
0234: * Sorts the fields.
0235: */
0236: private void sortFields() {
0237: HashMap fields = new HashMap();
0238: ArrayList fieldsWithId = new ArrayList();
0239: ArrayList fieldsWithoutId = new ArrayList();
0240: FieldDescriptorDef fieldDef;
0241:
0242: for (Iterator it = getFields(); it.hasNext();) {
0243: fieldDef = (FieldDescriptorDef) it.next();
0244: fields.put(fieldDef.getName(), fieldDef);
0245: if (fieldDef.hasProperty(PropertyHelper.OJB_PROPERTY_ID)) {
0246: fieldsWithId.add(fieldDef.getName());
0247: } else {
0248: fieldsWithoutId.add(fieldDef.getName());
0249: }
0250: }
0251:
0252: Collections.sort(fieldsWithId,
0253: new FieldWithIdComparator(fields));
0254:
0255: ArrayList result = new ArrayList();
0256:
0257: for (Iterator it = fieldsWithId.iterator(); it.hasNext();) {
0258: result.add(getField((String) it.next()));
0259: }
0260: for (Iterator it = fieldsWithoutId.iterator(); it.hasNext();) {
0261: result.add(getField((String) it.next()));
0262: }
0263:
0264: _fields = result;
0265: }
0266:
0267: /**
0268: * Checks the constraints on this class.
0269: *
0270: * @param checkLevel The amount of checks to perform
0271: * @exception ConstraintException If a constraint has been violated
0272: */
0273: public void checkConstraints(String checkLevel)
0274: throws ConstraintException {
0275: // now checking constraints
0276: FieldDescriptorConstraints fieldConstraints = new FieldDescriptorConstraints();
0277: ReferenceDescriptorConstraints refConstraints = new ReferenceDescriptorConstraints();
0278: CollectionDescriptorConstraints collConstraints = new CollectionDescriptorConstraints();
0279:
0280: for (Iterator it = getFields(); it.hasNext();) {
0281: fieldConstraints.check((FieldDescriptorDef) it.next(),
0282: checkLevel);
0283: }
0284: for (Iterator it = getReferences(); it.hasNext();) {
0285: refConstraints.check((ReferenceDescriptorDef) it.next(),
0286: checkLevel);
0287: }
0288: for (Iterator it = getCollections(); it.hasNext();) {
0289: collConstraints.check((CollectionDescriptorDef) it.next(),
0290: checkLevel);
0291: }
0292: new ClassDescriptorConstraints().check(this , checkLevel);
0293: }
0294:
0295: /**
0296: * Adds all relevant base types (depending on their include-inherited setting) to the given list.
0297: *
0298: * @param curType The type to process
0299: * @param baseTypes The list of basetypes
0300: */
0301: private void addRelevantBaseTypes(ClassDescriptorDef curType,
0302: ArrayList baseTypes) {
0303: ClassDescriptorDef baseDef;
0304:
0305: for (Iterator it = curType.getDirectBaseTypes(); it.hasNext();) {
0306: baseDef = (ClassDescriptorDef) it.next();
0307: if (!baseDef
0308: .getBooleanProperty(
0309: PropertyHelper.OJB_PROPERTY_INCLUDE_INHERITED,
0310: true)) {
0311: // the base type has include-inherited set to false which means that
0312: // it does not include base features
0313: // since we do want these base features, we have to traverse its base types
0314: addRelevantBaseTypes(baseDef, baseTypes);
0315: }
0316: baseTypes.add(baseDef);
0317: }
0318: }
0319:
0320: /**
0321: * Determines whether the given list contains a descriptor with the same name.
0322: *
0323: * @param defs The list to search
0324: * @param obj The object that is searched for
0325: * @return <code>true</code> if the list contains a descriptor with the same name
0326: */
0327: private boolean contains(ArrayList defs, DefBase obj) {
0328: for (Iterator it = defs.iterator(); it.hasNext();) {
0329: if (obj.getName().equals(((DefBase) it.next()).getName())) {
0330: return true;
0331: }
0332: }
0333: return false;
0334: }
0335:
0336: /**
0337: * Clones the features of the given base class (using modifications if available) and puts them into
0338: * the given lists.
0339: *
0340: * @param baseDef The base class descriptor
0341: * @param newFields Recieves the field copies
0342: * @param newReferences Recieves the reference copies
0343: * @param newCollections Recieves the collection copies
0344: */
0345: private void cloneInheritedFeatures(ClassDescriptorDef baseDef,
0346: ArrayList newFields, ArrayList newReferences,
0347: ArrayList newCollections) {
0348: FieldDescriptorDef copyFieldDef;
0349: ReferenceDescriptorDef copyRefDef;
0350: CollectionDescriptorDef copyCollDef;
0351:
0352: // note that we also copy features with the ignore-property set to true
0353: // they will be ignored later on
0354: for (Iterator fieldIt = baseDef.getFields(); fieldIt.hasNext();) {
0355: copyFieldDef = cloneField((FieldDescriptorDef) fieldIt
0356: .next(), null);
0357: if (!contains(newFields, copyFieldDef)) {
0358: copyFieldDef.setInherited();
0359: newFields.add(copyFieldDef);
0360: }
0361: }
0362: for (Iterator refIt = baseDef.getReferences(); refIt.hasNext();) {
0363: copyRefDef = cloneReference((ReferenceDescriptorDef) refIt
0364: .next(), null);
0365: if (!contains(newReferences, copyRefDef)) {
0366: copyRefDef.setInherited();
0367: newReferences.add(copyRefDef);
0368: }
0369: }
0370: for (Iterator collIt = baseDef.getCollections(); collIt
0371: .hasNext();) {
0372: copyCollDef = cloneCollection(
0373: (CollectionDescriptorDef) collIt.next(), null);
0374: if (!contains(newCollections, copyCollDef)) {
0375: copyCollDef.setInherited();
0376: newCollections.add(copyCollDef);
0377: }
0378: }
0379: }
0380:
0381: /**
0382: * Clones the features of the given nested object (using modifications if available) and puts them into
0383: * the given lists.
0384: *
0385: * @param nestedDef The nested object
0386: * @param newFields Recieves the field copies
0387: * @param newReferences Recieves the reference copies
0388: * @param newCollections Recieves the collection copies
0389: */
0390: private void cloneNestedFeatures(NestedDef nestedDef,
0391: ArrayList newFields, ArrayList newReferences,
0392: ArrayList newCollections) {
0393: ClassDescriptorDef nestedClassDef = nestedDef.getNestedType();
0394: String prefix = nestedDef.getName() + "::";
0395: FieldDescriptorDef copyFieldDef;
0396: ReferenceDescriptorDef copyRefDef;
0397: CollectionDescriptorDef copyCollDef;
0398: StringBuffer newForeignkey;
0399:
0400: for (Iterator fieldIt = nestedClassDef.getFields(); fieldIt
0401: .hasNext();) {
0402: copyFieldDef = cloneField((FieldDescriptorDef) fieldIt
0403: .next(), prefix);
0404: if (!contains(newFields, copyFieldDef)) {
0405: copyFieldDef.setNested();
0406: newFields.add(copyFieldDef);
0407: }
0408: }
0409: for (Iterator refIt = nestedClassDef.getReferences(); refIt
0410: .hasNext();) {
0411: copyRefDef = cloneReference((ReferenceDescriptorDef) refIt
0412: .next(), prefix);
0413: if (contains(newReferences, copyRefDef)) {
0414: continue;
0415: }
0416: copyRefDef.setNested();
0417:
0418: // we have to modify the foreignkey setting as it specifies a field of the same (nested) class
0419: newForeignkey = new StringBuffer();
0420:
0421: for (CommaListIterator it = new CommaListIterator(
0422: copyRefDef
0423: .getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY)); it
0424: .hasNext();) {
0425: if (newForeignkey.length() > 0) {
0426: newForeignkey.append(",");
0427: }
0428: newForeignkey.append(prefix);
0429: newForeignkey.append(it.next());
0430: }
0431: copyRefDef.setProperty(
0432: PropertyHelper.OJB_PROPERTY_FOREIGNKEY,
0433: newForeignkey.toString());
0434: newReferences.add(copyRefDef);
0435: }
0436: for (Iterator collIt = nestedClassDef.getCollections(); collIt
0437: .hasNext();) {
0438: copyCollDef = cloneCollection(
0439: (CollectionDescriptorDef) collIt.next(), prefix);
0440: if (!contains(newCollections, copyCollDef)) {
0441: copyCollDef.setNested();
0442: newCollections.add(copyCollDef);
0443: }
0444: }
0445: }
0446:
0447: /**
0448: * Clones the given field.
0449: *
0450: * @param fieldDef The field descriptor
0451: * @param prefix A prefix for the name
0452: * @return The cloned field
0453: */
0454: private FieldDescriptorDef cloneField(FieldDescriptorDef fieldDef,
0455: String prefix) {
0456: FieldDescriptorDef copyFieldDef = new FieldDescriptorDef(
0457: fieldDef, prefix);
0458:
0459: copyFieldDef.setOwner(this );
0460: // we remove properties that are only relevant to the class the features are declared in
0461: copyFieldDef.setProperty(PropertyHelper.OJB_PROPERTY_IGNORE,
0462: null);
0463:
0464: Properties mod = getModification(copyFieldDef.getName());
0465:
0466: if (mod != null) {
0467: if (!PropertyHelper.toBoolean(mod
0468: .getProperty(PropertyHelper.OJB_PROPERTY_IGNORE),
0469: false)
0470: && hasFeature(copyFieldDef.getName())) {
0471: LogHelper
0472: .warn(
0473: true,
0474: ClassDescriptorDef.class,
0475: "process",
0476: "Class "
0477: + getName()
0478: + " has a feature that has the same name as its included field "
0479: + copyFieldDef.getName()
0480: + " from class "
0481: + fieldDef.getOwner().getName());
0482: }
0483: copyFieldDef.applyModifications(mod);
0484: }
0485: return copyFieldDef;
0486: }
0487:
0488: /**
0489: * Clones the given reference.
0490: *
0491: * @param refDef The reference descriptor
0492: * @param prefix A prefix for the name
0493: * @return The cloned reference
0494: */
0495: private ReferenceDescriptorDef cloneReference(
0496: ReferenceDescriptorDef refDef, String prefix) {
0497: ReferenceDescriptorDef copyRefDef = new ReferenceDescriptorDef(
0498: refDef, prefix);
0499:
0500: copyRefDef.setOwner(this );
0501: // we remove properties that are only relevant to the class the features are declared in
0502: copyRefDef
0503: .setProperty(PropertyHelper.OJB_PROPERTY_IGNORE, null);
0504:
0505: Properties mod = getModification(copyRefDef.getName());
0506:
0507: if (mod != null) {
0508: if (!PropertyHelper.toBoolean(mod
0509: .getProperty(PropertyHelper.OJB_PROPERTY_IGNORE),
0510: false)
0511: && hasFeature(copyRefDef.getName())) {
0512: LogHelper
0513: .warn(
0514: true,
0515: ClassDescriptorDef.class,
0516: "process",
0517: "Class "
0518: + getName()
0519: + " has a feature that has the same name as its included reference "
0520: + copyRefDef.getName()
0521: + " from class "
0522: + refDef.getOwner().getName());
0523: }
0524: copyRefDef.applyModifications(mod);
0525: }
0526: return copyRefDef;
0527: }
0528:
0529: /**
0530: * Clones the given collection.
0531: *
0532: * @param collDef The collection descriptor
0533: * @param prefix A prefix for the name
0534: * @return The cloned collection
0535: */
0536: private CollectionDescriptorDef cloneCollection(
0537: CollectionDescriptorDef collDef, String prefix) {
0538: CollectionDescriptorDef copyCollDef = new CollectionDescriptorDef(
0539: collDef, prefix);
0540:
0541: copyCollDef.setOwner(this );
0542: // we remove properties that are only relevant to the class the features are declared in
0543: copyCollDef.setProperty(PropertyHelper.OJB_PROPERTY_IGNORE,
0544: null);
0545:
0546: Properties mod = getModification(copyCollDef.getName());
0547:
0548: if (mod != null) {
0549: if (!PropertyHelper.toBoolean(mod
0550: .getProperty(PropertyHelper.OJB_PROPERTY_IGNORE),
0551: false)
0552: && hasFeature(copyCollDef.getName())) {
0553: LogHelper
0554: .warn(
0555: true,
0556: ClassDescriptorDef.class,
0557: "process",
0558: "Class "
0559: + getName()
0560: + " has a feature that has the same name as its included collection "
0561: + copyCollDef.getName()
0562: + " from class "
0563: + collDef.getOwner().getName());
0564: }
0565: copyCollDef.applyModifications(mod);
0566: }
0567: return copyCollDef;
0568: }
0569:
0570: /**
0571: * Adds a direct base type.
0572: *
0573: * @param baseType The base type descriptor
0574: */
0575: public void addDirectBaseType(ClassDescriptorDef baseType) {
0576: _directBaseTypes.put(baseType.getName(), baseType);
0577: }
0578:
0579: /**
0580: * Returns the direct base types.
0581: *
0582: * @return An iterator of the direct base types
0583: */
0584: public Iterator getDirectBaseTypes() {
0585: return _directBaseTypes.values().iterator();
0586: }
0587:
0588: /**
0589: * Returns all base types.
0590: *
0591: * @return An iterator of the base types
0592: */
0593: public Iterator getAllBaseTypes() {
0594: ArrayList baseTypes = new ArrayList();
0595:
0596: baseTypes.addAll(_directBaseTypes.values());
0597:
0598: for (int idx = baseTypes.size() - 1; idx >= 0; idx--) {
0599: ClassDescriptorDef curClassDef = (ClassDescriptorDef) baseTypes
0600: .get(idx);
0601:
0602: for (Iterator it = curClassDef.getDirectBaseTypes(); it
0603: .hasNext();) {
0604: ClassDescriptorDef curBaseTypeDef = (ClassDescriptorDef) it
0605: .next();
0606:
0607: if (!baseTypes.contains(curBaseTypeDef)) {
0608: baseTypes.add(0, curBaseTypeDef);
0609: idx++;
0610: }
0611: }
0612: }
0613: return baseTypes.iterator();
0614: }
0615:
0616: /**
0617: * Adds a sub type.
0618: *
0619: * @param subType The sub type definition
0620: */
0621: public void addExtentClass(ClassDescriptorDef subType) {
0622: if (!_extents.contains(subType)) {
0623: _extents.add(subType);
0624: }
0625: }
0626:
0627: /**
0628: * Returns an iterator of the extents of this class.
0629: *
0630: * @return The extents iterator
0631: */
0632: public Iterator getExtentClasses() {
0633: // we sort the extents prior to returning them
0634: Collections.sort(_extents, new DefBaseComparator());
0635: return _extents.iterator();
0636: }
0637:
0638: /**
0639: * Returns an iterator of all direct and indirect extents of this class.
0640: *
0641: * @return The extents iterator
0642: */
0643: public Iterator getAllExtentClasses() {
0644: ArrayList subTypes = new ArrayList();
0645:
0646: subTypes.addAll(_extents);
0647:
0648: for (int idx = 0; idx < subTypes.size(); idx++) {
0649: ClassDescriptorDef curClassDef = (ClassDescriptorDef) subTypes
0650: .get(idx);
0651:
0652: for (Iterator it = curClassDef.getExtentClasses(); it
0653: .hasNext();) {
0654: ClassDescriptorDef curSubTypeDef = (ClassDescriptorDef) it
0655: .next();
0656:
0657: if (!subTypes.contains(curSubTypeDef)) {
0658: subTypes.add(curSubTypeDef);
0659: }
0660: }
0661: }
0662: return subTypes.iterator();
0663: }
0664:
0665: /**
0666: * Determines whether this class can be instantiated, i.e. not an interface or abstract class.
0667: *
0668: * @return <code>true</code> if objects can be created of this class
0669: */
0670: public boolean canBeInstantiated() {
0671: return !_origin.isAbstract() && !_origin.isInterface();
0672: }
0673:
0674: /**
0675: * Determines whether this class has a feature (field, reference, collection) of the given name.
0676: *
0677: * @param name The name
0678: * @return <code>true</code> if there is such a feature
0679: */
0680: public boolean hasFeature(String name) {
0681: return getFeature(name) != null;
0682: }
0683:
0684: /**
0685: * Returns the feature (field, reference, collection) of the given name.
0686: *
0687: * @param name The name
0688: * @return The feature or <code>null</code> if there is no such feature in the current class
0689: */
0690: public DefBase getFeature(String name) {
0691: DefBase result = getField(name);
0692:
0693: if (result == null) {
0694: result = getReference(name);
0695: }
0696: if (result == null) {
0697: result = getCollection(name);
0698: }
0699: return result;
0700: }
0701:
0702: /**
0703: * Adds a field descriptor to this class.
0704: *
0705: * @param fieldDef The field descriptor
0706: */
0707: public void addField(FieldDescriptorDef fieldDef) {
0708: fieldDef.setOwner(this );
0709: _fields.add(fieldDef);
0710: }
0711:
0712: /**
0713: * Adds a clone of the given field descriptor to this class.
0714: *
0715: * @param fieldDef The field descriptor
0716: */
0717: public void addFieldClone(FieldDescriptorDef fieldDef) {
0718: _fields.add(cloneField(fieldDef, ""));
0719: }
0720:
0721: /**
0722: * Returns the field definition with the specified name.
0723: *
0724: * @param name The name of the desired field
0725: * @return The field definition or <code>null</code> if there is no such field
0726: */
0727: public FieldDescriptorDef getField(String name) {
0728: FieldDescriptorDef fieldDef = null;
0729:
0730: for (Iterator it = _fields.iterator(); it.hasNext();) {
0731: fieldDef = (FieldDescriptorDef) it.next();
0732: if (fieldDef.getName().equals(name)) {
0733: return fieldDef;
0734: }
0735: }
0736: return null;
0737: }
0738:
0739: /**
0740: * Returns an iterator of the fields definitions.
0741: *
0742: * @return The field iterator
0743: */
0744: public Iterator getFields() {
0745: return _fields.iterator();
0746: }
0747:
0748: /**
0749: * Returns the field descriptors given in the the field names list.
0750: *
0751: * @param fieldNames The field names, separated by commas
0752: * @return The field descriptors in the order given by the field names
0753: * @throws NoSuchFieldException If a field hasn't been found
0754: */
0755: public ArrayList getFields(String fieldNames)
0756: throws NoSuchFieldException {
0757: ArrayList result = new ArrayList();
0758: FieldDescriptorDef fieldDef;
0759: String name;
0760:
0761: for (CommaListIterator it = new CommaListIterator(fieldNames); it
0762: .hasNext();) {
0763: name = it.getNext();
0764: fieldDef = getField(name);
0765: if (fieldDef == null) {
0766: throw new NoSuchFieldException(name);
0767: }
0768: result.add(fieldDef);
0769: }
0770: return result;
0771: }
0772:
0773: /**
0774: * Returns the primarykey fields.
0775: *
0776: * @return The field descriptors of the primarykey fields
0777: */
0778: public ArrayList getPrimaryKeys() {
0779: ArrayList result = new ArrayList();
0780: FieldDescriptorDef fieldDef;
0781:
0782: for (Iterator it = getFields(); it.hasNext();) {
0783: fieldDef = (FieldDescriptorDef) it.next();
0784: if (fieldDef.getBooleanProperty(
0785: PropertyHelper.OJB_PROPERTY_PRIMARYKEY, false)) {
0786: result.add(fieldDef);
0787: }
0788: }
0789: return result;
0790: }
0791:
0792: /**
0793: * Adds a reference descriptor to this class.
0794: *
0795: * @param refDef The reference descriptor
0796: */
0797: public void addReference(ReferenceDescriptorDef refDef) {
0798: refDef.setOwner(this );
0799: _references.add(refDef);
0800: }
0801:
0802: /**
0803: * Returns a reference definition of the given name if it exists.
0804: *
0805: * @param name The name of the reference
0806: * @return The reference def or <code>null</code> if there is no such reference
0807: */
0808: public ReferenceDescriptorDef getReference(String name) {
0809: ReferenceDescriptorDef refDef;
0810:
0811: for (Iterator it = _references.iterator(); it.hasNext();) {
0812: refDef = (ReferenceDescriptorDef) it.next();
0813: if (refDef.getName().equals(name)) {
0814: return refDef;
0815: }
0816: }
0817: return null;
0818: }
0819:
0820: /**
0821: * Returns an iterator of the reference definitionss.
0822: *
0823: * @return The iterator
0824: */
0825: public Iterator getReferences() {
0826: return _references.iterator();
0827: }
0828:
0829: /**
0830: * Adds a collection descriptor to this class.
0831: *
0832: * @param collDef The collection descriptor
0833: */
0834: public void addCollection(CollectionDescriptorDef collDef) {
0835: collDef.setOwner(this );
0836: _collections.add(collDef);
0837: }
0838:
0839: /**
0840: * Returns the collection definition of the given name if it exists.
0841: *
0842: * @param name The name of the collection
0843: * @return The collection definition or <code>null</code> if there is no such collection
0844: */
0845: public CollectionDescriptorDef getCollection(String name) {
0846: CollectionDescriptorDef collDef = null;
0847:
0848: for (Iterator it = _collections.iterator(); it.hasNext();) {
0849: collDef = (CollectionDescriptorDef) it.next();
0850: if (collDef.getName().equals(name)) {
0851: return collDef;
0852: }
0853: }
0854: return null;
0855: }
0856:
0857: /**
0858: * Returns an iterator of the collection definitions.
0859: *
0860: * @return The collection iterator
0861: */
0862: public Iterator getCollections() {
0863: return _collections.iterator();
0864: }
0865:
0866: /**
0867: * Adds a nested object to this class.
0868: *
0869: * @param nestedDef The nested object
0870: */
0871: public void addNested(NestedDef nestedDef) {
0872: nestedDef.setOwner(this );
0873: _nested.add(nestedDef);
0874: }
0875:
0876: /**
0877: * Returns the nested object definition with the specified name.
0878: *
0879: * @param name The name of the attribute of the nested object
0880: * @return The nested object definition or <code>null</code> if there is no such nested object
0881: */
0882: public NestedDef getNested(String name) {
0883: NestedDef nestedDef = null;
0884:
0885: for (Iterator it = _nested.iterator(); it.hasNext();) {
0886: nestedDef = (NestedDef) it.next();
0887: if (nestedDef.getName().equals(name)) {
0888: return nestedDef;
0889: }
0890: }
0891: return null;
0892: }
0893:
0894: /**
0895: * Returns an iterator of the nested object definitions.
0896: *
0897: * @return The nested object iterator
0898: */
0899: public Iterator getNested() {
0900: return _nested.iterator();
0901: }
0902:
0903: /**
0904: * Adds an index descriptor definition to this class descriptor.
0905: *
0906: * @param indexDef The index descriptor definition
0907: */
0908: public void addIndexDescriptor(IndexDescriptorDef indexDef) {
0909: indexDef.setOwner(this );
0910: _indexDescriptors.add(indexDef);
0911: }
0912:
0913: /**
0914: * Returns the index descriptor definition of the given name if it exists.
0915: *
0916: * @param name The name of the index
0917: * @return The index descriptor definition or <code>null</code> if there is no such index
0918: */
0919: public IndexDescriptorDef getIndexDescriptor(String name) {
0920: IndexDescriptorDef indexDef = null;
0921:
0922: for (Iterator it = _indexDescriptors.iterator(); it.hasNext();) {
0923: indexDef = (IndexDescriptorDef) it.next();
0924: if (indexDef.getName().equals(name)) {
0925: return indexDef;
0926: }
0927: }
0928: return null;
0929: }
0930:
0931: /**
0932: * Returns an iterator of the index descriptor definitions.
0933: *
0934: * @return The index descriptor iterator
0935: */
0936: public Iterator getIndexDescriptors() {
0937: return _indexDescriptors.iterator();
0938: }
0939:
0940: /**
0941: * Sets an object cache definition to an object cache of the given name (if necessary), and returns it.
0942: *
0943: * @param name The name of the object cache class
0944: * @return The object cache definition
0945: */
0946: public ObjectCacheDef setObjectCache(String name) {
0947: if ((_objectCache == null)
0948: || !_objectCache.getName().equals(name)) {
0949: _objectCache = new ObjectCacheDef(name);
0950:
0951: _objectCache.setOwner(this );
0952: }
0953: return _objectCache;
0954: }
0955:
0956: /**
0957: * Returns the object cache definition.
0958: *
0959: * @return The object cache definition
0960: */
0961: public ObjectCacheDef getObjectCache() {
0962: return _objectCache;
0963: }
0964:
0965: /**
0966: * Adds a procedure definition to this class descriptor.
0967: *
0968: * @param procDef The procedure definition
0969: */
0970: public void addProcedure(ProcedureDef procDef) {
0971: procDef.setOwner(this );
0972: _procedures.put(procDef.getName(), procDef);
0973: }
0974:
0975: /**
0976: * Returns the procedure definition of the given name if it exists.
0977: *
0978: * @param name The name of the procedure
0979: * @return The procedure definition or <code>null</code> if there is no such procedure
0980: */
0981: public ProcedureDef getProcedure(String name) {
0982: return (ProcedureDef) _procedures.get(name);
0983: }
0984:
0985: /**
0986: * Returns an iterator of the procedure definitions.
0987: *
0988: * @return The procedure iterator
0989: */
0990: public Iterator getProcedures() {
0991: return _procedures.values().iterator();
0992: }
0993:
0994: /**
0995: * Adds a procedure argument definition to this class descriptor.
0996: *
0997: * @param argDef The procedure argument definition
0998: */
0999: public void addProcedureArgument(ProcedureArgumentDef argDef) {
1000: argDef.setOwner(this );
1001: _procedureArguments.put(argDef.getName(), argDef);
1002: }
1003:
1004: /**
1005: * Returns the procedure argument definition of the given name if it exists.
1006: *
1007: * @param name The name of the procedure argument
1008: * @return The procedure argument definition or <code>null</code> if there is no such argument
1009: */
1010: public ProcedureArgumentDef getProcedureArgument(String name) {
1011: return (ProcedureArgumentDef) _procedureArguments.get(name);
1012: }
1013:
1014: /**
1015: * Returns an iterator of all procedure argument definitions.
1016: *
1017: * @return The procedure argument iterator
1018: */
1019: public Iterator getProcedureArguments() {
1020: return _procedureArguments.values().iterator();
1021: }
1022:
1023: /**
1024: * Adds a modification for the given inherited field/reference/collection.
1025: *
1026: * @param name The name of the inherited field, reference or collection
1027: * @param mods The modified properties
1028: */
1029: public void addModification(String name, Properties mods) {
1030: _modifications.put(name, mods);
1031: }
1032:
1033: /**
1034: * Returns an iterator of all field/reference/collection names for which modifications are stored in this class def.
1035: *
1036: * @return The iterator
1037: */
1038: public Iterator getModificationNames() {
1039: return _modifications.keySet().iterator();
1040: }
1041:
1042: /**
1043: * Returns the modification for the inherited field/reference/collection with the given name.
1044: *
1045: * @param name The name of the inherited field, reference or collection
1046: * @return The modified properties or <code>null</code> if there are no modifications for it
1047: */
1048: public Properties getModification(String name) {
1049: return (Properties) _modifications.get(name);
1050: }
1051:
1052: /* (non-Javadoc)
1053: * @see java.lang.Object#equals(java.lang.Object)
1054: */
1055: public boolean equals(Object other) {
1056: if ((other == null) || !(other instanceof ClassDescriptorDef)) {
1057: return false;
1058: }
1059: return _origin == ((ClassDescriptorDef) other)._origin;
1060: }
1061:
1062: /* (non-Javadoc)
1063: * @see java.lang.Object#hashCode()
1064: */
1065: public int hashCode() {
1066: return _origin.hashCode();
1067: }
1068: }
|