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