001: /*
002: * Copyright (C) The DNA Group. All rights reserved.
003: *
004: * This software is published under the terms of the DNA
005: * Software License version 1.1, a copy of which has been included
006: * with this distribution in the LICENSE.txt file.
007: */
008: package org.codehaus.dna.tools.metaclass;
009:
010: import com.thoughtworks.qdox.model.JavaClass;
011: import com.thoughtworks.qdox.model.JavaMethod;
012: import java.util.Properties;
013: import org.codehaus.metaclass.model.Attribute;
014: import org.codehaus.metaclass.tools.qdox.DefaultQDoxAttributeInterceptor;
015: import org.codehaus.metaclass.tools.qdox.QDoxAttributeInterceptor;
016:
017: /**
018: * This is an Attribute interceptor that invoked during construction
019: * of ClassDescriptors that will process DNA metadata. The processing
020: * involves setting default values for required attributes and resolving
021: * types in type-based attributes.
022: *
023: * @author Peter Donald
024: * @version $Revision: 1.2 $ $Date: 2004/05/01 09:51:48 $
025: */
026: public class DNAAttributeInterceptor extends
027: DefaultQDoxAttributeInterceptor implements
028: QDoxAttributeInterceptor {
029: /**
030: * @see QDoxAttributeInterceptor#processClassAttribute(JavaClass, Attribute)
031: */
032: public Attribute processClassAttribute(final JavaClass clazz,
033: final Attribute attribute) {
034: final String name = attribute.getName();
035: if (name.equals("dna.service")) {
036: final Properties parameters = new Properties();
037: final String type = attribute.getParameter("type", null);
038: if (null == type) {
039: final String message = "dna.service attribute on class "
040: + clazz.getFullyQualifiedName()
041: + " must specify the parameter 'type'";
042: throw new IllegalArgumentException(message);
043: }
044: final String resolvedType = resolveType(clazz, type);
045: parameters.setProperty("type", resolvedType);
046: return new Attribute("dna.service", parameters);
047: } else {
048: return attribute;
049: }
050: }
051:
052: /**
053: * @see QDoxAttributeInterceptor#processMethodAttribute(JavaMethod, Attribute)
054: */
055: public Attribute processMethodAttribute(final JavaMethod method,
056: final Attribute attribute) {
057: final JavaClass clazz = method.getParentClass();
058: final String name = attribute.getName();
059: if (name.equals("dna.configuration")
060: || name.equals("dna.parameters")) {
061: return processConfigurationAttribute(clazz, attribute);
062: } else if (name.equals("dna.dependency")) {
063: final Properties parameters = new Properties();
064: final String type = attribute.getParameter("type", null);
065: if (null == type) {
066: final String message = "dna.dependency attribute on class "
067: + clazz.getFullyQualifiedName()
068: + " must specify the parameter 'type'";
069: throw new IllegalArgumentException(message);
070: }
071: final String resolvedType = resolveType(clazz, type);
072: parameters.setProperty("type", resolvedType);
073:
074: final String optional = attribute.getParameter("optional",
075: "false");
076: parameters.setProperty("optional", optional);
077:
078: final String actualKey = determineKey(attribute,
079: resolvedType);
080: parameters.setProperty("key", actualKey);
081:
082: return new Attribute("dna.dependency", parameters);
083: } else {
084: return attribute;
085: }
086: }
087:
088: /**
089: * Calculate key used to lookup dependency.
090: *
091: * @param attribute the attribute
092: * @param resolvedType the type of dependency
093: * @return the key
094: */
095: String determineKey(final Attribute attribute,
096: final String resolvedType) {
097: final String key = attribute.getParameter("key", null);
098: final String qualifier = attribute.getParameter("qualifier",
099: null);
100: if (null != key) {
101: return key;
102: } else if (null != qualifier) {
103: return resolvedType + "/" + qualifier;
104: } else {
105: return resolvedType;
106: }
107: }
108:
109: /**
110: * Process a Configuration or Parameters Attribute.
111: *
112: * @param clazz the associated JavaClass
113: * @param attribute the attribute
114: * @return the resultant attribute
115: */
116: Attribute processConfigurationAttribute(final JavaClass clazz,
117: final Attribute attribute) {
118: final String type = attribute.getParameter("type", null);
119: final String classname = clazz.getName();
120: final String defaultLocation = getSchemaLocationFor(classname);
121: final String location = attribute.getParameter("location",
122: defaultLocation);
123: final Properties parameters = new Properties();
124: if (null != type) {
125: parameters.setProperty("type", type);
126: }
127: parameters.setProperty("location", location);
128: return new Attribute(attribute.getName(), parameters);
129: }
130:
131: /**
132: * Get the location of the schema. By default it is "Foo-schema.xml"
133: * for the com.biz.Foo component.
134: *
135: * @param classname the classname of component
136: * @return the location of the schema
137: */
138: String getSchemaLocationFor(final String classname) {
139: final int index = classname.lastIndexOf(".");
140: String location = classname;
141: if (-1 != index) {
142: location = classname.substring(index + 1);
143: }
144: location += "-schema.xml";
145: return location;
146: }
147:
148: /**
149: * Resolve the specified type.
150: * Resolving essentially means finding the fully qualified name of
151: * a class from just it's short name.
152: *
153: * @param javaClass the java class relative to which the type must be resolved
154: * @param type the unresolved type
155: * @return the resolved type
156: */
157: String resolveType(final JavaClass javaClass, final String type) {
158: String baseType = type;
159: String postFix = "";
160: if (type.endsWith("[]") || type.endsWith("{}")) {
161: final int index = type.length() - 2;
162: baseType = type.substring(0, index);
163: postFix = type.substring(index);
164: }
165: return javaClass.getParentSource().resolveType(baseType)
166: + postFix;
167: }
168: }
|