Source code: com/puppycrawl/tools/checkstyle/checks/indentation/HandlerFactory.java
1 ////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code for adherence to a set of rules.
3 // Copyright (C) 2001-2003 Oliver Burn
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ////////////////////////////////////////////////////////////////////////////////
19 package com.puppycrawl.tools.checkstyle.checks.indentation;
20
21 import java.lang.reflect.Constructor;
22 import java.lang.reflect.InvocationTargetException;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.Map;
26 import java.util.Set;
27
28 import com.puppycrawl.tools.checkstyle.api.DetailAST;
29 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33
34 /**
35 * Factory for handlers. Looks up constructor via reflection.
36 *
37 * @author jrichard
38 */
39 public class HandlerFactory
40 {
41 /** Logger for indentation check */
42 private static final Log LOG =
43 LogFactory.getLog("com.puppycrawl.tools.checkstyle.checks.indentation");
44
45 /**
46 * Registered handlers.
47 */
48 private Map mTypeHandlers = new HashMap();
49
50 /**
51 * registers a handler
52 *
53 * @param aType type from TokenTypes
54 * @param aHandlerClass the handler to register
55 */
56 private void register(int aType, Class aHandlerClass)
57 {
58 try {
59 Constructor ctor = aHandlerClass.getConstructor(new Class[] {
60 IndentationCheck.class,
61 DetailAST.class, // current AST
62 ExpressionHandler.class, // parent
63 });
64 mTypeHandlers.put(new Integer(aType), ctor);
65 }
66 ///CLOVER:OFF
67 catch (NoSuchMethodException e) {
68 throw new RuntimeException("couldn't find ctor for "
69 + aHandlerClass);
70 }
71 catch (SecurityException e) {
72 LOG.debug("couldn't find ctor for " + aHandlerClass, e);
73 throw new RuntimeException("couldn't find ctor for "
74 + aHandlerClass);
75 }
76 ///CLOVER:ON
77 }
78
79 /** Creates a HandlerFactory. */
80 public HandlerFactory()
81 {
82 register(TokenTypes.CASE_GROUP, CaseHandler.class);
83 register(TokenTypes.LITERAL_SWITCH, SwitchHandler.class);
84 register(TokenTypes.SLIST, SlistHandler.class);
85 register(TokenTypes.PACKAGE_DEF, PackageDefHandler.class);
86 register(TokenTypes.LITERAL_ELSE, ElseHandler.class);
87 register(TokenTypes.LITERAL_IF, IfHandler.class);
88 register(TokenTypes.LITERAL_TRY, TryHandler.class);
89 register(TokenTypes.LITERAL_CATCH, CatchHandler.class);
90 register(TokenTypes.LITERAL_FINALLY, FinallyHandler.class);
91 register(TokenTypes.LITERAL_DO, DoWhileHandler.class);
92 register(TokenTypes.LITERAL_WHILE, WhileHandler.class);
93 register(TokenTypes.LITERAL_FOR, ForHandler.class);
94 register(TokenTypes.METHOD_DEF, MethodDefHandler.class);
95 register(TokenTypes.CTOR_DEF, MethodDefHandler.class);
96 register(TokenTypes.CLASS_DEF, ClassDefHandler.class);
97 register(TokenTypes.OBJBLOCK, ObjectBlockHandler.class);
98 register(TokenTypes.INTERFACE_DEF, ClassDefHandler.class);
99 register(TokenTypes.IMPORT, ImportHandler.class);
100 register(TokenTypes.ARRAY_INIT, ArrayInitHandler.class);
101 register(TokenTypes.METHOD_CALL, MethodCallHandler.class);
102 register(TokenTypes.CTOR_CALL, MethodCallHandler.class);
103 register(TokenTypes.LABELED_STAT, LabelHandler.class);
104 register(TokenTypes.STATIC_INIT, StaticInitHandler.class);
105 register(TokenTypes.ASSIGN, AssignHandler.class);
106 register(TokenTypes.PLUS_ASSIGN, AssignHandler.class);
107 register(TokenTypes.MINUS_ASSIGN, AssignHandler.class);
108 register(TokenTypes.STAR_ASSIGN, AssignHandler.class);
109 register(TokenTypes.DIV_ASSIGN, AssignHandler.class);
110 register(TokenTypes.MOD_ASSIGN, AssignHandler.class);
111 register(TokenTypes.SR_ASSIGN, AssignHandler.class);
112 register(TokenTypes.BSR_ASSIGN, AssignHandler.class);
113 register(TokenTypes.SL_ASSIGN, AssignHandler.class);
114 register(TokenTypes.BAND_ASSIGN, AssignHandler.class);
115 register(TokenTypes.BXOR_ASSIGN, AssignHandler.class);
116 register(TokenTypes.BOR_ASSIGN, AssignHandler.class);
117 }
118
119 /**
120 * Returns true if this type (form TokenTypes) is handled.
121 *
122 * @param aType type from TokenTypes
123 * @return true if handler is registered, false otherwise
124 */
125 public boolean isHandledType(int aType)
126 {
127 Set typeSet = mTypeHandlers.keySet();
128 return typeSet.contains(new Integer(aType));
129 }
130
131 /**
132 * Gets list of registered handler types.
133 *
134 * @return int[] of TokenType types
135 */
136 public int[] getHandledTypes()
137 {
138 Set typeSet = mTypeHandlers.keySet();
139 int[] types = new int[typeSet.size()];
140 int index = 0;
141 for (Iterator i = typeSet.iterator(); i.hasNext(); index++) {
142 types[index] = ((Integer) i.next()).intValue();
143 }
144
145 return types;
146 }
147
148 /**
149 * Get the handler for an AST.
150 *
151 * @param aIndentCheck the indentation check
152 * @param aAst ast to handle
153 * @param aParent the handler parent of this AST
154 *
155 * @return the ExpressionHandler for aAst
156 */
157 public ExpressionHandler getHandler(IndentationCheck aIndentCheck,
158 DetailAST aAst, ExpressionHandler aParent)
159 {
160 if (aAst.getType() == TokenTypes.METHOD_CALL) {
161 return createMethodCallHandler(aIndentCheck, aAst, aParent);
162 }
163
164 Integer type = new Integer(aAst.getType());
165
166 ExpressionHandler expHandler = null;
167 try {
168 Constructor handlerCtor = (Constructor) mTypeHandlers.get(type);
169 if (handlerCtor != null) {
170 expHandler = (ExpressionHandler) handlerCtor.newInstance(
171 new Object[] {
172 aIndentCheck,
173 aAst,
174 aParent,
175 }
176 );
177 }
178 }
179 ///CLOVER:OFF
180 catch (InstantiationException e) {
181 LOG.debug("couldn't instantiate constructor for " + aAst, e);
182 throw new RuntimeException("couldn't instantiate constructor for "
183 + aAst);
184 }
185 catch (IllegalAccessException e) {
186 LOG.debug("couldn't access constructor for " + aAst, e);
187 throw new RuntimeException("couldn't access constructor for "
188 + aAst);
189 }
190 catch (InvocationTargetException e) {
191 LOG.debug("couldn't instantiate constructor for " + aAst, e);
192 throw new RuntimeException("couldn't instantiate constructor for "
193 + aAst);
194 }
195 if (expHandler == null) {
196 throw new RuntimeException("no handler for type " + type);
197 }
198 ///CLOVER:ON
199 return expHandler;
200 }
201
202 /**
203 * Create new instance of handler for METHOD_CALL.
204 *
205 * @param aIndentCheck the indentation check
206 * @param aAst ast to handle
207 * @param aParent the handler parent of this AST
208 *
209 * @return new instance.
210 */
211 ExpressionHandler createMethodCallHandler(IndentationCheck aIndentCheck,
212 DetailAST aAst, ExpressionHandler aParent)
213 {
214 ExpressionHandler handler =
215 (ExpressionHandler) mCreatedHandlers.get(aAst);
216 if (handler != null) {
217 return handler;
218 }
219
220 DetailAST ast = (DetailAST) aAst.getFirstChild();
221 while (ast != null && ast.getType() == TokenTypes.DOT) {
222 ast = (DetailAST) ast.getFirstChild();
223 }
224 if (ast != null && ast.getType() == TokenTypes.METHOD_CALL) {
225 aParent = createMethodCallHandler(aIndentCheck, ast, aParent);
226 mCreatedHandlers.put(ast, aParent);
227 }
228 return new MethodCallHandler(aIndentCheck, aAst, aParent);
229 }
230
231 /** Clears cache of created handlers. */
232 void clearCreatedHandlers()
233 {
234 mCreatedHandlers.clear();
235 }
236
237 /** cache for created method call handlers */
238 private Map mCreatedHandlers = new HashMap();
239 }