blob: 05766af81b5f82487520549458afe0481e2d6236 [file] [log] [blame]
/*
* Copyright 2006 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.dev.util.xml;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* Retains parsed information about a particular schema clas.
*/
public class HandlerClassInfo {
private static final HandlerMethod[] EMPTY_ARRAY_HANDLERMETHOD = new HandlerMethod[0];
private static Map<Class<?>,HandlerClassInfo> sClassInfoMap =
new HashMap<Class<?>,HandlerClassInfo>();
public static synchronized HandlerClassInfo getClassInfo(Class<?> c) {
if (sClassInfoMap.containsKey(c)) {
return sClassInfoMap.get(c);
} else {
throw new RuntimeException("The schema class '" + c.getName()
+ "' should have been registered prior to parsing");
}
}
public static synchronized void registerClass(Class<?> c) {
if (sClassInfoMap.containsKey(c)) {
return;
}
// Put a guard null in so that recursive registration of the same
// class won't die.
//
sClassInfoMap.put(c, null);
HandlerClassInfo classInfo = createClassInfo(c);
sClassInfoMap.put(c, classInfo);
}
private static HandlerClassInfo createClassInfo(Class<?> c) {
Map<String,HandlerMethod> namedHandlerMethods = new HashMap<String,HandlerMethod>();
try {
loadClassInfoRecursive(namedHandlerMethods, c);
} catch (Exception e) {
throw new RuntimeException("Unable to use class '" + c.getName()
+ "' as a handler", e);
}
HandlerClassInfo classInfo = new HandlerClassInfo(namedHandlerMethods);
return classInfo;
}
private static void loadClassInfoRecursive(Map<String,HandlerMethod> namedHandlerMethods,
Class<?> c) {
if (!Schema.class.isAssignableFrom(c)) {
// Have gone up as far as we can go.
//
return;
}
Method[] methods = c.getDeclaredMethods();
for (int i = 0, n = methods.length; i < n; ++i) {
Method method = methods[i];
HandlerMethod handlerMethod = HandlerMethod.tryCreate(method);
if (handlerMethod != null) {
// Put in the map, but only if that method isn't already there.
// (Allows inheritance where most-derived class wins).
//
String name = method.getName();
if (!namedHandlerMethods.containsKey(name)) {
namedHandlerMethods.put(name, handlerMethod);
}
}
}
// Recurse into superclass.
//
Class<?> superclass = c.getSuperclass();
if (superclass != null) {
loadClassInfoRecursive(namedHandlerMethods, superclass);
}
}
private final Map<String,HandlerMethod> namedHandlerMethods;
// Nobody else can create one.
private HandlerClassInfo(Map<String,HandlerMethod> namedHandlerMethods) {
this.namedHandlerMethods = namedHandlerMethods;
}
public HandlerMethod getEndMethod(String localName) {
String methodName = "__" + localName.replace('-', '_');
return namedHandlerMethods.get(methodName + "_end");
}
public HandlerMethod[] getHandlerMethods() {
return namedHandlerMethods.values().toArray(EMPTY_ARRAY_HANDLERMETHOD);
}
public HandlerMethod getStartMethod(String localName) {
String methodName = "__" + localName.replace('-', '_');
return namedHandlerMethods.get(methodName + "_begin");
}
public HandlerMethod getTextMethod() {
return namedHandlerMethods.get("__text");
}
}