/* * Copyright 2008 Niclas Hedhman. All rights Reserved. * * 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.beans.support; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.UndeclaredThrowableException; import java.util.Arrays; import java.util.List; import org.qi4j.api.composite.TransientBuilder; import org.qi4j.api.composite.TransientBuilderFactory; import org.qi4j.api.property.ComputedPropertyInstance; public class JavabeanProperty extends ComputedPropertyInstance { private Method pojoMethod; private JavabeanMixin javabeanMixin; public JavabeanProperty( JavabeanMixin javabeanMixin, Method qi4jPropertyMethod ) { super( qi4jPropertyMethod ); this.javabeanMixin = javabeanMixin; } public Object get() { try { Object resultObject = pojoMethod.invoke( javabeanMixin.pojo ); return wrap( javabeanMixin.cbf, resultObject ); } catch( IllegalAccessException e ) { throw new IllegalArgumentException( "POJO is not compatible with JavaBeans specification. Method must be public: " + pojoMethod ); } catch( InvocationTargetException e ) { throw new UndeclaredThrowableException( e.getTargetException() ); } } private Object wrap( TransientBuilderFactory factory, Object resultObject ) { if( resultObject == null ) { return null; } Type type = type(); if( type instanceof Class ) { Class clazz = (Class) type; if( clazz.isInterface() ) { if( clazz.equals( List.class ) ) { if( resultObject.getClass().isArray() ) { resultObject = Arrays.asList( (Object[]) resultObject ); } } if( clazz.isArray() ) { if( List.class.isAssignableFrom( resultObject.getClass() ) ) { resultObject = ( (List) resultObject ).toArray(); } } TransientBuilder<?> builder = factory.newTransientBuilder( clazz ); builder.use( resultObject ); return builder.newInstance(); } } if( type instanceof ParameterizedType ) { if( !resultObject.getClass().equals( type ) ) { ParameterizedType paramtype = (ParameterizedType) type; Type rawType = paramtype.getRawType(); Type actType = paramtype.getActualTypeArguments()[ 0 ]; if( List.class.isAssignableFrom( (Class<?>) rawType ) ) { if( !( actType instanceof Class ) || ( (Class) actType ).isInstance( resultObject ) ) { String message = "The type " + paramtype + " is not compatible with " + resultObject.getClass(); throw new IllegalArgumentException( message ); } if( resultObject.getClass().isArray() ) { resultObject = Arrays.asList( (Object[]) resultObject ); } } } } return resultObject; } void setPojoMethod( Method pojoMethod ) { this.pojoMethod = pojoMethod; } }