/* Copyright (2012) Schibsted ASA
* This file is part of Possom.
*
* Possom is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Possom 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Possom. If not, see <http://www.gnu.org/licenses/>.
*
* DataModelFactoryImpl.java
*
* Created on 27 January 2007, 22:49
*
*/
package no.sesat.search.datamodel;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Collections;
import no.sesat.commons.reflect.ConcurrentProxy;
import no.sesat.search.datamodel.access.ControlLevel;
import no.sesat.search.datamodel.generic.DataNode;
import no.sesat.search.datamodel.generic.DataObject;
import no.sesat.search.datamodel.generic.DataObject.Property;
import no.sesat.search.datamodel.generic.MapDataObjectSupport;
import org.apache.commons.beanutils.MappedPropertyDescriptor;
import org.apache.log4j.Logger;
/** Default implementation of the DataModelFactory.
*
*
* @version <tt>$Id$</tt>
*/
final class DataModelFactoryImpl extends DataModelFactory{
// Constants -----------------------------------------------------
private static final Logger LOG = Logger.getLogger(DataModelFactoryImpl.class);
private static final String ERR_ONLY_DATA_NODE_OR_OBJECT
= "DataModelFactory can only instantiate DataObject or DataNode classes";
private static final String ERR_ONLY_JAVA_BEAN_DATA_OBJECT
= "DataModelFactory can only instantiate DataObjects following a JavaBean pattern";
// Attributes ----------------------------------------------------
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
DataModelFactoryImpl(final Context cxt){
super(cxt);
}
// Public --------------------------------------------------------
@SuppressWarnings("unchecked")
public DataModel instantiate() {
try{
final Class<DataModel> cls = DataModel.class;
final PropertyDescriptor[] propDescriptors
= Introspector.getBeanInfo(DataModel.class).getPropertyDescriptors();
final Property[] properties = new Property[propDescriptors.length];
for(int i = 0; i < properties.length; ++i){
properties[i] = new Property(
propDescriptors[i].getName(),
propDescriptors[i] instanceof MappedPropertyDescriptor
? new MapDataObjectSupport(Collections.EMPTY_MAP)
: null);
}
final InvocationHandler handler = new BeanDataModelInvocationHandler(
new BeanDataModelInvocationHandler.PropertyInitialisor(DataModel.class, properties));
return (DataModel) ConcurrentProxy.newProxyInstance(cls.getClassLoader(), new Class[]{cls}, handler);
}catch(IntrospectionException ie){
throw new IllegalStateException("Need to introspect DataModel properties before instantiation");
}
}
@SuppressWarnings("unchecked")
public <T> T instantiate(final Class<T> cls, final DataModel datamodel, final Property... properties) {
try{
final InvocationHandler handler;
if(null != cls.getAnnotation(DataNode.class)){
handler = BeanDataNodeInvocationHandler.instanceOf(cls, datamodel, properties);
}else if(null != cls.getAnnotation(DataObject.class)){
handler = BeanDataObjectInvocationHandler.instanceOf(cls, properties);
}else{
throw new IllegalArgumentException(ERR_ONLY_DATA_NODE_OR_OBJECT);
}
return (T)ConcurrentProxy.newProxyInstance(cls.getClassLoader(), new Class[]{cls}, handler);
}catch(IntrospectionException ie){
throw new IllegalArgumentException(ERR_ONLY_JAVA_BEAN_DATA_OBJECT);
}
}
public DataModel assignControlLevel(final DataModel datamodel, final ControlLevel controlLevel){
final BeanDataModelInvocationHandler handler
= (BeanDataModelInvocationHandler) Proxy.getInvocationHandler(datamodel);
handler.setControlLevel(controlLevel);
return datamodel;
}
public ControlLevel currentControlLevel(final DataModel datamodel){
final BeanDataModelInvocationHandler handler
= (BeanDataModelInvocationHandler) Proxy.getInvocationHandler(datamodel);
return ((BeanDataModelInvocationHandler.DataModelBeanContextSupport)handler.context).getControlLevel();
}
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
// Private -------------------------------------------------------
// Inner classes -------------------------------------------------
}