com.bigdata.gom.skin.GenericSkinRegistry Maven / Gradle / Ivy
/**
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
[email protected]
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.bigdata.gom.skin;
// behavior skin registery.
import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Vector;
import org.apache.log4j.Logger;
import com.bigdata.gom.gpo.IGPO;
import com.bigdata.gom.gpo.IGenericSkin;
import com.bigdata.gom.gpo.ILinkSet;
/**
* Helper class provides a global (JVM wide) registery for {@link
* IGenericSkin}s. Generally, when writing an {@link IGenericSkin} or
* {@link ILinkSetSkin} that implements some interface, you will
* include a static initialization block in the implementation class
* that registers the skin using {@link #registerClass( Class theClass
* )}.
*
* Note: Registered {@link IGenericSkin} implementations that are to
* be instantiated for a backing {@link IGPO} MUST provide a
* public constructor accepting a single {@link IGenericSkin}
* argument.
*
* Note: Registered {@link ILinkSetSkin} implementations that are to
* be instantiated for a backing {@link ILinkSet} MUST provide a
* public constructor accepting a single {@link ILinkSetSkin}
* argument.
*/
public class GenericSkinRegistry
{
/**
* The {@link Logger} for the {@link GenericSkinRegistry}.
*/
public static final Logger log = Logger.getLogger
( GenericSkinRegistry.class
);
static Collection m_registeredClass =
Collections.synchronizedCollection( new Vector() );
/**
* This static method MUST be used to register any {@linkIGenericSkin}s.
* Once a skin has been registered, you can use
* {@link IGPO#asClass( Class theClassOrInterface )} or {@link
* ILinkSet#linkSetAsClass( Class theClassOrInterface )} to re-skin any
* {@link IGPO} object or {@link ILinkSet} by naming the interface (or
* implementation class) that you want to expose for the persistent data.
*
*
* @param theClass
* The implementation class.
*
* @todo Consider that more than one implementation class for the same
* interface may be registered. This should at LEAST generate a
* warning since only the first such implementation class for an
* interface will be used.
*
* @exception IllegalArgumentException
* If theClass does not implement either
* {@link IGenericSkin} or {@link ILinkSetSkin}.
*/
public static void registerClass
( Class theClass
)
{
if( theClass.isInterface() ) {
log.error
( "This is an interface, not an implementation class: "+
theClass.getName()
);
throw new IllegalArgumentException
( "This is an interface, not an implementation class: "+
theClass.getName()
);
}
if( ! IGenericSkin.class.isAssignableFrom( theClass ) //&&
// ! ILinkSetSkin.class.isAssignableFrom( theClass )
) {
// log.error
// ( "Implementation classes MUST implement: "+
// IGenericSkin.class.getName()
// );
throw new IllegalArgumentException
( "Class MUST implement: "+
IGenericSkin.class.getName()
// +" -or- "+
// ILinkSetSkin.class.getName()
);
}
/* Check to see if the skin has already been registered. If
* not, then we register it now.
*/
if( m_registeredClass.contains( theClass ) ) {
// log.info
// ( "Skin already registered: "+theClass
// );
} else {
m_registeredClass.add
( theClass
);
log.info
( "Registered skin: "+theClass
);
}
}
/**
* Returns a {@link Class} that has been registered using {@link
* #registerClass( Class theClassOrInterface )} as a skin.
*
* @param theClassOrInterface
*
* @return The implementation class.
*
* @exception UnsupportedOperationException if there is no registered
* skin identified by the specified class or interface.
*
* @exception IllegalArgumentException if theClassOrInterface is
* null
.
*/
public static Class getImplementationClass
( Class theClassOrInterface
)
{
if( theClassOrInterface == null ) {
throw new IllegalArgumentException
( "The class or interface may not be null."
);
}
Class theImplementationClass = null;
if( theClassOrInterface.isInterface() ) {
/* We need to find a registered implementation class for
* this interface.
*/
for( Iterator it = m_registeredClass.iterator(); it.hasNext(); ) {
Class aClass = ( Class ) it.next();
if( theClassOrInterface.isAssignableFrom( aClass ) ) {
theImplementationClass = aClass;
break;
}
}
if( theImplementationClass == null ) {
throw new UnsupportedOperationException
( "No implementation class has been registered for that interface: "+theClassOrInterface.getName()
);
}
} else if( m_registeredClass.contains( theClassOrInterface ) ) {
/*
* Otherwise this is already an implementation class.
*
* @todo Rather than requiring the Class to have been registered, we
* could simply register the class now.
*/
theImplementationClass = theClassOrInterface;
} else {
throw new UnsupportedOperationException
( "No registered class matches or is assignable from the parameter: "+theClassOrInterface.getName()
);
}
return theImplementationClass;
}
/**
* Helper method for {@link IGPO#asClass( Class
* theClassOrInterface )} implementations.
*
* @return A {@link IGenericSkin} for g that is an
* instance of the desired class or that implements the desired
* interface.
*
* @exception UnsupportedOperationException if a suitable {@link
* IGenericSkin} did not exist and could not be minted. Typically
* this means that no suitable implementation class has been registered,
* or that the class does not implement a suitable constructor.
*/
public static IGenericSkin asClass
( IGPO g,
Class theClassOrInterface
)
throws UnsupportedOperationException
{
if( g == null ) {
log.error
( "The generic object may not be null."
);
throw new IllegalArgumentException
( "The generic object may not be null."
);
}
if( theClassOrInterface == null ) {
log.error
( "The class or interface may not be null."
);
throw new IllegalArgumentException
( "The class or interface may not be null."
);
}
/* If _this_ object already implements the desired behavior
* then just return it.
*
* Note: If you are using the recommended pattern of
* delegating the IGeneric interface to a concrete
* implementation of that interface, then this will never be
* true. (Think about it as if this class were final - there
* would be no other interfaces that it could implement).
*/
if( theClassOrInterface.isInstance( g ) ) {
return g;
}
Class theImplementationClass = getImplementationClass
( theClassOrInterface
);
/* One way or another, we now have an implementation class.
* We test to make sure that there is an appropriate public
* constructor that will accept the IGeneric interface as its
* sole parameter.
*/
try {
return mintGenericSkin( theImplementationClass, g );
}
catch( Throwable t ) {
log.error
( "Unable to morph behavior to"+
": theClassOrInterface="+theClassOrInterface,
t
);
RuntimeException ex = new UnsupportedOperationException
( "Unable to morph behavior to"+
": theClassOrInterface="+theClassOrInterface+
", initCause="+t
);
ex.initCause( t );
throw ex;
}
}
// /**
// * Helper method for {@link ILinkSet#linkSetAsClass( Class
// * theClassOrInterface )} implementations.
// *
// * @return A {@link ILinkSetSkin} for ls that is an
// * instance of the desired class or implements the desired
// * interface.
// *
// * @exception UnsupportedOperationException if a suitable {@link
// * ILinkSetSkin} did not exist and could not be minted. Typically
// * this means that no suitable implementation class has been registered,
// * or that the class does not implement a suitable constructor.
// */
//
// public static ILinkSetSkin asClass
// ( ILinkSet ls,
// Class theClassOrInterface
// )
// throws UnsupportedOperationException
// {
//
// if( ls == null ) {
//
// log.error
// ( "The link set may not be null."
// );
//
// throw new IllegalArgumentException
// ( "The link set not be null."
// );
//
// }
//
// if( theClassOrInterface == null ) {
//
// log.error
// ( "The class or interface may not be null."
// );
//
// throw new IllegalArgumentException
// ( "The class or interface may not be null."
// );
//
// }
//
// /* If _this_ object already implements the desired behavior
// * then just return it.
// *
// * Note: If you are using the recommended pattern of
// * delegating the ILinkSet interface to a concrete
// * implementation of that interface, then this will never be
// * true. (Think about it as if this class were final - there
// * would be no other interfaces that it could implement).
// */
//
// if( theClassOrInterface.isInstance( ls ) ) {
//
// return ls;
//
// }
//
// Class theImplementationClass = getImplementationClass
// ( theClassOrInterface
// );
//
// /* One way or another, we now have an implementation class.
// * We test to make sure that there is an appropriate public
// * constructor that will accept the ILinkSet interface as its
// * sole parameter.
// */
//
// try {
//
// return mintLinkSetSkin( theImplementationClass, ls );
//
// }
//
// catch( Throwable t ) {
//
// log.error
// ( "Unable to morph behavior to"+
// ": "+theClassOrInterface
// );
//
// RuntimeException ex = new UnsupportedOperationException
// ( "Unable to morph behavior to"+
// ": "+theClassOrInterface
// );
//
// ex.initCause( t );
//
// throw ex;
//
// }
//
// }
public static IGenericSkin mintGenericSkin( Class implClass, IGPO g )
throws Exception
{
Constructor c = implClass.getDeclaredConstructor
( new Class[] { IGPO.class }
);
return (IGenericSkin) c.newInstance
( new Object[] { g }
);
}
// public static ILinkSetSkin mintLinkSetSkin( Class implClass, ILinkSet ls )
// throws Exception
// {
//
// Constructor c = implClass.getDeclaredConstructor
// ( new Class[] { ILinkSetSkin.class }
// );
//
// return (ILinkSetSkin) c.newInstance
// ( new Object[] { ls }
// );
//
// }
}