001: package xdoclet.modules.ojb.constraints;
002:
003: import xdoclet.modules.ojb.LogHelper;
004: import xdoclet.modules.ojb.model.ClassDescriptorDef;
005: import xdoclet.modules.ojb.model.ModelDef;
006: import xdoclet.modules.ojb.model.PropertyHelper;
007: import xdoclet.modules.ojb.model.ReferenceDescriptorDef;
008:
009: /* Copyright 2004-2005 The Apache Software Foundation
010: *
011: * Licensed under the Apache License, Version 2.0 (the "License");
012: * you may not use this file except in compliance with the License.
013: * You may obtain a copy of the License at
014: *
015: * http://www.apache.org/licenses/LICENSE-2.0
016: *
017: * Unless required by applicable law or agreed to in writing, software
018: * distributed under the License is distributed on an "AS IS" BASIS,
019: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
020: * See the License for the specific language governing permissions and
021: * limitations under the License.
022: */
023:
024: /**
025: * Checks constraints for reference descriptors. Note that constraints may modify the reference descriptor.
026: * For checks of the relationships (e.g. foreignkey) see ModelConstraints.
027: *
028: * @author <a href="mailto:tomdz@users.sourceforge.net">Thomas Dudziak (tomdz@users.sourceforge.net)</a>
029: */
030: public class ReferenceDescriptorConstraints extends
031: FeatureDescriptorConstraints {
032: /**
033: * Checks the given reference descriptor.
034: *
035: * @param refDef The reference descriptor
036: * @param checkLevel The amount of checks to perform
037: * @exception ConstraintException If a constraint has been violated
038: */
039: public void check(ReferenceDescriptorDef refDef, String checkLevel)
040: throws ConstraintException {
041: ensureClassRef(refDef, checkLevel);
042: checkProxyPrefetchingLimit(refDef, checkLevel);
043: }
044:
045: /**
046: * Ensures that the given reference descriptor has the class-ref property.
047: *
048: * @param refDef The reference descriptor
049: * @param checkLevel The current check level (this constraint is checked in basic (partly) and strict)
050: * @exception ConstraintException If a constraint has been violated
051: */
052: private void ensureClassRef(ReferenceDescriptorDef refDef,
053: String checkLevel) throws ConstraintException {
054: if (CHECKLEVEL_NONE.equals(checkLevel)) {
055: return;
056: }
057:
058: if (!refDef.hasProperty(PropertyHelper.OJB_PROPERTY_CLASS_REF)) {
059: if (refDef
060: .hasProperty(PropertyHelper.OJB_PROPERTY_DEFAULT_CLASS_REF)) {
061: // we use the type of the reference variable
062: refDef
063: .setProperty(
064: PropertyHelper.OJB_PROPERTY_CLASS_REF,
065: refDef
066: .getProperty(PropertyHelper.OJB_PROPERTY_DEFAULT_CLASS_REF));
067: } else {
068: throw new ConstraintException("Reference "
069: + refDef.getName() + " in class "
070: + refDef.getOwner().getName()
071: + " does not reference any class");
072: }
073: }
074:
075: // now checking the type
076: ClassDescriptorDef ownerClassDef = (ClassDescriptorDef) refDef
077: .getOwner();
078: ModelDef model = (ModelDef) ownerClassDef.getOwner();
079: String targetClassName = refDef
080: .getProperty(PropertyHelper.OJB_PROPERTY_CLASS_REF);
081: ClassDescriptorDef targetClassDef = model
082: .getClass(targetClassName);
083:
084: if (targetClassDef == null) {
085: throw new ConstraintException("The class "
086: + targetClassName + " referenced by "
087: + refDef.getName() + " in class "
088: + ownerClassDef.getName()
089: + " is unknown or not persistent");
090: }
091: if (!targetClassDef.getBooleanProperty(
092: PropertyHelper.OJB_PROPERTY_OJB_PERSISTENT, false)) {
093: throw new ConstraintException("The class "
094: + targetClassName + " referenced by "
095: + refDef.getName() + " in class "
096: + ownerClassDef.getName() + " is not persistent");
097: }
098:
099: if (CHECKLEVEL_STRICT.equals(checkLevel)) {
100: try {
101: InheritanceHelper helper = new InheritanceHelper();
102:
103: if (refDef.isAnonymous()) {
104: // anonymous reference: class must be a baseclass of the owner class
105: if (!helper.isSameOrSubTypeOf(ownerClassDef,
106: targetClassDef.getName(), true)) {
107: throw new ConstraintException(
108: "The class "
109: + targetClassName
110: + " referenced by the anonymous reference "
111: + refDef.getName()
112: + " in class "
113: + ownerClassDef.getName()
114: + " is not a basetype of the class");
115: }
116: } else {
117: // specified element class must be a subtype of the variable type (if it exists, i.e. not for anonymous references)
118: String varType = refDef
119: .getProperty(PropertyHelper.OJB_PROPERTY_VARIABLE_TYPE);
120: boolean performCheck = true;
121:
122: // but we first check whether there is a useable type for the the variable type
123: if (model.getClass(varType) == null) {
124: try {
125: InheritanceHelper.getClass(varType);
126: } catch (ClassNotFoundException ex) {
127: // no, so defer the check but issue a warning
128: performCheck = false;
129: LogHelper
130: .warn(
131: true,
132: getClass(),
133: "ensureClassRef",
134: "Cannot check whether the type "
135: + targetClassDef
136: .getQualifiedName()
137: + " specified as class-ref at reference "
138: + refDef.getName()
139: + " in class "
140: + ownerClassDef
141: .getName()
142: + " is assignable to the declared type "
143: + varType
144: + " of the reference because this variable type cannot be found in source or on the classpath");
145: }
146: }
147: if (performCheck
148: && !helper.isSameOrSubTypeOf(
149: targetClassDef, varType, true)) {
150: throw new ConstraintException(
151: "The class "
152: + targetClassName
153: + " referenced by "
154: + refDef.getName()
155: + " in class "
156: + ownerClassDef.getName()
157: + " is not the same or a subtype of the variable type "
158: + varType);
159: }
160: }
161: } catch (ClassNotFoundException ex) {
162: throw new ConstraintException(
163: "Could not find the class "
164: + ex.getMessage()
165: + " on the classpath while checking the reference "
166: + refDef.getName() + " in class "
167: + refDef.getOwner().getName());
168: }
169: }
170: // we're adjusting the property to use the classloader-compatible form
171: refDef.setProperty(PropertyHelper.OJB_PROPERTY_CLASS_REF,
172: targetClassDef.getName());
173: }
174: }
|