View Javadoc
1   /*
2    * Copyright 2006 Werner Guttmann
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5    * in compliance with the License. You may obtain a copy of the License at
6    * 
7    * http://www.apache.org/licenses/LICENSE-2.0
8    * 
9    * Unless required by applicable law or agreed to in writing, software distributed under the License
10   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11   * or implied. See the License for the specific language governing permissions and limitations under
12   * the License.
13   */
14  package org.exolab.javasource;
15  
16  import java.util.HashMap;
17  
18  /**
19   * Makes an effort to identify where Override annotations belong. We are limited in what we look at
20   * and we do not use reflection to identify if a class truly extends the appropriate class. We only
21   * check the class of the arguments. This class may not be generically useful, but is useful with
22   * the code generated by Castor. <br/>
23   * Our one public method, {@link #addOverrideAnnotations(JMethodSignature)}, should only be called
24   * when you already know that you are generating Java-5 style code.
25   * 
26   * @author <a href="mailto:werner DOT guttmann AT gmx DOT net">Werner Guttman</a>
27   * @version $Revision: 5951 $ $Date: 2006-04-25 16:09:10 -0600 (Tue, 25 Apr 2006) $
28   * @since 1.0.4
29   */
30  public final class Java5HacksHelper {
31  
32    /**
33     * As a static utility class, we want a private constructor.
34     */
35    private Java5HacksHelper() {}
36  
37    private static class MethodSpec {
38      private String _methodName;
39      private int _paramCount;
40      private String _param1ClassName;
41      private String _param2ClassName;
42  
43      public MethodSpec(final String methodName, final int paramCount, final String param1ClassName,
44          final String param2ClassName) {
45        _methodName = methodName;
46        _paramCount = paramCount;
47        _param1ClassName = param1ClassName;
48        _param2ClassName = param2ClassName;
49      }
50  
51      public String getMethodName() {
52        return _methodName;
53      }
54  
55      public int getParamCount() {
56        return _paramCount;
57      }
58  
59      public String getParam1ClassName() {
60        return _param1ClassName;
61      }
62  
63      public String getParam2ClassName() {
64        return _param2ClassName;
65      }
66    }
67  
68    private static final HashMap<String, MethodSpec> DEFINED_SPECS =
69        new HashMap<String, MethodSpec>();
70  
71    private static void createMethodSpec(final String methodName, final int paramCount,
72        final String param1ClassName, final String param2ClassName) {
73      MethodSpec temp = new MethodSpec(methodName, paramCount, param1ClassName, param2ClassName);
74  
75      DEFINED_SPECS.put(methodName, temp);
76    }
77  
78    static {
79      createMethodSpec("getAccessMode", 0, "", "");
80      // createMethodSpec("getExtends", 0, "", "");
81      // createMethodSpec("getIdentity", 0, "", "");
82      createMethodSpec("getNameSpacePrefix", 0, "", "");
83      createMethodSpec("getNameSpaceURI", 0, "", "");
84      createMethodSpec("getValidator", 0, "", "");
85      createMethodSpec("getXMLName", 0, "", "");
86      createMethodSpec("getXTransients", 0, "", "");
87      createMethodSpec("newInstance", 1, "java.lang.Object", "");
88      createMethodSpec("setValue", 1, "java.lang.Object", "");
89      createMethodSpec("equals", 1, "java.lang.Object", "");
90      createMethodSpec("getValue", 1, "java.lang.Object", "");
91      createMethodSpec("marshal", 1, "java.io.Writer", "");
92      createMethodSpec("newInstance", 1, "java.lang.Object", "");
93      createMethodSpec("setValue", 2, "java.lang.Object", "java.lang.Object");
94      createMethodSpec("setXTransients", 1, "org.openmrm.core.data.castor.XTransients", "");
95    };
96  
97    /** An override annotation we use to see if we can get others of its type. */
98    private static final JAnnotationType OVERRIDE_ANNOTATION = new JAnnotationType("Override");
99  
100   /**
101    * Given the method signature, add the Override annotation if this class is one that we know
102    * requires this annotation.
103    *
104    * @param jms The method signature to inspect.
105    */
106   public static void addOverrideAnnotations(final JMethodSignature jms) {
107     String name = jms.getName();
108     boolean addOverrideAnnotation = false;
109 
110     // It the method already has an override annotation, then jump out
111     JAnnotation override = jms.getAnnotation(OVERRIDE_ANNOTATION);
112     if (override != null) {
113       return;
114     }
115 
116     // If the method name doesn't exist in our list, then jump out
117     MethodSpec methodSpec = DEFINED_SPECS.get(name);
118     if (methodSpec == null) {
119       return;
120     }
121 
122     // If the number of parameters isn't what we're prepared for, then jump out
123     int paramCount = jms.getParameters().length;
124     if (paramCount != methodSpec.getParamCount()) {
125       return;
126     }
127 
128     // Do we add the Override annotation? Check vs number of arguments.
129     switch (paramCount) {
130       case 0:
131         addOverrideAnnotation = true;
132         break;
133       case 1:
134         String incomingClassName1 = jms.getParameter(0).getType().getName();
135         if (incomingClassName1.equalsIgnoreCase(methodSpec.getParam1ClassName())) {
136           addOverrideAnnotation = true;
137         }
138         break;
139       case 2:
140         String className1 = jms.getParameter(0).getType().getName();
141         String className2 = jms.getParameter(1).getType().getName();
142         if (className1.equalsIgnoreCase(methodSpec.getParam1ClassName())
143             && className2.equalsIgnoreCase(methodSpec.getParam2ClassName())) {
144           addOverrideAnnotation = true;
145         }
146         break;
147       default:
148         // We aren't prepared for > 2 parameters, so we don't add an Override annotation
149         break;
150     }
151 
152     // Do the work if we need to
153     if (addOverrideAnnotation) {
154       jms.addAnnotation(new JAnnotation(new JAnnotationType("Override")));
155     }
156   }
157 
158 }