/* Copyright 2008 Edward Yakop. * * Licensed 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.qi4j.library.struts2; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.inject.Inject; import java.util.HashMap; import java.util.Map; import org.apache.struts2.util.ObjectFactoryDestroyable; import org.qi4j.api.common.ConstructionException; import org.qi4j.api.composite.NoSuchTransientException; import org.qi4j.api.composite.TransientBuilderFactory; import org.qi4j.api.object.NoSuchObjectException; import org.qi4j.api.object.ObjectFactory; import static org.qi4j.library.struts2.Qi4jObjectFactory.ClassType.*; /** * Qi4j implementation of struts object factory. */ public class Qi4jObjectFactory extends com.opensymphony.xwork2.ObjectFactory implements ObjectFactoryDestroyable { private static final long serialVersionUID = 1L; static enum ClassType { qi4jComposite, qi4jObject, object } private final Map<Class, ClassType> types; private ObjectFactory objectFactory; private TransientBuilderFactory compositeBuilderFactory; public Qi4jObjectFactory() { types = new HashMap<Class, ClassType>(); } @Inject public void setObjectFactory( ObjectFactory objectFactory ) { this.objectFactory = objectFactory; } @Inject public void setCompositeBuilderFactory( TransientBuilderFactory compositeBuilderFactory ) { this.compositeBuilderFactory = compositeBuilderFactory; } /** * Build a generic Java object of the given type. * * @param classType Type of Object to build * @param extraContext A map of extra context which uses the same keys as the {@link ActionContext} */ @Override @SuppressWarnings( "unchecked" ) public Object buildBean( Class classType, Map extraContext ) throws Exception { // TODO: What to do with extraContext ClassType type = types.get( classType ); if( type != null ) { switch( type ) { case object: return createStandardObject( classType, false ); case qi4jComposite: return createQi4jComposite( classType, false ); case qi4jObject: return createQi4jObject( classType, false ); } } // Figure out what kind of object is this. Object object = createQi4jComposite( classType, true ); if( object == null ) { object = createQi4jObject( classType, true ); if( object == null ) { object = createStandardObject( classType, true ); } } return object; } private Object createStandardObject( Class aClass, boolean isAddToTypes ) throws Exception { Object obj = null; Exception exception = null; try { obj = aClass.newInstance(); } catch( InstantiationException e ) { exception = e; } catch( IllegalAccessException e ) { exception = e; } if( isAddToTypes ) { addToType( aClass, object ); } if( exception != null ) { throw exception; } return obj; } @SuppressWarnings( "unchecked" ) private Object createQi4jObject( Class aClass, boolean isAddToTypes ) { if( objectFactory == null ) { return null; } ConstructionException exception = null; Object obj = null; try { obj = objectFactory.newObject( aClass ); } catch( NoSuchObjectException e ) { return null; } catch( ConstructionException e ) { exception = e; } if( isAddToTypes ) { addToType( aClass, qi4jObject ); } if( exception != null ) { throw exception; } return obj; } @SuppressWarnings( "unchecked" ) private Object createQi4jComposite( Class aClass, boolean isAddToTypes ) { if( compositeBuilderFactory == null ) { return null; } Object obj = null; ConstructionException exception = null; try { obj = compositeBuilderFactory.newTransient( aClass ); } catch( NoSuchTransientException e ) { return null; } catch( ConstructionException e ) { exception = e; } if( isAddToTypes ) { addToType( aClass, qi4jComposite ); } if( exception != null ) { throw exception; } return obj; } private void addToType( Class aClass, ClassType aClassType ) { synchronized( types ) { types.put( aClass, aClassType ); } } /** * Allows for ObjectFactory implementations that support Actions without no-arg constructors. * * @return {@code false}. */ @Override public boolean isNoArgConstructorRequired() { return false; } @Override public final void destroy() { types.clear(); } }