Package org.qi4j.runtime.composite

Source Code of org.qi4j.runtime.composite.MixinModel

/*
* Copyright (c) 2008, Rickard Öberg. 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.runtime.composite;

import org.qi4j.api.common.ConstructionException;
import org.qi4j.api.composite.Composite;
import org.qi4j.api.composite.CompositeInstance;
import org.qi4j.api.composite.InvalidCompositeException;
import org.qi4j.api.injection.scope.This;
import org.qi4j.api.mixin.Initializable;
import org.qi4j.api.mixin.InitializationException;
import org.qi4j.api.mixin.MixinDescriptor;
import org.qi4j.api.property.StateHolder;
import org.qi4j.api.service.Activatable;
import org.qi4j.functional.HierarchicalVisitor;
import org.qi4j.functional.Iterables;
import org.qi4j.functional.Specification;
import org.qi4j.functional.VisitableHierarchy;
import org.qi4j.runtime.bootstrap.AssemblyHelper;
import org.qi4j.runtime.injection.DependencyModel;
import org.qi4j.runtime.injection.InjectedFieldsModel;
import org.qi4j.runtime.injection.InjectedMethodsModel;
import org.qi4j.runtime.injection.InjectionContext;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static org.qi4j.functional.Iterables.map;
import static org.qi4j.functional.Iterables.unique;

/**
* JAVADOC
*/
public final class MixinModel
    implements MixinDescriptor, VisitableHierarchy<Object, Object>
{
    private final Class mixinClass;
    private final Class instantiationClass;
    private final ConstructorsModel constructorsModel;
    private final InjectedFieldsModel injectedFieldsModel;
    private final InjectedMethodsModel injectedMethodsModel;
    private final Iterable<Class<?>> thisMixinTypes;

    public MixinModel( Class declaredMixinClass, Class instantiationClass )
    {
        injectedFieldsModel = new InjectedFieldsModel( declaredMixinClass );
        injectedMethodsModel = new InjectedMethodsModel( declaredMixinClass );

        this.mixinClass = declaredMixinClass;
        this.instantiationClass = instantiationClass;
        constructorsModel = new ConstructorsModel( instantiationClass );

        thisMixinTypes = buildThisMixinTypes();
    }

    public Class mixinClass()
    {
        return mixinClass;
    }

    public Class instantiationClass()
    {
        return instantiationClass;
    }

    public boolean isGeneric()
    {
        return InvocationHandler.class.isAssignableFrom( mixinClass );
    }

    public Iterable<DependencyModel> dependencies()
    {
        return Iterables.flatten( constructorsModel.dependencies(), injectedFieldsModel.dependencies(), injectedMethodsModel.dependencies() );
    }

    @Override
    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor ) throws ThrowableType
    {
        if (visitor.visitEnter( this ))
        {
            if (constructorsModel.accept( visitor ))
                if (injectedFieldsModel.accept( visitor ))
                    injectedMethodsModel.accept( visitor );
        }
        return visitor.visitLeave( this );
    }

    // Context
    public Object newInstance( CompositeInstance compositeInstance, StateHolder state, UsesInstance uses )
    {
        InjectionContext injectionContext = new InjectionContext( compositeInstance, uses, state );
        return newInstance( injectionContext );
    }

    public Object newInstance( InjectionContext injectionContext )
    {
        Object mixin;
        CompositeInstance compositeInstance = injectionContext.compositeInstance();

        mixin = constructorsModel.newInstance( injectionContext );

        if( FragmentClassLoader.isGenerated( instantiationClass ) )
        {
            try
            {
                instantiationClass.getDeclaredField( "_instance" ).set( mixin,
                                                                        injectionContext.compositeInstance() );
            }
            catch( IllegalAccessException e )
            {
                e.printStackTrace();
            }
            catch( NoSuchFieldException e )
            {
                e.printStackTrace();
            }
        }

        injectedFieldsModel.inject( injectionContext, mixin );
        injectedMethodsModel.inject( injectionContext, mixin );
        if( mixin instanceof Initializable )
        {
            try
            {
                ( (Initializable) mixin ).initialize();
            }
            catch( InitializationException e )
            {
                Class<?> compositeType = compositeInstance.type();
                String message = "Unable to initialize " + mixinClass + " in composite " + compositeType;
                throw new ConstructionException( message, e );
            }
        }
        return mixin;
    }

    public Iterable<Class<?>> thisMixinTypes()
    {
        return thisMixinTypes;
    }

    private Iterable<Class<?>> buildThisMixinTypes()
    {
        return map( new DependencyModel.InjectionTypeFunction(), unique( Iterables.filter( new DependencyModel.ScopeSpecification( This.class ), dependencies() ) ) );
    }

    protected FragmentInvocationHandler newInvocationHandler( Method method )
    {
        if( InvocationHandler.class.isAssignableFrom( mixinClass )
            && !method.getDeclaringClass().isAssignableFrom( mixinClass ) )
        {
            return new GenericFragmentInvocationHandler();
        }
        else
        {
            return new TypedModifierInvocationHandler();
        }
    }

    @Override
    public String toString()
    {
        return mixinClass.getName();
    }

    public void activate( Object mixin )
        throws Exception
    {
        if( mixin instanceof Activatable )
        {
            ( (Activatable) mixin ).activate();
        }
    }

    public void passivate( Object mixin )
        throws Exception
    {
        if( mixin instanceof Activatable )
        {
            ( (Activatable) mixin ).passivate();
        }
    }
}
TOP

Related Classes of org.qi4j.runtime.composite.MixinModel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.