You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by ni...@apache.org on 2016/12/17 10:27:45 UTC

[09/81] [abbrv] [partial] zest-java git commit: ZEST-195 ; Replace all "zest" with "polygene"

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderFactoryStrategy.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderFactoryStrategy.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderFactoryStrategy.java
new file mode 100644
index 0000000..38bc5ba
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderFactoryStrategy.java
@@ -0,0 +1,106 @@
+/*
+ *  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 java.lang.annotation.Annotation;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.composite.InvalidValueCompositeException;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.concern.internal.ConcernFor;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.sideeffect.internal.SideEffectFor;
+import org.apache.polygene.api.value.ValueComposite;
+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 final class InjectionProviderFactoryStrategy
+    implements InjectionProviderFactory
+{
+    private final Map<Class<? extends Annotation>, InjectionProviderFactory> generalProviderFactories = new HashMap<>();
+    private final Map<Class<? extends Annotation>, InjectionProviderFactory> valuesProviderFactories = new HashMap<>();
+    private MetaInfo metaInfo;
+
+    public InjectionProviderFactoryStrategy( MetaInfo metaInfo )
+    {
+        this.metaInfo = metaInfo;
+        valuesProviderFactories.put( This.class, new ThisInjectionProviderFactory() );
+        ModifiesInjectionProviderFactory modifiesInjectionProviderFactory = new ModifiesInjectionProviderFactory();
+        valuesProviderFactories.put( ConcernFor.class, modifiesInjectionProviderFactory );
+        valuesProviderFactories.put( SideEffectFor.class, modifiesInjectionProviderFactory );
+        valuesProviderFactories.put( State.class, new StateInjectionProviderFactory() );
+
+        valuesProviderFactories.put( Structure.class, new CachingInjectionProviderFactoryDecorator( new StructureInjectionProviderFactory() ) );
+        valuesProviderFactories.put( Service.class, new CachingInjectionProviderFactoryDecorator( new ServiceInjectionProviderFactory() ) );
+        generalProviderFactories.put( Invocation.class, new InvocationInjectionProviderFactory() );
+        generalProviderFactories.put( Uses.class, new UsesInjectionProviderFactory() );
+    }
+
+    @Override
+    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        Class<? extends Annotation> injectionAnnotationType = dependencyModel.injectionAnnotation().annotationType();
+        InjectionProviderFactory factory1 = generalProviderFactories.get( injectionAnnotationType );
+        InjectionProviderFactory factory2 = valuesProviderFactories.get( injectionAnnotationType );
+        if( factory1 == null && factory2 == null )
+        {
+            InjectionProviderFactory factory = metaInfo.get( InjectionProviderFactory.class );
+            if( factory != null )
+            {
+                return factory.newInjectionProvider( resolution, dependencyModel );
+            }
+            else
+            {
+                throw new InvalidInjectionException( "Unknown injection annotation @" + injectionAnnotationType.getSimpleName() );
+            }
+        }
+        ModelDescriptor composite = resolution.model();
+        Class<?> compositeType = composite.types().findFirst().orElse( null );
+        if( factory1 != null && ValueComposite.class.isAssignableFrom( compositeType ) )
+        {
+            throw new InvalidValueCompositeException( "@" + injectionAnnotationType.getSimpleName() + " is not allowed in ValueComposites: " + compositeType );
+        }
+
+        InjectionProviderFactory factory;
+        if( factory1 == null )
+        {
+            factory = factory2;
+        }
+        else
+        {
+            factory = factory1;
+        }
+        return factory.newInjectionProvider( resolution, dependencyModel );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InvocationInjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InvocationInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InvocationInjectionProviderFactory.java
new file mode 100644
index 0000000..90e2987
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InvocationInjectionProviderFactory.java
@@ -0,0 +1,118 @@
+/*
+ *  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 java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.composite.CompositeMethodModel;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class InvocationInjectionProviderFactory
+    implements InjectionProviderFactory
+{
+    @Override
+    @SuppressWarnings( "raw" )
+    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        Class injectionClass = Classes.RAW_CLASS.apply( dependencyModel.injectionType() );
+        if( injectionClass.equals( Method.class ) ||
+            injectionClass.equals( AnnotatedElement.class ) ||
+            injectionClass.equals( Iterable.class ) ||
+            Annotation.class.isAssignableFrom( injectionClass ) )
+        {
+            return new InvocationDependencyResolution( resolution, dependencyModel );
+        }
+        else
+        {
+            String injectedTo = dependencyModel.injectedClass().getName();
+            throw new InvalidInjectionException( "Invalid injection type " + injectionClass + " in " + injectedTo );
+        }
+    }
+
+    private static class InvocationDependencyResolution
+        implements InjectionProvider
+    {
+        private final Resolution resolution;
+        private final DependencyModel dependencyModel;
+
+        private InvocationDependencyResolution( Resolution resolution, DependencyModel dependencyModel )
+        {
+            this.resolution = resolution;
+            this.dependencyModel = dependencyModel;
+        }
+
+        @Override
+        @SuppressWarnings( {"raw", "unchecked"} )
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            Class injectionClass = Classes.RAW_CLASS.apply( dependencyModel.injectionType() );
+            final CompositeMethodModel methodModel = resolution.method();
+            if( injectionClass.equals( Method.class ) )
+            {
+                return methodModel.method();
+            }
+
+            final AnnotatedElement annotatedElement = methodModel.annotatedElement();
+            if( injectionClass.equals( AnnotatedElement.class ) )
+            {
+                return annotatedElement;
+            }
+            final Annotation annotation = annotatedElement.getAnnotation( injectionClass );
+            if( annotation != null )
+            {
+                return annotation;
+            }
+            if( dependencyModel.injectionType() instanceof Class<?> )
+            {
+                return annotatedElement.getAnnotation( (Class<Annotation>) dependencyModel.injectionType() );
+            }
+            if( dependencyModel.injectionType() instanceof ParameterizedType )
+            {
+                ParameterizedType injectionType = (ParameterizedType) dependencyModel.injectionType();
+                Type rawType = injectionType.getRawType();
+                Type[] actualTypeArguments = injectionType.getActualTypeArguments();
+                boolean isAnIterable = rawType.equals( Iterable.class );
+                boolean haveOneGenericType = actualTypeArguments.length == 1;
+                boolean thatIsOfTypeMethod = actualTypeArguments[ 0 ].equals( Method.class );
+                if( isAnIterable && haveOneGenericType && thatIsOfTypeMethod )
+                {
+                    Class<?> injectedClass = dependencyModel.injectedClass();
+                    Iterable<Method> result = methodModel.invocationsFor( injectedClass );
+                    return result;
+                }
+            }
+            return null;
+        }
+    }
+}
\ 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/provider/ModifiesInjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ModifiesInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ModifiesInjectionProviderFactory.java
new file mode 100644
index 0000000..b0f662b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ModifiesInjectionProviderFactory.java
@@ -0,0 +1,71 @@
+/*
+ *  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.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class ModifiesInjectionProviderFactory
+    implements InjectionProviderFactory
+{
+    @Override
+    public InjectionProvider newInjectionProvider( Resolution bindingContext, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        if( bindingContext.model() instanceof CompositeDescriptor )
+        {
+            Class<?> type = Classes.RAW_CLASS.apply( dependencyModel.injectionType() );
+            if( type.isAssignableFrom( dependencyModel.injectedClass() ) )
+            {
+                return new ModifiedInjectionProvider();
+            }
+            else
+            {
+                throw new InvalidInjectionException( "Composite " + bindingContext.model() + " does not implement @ConcernFor type " + type
+                    .getName() + " in modifier " + dependencyModel.injectedClass().getName() );
+            }
+        }
+        else
+        {
+            throw new InvalidInjectionException( "The class " + dependencyModel.injectedClass()
+                .getName() + " is not a modifier" );
+        }
+    }
+
+    private static class ModifiedInjectionProvider
+        implements InjectionProvider
+    {
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            return context.next();
+        }
+    }
+}
\ 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/provider/ServiceInjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ServiceInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ServiceInjectionProviderFactory.java
new file mode 100644
index 0000000..f3dc70c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ServiceInjectionProviderFactory.java
@@ -0,0 +1,224 @@
+/*
+ *  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 java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.service.NoSuchServiceException;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.service.qualifier.Qualifier;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+import static java.util.stream.Collectors.toCollection;
+import static org.apache.polygene.api.util.Annotations.typeHasAnnotation;
+
+public final class ServiceInjectionProviderFactory
+    implements InjectionProviderFactory
+{
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        // TODO This could be changed to allow multiple @Qualifier annotations
+        Annotation qualifierAnnotation = Stream.of( dependencyModel.annotations() )
+                                               .filter( typeHasAnnotation( Qualifier.class ) )
+                                               .findFirst().orElse( null );
+        Predicate<ServiceReference<?>> serviceQualifier = null;
+        if( qualifierAnnotation != null )
+        {
+            Qualifier qualifier = qualifierAnnotation.annotationType().getAnnotation( Qualifier.class );
+            try
+            {
+                serviceQualifier = qualifier.value().newInstance().qualifier( qualifierAnnotation );
+            }
+            catch( Exception e )
+            {
+                throw new InvalidInjectionException( "Could not instantiate qualifier serviceQualifier", e );
+            }
+        }
+
+        if( dependencyModel.rawInjectionType().equals( Iterable.class ) )
+        {
+            Type iterableType = ( (ParameterizedType) dependencyModel.injectionType() ).getActualTypeArguments()[ 0 ];
+            if( Classes.RAW_CLASS.apply( iterableType ).equals( ServiceReference.class ) )
+            {
+                // @Service Iterable<ServiceReference<MyService<Foo>> serviceRefs
+                Type serviceType = ( (ParameterizedType) iterableType ).getActualTypeArguments()[ 0 ];
+
+                return new IterableServiceReferenceProvider( serviceType, serviceQualifier );
+            }
+            else
+            {
+                // @Service Iterable<MyService<Foo>> services
+                return new IterableServiceProvider( iterableType, serviceQualifier );
+            }
+        }
+        else if( dependencyModel.rawInjectionType().equals( ServiceReference.class ) )
+        {
+            // @Service ServiceReference<MyService<Foo>> serviceRef
+            Type referencedType = ( (ParameterizedType) dependencyModel.injectionType() ).getActualTypeArguments()[ 0 ];
+            return new ServiceReferenceProvider( referencedType, serviceQualifier );
+        }
+        else
+        {
+            // @Service MyService<Foo> service
+            return new ServiceProvider( dependencyModel.injectionType(), serviceQualifier );
+        }
+    }
+
+    private static class IterableServiceReferenceProvider
+        extends ServiceInjectionProvider
+    {
+        private IterableServiceReferenceProvider( Type serviceType, Predicate<ServiceReference<?>> serviceQualifier )
+        {
+            super( serviceType, serviceQualifier );
+        }
+
+        @Override
+        public synchronized Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            return getServiceReferences( context ).collect( toCollection( ArrayList::new ) );
+        }
+    }
+
+    private static class IterableServiceProvider
+        extends ServiceInjectionProvider
+        implements Function<ServiceReference<?>, Object>
+    {
+        private IterableServiceProvider( Type serviceType, Predicate<ServiceReference<?>> serviceQualifier )
+        {
+            super( serviceType, serviceQualifier );
+        }
+
+        @Override
+        public synchronized Object provideInjection( final InjectionContext context )
+            throws InjectionProviderException
+        {
+            return getServiceReferences( context ).map( ServiceReference::get )
+                                                  .collect( toCollection( ArrayList::new ) );
+        }
+
+        @Override
+        public Object apply( ServiceReference<?> objectServiceReference )
+        {
+            return objectServiceReference.get();
+        }
+    }
+
+    private static class ServiceReferenceProvider
+        extends ServiceInjectionProvider
+    {
+        ServiceReferenceProvider( Type serviceType, Predicate<ServiceReference<?>> qualifier )
+        {
+            super( serviceType, qualifier );
+        }
+
+        @Override
+        public synchronized Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            return getServiceReference( context );
+        }
+    }
+
+    private static class ServiceProvider
+        extends ServiceInjectionProvider
+    {
+        ServiceProvider( Type serviceType, Predicate<ServiceReference<?>> qualifier )
+        {
+            super( serviceType, qualifier );
+        }
+
+        @Override
+        public synchronized Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            ServiceReference<?> ref = getServiceReference( context );
+
+            if( ref != null )
+            {
+                return ref.get();
+            }
+            else
+            {
+                return null;
+            }
+        }
+    }
+
+    public abstract static class ServiceInjectionProvider
+        implements InjectionProvider
+    {
+        private final Type serviceType;
+        private final Predicate<ServiceReference<?>> serviceQualifier;
+
+        private ServiceInjectionProvider( Type serviceType, Predicate<ServiceReference<?>> serviceQualifier )
+        {
+            this.serviceType = serviceType;
+            this.serviceQualifier = serviceQualifier;
+        }
+
+        protected ServiceReference<Object> getServiceReference( InjectionContext context )
+        {
+            try
+            {
+                if( serviceQualifier == null )
+                {
+                    return context.module().instance().findService( serviceType );
+                }
+                else
+                {
+                    return context.module().instance().findServices( serviceType )
+                                  .filter( serviceQualifier ).findFirst().orElse( null );
+                }
+            }
+            catch( NoSuchServiceException e )
+            {
+                return null;
+            }
+        }
+
+        protected Stream<ServiceReference<Object>> getServiceReferences( final InjectionContext context )
+        {
+            if( serviceQualifier == null )
+            {
+                return context.module().instance().findServices( serviceType );
+            }
+            else
+            {
+                return context.module().instance().findServices( serviceType ).filter( serviceQualifier );
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StateInjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StateInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StateInjectionProviderFactory.java
new file mode 100644
index 0000000..3a3a80e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StateInjectionProviderFactory.java
@@ -0,0 +1,273 @@
+/*
+ *  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.api.association.AbstractAssociation;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateDescriptor;
+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.composite.StateDescriptor;
+import org.apache.polygene.api.composite.StatefulCompositeDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.entity.EntityInstance;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class StateInjectionProviderFactory
+    implements InjectionProviderFactory
+{
+    @Override
+    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        if( StateHolder.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+        {
+            // @State StateHolder properties;
+            return new StateInjectionProvider();
+        }
+        else if( UnitOfWork.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+        {
+            if( !( resolution.model() instanceof EntityDescriptor ) )
+            {
+                throw new InvalidInjectionException( "Only EntityComposites can be injected with '@State UnitOfWork'" );
+            }
+            return new UnitOfWorkInjectionProvider();
+        }
+        else if( Property.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+        {
+            // @State Property<String> name;
+            StateDescriptor descriptor;
+            descriptor = ( (StatefulCompositeDescriptor) resolution.model() ).state();
+
+            State annotation = (State) dependencyModel.injectionAnnotation();
+            String name;
+            if( annotation.value().isEmpty() )
+            {
+                name = resolution.field().getName();
+            }
+            else
+            {
+                name = annotation.value();
+            }
+
+            PropertyDescriptor propertyDescriptor = descriptor.findPropertyModelByName( name );
+            return new PropertyInjectionProvider( propertyDescriptor );
+        }
+        else if( Association.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+        {
+            // @State Association<MyEntity> name;
+            AssociationStateDescriptor descriptor = ( (EntityDescriptor) resolution.model() ).state();
+            State annotation = (State) dependencyModel.injectionAnnotation();
+            String name;
+            if( annotation.value().isEmpty() )
+            {
+                name = resolution.field().getName();
+            }
+            else
+            {
+                name = annotation.value();
+            }
+            AssociationDescriptor model = descriptor.getAssociationByName( name );
+            return new AssociationInjectionProvider( model );
+        }
+        else if( ManyAssociation.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+        {
+            // @State ManyAssociation<MyEntity> name;
+            AssociationStateDescriptor descriptor = ( (EntityDescriptor) resolution.model() ).state();
+            State annotation = (State) dependencyModel.injectionAnnotation();
+            String name;
+            if( annotation.value().isEmpty() )
+            {
+                name = resolution.field().getName();
+            }
+            else
+            {
+                name = annotation.value();
+            }
+            AssociationDescriptor model = descriptor.getManyAssociationByName( name );
+            return new ManyAssociationInjectionProvider( model );
+        }
+        else if( NamedAssociation.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+        {
+            // @State NamedAssociation<MyEntity> name;
+            AssociationStateDescriptor descriptor = ( (EntityDescriptor) resolution.model() ).state();
+            State annotation = (State) dependencyModel.injectionAnnotation();
+            String name;
+            if( annotation.value().isEmpty() )
+            {
+                name = resolution.field().getName();
+            }
+            else
+            {
+                name = annotation.value();
+            }
+            AssociationDescriptor model = descriptor.getNamedAssociationByName( name );
+            return new NamedAssociationInjectionProvider( model );
+        }
+
+        throw new InjectionProviderException( "Injected value has invalid type" );
+    }
+
+    private static class PropertyInjectionProvider
+        implements InjectionProvider
+    {
+        private final PropertyDescriptor propertyDescriptor;
+
+        private PropertyInjectionProvider( PropertyDescriptor propertyDescriptor )
+        {
+            this.propertyDescriptor = propertyDescriptor;
+        }
+
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            Property<?> value = context.state().propertyFor( propertyDescriptor.accessor() );
+            if( value != null )
+            {
+                return value;
+            }
+            else
+            {
+                throw new InjectionProviderException( "Non-optional property " + propertyDescriptor + " had no value" );
+            }
+        }
+    }
+
+    private static class AssociationInjectionProvider
+        implements InjectionProvider
+    {
+        private final AssociationDescriptor associationDescriptor;
+
+        private AssociationInjectionProvider( AssociationDescriptor associationDescriptor )
+        {
+            this.associationDescriptor = associationDescriptor;
+        }
+
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            AbstractAssociation abstractAssociation = ( (AssociationStateHolder) context.state() ).
+                associationFor( associationDescriptor.accessor() );
+            if( abstractAssociation != null )
+            {
+                return abstractAssociation;
+            }
+            else
+            {
+                throw new InjectionProviderException( "Non-optional association " + associationDescriptor.qualifiedName() + " had no association" );
+            }
+        }
+    }
+
+    private static class ManyAssociationInjectionProvider
+        implements InjectionProvider
+    {
+        private final AssociationDescriptor manyAssociationDescriptor;
+
+        private ManyAssociationInjectionProvider( AssociationDescriptor manyAssociationDescriptor )
+        {
+            this.manyAssociationDescriptor = manyAssociationDescriptor;
+        }
+
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            ManyAssociation<?> abstractAssociation = ( (AssociationStateHolder) context.state() ).
+                manyAssociationFor( manyAssociationDescriptor.accessor() );
+            if( abstractAssociation != null )
+            {
+                return abstractAssociation;
+            }
+            else
+            {
+                throw new InjectionProviderException( "Non-optional association " + manyAssociationDescriptor.qualifiedName() + " had no association" );
+            }
+        }
+    }
+
+    private static class NamedAssociationInjectionProvider
+        implements InjectionProvider
+    {
+        private final AssociationDescriptor namedAssociationDescriptor;
+
+        private NamedAssociationInjectionProvider( AssociationDescriptor namedAssociationDescriptor )
+        {
+            this.namedAssociationDescriptor = namedAssociationDescriptor;
+        }
+
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            NamedAssociation<?> abstractAssociation = ( (AssociationStateHolder) context.state() ).
+                namedAssociationFor( namedAssociationDescriptor.accessor() );
+            if( abstractAssociation != null )
+            {
+                return abstractAssociation;
+            }
+            else
+            {
+                throw new InjectionProviderException( "Non-optional association " + namedAssociationDescriptor.qualifiedName() + " had no association" );
+            }
+        }
+    }
+
+    static private class StateInjectionProvider
+        implements InjectionProvider
+    {
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            return context.state();
+        }
+    }
+
+    static private class UnitOfWorkInjectionProvider
+        implements InjectionProvider
+    {
+
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            return ( (EntityInstance) context.compositeInstance() ).unitOfWork();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StructureInjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StructureInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StructureInjectionProviderFactory.java
new file mode 100644
index 0000000..0d20dab
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StructureInjectionProviderFactory.java
@@ -0,0 +1,129 @@
+/*
+ *  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 java.lang.reflect.Type;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+import org.apache.polygene.runtime.structure.ApplicationInstance;
+
+public final class StructureInjectionProviderFactory
+    implements InjectionProviderFactory
+{
+    @Override
+    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        return new StructureInjectionProvider( dependencyModel );
+    }
+
+    private static class StructureInjectionProvider
+        implements InjectionProvider
+    {
+        private final DependencyModel dependencyModel;
+
+        private StructureInjectionProvider( DependencyModel dependencyModel )
+        {
+            this.dependencyModel = dependencyModel;
+        }
+
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            Type type1 = dependencyModel.injectionType();
+            if( !( type1 instanceof Class ) )
+            {
+                throw new InjectionProviderException( "Type [" + type1 + "] can not be injected from the @Structure injection scope: " + context );
+            }
+            Class clazz = (Class) type1;
+            if( clazz.equals( TransientBuilderFactory.class ) )
+            {
+                return context.module().instance();
+            }
+            else if( clazz.equals( ObjectFactory.class ) )
+            {
+                return context.module().instance();
+            }
+            else if( clazz.equals( ValueBuilderFactory.class ) )
+            {
+                return context.module().instance();
+            }
+            else if( clazz.equals( UnitOfWorkFactory.class ) )
+            {
+                return context.module().instance().unitOfWorkFactory();
+            }
+            else if( clazz.equals( QueryBuilderFactory.class ) )
+            {
+                return context.module().instance();
+            }
+            else if( clazz.equals( ServiceFinder.class ) )
+            {
+                return context.module().instance();
+            }
+            else if( Module.class.isAssignableFrom( clazz ) )
+            {
+                return context.module().instance();
+            }
+            else if( ModuleDescriptor.class.isAssignableFrom( clazz ) )
+            {
+                return context.module();
+            }
+            else if( Layer.class.isAssignableFrom( clazz ) )
+            {
+                return context.module().layer().instance();
+            }
+            else if( LayerDescriptor.class.isAssignableFrom( clazz ) )
+            {
+                return context.module().layer();
+            }
+            else if( Application.class.isAssignableFrom( clazz ) )
+            {
+                return context.module().layer().instance().application();
+            }
+            else if( ApplicationDescriptor.class.isAssignableFrom( clazz ) )
+            {
+                return context.module().layer().instance().application().descriptor();
+            }
+            else if( PolygeneAPI.class.isAssignableFrom( clazz ) )
+            {
+                return (( ApplicationInstance) context.module().layer().instance().application()).runtime();
+            }
+            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/ThisInjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ThisInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ThisInjectionProviderFactory.java
new file mode 100644
index 0000000..161cfbd
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ThisInjectionProviderFactory.java
@@ -0,0 +1,130 @@
+/*
+ *  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 java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.composite.ProxyGenerator;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class ThisInjectionProviderFactory
+    implements InjectionProviderFactory
+{
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public InjectionProvider newInjectionProvider( Resolution bindingContext, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        if( bindingContext.model() instanceof CompositeDescriptor )
+        {
+            // If Composite type then return real type, otherwise use the specified one
+            final Class<?> thisType = dependencyModel.rawInjectionType();
+
+            Stream<Class<?>> injectionTypes;
+            if( Classes.assignableTypeSpecification( thisType ).test( bindingContext.model() ) )
+            {
+                injectionTypes = bindingContext.model().types();
+            }
+            else
+            {
+                CompositeDescriptor acd = ( (CompositeDescriptor) bindingContext.model() );
+                injectionTypes = acd.mixinTypes().filter( thisType::isAssignableFrom );
+            }
+
+            List<Class<?>> classes = injectionTypes.collect( Collectors.toList() );
+            if( classes.size() == 0 )
+            {
+                throw new InvalidInjectionException( "Composite " + bindingContext.model()
+                                                     + " does not implement @This type " + thisType.getName() + " in fragment "
+                                                     + dependencyModel.injectedClass().getName() );
+            }
+            return new ThisInjectionProvider( classes );
+        }
+        else
+        {
+            throw new InvalidInjectionException( "Object " + dependencyModel.injectedClass() + " may not use @This" );
+        }
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    private static class ThisInjectionProvider
+        implements InjectionProvider
+    {
+        Constructor proxyConstructor;
+        private Class[] interfaces;
+
+        private ThisInjectionProvider( List<Class<?>> types )
+        {
+            try
+            {
+                Class proxyClass;
+                Class<?> mainType = types.get( 0 );
+                if( Proxy.class.isAssignableFrom( mainType ) )
+                {
+                    proxyClass = mainType;
+                }
+                else
+                {
+                    interfaces = types.stream().map( Class.class::cast ).toArray( Class[]::new );
+                    proxyClass = ProxyGenerator.createProxyClass( mainType.getClassLoader(), interfaces );
+                }
+
+                proxyConstructor = proxyClass.getConstructor( InvocationHandler.class );
+            }
+            catch( Exception e )
+            {
+                // Ignore
+                e.printStackTrace();
+            }
+        }
+
+        @Override
+        public Object provideInjection( InjectionContext context )
+        {
+            try
+            {
+                InvocationHandler handler = context.compositeInstance();
+                if( handler == null )
+                {
+                    handler = context.proxyHandler();
+                }
+                return proxyConstructor.newInstance( handler );
+            }
+            catch( Exception e )
+            {
+                throw new InjectionProviderException( "Could not instantiate @This proxy", e );
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/UsesInjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/UsesInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/UsesInjectionProviderFactory.java
new file mode 100644
index 0000000..f4549c5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/UsesInjectionProviderFactory.java
@@ -0,0 +1,132 @@
+/*
+ *  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 java.lang.reflect.Constructor;
+import org.apache.polygene.api.composite.NoSuchTransientException;
+import org.apache.polygene.api.object.NoSuchObjectException;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.composite.UsesInstance;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class UsesInjectionProviderFactory
+    implements InjectionProviderFactory
+{
+    public UsesInjectionProviderFactory()
+    {
+    }
+
+    @Override
+    public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+        throws InvalidInjectionException
+    {
+        return new UsesInjectionProvider( dependencyModel );
+    }
+
+    private static class UsesInjectionProvider
+        implements InjectionProvider
+    {
+        private final DependencyModel dependency;
+
+        public UsesInjectionProvider( DependencyModel dependency )
+        {
+            this.dependency = dependency;
+        }
+
+        @SuppressWarnings( "unchecked" )
+        @Override
+        public Object provideInjection( InjectionContext context )
+            throws InjectionProviderException
+        {
+            UsesInstance uses = context.uses();
+
+            Class injectionType = dependency.rawInjectionType();
+            Object usesObject = uses.useForType( injectionType );
+
+            if( usesObject == null && !dependency.optional() )
+            {
+                // No @Uses object provided
+                // Try instantiating a Transient or Object for the given type
+                Module moduleInstance = context.module().instance();
+
+                try
+                {
+                    if( context.instance() != null )
+                    {
+                        uses = uses.use( context.instance() );
+                    }
+                    usesObject = moduleInstance.newTransient( injectionType, uses.toArray() );
+                }
+                catch( NoSuchTransientException e )
+                {
+                    try
+                    {
+                        usesObject = moduleInstance.newObject( injectionType, uses.toArray() );
+                    }
+                    catch( NoSuchObjectException e1 )
+                    {
+                        // Could not instantiate an instance - to try instantiate as plain class
+                        try
+                        {
+                            usesObject = injectionType.newInstance();
+                        }
+                        catch( Throwable e2 )
+                        {
+                            // Could not instantiate - try with this as first argument
+                            try
+                            {
+                                Constructor constructor = injectionType.getDeclaredConstructor( context.instance()
+                                                                                                    .getClass() );
+                                if( !constructor.isAccessible() )
+                                {
+                                    constructor.setAccessible( true );
+                                }
+                                usesObject = constructor.newInstance( context.instance() );
+                            }
+                            catch( Throwable e3 )
+                            {
+                                // Really can't instantiate it - ignore
+                            }
+                        }
+                    }
+                }
+
+                if( usesObject != null )
+                {
+                    context.setUses( context.uses().use( usesObject ) ); // Use this for other injections in same graph
+                }
+
+                return usesObject;
+            }
+            else
+            {
+                return usesObject;
+            }
+        }
+    }
+}
\ 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/internal/Activator.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/internal/Activator.java b/core/runtime/src/main/java/org/apache/polygene/runtime/internal/Activator.java
new file mode 100644
index 0000000..6a0481f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/internal/Activator.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.internal;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.apache.polygene.bootstrap.PolygeneRuntime;
+import org.apache.polygene.bootstrap.RuntimeFactory;
+import org.apache.polygene.runtime.PolygeneRuntimeImpl;
+
+/**
+ *
+ */
+public class Activator
+    implements BundleActivator
+{
+    private ServiceRegistration registration;
+
+    @Override
+    public void start( BundleContext bundleContext )
+        throws Exception
+    {
+        RuntimeFactory factory = new RuntimeFactory()
+        {
+            @Override
+            public PolygeneRuntime createRuntime()
+            {
+                return new PolygeneRuntimeImpl();
+            }
+        };
+        registration = bundleContext.registerService( RuntimeFactory.class.getName(), factory, null );
+    }
+
+    @Override
+    public void stop( BundleContext bundleContext )
+        throws Exception
+    {
+        registration.unregister();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/model/Binder.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/model/Binder.java b/core/runtime/src/main/java/org/apache/polygene/runtime/model/Binder.java
new file mode 100644
index 0000000..c59cc96
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/model/Binder.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.model;
+
+import org.apache.polygene.bootstrap.BindingException;
+
+/**
+ * Interface for models that can understand binding of dependencies
+ */
+public interface Binder
+{
+    void bind( Resolution resolution )
+        throws BindingException;
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/model/Resolution.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/model/Resolution.java b/core/runtime/src/main/java/org/apache/polygene/runtime/model/Resolution.java
new file mode 100644
index 0000000..f5ff0f5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/model/Resolution.java
@@ -0,0 +1,92 @@
+/*
+ *  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.model;
+
+import java.lang.reflect.Field;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.runtime.composite.CompositeMethodModel;
+import org.apache.polygene.runtime.structure.ApplicationModel;
+import org.apache.polygene.runtime.structure.LayerModel;
+import org.apache.polygene.runtime.structure.ModuleModel;
+
+/**
+ * JAVADOC
+ */
+public final class Resolution
+{
+    private final ApplicationModel application;
+    private final LayerModel layer;
+    private final ModuleModel module;
+    private final ModelDescriptor modelDescriptor;
+    private final CompositeMethodModel method;
+    private final Field field;
+
+    public Resolution( ApplicationModel application,
+                       LayerModel layer,
+                       ModuleModel module,
+                       ModelDescriptor modelDescriptor,
+                       CompositeMethodModel method,
+                       Field field
+    )
+    {
+        this.application = application;
+        this.layer = layer;
+        this.module = module;
+        this.modelDescriptor = modelDescriptor;
+        this.method = method;
+        this.field = field;
+    }
+
+    public ApplicationModel application()
+    {
+        return application;
+    }
+
+    public LayerModel layer()
+    {
+        return layer;
+    }
+
+    public ModuleModel module()
+    {
+        return module;
+    }
+
+    public ModelDescriptor model()
+    {
+        return modelDescriptor;
+    }
+
+    public CompositeMethodModel method()
+    {
+        return method;
+    }
+
+    public Field field()
+    {
+        return field;
+    }
+
+    public Resolution forField( final Field injectedField )
+    {
+        return new Resolution( application, layer, module, modelDescriptor, method, injectedField );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectModel.java
new file mode 100644
index 0000000..c1a3dbf
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectModel.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.object;
+
+import java.util.stream.Stream;
+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.mixin.Initializable;
+import org.apache.polygene.api.mixin.InitializationException;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.composite.ConstructorsModel;
+import org.apache.polygene.runtime.injection.InjectedFieldsModel;
+import org.apache.polygene.runtime.injection.InjectedMethodsModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+
+/**
+ * JAVADOC
+ */
+public final class ObjectModel
+    implements ObjectDescriptor, VisitableHierarchy<Object, Object>
+{
+    private final ModuleDescriptor module;
+    private final Class<?> objectType;
+    private final Visibility visibility;
+    private final MetaInfo metaInfo;
+    private final ConstructorsModel constructorsModel;
+    private final InjectedFieldsModel injectedFieldsModel;
+    private final InjectedMethodsModel injectedMethodsModel;
+
+    public ObjectModel( ModuleDescriptor module,
+                        Class<?> objectType,
+                        Visibility visibility,
+                        MetaInfo metaInfo
+    )
+    {
+        this.module = module;
+        this.objectType = objectType;
+        this.visibility = visibility;
+        this.metaInfo = metaInfo;
+
+        constructorsModel = new ConstructorsModel( objectType );
+        injectedFieldsModel = new InjectedFieldsModel( objectType );
+        injectedMethodsModel = new InjectedMethodsModel( objectType );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public Stream<Class<?>> types()
+    {
+        return Stream.of( objectType );
+    }
+
+    @Override
+    public Visibility visibility()
+    {
+        return visibility;
+    }
+
+    @Override
+    public ModuleDescriptor module()
+    {
+        return module;
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    @Override
+    public boolean isAssignableTo( Class<?> type )
+    {
+        return type.isAssignableFrom( objectType );
+    }
+
+    @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 );
+    }
+
+    public Object newInstance( InjectionContext injectionContext )
+    {
+        Object instance;
+        try
+        {
+            instance = constructorsModel.newInstance( injectionContext );
+            injectionContext = new InjectionContext( injectionContext.module(), injectionContext.uses(), instance );
+            injectedFieldsModel.inject( injectionContext, instance );
+            injectedMethodsModel.inject( injectionContext, instance );
+        }
+        catch( Exception e )
+        {
+            throw new ConstructionException( "Could not instantiate " + objectType.getName(), e );
+        }
+
+        if( instance instanceof Initializable )
+        {
+            try
+            {
+                ( (Initializable) instance ).initialize();
+            }
+            catch( Exception e )
+            {
+                String message = "Unable to initialize " + objectType;
+                throw new ConstructionException( new InitializationException( message, e ) );
+            }
+        }
+
+        return instance;
+    }
+
+    public void inject( InjectionContext injectionContext, Object instance )
+    {
+        injectedFieldsModel.inject( injectionContext, instance );
+        injectedMethodsModel.inject( injectionContext, instance );
+    }
+
+    @Override
+    public String toString()
+    {
+        return objectType.getName();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectsModel.java
new file mode 100644
index 0000000..84d2c11
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectsModel.java
@@ -0,0 +1,62 @@
+/*
+ *  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.object;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public class ObjectsModel
+    implements VisitableHierarchy<Object, Object>
+{
+    private final List<ObjectModel> objectModels;
+
+    public ObjectsModel( List<ObjectModel> objectModels )
+    {
+        this.objectModels = objectModels;
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( ObjectModel objectModel : objectModels )
+            {
+                if( !objectModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+        return visitor.visitLeave( this );
+    }
+
+    public Stream<ObjectModel> models()
+    {
+        return objectModels.stream();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/package.html
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/package.html b/core/runtime/src/main/java/org/apache/polygene/runtime/package.html
new file mode 100644
index 0000000..1ed6d55
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  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.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Apache Polygene\u2122 Runtime.</h2>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertiesModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertiesModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertiesModel.java
new file mode 100644
index 0000000..cfcfcb5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertiesModel.java
@@ -0,0 +1,107 @@
+/*
+ *  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.property;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * Base class for properties model
+ */
+public class PropertiesModel
+    implements VisitableHierarchy<Object, Object>
+{
+    protected final Map<AccessibleObject, PropertyModel> mapAccessiblePropertyModel = new LinkedHashMap<>();
+
+    public PropertiesModel()
+    {
+    }
+
+    public void addProperty( PropertyModel property )
+    {
+        mapAccessiblePropertyModel.put( property.accessor(), property );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        if( visitor.visitEnter( this ) )
+        {
+            for( PropertyModel propertyModel : mapAccessiblePropertyModel.values() )
+            {
+                if( !propertyModel.accept( visitor ) )
+                {
+                    break;
+                }
+            }
+        }
+
+        return visitor.visitLeave( this );
+    }
+
+    public Stream<PropertyModel> properties()
+    {
+        return mapAccessiblePropertyModel.values().stream();
+    }
+
+    public PropertyModel getProperty( AccessibleObject accessor )
+    {
+        PropertyModel propertyModel = mapAccessiblePropertyModel.get( accessor );
+        if( propertyModel == null )
+        {
+            throw new IllegalArgumentException( "No property found with name: " + ( (Member) accessor ).getName() );
+        }
+
+        return propertyModel;
+    }
+
+    public PropertyModel getPropertyByName( String name )
+        throws IllegalArgumentException
+    {
+        for( PropertyModel propertyModel : mapAccessiblePropertyModel.values() )
+        {
+            if( propertyModel.qualifiedName().name().equals( name ) )
+            {
+                return propertyModel;
+            }
+        }
+        throw new IllegalArgumentException( "No property found with name: " + name );
+    }
+
+    public PropertyModel getPropertyByQualifiedName( QualifiedName name )
+        throws IllegalArgumentException
+    {
+        for( PropertyModel propertyModel : mapAccessiblePropertyModel.values() )
+        {
+            if( propertyModel.qualifiedName().equals( name ) )
+            {
+                return propertyModel;
+            }
+        }
+        throw new IllegalArgumentException( "No property found with qualified name: " + name );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInfo.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInfo.java b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInfo.java
new file mode 100644
index 0000000..fa8e1e6
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInfo.java
@@ -0,0 +1,37 @@
+/*
+ *  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.property;
+
+import java.lang.reflect.Type;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.runtime.composite.ConstraintsCheck;
+
+/**
+ * TODO
+ */
+public interface PropertyInfo
+    extends ConstraintsCheck
+{
+    boolean isImmutable();
+
+    QualifiedName qualifiedName();
+
+    Type type();
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInstance.java
new file mode 100644
index 0000000..72d39cb
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInstance.java
@@ -0,0 +1,326 @@
+/*
+ *  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.property;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.property.PropertyWrapper;
+import org.apache.polygene.api.type.CollectionType;
+import org.apache.polygene.api.type.MapType;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.runtime.value.ValueInstance;
+
+/**
+ * {@code PropertyInstance} represents a property.
+ */
+public class PropertyInstance<T>
+    implements Property<T>
+{
+    protected volatile T value;
+    protected PropertyInfo model;
+
+    /**
+     * Construct an instance of {@code PropertyInstance} with the specified arguments.
+     *
+     * @param model  The property model. This argument must not be {@code null}.
+     * @param aValue The property value.
+     */
+    public PropertyInstance( PropertyInfo model, T aValue )
+    {
+        this.model = model;
+        value = aValue;
+    }
+
+    public PropertyInfo propertyInfo()
+    {
+        return model;
+    }
+
+    /**
+     * @param model The property model. This argument must not be {@code null}.
+     */
+    public void setPropertyInfo( PropertyInfo model )
+    {
+        this.model = model;
+    }
+
+    /**
+     * Returns this property value.
+     *
+     * @return This property value.
+     */
+    @Override
+    public T get()
+    {
+        return value;
+    }
+
+    /**
+     * Sets this property value.
+     *
+     * @param aNewValue The new value.
+     */
+    @Override
+    public void set( T aNewValue )
+    {
+        if( model.isImmutable() )
+        {
+            throw new IllegalStateException( "Property [" + model.qualifiedName() + "] is immutable." );
+        }
+
+        model.checkConstraints( aNewValue );
+
+        value = aNewValue;
+    }
+
+    /**
+     * Perform equals with {@code o} argument.
+     * <p>
+     *     The definition of equals() for the Property is that if both the state and descriptor are equal,
+     *     then the properties are equal.
+     * </p>
+     *
+     * @param o The other object to compare.
+     * @return Returns a {@code boolean} indicator whether this object is equals the other.
+     */
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        Property<?> that = (Property<?>) o;
+        // Unwrap if needed
+        while( that instanceof PropertyWrapper )
+        {
+            that = ( (PropertyWrapper) that ).next();
+        }
+        // Descriptor equality
+        PropertyDescriptor thatDescriptor = (PropertyDescriptor) ( (PropertyInstance) that ).propertyInfo();
+        if( !model.equals( thatDescriptor ) )
+        {
+            return false;
+        }
+        // State equality
+        T value = get();
+        if( value == null )
+        {
+            return that.get() == null;
+        }
+        return value.equals( that.get() );
+    }
+
+    /**
+     * Calculate hash code.
+     *
+     * @return the hashcode of this instance.
+     */
+    @Override
+    public int hashCode()
+    {
+        int hash = model.hashCode() * 19; // Descriptor
+        T value = get();
+        if( value != null )
+        {
+            hash += value.hashCode() * 13; // State
+        }
+        return hash;
+    }
+
+    /**
+     * Returns the value as string.
+     *
+     * @return The value as string.
+     */
+    @Override
+    public String toString()
+    {
+        Object value = get();
+        return value == null ? "" : value.toString();
+    }
+
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public void prepareToBuild( PropertyModel propertyDescriptor )
+    {
+        // Check if state has to be modified
+        model = propertyDescriptor.getBuilderInfo();
+        if( propertyDescriptor.valueType() instanceof ValueCompositeType )
+        {
+            Object value = get();
+            if( value != null )
+            {
+                ValueInstance.valueInstanceOf( (ValueComposite) value ).prepareToBuild();
+            }
+        }
+        else if( propertyDescriptor.valueType() instanceof CollectionType )
+        {
+            Object value = get();
+
+            if( value != null )
+            {
+                if( value instanceof List )
+                {
+                    value = new ArrayList( (Collection) value );
+                }
+                else if( value instanceof Set )
+                {
+                    value = new LinkedHashSet( (Collection) value );
+                }
+
+                // Check if items are Values
+                CollectionType collection = (CollectionType) propertyDescriptor.valueType();
+                if( collection.collectedType() instanceof ValueCompositeType )
+                {
+                    Collection coll = (Collection) value;
+                    for( Object instance : coll )
+                    {
+                        ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareToBuild();
+                    }
+                }
+
+                set( (T) value );
+            }
+        }
+        else if( propertyDescriptor.valueType() instanceof MapType )
+        {
+            Object value = get();
+
+            if( value != null )
+            {
+                Map map = new LinkedHashMap( (Map) value );
+
+                // Check if keys/values are Values
+                MapType mapType = (MapType) propertyDescriptor.valueType();
+                if( mapType.keyType() instanceof ValueCompositeType )
+                {
+                    for( Object instance : map.keySet() )
+                    {
+                        ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareToBuild();
+                    }
+                }
+                if( mapType.valueType() instanceof ValueCompositeType )
+                {
+                    for( Object instance : map.values() )
+                    {
+                        ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareToBuild();
+                    }
+                }
+
+                set( (T) value );
+            }
+        }
+    }
+
+    @SuppressWarnings( {"raw", "unchecked"} )
+    public void prepareBuilderState( PropertyModel propertyDescriptor )
+    {
+        // Check if state has to be modified
+        if( propertyDescriptor.valueType() instanceof ValueCompositeType )
+        {
+            Object value = get();
+            if( value != null )
+            {
+                ValueInstance.valueInstanceOf( (ValueComposite) value ).prepareBuilderState();
+            }
+        }
+        else if( propertyDescriptor.valueType() instanceof CollectionType )
+        {
+            T value = get();
+            if( value != null )
+            {
+                if( propertyDescriptor.isImmutable() )
+                {
+                    if( value instanceof List )
+                    {
+                        value = (T) Collections.unmodifiableList( (List<? extends Object>) value );
+                    }
+                    else if( value instanceof Set )
+                    {
+                        value = (T) Collections.unmodifiableSet( (Set<? extends Object>) value );
+                    }
+                    else
+                    {
+                        value = (T) Collections.unmodifiableCollection( (Collection<? extends Object>) value );
+                    }
+
+                    this.value = value;
+                }
+
+                CollectionType collection = (CollectionType) propertyDescriptor.valueType();
+                if( collection.collectedType() instanceof ValueCompositeType )
+                {
+                    Collection coll = (Collection) value;
+                    for( Object instance : coll )
+                    {
+                        ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareBuilderState();
+                    }
+                }
+            }
+        }
+        else if( propertyDescriptor.valueType() instanceof MapType )
+        {
+            T value = get();
+
+            if( value != null )
+            {
+                MapType mapType = (MapType) propertyDescriptor.valueType();
+                if( mapType.keyType() instanceof ValueCompositeType )
+                {
+                    Map map = (Map) value;
+                    for( Object instance : map.keySet() )
+                    {
+                        ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareBuilderState();
+                    }
+                }
+                if( mapType.valueType() instanceof ValueCompositeType )
+                {
+                    Map map = (Map) value;
+                    for( Object instance : map.values() )
+                    {
+                        ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareBuilderState();
+                    }
+                }
+                if( propertyDescriptor.isImmutable() )
+                {
+                    value = (T) Collections.unmodifiableMap( (Map<?, ?>) value );
+                }
+
+                this.value = value;
+            }
+        }
+
+        model = propertyDescriptor;
+    }
+}