polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject [10/81] [abbrv] [partial] zest-java git commit: ZEST-195 ; Replace all "zest" with "polygene"
Date Sat, 17 Dec 2016 10:27:46 GMT
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityMixinsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityMixinsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityMixinsModel.java
new file mode 100644
index 0000000..6993b6f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityMixinsModel.java
@@ -0,0 +1,117 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.entity;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.entity.Lifecycle;
+import org.apache.polygene.api.entity.LifecycleException;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.runtime.composite.MixinModel;
+import org.apache.polygene.runtime.composite.MixinsModel;
+import org.apache.polygene.runtime.composite.UsesInstance;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class EntityMixinsModel
+    extends MixinsModel
+{
+    List<Integer> lifecycleMixins;
+
+    @Override
+    public void bind( Resolution resolution )
+        throws BindingException
+    {
+        super.bind( resolution );
+
+        // Find what mixins implement Lifecycle
+        for( int i = 0; i < mixinModels.size(); i++ )
+        {
+            MixinModel mixinModel = mixinModels.get( i );
+            if( Lifecycle.class.isAssignableFrom( mixinModel.mixinClass() ) )
+            {
+                if( lifecycleMixins == null )
+                {
+                    lifecycleMixins = new ArrayList<Integer>();
+                }
+
+                lifecycleMixins.add( i );
+            }
+        }
+    }
+
+    public Object newMixin( EntityInstance entityInstance, StateHolder state, Object[] mixins, Method method )
+    {
+        MixinModel model = methodImplementation.get( method );
+        InjectionContext injectionContext = new InjectionContext( entityInstance, UsesInstance.EMPTY_USES, state );
+        Object mixin = model.newInstance( injectionContext );
+        mixins[ methodIndex.get( method ) ] = mixin;
+        return mixin;
+    }
+
+    public void invokeLifecycle( boolean create, Object[] mixins, CompositeInstance instance, StateHolder state )
+    {
+        if( lifecycleMixins != null )
+        {
+            InjectionContext injectionContext = new InjectionContext( instance, UsesInstance.EMPTY_USES, state );
+            for( Integer lifecycleMixin : lifecycleMixins )
+            {
+                Lifecycle lifecycle = (Lifecycle) mixins[ lifecycleMixin ];
+
+                if( lifecycle == null )
+                {
+                    lifecycle = (Lifecycle) mixinModels.get( lifecycleMixin ).newInstance( injectionContext );
+                }
+
+                if( create )
+                {
+                    try
+                    {
+                        lifecycle.create();
+                    }
+                    catch( Exception ex )
+                    {
+                        String message = "Unable to invoke create lifecycle on " + lifecycle;
+                        throw new LifecycleException( message, ex );
+                    }
+                }
+                else
+                {
+                    try
+                    {
+                        lifecycle.remove();
+                    }
+                    catch( Exception ex )
+                    {
+                        String message = "Unable to invoke remove lifecycle on " + lifecycle;
+                        throw new LifecycleException( message, ex );
+                    }
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityModel.java
new file mode 100644
index 0000000..4fd073d
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityModel.java
@@ -0,0 +1,158 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.entity;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.unitofwork.EntityCompositeAlreadyExistsException;
+import org.apache.polygene.api.util.Annotations;
+import org.apache.polygene.runtime.composite.CompositeMethodsModel;
+import org.apache.polygene.runtime.composite.CompositeModel;
+import org.apache.polygene.runtime.unitofwork.ModuleUnitOfWork;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entitystore.EntityAlreadyExistsException;
+import org.apache.polygene.spi.entitystore.EntityStoreException;
+import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
+import org.apache.polygene.spi.module.ModuleSpi;
+
+import static org.apache.polygene.api.identity.HasIdentity.IDENTITY_METHOD;
+
+/**
+ * JAVADOC
+ */
+public final class EntityModel extends CompositeModel
+    implements EntityDescriptor
+{
+
+    private final boolean queryable;
+
+    public EntityModel( ModuleDescriptor module,
+                        List<Class<?>> types,
+                        Visibility visibility,
+                        MetaInfo info,
+                        EntityMixinsModel mixinsModel,
+                        EntityStateModel stateModel,
+                        CompositeMethodsModel compositeMethodsModel
+    )
+    {
+        super( module, types, visibility, info, mixinsModel, stateModel, compositeMethodsModel );
+
+        this.queryable = types.stream()
+            .flatMap( Annotations.ANNOTATIONS_OF )
+            .filter( Annotations.isType( Queryable.class ) )
+            .map( annot -> ( (Queryable) annot ).value() )
+            .findFirst()
+            .orElse( true );
+    }
+
+    @Override
+    public boolean queryable()
+    {
+        return queryable;
+    }
+
+    @Override
+    public EntityStateModel state()
+    {
+        return (EntityStateModel) super.state();
+    }
+
+    public EntityInstance newInstance( ModuleUnitOfWork uow, ModuleSpi moduleInstance, EntityState state )
+    {
+        return new EntityInstance( uow, this, state );
+    }
+
+    public Object[] newMixinHolder()
+    {
+        return mixinsModel.newMixinHolder();
+    }
+
+    public Object newMixin( Object[] mixins,
+                            EntityStateInstance entityState,
+                            EntityInstance entityInstance,
+                            Method method
+    )
+    {
+        return ( (EntityMixinsModel) mixinsModel ).newMixin( entityInstance, entityState, mixins, method );
+    }
+
+    public EntityState newEntityState( EntityStoreUnitOfWork store, EntityReference reference )
+        throws ConstraintViolationException, EntityStoreException
+    {
+        try
+        {
+            // New EntityState
+            EntityState entityState = store.newEntityState( reference, this );
+
+            // Set reference property
+            PropertyDescriptor persistentPropertyDescriptor = state().propertyModelFor( IDENTITY_METHOD );
+            entityState.setPropertyValue( persistentPropertyDescriptor.qualifiedName(), reference.identity() );
+
+            return entityState;
+        }
+        catch( EntityAlreadyExistsException e )
+        {
+            throw new EntityCompositeAlreadyExistsException( reference );
+        }
+        catch( EntityStoreException e )
+        {
+            throw new ConstructionException( "Could not create new entity in store", e );
+        }
+    }
+
+    public void initState( ModuleDescriptor module, EntityState entityState )
+    {
+        // Set new properties to default value
+        state().properties().forEach( propertyDescriptor -> {
+            entityState.setPropertyValue( propertyDescriptor.qualifiedName(), propertyDescriptor.initialValue( module ) );
+        } );
+
+        // Set new associations to null
+        state().associations().forEach( associationDescriptor -> {
+            entityState.setAssociationValue( associationDescriptor.qualifiedName(), null );
+        } );
+
+        // Set new many-associations to empty
+        state().manyAssociations().forEach( associationDescriptor -> {
+            entityState.manyAssociationValueOf( associationDescriptor.qualifiedName() );
+        } );
+
+        // Set new named-associations to empty
+        state().namedAssociations().forEach( associationDescriptor -> {
+            entityState.namedAssociationValueOf( associationDescriptor.qualifiedName() );
+        } );
+    }
+
+    public void invokeLifecycle( boolean create, Object[] mixins, CompositeInstance instance, StateHolder state )
+    {
+        ( (EntityMixinsModel) mixinsModel ).invokeLifecycle( create, mixins, instance, state );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityPropertyInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityPropertyInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityPropertyInstance.java
new file mode 100644
index 0000000..2f57d9e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityPropertyInstance.java
@@ -0,0 +1,58 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.entity;
+
+import org.apache.polygene.runtime.property.PropertyInfo;
+import org.apache.polygene.runtime.property.PropertyInstance;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * {@code EntityPropertyInstance} represents a property whose value must be backed by an EntityState.
+ */
+public class EntityPropertyInstance<T>
+    extends PropertyInstance<T>
+{
+    private final EntityState entityState;
+
+    /**
+     * Construct an instance of {@code PropertyInstance} with the specified arguments.
+     *
+     * @param aPropertyInfo The property info. This argument must not be {@code null}.
+     * @param entityState EntityState
+     */
+    @SuppressWarnings( "unchecked" )
+    public EntityPropertyInstance( PropertyInfo aPropertyInfo, EntityState entityState )
+    {
+        super( aPropertyInfo, (T) entityState.propertyValueOf( aPropertyInfo.qualifiedName() ) );
+        this.entityState = entityState;
+    }
+
+    /**
+     * Sets this property value.
+     *
+     * @param aNewValue The new value.
+     */
+    @Override
+    public void set( T aNewValue )
+    {
+        super.set( aNewValue );
+        entityState.setPropertyValue( model.qualifiedName(), aNewValue );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateInstance.java
new file mode 100644
index 0000000..27660cc
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateInstance.java
@@ -0,0 +1,232 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.entity;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.runtime.association.AssociationInstance;
+import org.apache.polygene.runtime.association.AssociationModel;
+import org.apache.polygene.runtime.association.ManyAssociationInstance;
+import org.apache.polygene.runtime.association.ManyAssociationModel;
+import org.apache.polygene.runtime.association.NamedAssociationInstance;
+import org.apache.polygene.runtime.association.NamedAssociationModel;
+import org.apache.polygene.runtime.property.PropertyModel;
+import org.apache.polygene.runtime.unitofwork.BuilderEntityState;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * TODO
+ */
+public final class EntityStateInstance
+    implements AssociationStateHolder
+{
+    private Map<AccessibleObject, Object> state;
+
+    private final EntityStateModel stateModel;
+    private EntityState entityState;
+    private final BiFunction<EntityReference, Type, Object> entityFunction;
+
+    public EntityStateInstance( EntityStateModel stateModel, final UnitOfWork uow, EntityState entityState )
+    {
+        this.stateModel = stateModel;
+        this.entityState = entityState;
+
+        entityFunction = ( entityReference, type ) -> uow.get( Classes.RAW_CLASS.apply( type ), entityReference.identity() );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> Property<T> propertyFor( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        Map<AccessibleObject, Object> state = state();
+
+        Property<T> property = (Property<T>) state.get( accessor );
+
+        if( property == null )
+        {
+            PropertyModel entityPropertyModel = stateModel.propertyModelFor( accessor );
+            property = new EntityPropertyInstance<>(
+                entityState instanceof BuilderEntityState
+                ? entityPropertyModel.getBuilderInfo()
+                : entityPropertyModel,
+                entityState );
+            state.put( accessor, property );
+        }
+
+        return property;
+    }
+
+    @Override
+    public Stream<Property<?>> properties()
+    {
+        return stateModel.properties().map( descriptor -> propertyFor( descriptor.accessor() ) );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> Association<T> associationFor( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        Map<AccessibleObject, Object> state = state();
+        Association<T> association = (Association<T>) state.get( accessor );
+
+        if( association == null )
+        {
+            final AssociationModel associationModel = stateModel.getAssociation( accessor );
+            association = new AssociationInstance<>(
+                entityState instanceof BuilderEntityState
+                ? associationModel.getBuilderInfo()
+                : associationModel,
+                entityFunction,
+                new Property<EntityReference>()
+                {
+                    @Override
+                    public EntityReference get()
+                    {
+                        return entityState.associationValueOf( associationModel.qualifiedName() );
+                    }
+
+                    @Override
+                    public void set( EntityReference newValue )
+                        throws IllegalArgumentException, IllegalStateException
+                    {
+                        entityState.setAssociationValue( associationModel.qualifiedName(), newValue );
+                    }
+                } );
+            state.put( accessor, association );
+        }
+
+        return association;
+    }
+
+    @Override
+    public Stream<? extends Association<?>> allAssociations()
+    {
+        return stateModel.associations().map( descriptor -> associationFor( descriptor.accessor() ) );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> ManyAssociation<T> manyAssociationFor( AccessibleObject accessor )
+    {
+        Map<AccessibleObject, Object> state = state();
+
+        ManyAssociation<T> manyAssociation = (ManyAssociation<T>) state.get( accessor );
+
+        if( manyAssociation == null )
+        {
+            ManyAssociationModel associationModel = stateModel.getManyAssociation( accessor );
+            manyAssociation = new ManyAssociationInstance<>(
+                entityState instanceof BuilderEntityState
+                ? associationModel.getBuilderInfo()
+                : associationModel,
+                entityFunction,
+                entityState.manyAssociationValueOf( associationModel.qualifiedName() ) );
+            state.put( accessor, manyAssociation );
+        }
+
+        return manyAssociation;
+    }
+
+    @Override
+    public Stream<ManyAssociation<?>> allManyAssociations()
+    {
+        return stateModel.manyAssociations().map( descriptor -> manyAssociationFor( descriptor.accessor() ) );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> NamedAssociation<T> namedAssociationFor( AccessibleObject accessor )
+    {
+        Map<AccessibleObject, Object> state = state();
+
+        NamedAssociation<T> namedAssociation = (NamedAssociation<T>) state.get( accessor );
+
+        if( namedAssociation == null )
+        {
+            NamedAssociationModel associationModel = stateModel.getNamedAssociation( accessor );
+            namedAssociation = new NamedAssociationInstance<>(
+                entityState instanceof BuilderEntityState
+                ? associationModel.getBuilderInfo()
+                : associationModel,
+                entityFunction,
+                entityState.namedAssociationValueOf( associationModel.qualifiedName() ) );
+            state.put( accessor, namedAssociation );
+        }
+
+        return namedAssociation;
+    }
+
+    @Override
+    public Stream<? extends NamedAssociation<?>> allNamedAssociations()
+    {
+        return stateModel.namedAssociations().map( descriptor -> namedAssociationFor( descriptor.accessor() ) );
+    }
+
+    public void checkConstraints()
+    {
+        stateModel.properties().forEach( propertyDescriptor -> {
+            Property<Object> property = this.propertyFor( propertyDescriptor.accessor() );
+            propertyDescriptor.checkConstraints( property.get() );
+        } );
+
+        stateModel.associations().forEach( associationDescriptor -> {
+            Association<Object> association = this.associationFor( associationDescriptor.accessor() );
+            associationDescriptor.checkConstraints( association.get() );
+        } );
+
+        // TODO Should ManyAssociations and NamedAssociations be checked too?
+    }
+
+    private Map<AccessibleObject, Object> state()
+    {
+        if( state == null )
+        {
+            state = new HashMap<>();
+        }
+
+        return state;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "EntityState[" + state.entrySet().stream()
+            .map( entry -> ((Method) entry.getKey()).getName() + "=" + entry.getValue())
+            .collect( Collectors.joining("\n  ", "  ", "\n") )
+            + "]"
+            ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateModel.java
new file mode 100644
index 0000000..7601b4e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/entity/EntityStateModel.java
@@ -0,0 +1,158 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.entity;
+
+import java.lang.reflect.AccessibleObject;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateDescriptor;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.association.AssociationModel;
+import org.apache.polygene.runtime.association.AssociationsModel;
+import org.apache.polygene.runtime.association.ManyAssociationModel;
+import org.apache.polygene.runtime.association.ManyAssociationsModel;
+import org.apache.polygene.runtime.association.NamedAssociationModel;
+import org.apache.polygene.runtime.association.NamedAssociationsModel;
+import org.apache.polygene.runtime.composite.StateModel;
+import org.apache.polygene.runtime.property.PropertiesModel;
+
+/**
+ * Model for EntityComposite state.
+ */
+public final class EntityStateModel
+    extends StateModel
+    implements AssociationStateDescriptor
+{
+    private final AssociationsModel associationsModel;
+    private final ManyAssociationsModel manyAssociationsModel;
+    private final NamedAssociationsModel namedAssociationsModel;
+
+    public EntityStateModel( PropertiesModel propertiesModel,
+                             AssociationsModel associationsModel,
+                             ManyAssociationsModel manyAssociationsModel,
+                             NamedAssociationsModel namedAssociationsModel )
+    {
+        super( propertiesModel );
+        this.associationsModel = associationsModel;
+        this.manyAssociationsModel = manyAssociationsModel;
+        this.namedAssociationsModel = namedAssociationsModel;
+    }
+
+    public AssociationModel getAssociation( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        return associationsModel.getAssociation( accessor );
+    }
+
+    @Override
+    public AssociationDescriptor getAssociationByName( String name )
+        throws IllegalArgumentException
+    {
+        return associationsModel.getAssociationByName( name );
+    }
+
+    @Override
+    public AssociationDescriptor getAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        return associationsModel.getAssociationByQualifiedName( name );
+    }
+
+    public ManyAssociationModel getManyAssociation( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        return manyAssociationsModel.getManyAssociation( accessor );
+    }
+
+    @Override
+    public AssociationDescriptor getManyAssociationByName( String name )
+        throws IllegalArgumentException
+    {
+        return manyAssociationsModel.getManyAssociationByName( name );
+    }
+
+    @Override
+    public AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        return manyAssociationsModel.getManyAssociationByQualifiedName( name );
+    }
+
+    public NamedAssociationModel getNamedAssociation( AccessibleObject accessor )
+        throws IllegalArgumentException
+    {
+        return namedAssociationsModel.getNamedAssociation( accessor );
+    }
+
+    @Override
+    public AssociationDescriptor getNamedAssociationByName( String name )
+        throws IllegalArgumentException
+    {
+        return namedAssociationsModel.getNamedAssociationByName( name );
+    }
+
+    @Override
+    public AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        return namedAssociationsModel.getNamedAssociationByQualifiedName( name );
+    }
+
+    @Override
+    public Stream<AssociationModel> associations()
+    {
+        return associationsModel.associations();
+    }
+
+    @Override
+    public Stream<ManyAssociationModel> manyAssociations()
+    {
+        return manyAssociationsModel.manyAssociations();
+    }
+
+    @Override
+    public Stream<NamedAssociationModel> namedAssociations()
+    {
+        return namedAssociationsModel.namedAssociations();
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            if( ( (VisitableHierarchy<Object, Object>) propertiesModel ).accept( visitor ) )
+            {
+                if( ( (VisitableHierarchy<AssociationsModel, AssociationModel>) associationsModel ).accept( visitor ) )
+                {
+                    if( ( (VisitableHierarchy<ManyAssociationsModel, ManyAssociationModel>) manyAssociationsModel ).accept( visitor ) )
+                    {
+                        ( (VisitableHierarchy<NamedAssociationsModel, NamedAssociationModel>) namedAssociationsModel ).accept( visitor );
+                    }
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/Dependencies.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/Dependencies.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/Dependencies.java
new file mode 100644
index 0000000..31d8b75
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/Dependencies.java
@@ -0,0 +1,33 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.injection;
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+/**
+ * TODO
+ */
+public interface Dependencies
+{
+    Function<Dependencies, Stream<DependencyModel>> DEPENDENCIES_FUNCTION = Dependencies::dependencies;
+
+    Stream<DependencyModel> dependencies();
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/DependencyModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/DependencyModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/DependencyModel.java
new file mode 100644
index 0000000..0c72658
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/DependencyModel.java
@@ -0,0 +1,421 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.injection;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.DependencyDescriptor;
+import org.apache.polygene.api.util.Visitable;
+import org.apache.polygene.api.util.Visitor;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.provider.CachingInjectionProviderDecorator;
+import org.apache.polygene.runtime.injection.provider.InjectionProviderException;
+import org.apache.polygene.runtime.injection.provider.ServiceInjectionProviderFactory;
+import org.apache.polygene.runtime.model.Binder;
+import org.apache.polygene.runtime.model.Resolution;
+
+import static org.apache.polygene.api.util.Annotations.isType;
+
+/**
+ * JAVADOC
+ * move all the extraction code to a TypeUtils class
+ */
+public final class DependencyModel
+    implements Binder, DependencyDescriptor, Visitable<DependencyModel>
+{
+    public static boolean isOptional( Annotation injectionAnnotation, Annotation[] annotations )
+    {
+        if( Stream.of( annotations ).anyMatch( isType( Optional.class ) ) )
+        {
+            return true;
+        }
+
+        Method[] methods = injectionAnnotation.annotationType().getMethods();
+        for( Method method : methods )
+        {
+            if( method.getName().equals( "optional" ) )
+            {
+                try
+                {
+                    return (Boolean) method.invoke( injectionAnnotation );
+                }
+                catch( Throwable e )
+                {
+                    return false;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    // Model
+    private final Annotation injectionAnnotation;
+    private final Type injectionType;
+    private final Class<?> injectedClass;
+    private final Class<?> rawInjectionClass;
+    private final boolean optional;
+    private final Annotation[] annotations;
+
+    // Binding
+    private InjectionProvider injectionProvider;
+
+    public DependencyModel( Annotation injectionAnnotation,
+                            Type genericType,
+                            Class<?> injectedClass,
+                            boolean optional,
+                            Annotation[] annotations
+    )
+    {
+        this.injectionAnnotation = injectionAnnotation;
+        this.injectedClass = injectedClass;
+
+        this.injectionType = genericType;
+        this.optional = optional;
+        this.annotations = annotations;
+        this.rawInjectionClass = mapPrimitiveTypes( extractRawInjectionClass( injectedClass, injectionType ) );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( Visitor<? super DependencyModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        return visitor.visit( this );
+    }
+
+    private Class<?> extractRawInjectionClass( Class<?> injectedClass, final Type injectionType )
+    {
+        // Calculate raw injection type
+        if( injectionType instanceof Class )
+        {
+            return (Class<?>) injectionType;
+        }
+        else if( injectionType instanceof ParameterizedType )
+        {
+            return (Class<?>) ( (ParameterizedType) injectionType ).getRawType();
+        }
+        else if( injectionType instanceof TypeVariable )
+        {
+            return extractRawInjectionClass( injectedClass, (TypeVariable<?>) injectionType );
+        }
+        throw new IllegalArgumentException(
+            "Could not extract the rawInjectionClass of " + injectedClass + " and " + injectionType );
+    }
+
+    private Class<?> extractRawInjectionClass( Class<?> injectedClass, TypeVariable<?> injectionTypeVariable )
+    {
+        int index = 0;
+        for( TypeVariable<?> typeVariable : injectionTypeVariable.getGenericDeclaration().getTypeParameters() )
+        {
+            if( injectionTypeVariable.getName().equals( typeVariable.getName() ) )
+            {
+                return (Class<?>) getActualType( injectedClass, index );
+            }
+            index++;
+        }
+        throw new IllegalArgumentException(
+            "Could not extract the rawInjectionClass of " + injectedClass + " and " + injectionTypeVariable );
+    }
+
+    // todo continue refactoring
+
+    private Type getActualType( Class<?> injectedClass, int index )
+    {
+        // Type index found - map it to actual type
+        Type genericType = injectedClass;
+        Type type = null;
+
+        while( !Object.class.equals( genericType ) && type == null )
+        {
+            genericType = ( (Class<?>) genericType ).getGenericSuperclass();
+            if( genericType instanceof ParameterizedType )
+            {
+                type = ( (ParameterizedType) genericType ).getActualTypeArguments()[ index ];
+            }
+            else
+            {
+                Type[] genericInterfaces = ( (Class<?>) genericType ).getGenericInterfaces();
+                if( genericInterfaces.length > index )
+                {
+                    type = genericInterfaces[ index ];
+                    if( type instanceof ParameterizedType )
+                    {
+                        type = ( (ParameterizedType) type ).getActualTypeArguments()[ index ];
+                    }
+                    // TODO type may still be one of the generic interfaces???
+                }
+            }
+        }
+
+        if( type == null )
+        {
+            type = Object.class; // Generic type with no constraints so Object is fine
+        }
+
+        return type;
+    }
+
+    // FIXME This method is unused, remove it.
+    private Type extractDependencyType( Type injectionType )
+    {
+        if( injectionType instanceof ParameterizedType )
+        {
+            return ( (ParameterizedType) injectionType ).getActualTypeArguments()[ 0 ];
+        }
+        else if( injectionType instanceof TypeVariable )
+        {
+            return ( (TypeVariable) injectionType ).getBounds()[ 0 ];
+        }
+        return injectionType;
+    }
+
+    // Model
+    @Override
+    public Annotation injectionAnnotation()
+    {
+        return injectionAnnotation;
+    }
+
+    @Override
+    public Type injectionType()
+    {
+        return injectionType;
+    }
+
+    @Override
+    public Class<?> injectedClass()
+    {
+        return injectedClass;
+    }
+
+    /**
+     * Get the raw dependency type.
+     * <p>
+     * If the dependency uses generics this is the raw type,
+     * and otherwise it is the type of the field.
+     * <p>
+     * Examples:
+     * <p>
+     * {@code @Service MyService service} -&gt; MyService
+     * <p>
+     * {@code @Entity Iterable<Foo> fooList} -&gt; Iterable
+     * <p>
+     * {@code @Entity Query<Foo> fooQuery} -&gt; Query
+     *
+     * @return raw injection type.
+     */
+    @Override
+    public Class<?> rawInjectionType()
+    {
+        return rawInjectionClass;
+    }
+
+    @Override
+    public boolean optional()
+    {
+        return optional;
+    }
+
+    @Override
+    public Annotation[] annotations()
+    {
+        return annotations;
+    }
+
+    @Override
+    public void bind( Resolution resolution )
+        throws BindingException
+    {
+        InjectionProviderFactory providerFactory = resolution.application().injectionProviderFactory();
+
+        try
+        {
+            injectionProvider = providerFactory.newInjectionProvider( resolution, this );
+
+            if( injectionProvider == null && !optional )
+            {
+                String message =
+                    "[Module " + resolution.module()
+                        .name() + "] Non-optional @" + rawInjectionClass.getName() + " was not bound in " + injectedClass
+                        .getName();
+                throw new ConstructionException( message );
+            }
+        }
+        catch( InvalidInjectionException e )
+        {
+            throw new BindingException( "Could not bind dependency injection", e );
+        }
+    }
+
+    // Context
+    public Object inject( InjectionContext context )
+    {
+        if( injectionProvider == null )
+        {
+            return null;
+        }
+        Object injectedValue;
+        try
+        {
+            injectedValue = injectionProvider.provideInjection( context );
+        }
+        catch( InjectionProviderException e )
+        {
+            Throwable ex = e;
+            if( ex.getCause() != null )
+            {
+                ex = ex.getCause();
+            }
+
+            String message = "[Module " + context.module().name() + "] InjectionProvider unable to resolve @" +
+                             injectionAnnotation.annotationType().getSimpleName() + " " + injectionType.toString();
+            throw new ConstructionException( message, ex );
+        }
+        if( injectedValue == null && !optional )
+        {
+            String simpleName = injectionAnnotation.annotationType().getSimpleName();
+            String message = "[Module " + context.module().name() + "] Non-optional @" +
+                             simpleName + " " + injectionType.toString() +
+                             " was null in " + injectedClass.getName();
+            if( simpleName.toLowerCase().contains( "service" )
+                && !isServiceInjectionProvider() )
+            {
+                message = message + ". Did you mean the @Service injection scope?";
+            }
+            throw new ConstructionException( message );
+        }
+        return getInjectedValue( injectedValue );
+    }
+
+    private boolean isServiceInjectionProvider()
+    {
+
+        InjectionProvider provider = this.injectionProvider;
+        if( provider instanceof CachingInjectionProviderDecorator ){
+            provider = ((CachingInjectionProviderDecorator) provider ).decoratedProvider();
+        }
+        return ServiceInjectionProviderFactory.ServiceInjectionProvider.class.isAssignableFrom( provider.getClass() );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Object getInjectedValue( Object injectionResult )
+    {
+        if( injectionResult == null )
+        {
+            return null;
+        }
+
+        if( injectionResult instanceof Iterable )
+        {
+            if( Iterable.class.isAssignableFrom( rawInjectionClass )
+                || rawInjectionClass.isInstance( injectionResult ) )
+            {
+                return injectionResult;
+            }
+            else
+            {
+                Iterator iterator = ( (Iterable) injectionResult ).iterator();
+                return iterator.hasNext() ? iterator.next() : null;
+            }
+        }
+        else
+        {
+            if( Iterable.class.equals( injectionType ) )
+            {
+                return Collections.singleton( injectionResult );
+            }
+        }
+        return injectionResult;
+    }
+
+    private final static Class<?>[] primitiveTypeMapping = {
+        boolean.class, Boolean.class,
+        byte.class, Byte.class,
+        short.class, Short.class,
+        char.class, Character.class,
+        long.class, Long.class,
+        double.class, Double.class,
+        float.class, Float.class,
+        int.class, Integer.class,
+        };
+
+    private Class<?> mapPrimitiveTypes( Class<?> rawInjectionType )
+    {
+        if( rawInjectionType == null || !rawInjectionType.isPrimitive() )
+        {
+            return rawInjectionType;
+        }
+        for( int i = 0; i < primitiveTypeMapping.length; i += 2 )
+        {
+            if( primitiveTypeMapping[ i ].equals( rawInjectionType ) )
+            {
+                return primitiveTypeMapping[ i + 1 ];
+            }
+        }
+        return rawInjectionType;
+    }
+
+    public boolean hasScope( final Class<? extends Annotation> scope )
+    {
+        return scope == null || scope.equals( injectionAnnotation().annotationType() );
+    }
+
+    public Class<? extends Annotation> injectionAnnotationType()
+    {
+        if( injectionAnnotation == null )
+        {
+            return null;
+        }
+        return injectionAnnotation.annotationType();
+    }
+
+    @Override
+    public String toString()
+    {
+        return injectionAnnotation + " for " + injectionType + " in " + injectedClass.getName();
+    }
+
+    public static class ScopeSpecification
+        implements Predicate<DependencyModel>
+    {
+        private final Class<? extends Annotation> scope;
+
+        public ScopeSpecification( Class<? extends Annotation> scope )
+        {
+            this.scope = scope;
+        }
+
+        @Override
+        public boolean test( DependencyModel model )
+        {
+            return model.hasScope( scope );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldModel.java
new file mode 100644
index 0000000..e4fd289
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldModel.java
@@ -0,0 +1,165 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.injection;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.util.Collection;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.DependencyDescriptor;
+import org.apache.polygene.api.composite.InjectedFieldDescriptor;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.bootstrap.InjectionException;
+import org.apache.polygene.runtime.composite.TransientInstance;
+import org.apache.polygene.runtime.model.Resolution;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singleton;
+
+/**
+ * JAVADOC
+ */
+public final class InjectedFieldModel
+    implements InjectedFieldDescriptor, Dependencies, VisitableHierarchy<InjectedFieldModel, DependencyModel>
+{
+    private DependencyModel dependencyModel;
+    private Field injectedField;
+
+    public InjectedFieldModel( Field injectedField, DependencyModel dependencyModel )
+    {
+        injectedField.setAccessible( true );
+        this.injectedField = injectedField;
+        this.dependencyModel = dependencyModel;
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        return Stream.of( dependencyModel );
+    }
+
+    @Override
+    public Field field()
+    {
+        return injectedField;
+    }
+
+    @Override
+    public DependencyDescriptor dependency()
+    {
+        return dependencyModel;
+    }
+
+    public void bind( Resolution resolution )
+        throws BindingException
+    {
+        dependencyModel.bind( resolution.forField( injectedField ) );
+    }
+
+    public void inject( InjectionContext context, Object instance )
+    {
+        Object value = dependencyModel.inject( context );
+        try
+        {
+            injectedField.set( instance, value );
+        }
+        catch( IllegalAccessException e )
+        {
+            throw new InjectionException( e );
+        }
+        catch( IllegalArgumentException e )
+        {
+            String valueClassName;
+            if( value == null )
+            {
+                valueClassName = "<null>";
+            }
+            else if( Proxy.isProxyClass( value.getClass() ) )
+            {
+                InvocationHandler invocationHandler = Proxy.getInvocationHandler( value );
+                if( invocationHandler instanceof TransientInstance )
+                {
+                    TransientInstance handler = (TransientInstance) invocationHandler;
+                    valueClassName = Classes.toString( handler.descriptor().types() )
+                                     + " in [" + handler.module().name() + "] of [" + handler.layer().name() + "]";
+                }
+                else
+                {
+                    valueClassName = invocationHandler.toString();
+                }
+            }
+            else
+            {
+                valueClassName = value.getClass().getName();
+            }
+            StringBuilder annotBuilder = new StringBuilder();
+            for( Annotation annot : injectedField.getAnnotations() )
+            {
+                String s = annot.toString();
+                annotBuilder.append( "@" ).append( s.substring( s.lastIndexOf( '.' ) + 1, s.length() - 2 ) );
+                annotBuilder.append( " " );
+            }
+            String annots = annotBuilder.toString();
+            String message = "Can not inject the field\n    "
+                             + injectedField.getDeclaringClass()
+                             + "\n    {\n        " + annots + "\n        "
+                             + injectedField.getType().getSimpleName() + " " + injectedField.getName()
+                             + "\n    }\nwith value \n    " + value + "\nof type\n    "
+                             + valueClassName;
+            throw new InjectionException( message, e );
+        }
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super InjectedFieldModel, ? super DependencyModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            visitor.visit( dependencyModel );
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public Collection<DependencyModel> filter( Predicate<DependencyModel> specification )
+    {
+        if( specification.test( dependencyModel ) )
+        {
+            return singleton( dependencyModel );
+        }
+        else
+        {
+            return emptyList();
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        return "InjectedFieldModel{" + ", injectedField=" + injectedField + '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldsModel.java
new file mode 100644
index 0000000..54c8312
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedFieldsModel.java
@@ -0,0 +1,117 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.injection;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
+import org.apache.polygene.api.injection.InjectionScope;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.Fields;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+import static org.apache.polygene.api.util.Annotations.typeHasAnnotation;
+
+/**
+ * JAVADOC
+ */
+public final class InjectedFieldsModel
+    implements Dependencies, VisitableHierarchy<Object, Object>
+{
+    private final List<InjectedFieldModel> fields = new ArrayList<>();
+
+    public InjectedFieldsModel( Class fragmentClass )
+    {
+        Fields.fieldsOf( fragmentClass ).forEach( field ->
+            Arrays.stream( field.getAnnotations() )
+                  .filter( typeHasAnnotation( InjectionScope.class ) )
+                  .filter( Objects::nonNull )
+                  .forEach( injectionAnnotation ->  addModel( fragmentClass, field, injectionAnnotation )
+            )
+        );
+    }
+
+    private void addModel( Class fragmentClass, Field field, Annotation injectionAnnotation )
+    {
+        Type genericType = field.getGenericType();
+        if( genericType instanceof ParameterizedType )
+        {
+            Type[] actualTypeArguments = ( (ParameterizedType) genericType ).getActualTypeArguments();
+            Type rawType = ( (ParameterizedType) genericType ).getRawType();
+            Type ownerType = ( (ParameterizedType) genericType ).getOwnerType();
+            genericType = new ParameterizedTypeInstance( actualTypeArguments, rawType, ownerType );
+
+            for( int i = 0; i < actualTypeArguments.length; i++ )
+            {
+                Type type = actualTypeArguments[ i ];
+                if( type instanceof TypeVariable )
+                {
+                    type = Classes.resolveTypeVariable( (TypeVariable) type, field.getDeclaringClass(), fragmentClass );
+                    actualTypeArguments[ i ] = type;
+                }
+            }
+        }
+
+        boolean optional = DependencyModel.isOptional( injectionAnnotation, field.getAnnotations() );
+        DependencyModel dependencyModel = new DependencyModel( injectionAnnotation, genericType, fragmentClass, optional, field.getAnnotations() );
+        InjectedFieldModel injectedFieldModel = new InjectedFieldModel( field, dependencyModel );
+        this.fields.add( injectedFieldModel );
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        return fields.stream().flatMap( Dependencies::dependencies );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            for( InjectedFieldModel field : fields )
+            {
+                if( !field.accept( modelVisitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+
+    public void inject( InjectionContext context, Object instance )
+    {
+        for( InjectedFieldModel field : fields )
+        {
+            field.inject( context, instance );
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodModel.java
new file mode 100644
index 0000000..f1dc19b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodModel.java
@@ -0,0 +1,93 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.injection;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.InjectedMethodDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.bootstrap.InjectionException;
+
+/**
+ * JAVADOC
+ */
+public final class InjectedMethodModel
+    implements InjectedMethodDescriptor, Dependencies, VisitableHierarchy<Object, Object>
+{
+    // Model
+    private Method method;
+    private InjectedParametersModel parameters;
+
+    public InjectedMethodModel( Method method, InjectedParametersModel parameters )
+    {
+        this.method = method;
+        this.method.setAccessible( true );
+        this.parameters = parameters;
+    }
+
+    @Override
+    public Method method()
+    {
+        return method;
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        return parameters.dependencies();
+    }
+
+    // Context
+    public void inject( InjectionContext context, Object instance )
+        throws InjectionException
+    {
+        Object[] params = parameters.newParametersInstance( context );
+        try
+        {
+            if( !method.isAccessible() )
+            {
+                method.setAccessible( true );
+            }
+            method.invoke( instance, params );
+        }
+        catch( IllegalAccessException e )
+        {
+            throw new InjectionException( e );
+        }
+        catch( InvocationTargetException e )
+        {
+            throw new InjectionException( e.getTargetException() );
+        }
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            parameters.accept( visitor );
+        }
+        return visitor.visitLeave( this );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodsModel.java
new file mode 100644
index 0000000..388a17b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedMethodsModel.java
@@ -0,0 +1,137 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.injection;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+import org.apache.polygene.api.injection.InjectionScope;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.Methods;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+import static org.apache.polygene.api.util.Annotations.typeHasAnnotation;
+
+/**
+ * JAVADOC
+ */
+public final class InjectedMethodsModel
+    implements Dependencies, VisitableHierarchy<Object, Object>
+{
+    // Model
+    private final List<InjectedMethodModel> methodModels = new ArrayList<>();
+
+    public InjectedMethodsModel( Class fragmentClass )
+    {
+        Methods.methodsOf( fragmentClass ).forEach( method -> {
+            Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+            if( parameterAnnotations.length > 0 )
+            {
+                InjectedParametersModel parametersModel = new InjectedParametersModel();
+                final Type[] genericParameterTypes = method.getGenericParameterTypes();
+                boolean found = true;
+                for( int i = 0; i < parameterAnnotations.length; i++ )
+                {
+                    Optional<Annotation> opt = Arrays.stream( parameterAnnotations[ i ] )
+                        .filter( typeHasAnnotation( InjectionScope.class ) )
+                        .findFirst();
+                    if( opt.isPresent() )
+                    {
+                        Annotation injectionAnnotation = opt.get();
+                        Type genericType = genericParameterTypes[ i ];
+                        if( genericType instanceof ParameterizedType )
+                        {
+                            genericType = createParameterizedTypeInstance( (ParameterizedType) genericType );
+
+                            for( int j = 0; j < ( (ParameterizedType) genericType ).getActualTypeArguments().length; j++ )
+                            {
+                                Type type = ( (ParameterizedType) genericType ).getActualTypeArguments()[ j ];
+                                if( type instanceof TypeVariable )
+                                {
+                                    type = Classes.resolveTypeVariable( (TypeVariable) type, method.getDeclaringClass(), fragmentClass );
+                                    ( (ParameterizedType) genericType ).getActualTypeArguments()[ j ] = type;
+                                }
+                            }
+                        }
+                        boolean optional = DependencyModel.isOptional( injectionAnnotation, parameterAnnotations[ i ] );
+                        DependencyModel dependencyModel = new DependencyModel( injectionAnnotation, genericType, fragmentClass, optional, parameterAnnotations[ i ] );
+                        parametersModel.addDependency( dependencyModel );
+                    }
+                    else
+                    {
+                        found = false;
+                        break;
+                    }
+                }
+                if( found )
+                {
+                    methodModels.add( new InjectedMethodModel( method, parametersModel ) );
+                }
+            }
+        } );
+    }
+
+    private Type createParameterizedTypeInstance( ParameterizedType genericType )
+    {
+        return new ParameterizedTypeInstance(
+            genericType.getActualTypeArguments(), genericType.getRawType(), genericType.getOwnerType()
+        );
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        return methodModels.stream().flatMap( InjectedMethodModel::dependencies );
+    }
+
+    // Context
+    public void inject( InjectionContext context, Object instance )
+    {
+        for( InjectedMethodModel methodModel : methodModels )
+        {
+            methodModel.inject( context, instance );
+        }
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( InjectedMethodModel methodModel : methodModels )
+            {
+                if( !methodModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedParametersModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedParametersModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedParametersModel.java
new file mode 100644
index 0000000..82ccd20
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectedParametersModel.java
@@ -0,0 +1,95 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.injection;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.InjectedParametersDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public final class InjectedParametersModel
+    implements InjectedParametersDescriptor, Dependencies, VisitableHierarchy<Object, Object>
+{
+    private final List<DependencyModel> parameterDependencies;
+
+    public InjectedParametersModel()
+    {
+        parameterDependencies = new ArrayList<>();
+    }
+
+    @Override
+    public Stream<DependencyModel> dependencies()
+    {
+        return parameterDependencies.stream();
+    }
+
+    // Context
+    public Object[] newParametersInstance( InjectionContext context )
+    {
+        Object[] parametersInstance = new Object[ parameterDependencies.size() ];
+
+        // Inject parameterDependencies
+        for( int j = 0; j < parameterDependencies.size(); j++ )
+        {
+            DependencyModel dependencyModel = parameterDependencies.get( j );
+            Object parameter = dependencyModel.inject( context );
+            parametersInstance[ j ] = parameter;
+        }
+
+        return parametersInstance;
+    }
+
+    public void addDependency( DependencyModel dependency )
+    {
+        parameterDependencies.add( dependency );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( DependencyModel parameterDependency : parameterDependencies )
+            {
+                if( !visitor.visit( parameterDependency ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "InjectedParametersModel{" +
+               "parameterDependencies=" + parameterDependencies +
+               '}';
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionContext.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionContext.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionContext.java
new file mode 100644
index 0000000..dd89d85
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionContext.java
@@ -0,0 +1,126 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.injection;
+
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.runtime.composite.ProxyReferenceInvocationHandler;
+import org.apache.polygene.runtime.composite.UsesInstance;
+
+/**
+ * JAVADOC
+ */
+public final class InjectionContext
+{
+    private final ModuleDescriptor module;
+    private CompositeInstance compositeInstance;
+    private UsesInstance uses;
+    private StateHolder state;
+    private Object next; // Only used for concerns and side-effects
+    private ProxyReferenceInvocationHandler proxyHandler;
+    private Object instance; // Only used for inner classes
+
+    // For mixins
+
+    public InjectionContext( CompositeInstance compositeInstance, UsesInstance uses, StateHolder state )
+    {
+        this.module = compositeInstance.module();
+        this.compositeInstance = compositeInstance;
+        this.uses = uses;
+        this.state = state;
+    }
+
+    // For concerns and side-effects
+    public InjectionContext( ModuleDescriptor module, Object next, ProxyReferenceInvocationHandler proxyHandler )
+    {
+        this.module = module;
+        this.next = next;
+        this.proxyHandler = proxyHandler;
+    }
+
+    public InjectionContext( ModuleDescriptor module, UsesInstance uses )
+    {
+        this.module = module;
+        this.uses = uses;
+    }
+
+    // For inner classes
+    public InjectionContext( ModuleDescriptor module, UsesInstance uses, Object instance )
+    {
+        this.module = module;
+        this.uses = uses;
+        this.instance = instance;
+    }
+
+    public ModuleDescriptor module()
+    {
+        return module;
+    }
+
+    public CompositeInstance compositeInstance()
+    {
+        return compositeInstance;
+    }
+
+    public UsesInstance uses()
+    {
+        return uses;
+    }
+
+    public StateHolder state()
+    {
+        return state;
+    }
+
+    public Object next()
+    {
+        return next;
+    }
+
+    public Object instance()
+    {
+        return instance;
+    }
+
+    public ProxyReferenceInvocationHandler proxyHandler()
+    {
+        return proxyHandler;
+    }
+
+    public void setUses( UsesInstance uses )
+    {
+        this.uses = uses;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "InjectionContext{" +
+               "compositeInstance=" + compositeInstance +
+               ", module=" + module +
+               ", uses=" + uses +
+               ", state=" + state +
+               ", next=" + next +
+               ", proxyHandler=" + proxyHandler +
+               '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProvider.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProvider.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProvider.java
new file mode 100644
index 0000000..a21a352
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProvider.java
@@ -0,0 +1,32 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.injection;
+
+import org.apache.polygene.runtime.injection.provider.InjectionProviderException;
+
+/**
+ * JAVADOC
+ */
+public interface InjectionProvider
+{
+    Object provideInjection( InjectionContext context )
+        throws InjectionProviderException;
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProviderFactory.java
new file mode 100644
index 0000000..8671d4c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/InjectionProviderFactory.java
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.injection;
+
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public interface InjectionProviderFactory
+{
+    /**
+     * Binding a dependency given an injection resolution. If no binding
+     * can be found, return null. If the dependency is optional the dependency will
+     * then be explicitly set to null.
+     *
+     * @param resolution Injection resolution
+     * @param dependencyModel Dependency model
+     * @return InjectionProvider
+     * @throws InvalidInjectionException if the injection is invalid
+     */
+    InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException;
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/ParameterizedTypeInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/ParameterizedTypeInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/ParameterizedTypeInstance.java
new file mode 100644
index 0000000..d1f2bc7
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/ParameterizedTypeInstance.java
@@ -0,0 +1,66 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.injection;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+
+/**
+ * TODO
+ */
+public class ParameterizedTypeInstance
+    implements ParameterizedType
+{
+    private Type[] actualTypeArguments;
+    private Type rawType;
+    private Type ownerType;
+
+    public ParameterizedTypeInstance( Type[] actualTypeArguments, Type rawType, Type ownerType )
+    {
+        this.actualTypeArguments = actualTypeArguments;
+        this.rawType = rawType;
+        this.ownerType = ownerType;
+    }
+
+    @Override
+    public Type[] getActualTypeArguments()
+    {
+        return actualTypeArguments;
+    }
+
+    @Override
+    public Type getRawType()
+    {
+        return rawType;
+    }
+
+    @Override
+    public Type getOwnerType()
+    {
+        return ownerType;
+    }
+
+    @Override
+    public String toString()
+    {
+        return rawType.toString() + Arrays.asList( actualTypeArguments );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderDecorator.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderDecorator.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderDecorator.java
new file mode 100644
index 0000000..3339a48
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderDecorator.java
@@ -0,0 +1,63 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.injection.provider;
+
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+
+/**
+ * If a dependency resolution should be a singleton, wrap it with this
+ * to provide a single instance "cache".
+ */
+public final class CachingInjectionProviderDecorator
+    implements InjectionProvider
+{
+    private final InjectionProvider decoratedProvider;
+    private volatile Object singletonInstance;
+
+    public CachingInjectionProviderDecorator( InjectionProvider injectionProvider )
+    {
+        this.decoratedProvider = injectionProvider;
+    }
+
+    public InjectionProvider decoratedProvider()
+    {
+        return decoratedProvider;
+    }
+
+    @Override
+    public Object provideInjection( InjectionContext context )
+        throws InjectionProviderException
+    {
+        if( singletonInstance == null )
+        {
+            synchronized( this )
+            {
+                if( singletonInstance == null )
+                {
+                    singletonInstance = decoratedProvider.provideInjection( context );
+                }
+            }
+        }
+
+        return singletonInstance;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderFactoryDecorator.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderFactoryDecorator.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderFactoryDecorator.java
new file mode 100644
index 0000000..3e0ea74
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/CachingInjectionProviderFactoryDecorator.java
@@ -0,0 +1,56 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.injection.provider;
+
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public class CachingInjectionProviderFactoryDecorator
+    implements InjectionProviderFactory
+{
+    private final InjectionProviderFactory decoratedFactory;
+
+    public CachingInjectionProviderFactoryDecorator( InjectionProviderFactory decoratedFactory )
+    {
+        this.decoratedFactory = decoratedFactory;
+    }
+
+    @Override
+    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        InjectionProvider injectionProvider = decoratedFactory.newInjectionProvider( resolution, dependencyModel );
+        if( injectionProvider != null )
+        {
+            return new CachingInjectionProviderDecorator( injectionProvider );
+        }
+        else
+        {
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderException.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderException.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderException.java
new file mode 100644
index 0000000..43a8872
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderException.java
@@ -0,0 +1,38 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.apache.polygene.runtime.injection.provider;
+
+/**
+ * JAVADOC
+ */
+public class InjectionProviderException
+    extends RuntimeException
+{
+    public InjectionProviderException( String string )
+    {
+        super( string );
+    }
+
+    public InjectionProviderException( String string, Throwable throwable )
+    {
+        super( string, throwable );
+    }
+}


Mime
View raw message