| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.qpid.agent.binding; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Hashtable; |
| import java.util.List; |
| import java.util.Map; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.qpid.agent.annotations.QMFEvent; |
| import org.apache.qpid.agent.annotations.QMFObject; |
| import org.apache.qpid.agent.annotations.QMFSeeAlso; |
| import org.apache.qpid.agent.annotations.QMFType; |
| |
| /** |
| * Contains the mappings from java classes to QMF schema and back. There is one |
| * context per agent, and it contains all the metadata. |
| */ |
| public class BindingContext |
| { |
| private static Log log = LogFactory.getLog(BindingContext.class); |
| private Map<Key, ClassBinding> classes = new Hashtable<Key, ClassBinding>(); |
| private ArrayList<String> packages = new ArrayList<String>(); |
| |
| static class Key |
| { |
| String packageName = ""; |
| String className = ""; |
| boolean object = false; |
| |
| @Override |
| public int hashCode() |
| { |
| return (packageName + "." + className).hashCode(); |
| } |
| |
| @Override |
| public boolean equals(Object obj) |
| { |
| return (obj instanceof Key |
| && (((Key) obj).packageName.equals(packageName)) && (((Key) obj).className |
| .equals(className))); |
| } |
| } |
| |
| public BindingContext() |
| { |
| Key key = new Key(); |
| key.className = "Object"; |
| key.packageName = "org.apache.qmf"; |
| key.object = false; |
| ClassBinding cb = new ClassBinding("org.apache.qmf", "Object", |
| Object.class, false, this); |
| classes.put(key, cb); |
| packages.add("org.apache.qmf"); |
| } |
| |
| public ClassBinding getClassBinding(Class clazz) |
| { |
| return classes.get(getClassKey(clazz)); |
| } |
| |
| public ClassBinding getClassBinding(String packageName, String className) |
| { |
| Key key = new Key(); |
| key.packageName = packageName; |
| key.className = className; |
| return classes.get(key); |
| } |
| |
| public ClassBinding register(Class cls) |
| { |
| String name = cls.getName(); |
| ClassBinding cb = getClassBinding(cls); |
| if (cb == null) |
| { |
| Key key = getClassKey(cls); |
| // Create and store the internal representations |
| if (cls.isEnum()) |
| { |
| cb = new EnumBinding(key.packageName, key.className, cls, |
| key.object, this); |
| } else |
| { |
| cb = new ClassBinding(key.packageName, key.className, cls, |
| key.object, this); |
| } |
| log.debug(String.format( |
| "Added class binding '%s' in package %s for class %s'", |
| key.className, key.packageName, cls.getCanonicalName())); |
| classes.put(key, cb); |
| if (!packages.contains(key.packageName)) |
| { |
| packages.add(key.packageName); |
| } |
| // Parse the methods after adding the class to avoid recursion |
| cb.parse(); |
| // See if there are other classes which should be looked at |
| QMFSeeAlso seeAlso = (QMFSeeAlso) cls |
| .getAnnotation(QMFSeeAlso.class); |
| if (seeAlso != null) |
| { |
| for (Class seeAlsoCls : seeAlso.value()) |
| { |
| this.register(seeAlsoCls); |
| } |
| } |
| } |
| return cb; |
| } |
| |
| public TypeBinding getTypeBinding(Class cls) |
| { |
| // Look for a built in type |
| TypeBinding type = QMFTypeBinding.forClass(cls); |
| // Have we seen it before? |
| if (type == null) |
| { |
| type = this.getClassBinding(cls); |
| } |
| if ((type == null) && List.class.isAssignableFrom(cls)) |
| { |
| type = new ListBinding(this, cls); |
| } |
| if ((type == null) && Map.class.isAssignableFrom(cls)) |
| { |
| type = new MapBinding(this, cls); |
| } |
| // Add it, but since we have not seen it before do not expose methods |
| if (type == null) |
| { |
| type = this.register(cls); |
| } |
| return type; |
| } |
| |
| // FIXME: Need to store these keys off so we dont create alot of objects |
| protected Key getClassKey(Class cls) |
| { |
| Key key = new Key(); |
| QMFObject objAnnotation = (QMFObject) cls |
| .getAnnotation(QMFObject.class); |
| if (objAnnotation != null) |
| { |
| key.className = objAnnotation.className(); |
| key.packageName = objAnnotation.packageName(); |
| key.object = true; |
| } else |
| { |
| QMFType typeAnnotation = (QMFType) cls.getAnnotation(QMFType.class); |
| if (typeAnnotation != null) |
| { |
| key.className = typeAnnotation.className(); |
| key.packageName = typeAnnotation.packageName(); |
| } else |
| { |
| QMFEvent eventAnnotation = (QMFEvent) cls |
| .getAnnotation(QMFEvent.class); |
| if (eventAnnotation != null) |
| { |
| key.className = eventAnnotation.eventName(); |
| key.packageName = eventAnnotation.packageName(); |
| } else |
| { |
| // If this is Object, we return the fake |
| // object value |
| if (cls == Object.class) |
| { |
| key.className = "Object"; |
| key.packageName = "org.apache.qmf"; |
| } else |
| { |
| String name = cls.getName(); |
| int lastDot = name.lastIndexOf('.'); |
| key.className = name.substring(lastDot + 1); |
| key.packageName = name.substring(0, lastDot); |
| } |
| } |
| } |
| } |
| return key; |
| } |
| |
| public ArrayList<String> getPackages() |
| { |
| return packages; |
| } |
| |
| public Collection<ClassBinding> getAllBindings() |
| { |
| return classes.values(); |
| } |
| } |