001: /*
002: * Copyright 2006 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.dev.util.xml;
017:
018: import java.lang.reflect.Method;
019: import java.util.HashMap;
020: import java.util.Map;
021:
022: /**
023: * Retains parsed information about a particular schema clas.
024: */
025: public class HandlerClassInfo {
026: private static final HandlerMethod[] EMPTY_ARRAY_HANDLERMETHOD = new HandlerMethod[0];
027: private static Map sClassInfoMap = new HashMap();
028:
029: public static synchronized HandlerClassInfo getClassInfo(Class c) {
030: if (sClassInfoMap.containsKey(c)) {
031: return (HandlerClassInfo) sClassInfoMap.get(c);
032: } else {
033: throw new RuntimeException("The schema class '"
034: + c.getName()
035: + "' should have been registered prior to parsing");
036: }
037: }
038:
039: public static synchronized void registerClass(Class c) {
040: if (sClassInfoMap.containsKey(c)) {
041: return;
042: }
043:
044: // Put a guard null in so that recursive registration of the same
045: // class won't die.
046: //
047: sClassInfoMap.put(c, null);
048: HandlerClassInfo classInfo = createClassInfo(c);
049: sClassInfoMap.put(c, classInfo);
050: }
051:
052: private static HandlerClassInfo createClassInfo(Class c) {
053: Map namedHandlerMethods = new HashMap();
054: try {
055: loadClassInfoRecursive(namedHandlerMethods, c);
056: } catch (Exception e) {
057: throw new RuntimeException("Unable to use class '"
058: + c.getName() + "' as a handler", e);
059: }
060: HandlerClassInfo classInfo = new HandlerClassInfo(
061: namedHandlerMethods);
062: return classInfo;
063: }
064:
065: private static void loadClassInfoRecursive(Map namedHandlerMethods,
066: Class c) {
067: if (!Schema.class.isAssignableFrom(c)) {
068: // Have gone up as far as we can go.
069: //
070: return;
071: }
072:
073: Method[] methods = c.getDeclaredMethods();
074: for (int i = 0, n = methods.length; i < n; ++i) {
075: Method method = methods[i];
076: HandlerMethod handlerMethod = HandlerMethod
077: .tryCreate(method);
078: if (handlerMethod != null) {
079: // Put in the map, but only if that method isn't already there.
080: // (Allows inheritance where most-derived class wins).
081: //
082: String name = method.getName();
083: if (!namedHandlerMethods.containsKey(name)) {
084: namedHandlerMethods.put(name, handlerMethod);
085: }
086: }
087: }
088:
089: // Recurse into superclass.
090: //
091: Class super class = c.getSuperclass();
092: if (super class != null) {
093: loadClassInfoRecursive(namedHandlerMethods, super class);
094: }
095: }
096:
097: private final Map namedHandlerMethods;
098:
099: // Nobody else can create one.
100: private HandlerClassInfo(Map namedHandlerMethods) {
101: this .namedHandlerMethods = namedHandlerMethods;
102: }
103:
104: public HandlerMethod getEndMethod(String localName) {
105: String methodName = "__" + localName.replace('-', '_');
106: return (HandlerMethod) namedHandlerMethods.get(methodName
107: + "_end");
108: }
109:
110: public HandlerMethod[] getHandlerMethods() {
111: return (HandlerMethod[]) namedHandlerMethods.values().toArray(
112: EMPTY_ARRAY_HANDLERMETHOD);
113: }
114:
115: public HandlerMethod getStartMethod(String localName) {
116: String methodName = "__" + localName.replace('-', '_');
117: return (HandlerMethod) namedHandlerMethods.get(methodName
118: + "_begin");
119: }
120:
121: public HandlerMethod getTextMethod() {
122: return (HandlerMethod) namedHandlerMethods.get("__text");
123: }
124: }
|