org.jdesktop.wonderland.server.cell
Class CellMOProvider

java.lang.Object
  extended by org.jdesktop.wonderland.server.cell.CellMOProvider

public abstract class CellMOProvider
extends java.lang.Object

Provider that loads cells. Providers must have a no-argument constructor.

A Provider exists to instantiate cells, for example cells loaded from modules. Since these modules are not typically in the Wonderland classpath at compile time, cells can be loaded dynamically using these providers. There is no compile-time argument checking when cells are loaded this way, so an incorrect set of arguments will lead to a runtime exception.

Each provider supports a certain set of cell types, identified by name. While this name may be the fully-qualified class name of a cell, it may also be a shorthand, such as "SlideShowCellGLO". If multiple providers support the same name, it is undefined which provider will be called for that name. In general, the system iterates through each provider. The value returned by the first provider to return a non-null value (either an instantiated cell or an exception) will be passed back to the client. If no provider accepts the given type name, the call will return null.

Each provider is responsible for loading cells using its own mechanisms. A default, reflection-based mechanism is provided to load cells using a constructor that accepts the given argument list.

Author:
jkaplan

Constructor Summary
CellMOProvider()
           
 
Method Summary
protected
<T> java.lang.reflect.Constructor<T>
bestMatchingConstructor(java.lang.Class<T> clazz, java.lang.Object... args)
          Find the best matching constructor for the given class and arguments
 int compare(java.lang.reflect.Constructor c0, java.lang.reflect.Constructor c1)
          Compare two constructors.
<T extends CellMO>
T
createCell(java.lang.Class<T> clazz, java.lang.Object... args)
          Load a cell through reflection.
abstract  CellMO loadCellMO(java.lang.String typeName, java.lang.Object... args)
          Load a cell of the given type.
protected  boolean matches(java.lang.reflect.Constructor ctor, java.lang.Object... args)
          Test if a given constructor accepts the given list of arguments
protected  boolean matchPrimitive(java.lang.Class<?> prim, java.lang.Class<?> other)
          Match two classes, one of which is a primitive type and a matching non-primitive type.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

CellMOProvider

public CellMOProvider()
Method Detail

loadCellMO

public abstract CellMO loadCellMO(java.lang.String typeName,
                                  java.lang.Object... args)
                           throws LoadCellMOException
Load a cell of the given type. If this provider supports the given type name, it should return an instantiated cell or throw an exception. Otherwise this method should return null.

Parameters:
typeName - the name of the cell type to load -- this is an abstract name (e.g. "SampleCellGLO") and not a fully-qualified class name.
args - the arguments to use while loading the cell
Returns:
an instantiated cell with the given type name, or null if the given cell type is not supported
Throws:
LoadCellMOException - if there is an error loading the cell

createCell

public <T extends CellMO> T createCell(java.lang.Class<T> clazz,
                                       java.lang.Object... args)
                            throws java.lang.NoSuchMethodException,
                                   java.lang.reflect.InvocationTargetException,
                                   java.lang.IllegalAccessException,
                                   java.lang.IllegalArgumentException,
                                   java.lang.InstantiationException
Load a cell through reflection.

It is very important to note that this method takes the given arguments and finds the best matching constructor. A matching constructor is one which has the same number of arguments as the provided arguments, and each argument is of a type that the given argument can be cast to. While this is similar to regular Java method invocation, it is more likely to find conflicts than regular Java

Parameters:
clazz - the class type to load
args - the argument list to use when loading
Returns:
a cell of the given class, constructed with the given arguments
Throws:
java.lang.NoSuchMethodException - if no constructor can be found in the given class for the given arguments
java.lang.reflect.InvocationTargetException - if there is an error creating the cell
java.lang.IllegalAccessException - if there is a permission problem
java.lang.IllegalArgumentException - if there is an error in one of the arguments
java.lang.InstantiationException - if there is another kind of error

bestMatchingConstructor

protected <T> java.lang.reflect.Constructor<T> bestMatchingConstructor(java.lang.Class<T> clazz,
                                                                       java.lang.Object... args)
                                                            throws java.lang.NoSuchMethodException
Find the best matching constructor for the given class and arguments

Parameters:
clazz - the class to search
args - the arguments to compare
Returns:
the best matching constructor
Throws:
java.lang.NoSuchMethodException - if there is no matching constructor or an ambiguous match

matches

protected boolean matches(java.lang.reflect.Constructor ctor,
                          java.lang.Object... args)
Test if a given constructor accepts the given list of arguments

Parameters:
ctor - the constructor to test
args - the arguments
Returns:
true if this constructor could be called with the given arguments, or false if not

matchPrimitive

protected final boolean matchPrimitive(java.lang.Class<?> prim,
                                       java.lang.Class<?> other)
Match two classes, one of which is a primitive type and a matching non-primitive type.

Parameters:
prim - the primitive class to look at
other - the second class to look at
Returns:
true if the primitive type matches the non-primitive type in autoboxing.

compare

public int compare(java.lang.reflect.Constructor c0,
                   java.lang.reflect.Constructor c1)
Compare two constructors. These constructors must be known to match using the matches() method in order to be compared.

The general idea is to look at each argument and see if it can be cast to the comparable argument of the other class. The goal is to find a constructor that is more specific than another constructor. A constructor is more specific than another iff all its parameter types are assignable to the type of the other constructor, but not vice versa. For example if one constructor takes a String argument and another takes an Object, the one that takes the String is more specific because String can be cast to Object, but not vice-versa.

If some arguments of one constructor are more specific and some arguments of the other are more specific, the constructors are equally specific.

This method compares two constructors, and returns 1 if the first constructor is more specific than the second, 0 if they are equally specific and -1 if the second constructor is more specific than the first.

Parameters:
c0 - the first constructor
c1 - the second constructor
Returns:
1 if c0 is more specific than c1, 0 if they are equally specific and -1 if c1 is more specific than c0.


Open Wonderland - http://openwonderland.org