/* 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/>. * * DataModelFactoryImplTest.java * * Created on 30 January 2007, 15:33 * */ package no.sesat.search.datamodel; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Properties; 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.site.Site; import no.sesat.search.site.SiteContext; import no.sesat.search.site.config.FileResourceLoader; import no.sesat.search.site.config.PropertiesLoader; import org.apache.commons.beanutils.MappedPropertyDescriptor; import org.apache.log4j.Logger; import org.testng.annotations.Test; /** Instantiate all the nodes and objects that exist in the datamodel. * * * @version <tt>$Id$</tt> */ public final class DataModelFactoryImplTest { // Constants ----------------------------------------------------- private static final Logger LOG = Logger.getLogger(DataModelFactoryImplTest.class); private static final String ASSERT_METHOD_NOT_GETTER_OR_SETTER = " is not either a getter or setter to this javaBean. Properties are "; // Attributes ---------------------------------------------------- private final DataModelFactory factory; private final DataModel datamodel; // Static -------------------------------------------------------- // Constructors -------------------------------------------------- /** Creates a new instance of DataModelTest */ public DataModelFactoryImplTest() { factory = new DataModelFactoryImpl(new DataModelFactory.Context(){ public Site getSite() { return Site.DEFAULT; } public PropertiesLoader newPropertiesLoader(final SiteContext siteCxt, final String resource, final Properties properties) { return FileResourceLoader.newPropertiesLoader(siteCxt, resource, properties); } }); datamodel = factory.instantiate(); } // Public -------------------------------------------------------- /** **/ @Test public void testInstantiateDataObjects() throws Exception{ LOG.info("testInstantiateDataObjects()"); scan(DataObject.class, DataModel.class, new Command(){ public void execute(Object... args) { try{ final Class<?> cls = (Class<?>)args[0]; testInstantiate(cls); }catch(IntrospectionException ie){ LOG.info(ie.getMessage(), ie); throw new RuntimeException(ie.getMessage(), ie); } } }); } /** * * @throws java.lang.Exception */ @Test public void testInstantiateDataNodes() throws Exception{ LOG.info("testInstantiateDataNodes()"); scan(DataNode.class, DataModel.class, new Command(){ public void execute(Object... args) { try{ final Class<?> cls = (Class<?>)args[0]; testInstantiate(cls); }catch(IntrospectionException ie){ LOG.info(ie.getMessage(), ie); throw new RuntimeException(ie.getMessage(), ie); } } }); } /** * * @throws java.lang.Exception */ @Test public void testDataObjectGetters() throws Exception{ LOG.info("testDataObjectGetters()"); scan(DataObject.class, DataModel.class, new Command(){ public void execute(Object... args) { try{ final Class<?> cls = (Class<?>)args[0]; final Object dataObject = testInstantiate(cls); final PropertyDescriptor[] properties = Introspector.getBeanInfo(cls).getPropertyDescriptors(); for(PropertyDescriptor property : properties){ if( null != property.getReadMethod() ){ final Object value = invoke(property.getReadMethod(), dataObject, new Object[0]); LOG.info(" Getter on " + property.getName() + " returned " + value); } if( property instanceof MappedPropertyDescriptor ){ final MappedPropertyDescriptor mappedProperty = (MappedPropertyDescriptor)property; if(null != mappedProperty.getReadMethod()){ final Object value = invoke(mappedProperty.getMappedReadMethod(), dataObject, ""); LOG.info(" Getter on " + mappedProperty.getName() + " returned " + value); } } } }catch(IntrospectionException ie){ LOG.info(ie.getMessage(), ie); throw new RuntimeException(ie.getMessage(), ie); } } }); } // Package protected --------------------------------------------- // Protected ----------------------------------------------------- // Private ------------------------------------------------------- private <T> T testInstantiate(final Class<T> cls) throws IntrospectionException{ LOG.info(" instantiating " + cls.getSimpleName()); final PropertyDescriptor[] properties = Introspector.getBeanInfo(cls).getPropertyDescriptors(); final Property[] props = new Property[properties.length]; for(int i = 0; i < props.length; ++i){ props[i] = new Property(properties[i].getName(), null); } final T data = factory.instantiate(cls, datamodel, props); assert null != data : "instantiate(" + cls.getSimpleName() + ", properties) returned null"; LOG.info(" instantiated .." + data.toString().replaceFirst("no.sesat.search.datamodel", "")); return data; } private void scan( final Class<? extends Annotation> type, final Class<?> cls, final Command command) throws IntrospectionException{ LOG.info("scanning " + cls.getSimpleName()); final PropertyDescriptor[] properties = Introspector.getBeanInfo(cls).getPropertyDescriptors(); for(PropertyDescriptor property : properties){ final Class<?> propCls = property instanceof MappedPropertyDescriptor ? ((MappedPropertyDescriptor)property).getMappedPropertyType() : property.getPropertyType(); LOG.info(" checking property " + property.getName() + " [" + propCls.getSimpleName() + ']'); if(null != propCls.getAnnotation(type)){ command.execute(propCls); } if(null != propCls.getAnnotation(DataNode.class)){ // also descend down dataNodes in the datamodel scan(type, propCls, command); } } // repeat again on all implemented interfaces for(Class<?> c : cls.getInterfaces()){ scan(type, c, command); } } /** Calls the method.invoke(..) wrapping any thrown exceptions with a RuntimeException. **/ private Object invoke(final Method method, final Object dataObject, final Object... args){ try{ return method.invoke(dataObject, args); }catch(IllegalAccessException iae){ LOG.error(iae.getMessage(), iae); throw new RuntimeException(iae.getMessage(), iae); }catch(IllegalArgumentException iae){ LOG.info(iae.getMessage(), iae); throw new RuntimeException(iae.getMessage(), iae); }catch(InvocationTargetException ite){ LOG.info(ite.getMessage(), ite); throw new RuntimeException(ite.getMessage(), ite); } } // Inner classes ------------------------------------------------- private interface Command{ void execute(Object... args); } }