blob: a60178e8b9b49ced7412c143889f70a67853850a [file] [log] [blame]
/*
*
* 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();
}
}