001: package xdoclet.modules.ojb.constraints;
002:
003: import java.util.ArrayList;
004: import java.util.Iterator;
005:
006: import xdoclet.modules.ojb.model.*;
007: import xjavadoc.XClass;
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: * Helper class for functionality related to inheritance between classes/interfaces.
026: *
027: * @author <a href="mailto:tomdz@users.sourceforge.net">Thomas Dudziak (tomdz@users.sourceforge.net)</a>
028: */
029: public class InheritanceHelper {
030: /**
031: * Retrieves the class object for the class with the given name.
032: *
033: * @param name The class name
034: * @return The class object
035: * @throws ClassNotFoundException If the class is not on the classpath (the exception message contains the class name)
036: */
037: public static Class getClass(String name)
038: throws ClassNotFoundException {
039: try {
040: return Class.forName(name);
041: } catch (ClassNotFoundException ex) {
042: throw new ClassNotFoundException(name);
043: }
044: }
045:
046: /**
047: * Determines whether the given type is the same or a sub type of the other type.
048: *
049: * @param type The type
050: * @param baseType The possible base type
051: * @param checkActualClasses Whether to use the actual classes for the test
052: * @return <code>true</code> If <code>type</code> specifies the same or a sub type of <code>baseType</code>
053: * @throws ClassNotFoundException If the two classes are not on the classpath
054: */
055: public boolean isSameOrSubTypeOf(XClass type, String baseType,
056: boolean checkActualClasses) throws ClassNotFoundException {
057: String qualifiedBaseType = baseType.replace('$', '.');
058:
059: if (type.getQualifiedName().equals(qualifiedBaseType)) {
060: return true;
061: }
062:
063: // first search via XDoclet
064: ArrayList queue = new ArrayList();
065: boolean canSpecify = false;
066: XClass curType;
067:
068: queue.add(type);
069: while (!queue.isEmpty()) {
070: curType = (XClass) queue.get(0);
071: queue.remove(0);
072: if (qualifiedBaseType.equals(curType.getQualifiedName())) {
073: return true;
074: }
075: if (curType.getInterfaces() != null) {
076: for (Iterator it = curType.getInterfaces().iterator(); it
077: .hasNext();) {
078: queue.add(it.next());
079: }
080: }
081: if (!curType.isInterface()) {
082: if (curType.getSuperclass() != null) {
083: queue.add(curType.getSuperclass());
084: }
085: }
086: }
087:
088: // if not found, we try via actual classes
089: return checkActualClasses ? isSameOrSubTypeOf(type
090: .getQualifiedName(), qualifiedBaseType) : false;
091: }
092:
093: /**
094: * Determines whether the given type is the same or a sub type of the other type.
095: *
096: * @param type The type
097: * @param baseType The possible base type
098: * @param checkActualClasses Whether to use the actual classes for the test
099: * @return <code>true</code> If <code>type</code> specifies the same or a sub type of <code>baseType</code>
100: * @throws ClassNotFoundException If the two classes are not on the classpath
101: */
102: public boolean isSameOrSubTypeOf(ClassDescriptorDef type,
103: String baseType, boolean checkActualClasses)
104: throws ClassNotFoundException {
105: if (type.getQualifiedName().equals(baseType.replace('$', '.'))) {
106: return true;
107: } else if (type.getOriginalClass() != null) {
108: return isSameOrSubTypeOf(type.getOriginalClass(), baseType,
109: checkActualClasses);
110: } else {
111: return checkActualClasses ? isSameOrSubTypeOf(type
112: .getName(), baseType) : false;
113: }
114: }
115:
116: /**
117: * Determines whether the given type is the same or a sub type of the other type.
118: *
119: * @param type The type
120: * @param baseType The possible base type
121: * @return <code>true</code> If <code>type</code> specifies the same or a sub type of <code>baseType</code>
122: * @throws ClassNotFoundException If the two classes are not on the classpath
123: */
124: public boolean isSameOrSubTypeOf(String type, String baseType)
125: throws ClassNotFoundException {
126: return type.replace('$', '.')
127: .equals(baseType.replace('$', '.')) ? true
128: : isSameOrSubTypeOf(getClass(type), baseType);
129: }
130:
131: /**
132: * Determines whether the given type is the same or a sub type of the other type.
133: *
134: * @param type The type
135: * @param baseType The possible base type
136: * @return <code>true</code> If <code>type</code> specifies the same or a sub type of <code>baseType</code>
137: * @throws ClassNotFoundException If the two classes are not on the classpath
138: */
139: public boolean isSameOrSubTypeOf(Class type, String baseType)
140: throws ClassNotFoundException {
141: return type.getName().equals(baseType.replace('$', '.')) ? true
142: : getClass(baseType).isAssignableFrom(type);
143: }
144: }
|