/* * 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"); } }