polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject [15/81] [abbrv] [partial] zest-java git commit: ZEST-195 ; Replace all "zest" with "polygene"
Date Sat, 17 Dec 2016 10:27:51 GMT
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AssemblyHelper.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AssemblyHelper.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AssemblyHelper.java
new file mode 100644
index 0000000..1263e29
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AssemblyHelper.java
@@ -0,0 +1,214 @@
+/*
+ *  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.bootstrap;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.common.AppliesToFilter;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.runtime.composite.ConcernModel;
+import org.apache.polygene.runtime.composite.ConstraintDeclaration;
+import org.apache.polygene.runtime.composite.FragmentClassLoader;
+import org.apache.polygene.runtime.composite.MixinModel;
+import org.apache.polygene.runtime.composite.SideEffectModel;
+
+/**
+ * This helper is used when building the application model. It keeps track
+ * of already created classloaders and various models
+ */
+@SuppressWarnings("WeakerAccess")
+public class AssemblyHelper
+{
+    private Map<Class, Class> instantiationClasses = new HashMap<>();
+    private Map<Class, ConstraintDeclaration> constraintDeclarations = new HashMap<>();
+    private Map<ClassLoader, FragmentClassLoader> modifierClassLoaders = new HashMap<>();
+    private Map<Class<?>, AppliesToFilter> appliesToInstances = new HashMap<>();
+
+    protected MixinModel getMixinModel(Class mixinClass)
+    {
+        return new MixinModel( mixinClass, instantiationClass( mixinClass ) );
+    }
+
+    protected ConcernModel getConcernModel(Class concernClass)
+    {
+        return new ConcernModel( concernClass, instantiationClass( concernClass ) );
+    }
+
+    protected SideEffectModel getSideEffectModel(Class sideEffectClass)
+    {
+        return new SideEffectModel( sideEffectClass, instantiationClass( sideEffectClass ) );
+    }
+
+    protected Class instantiationClass(Class fragmentClass)
+    {
+        Class instantiationClass = fragmentClass;
+        if( !InvocationHandler.class.isAssignableFrom( fragmentClass ) )
+        {
+            instantiationClass = instantiationClasses.get( fragmentClass );
+
+            if( instantiationClass == null )
+            {
+                try
+                {
+                    FragmentClassLoader fragmentLoader = getModifierClassLoader( fragmentClass.getClassLoader() );
+                    instantiationClass = fragmentLoader.loadFragmentClass( fragmentClass );
+                    instantiationClasses.put( fragmentClass, instantiationClass );
+                }
+                catch( ClassNotFoundException | VerifyError e )
+                {
+                    throw new ConstructionException( "Could not generate mixin subclass " + fragmentClass.getName(), e );
+                }
+            }
+        }
+        return instantiationClass;
+    }
+
+    protected FragmentClassLoader getModifierClassLoader( ClassLoader classLoader )
+    {
+        FragmentClassLoader cl = modifierClassLoaders.get( classLoader );
+        if( cl == null )
+        {
+            cl = instantiateFragmentClassLoader( classLoader );
+            modifierClassLoaders.put( classLoader, cl );
+        }
+        return cl;
+    }
+
+    protected FragmentClassLoader instantiateFragmentClassLoader( ClassLoader classLoader )
+    {
+        return new FragmentClassLoader( classLoader );
+    }
+
+    public boolean appliesTo( Class<?> fragmentClass, Method method, Iterable<Class<?>> types, Class<?> mixinClass )
+    {
+        AppliesToFilter appliesToFilter = appliesToInstances.get( fragmentClass );
+        if( appliesToFilter == null )
+        {
+            appliesToFilter = createAppliesToFilter( fragmentClass );
+            appliesToInstances.put( fragmentClass, appliesToFilter );
+        }
+        for( Class<?> compositeType : types )
+        {
+            if( appliesToFilter.appliesTo( method, mixinClass, compositeType, fragmentClass ) )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected AppliesToFilter createAppliesToFilter( Class<?> fragmentClass )
+    {
+        AppliesToFilter result = null;
+        if( !InvocationHandler.class.isAssignableFrom( fragmentClass ) )
+        {
+            result = new TypedFragmentAppliesToFilter();
+            if( Modifier.isAbstract( fragmentClass.getModifiers() ) )
+            {
+                result = new AndAppliesToFilter( result, new ImplementsMethodAppliesToFilter() );
+            }
+        }
+        result = applyAppliesTo( result, fragmentClass );
+        if( result == null )
+        {
+            return AppliesToFilter.ALWAYS;
+        }
+        return result;
+    }
+
+    protected AppliesToFilter applyAppliesTo( AppliesToFilter existing, Class<?> modifierClass )
+    {
+        AppliesTo appliesTo = modifierClass.getAnnotation( AppliesTo.class );
+        if( appliesTo != null )
+        {
+            // Use "or" for all filters specified in the annotation
+            AppliesToFilter appliesToAnnotation = null;
+            for( Class<?> appliesToClass : appliesTo.value() )
+            {
+                AppliesToFilter filter;
+                if( AppliesToFilter.class.isAssignableFrom( appliesToClass ) )
+                {
+                    try
+                    {
+                        @SuppressWarnings("unchecked")
+                        Constructor<AppliesToFilter> cons = (Constructor<AppliesToFilter>) appliesToClass.getDeclaredConstructor();
+                        cons.setAccessible(true);
+                        filter = cons.newInstance();
+                    }
+                    catch( Exception e )
+                    {
+                        throw new ConstructionException( e );
+                    }
+                }
+                else if( Annotation.class.isAssignableFrom( appliesToClass ) )
+                {
+                    filter = new AnnotationAppliesToFilter( appliesToClass );
+                }
+                else // Type check
+                {
+                    filter = new TypeCheckAppliesToFilter( appliesToClass );
+                }
+
+                if( appliesToAnnotation == null )
+                {
+                    appliesToAnnotation = filter;
+                }
+                else
+                {
+                    appliesToAnnotation = new OrAppliesToFilter( appliesToAnnotation, filter );
+                }
+            }
+            // Add to the rest of the rules using "and"
+            if( existing == null )
+            {
+                return appliesToAnnotation;
+            }
+            else
+            {
+                return new AndAppliesToFilter( existing, appliesToAnnotation );
+            }
+        }
+        return existing;
+    }
+
+    public boolean appliesTo( Class<? extends Constraint<?, ?>> constraint,
+                              Class<? extends Annotation> annotationType,
+                              Type valueType
+    )
+    {
+        ConstraintDeclaration constraintDeclaration = constraintDeclarations.get( constraint );
+        if( constraintDeclaration == null )
+        {
+            constraintDeclaration = new ConstraintDeclaration( constraint );
+            constraintDeclarations.put( constraint, constraintDeclaration );
+        }
+
+        return constraintDeclaration.appliesTo( annotationType, valueType );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java
new file mode 100644
index 0000000..1e0fb26
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/CompositeAssemblyImpl.java
@@ -0,0 +1,909 @@
+/*
+ *  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.bootstrap;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.GenericAssociationInfo;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.InvalidCompositeException;
+import org.apache.polygene.api.concern.Concerns;
+import org.apache.polygene.api.constraint.Constraint;
+import org.apache.polygene.api.constraint.ConstraintDeclaration;
+import org.apache.polygene.api.constraint.Constraints;
+import org.apache.polygene.api.constraint.Name;
+import org.apache.polygene.api.entity.Lifecycle;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.GenericPropertyInfo;
+import org.apache.polygene.api.property.Immutable;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.sideeffect.SideEffects;
+import org.apache.polygene.api.type.HasTypes;
+import org.apache.polygene.api.util.Annotations;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.Fields;
+import org.apache.polygene.api.util.HierarchicalVisitorAdapter;
+import org.apache.polygene.bootstrap.StateDeclarations;
+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.AbstractConstraintModel;
+import org.apache.polygene.runtime.composite.CompositeConstraintModel;
+import org.apache.polygene.runtime.composite.CompositeMethodModel;
+import org.apache.polygene.runtime.composite.CompositeMethodsModel;
+import org.apache.polygene.runtime.composite.ConcernModel;
+import org.apache.polygene.runtime.composite.ConcernsModel;
+import org.apache.polygene.runtime.composite.ConstraintModel;
+import org.apache.polygene.runtime.composite.ConstraintsModel;
+import org.apache.polygene.runtime.composite.Genericpredicate;
+import org.apache.polygene.runtime.composite.MixinModel;
+import org.apache.polygene.runtime.composite.MixinsModel;
+import org.apache.polygene.runtime.composite.SideEffectModel;
+import org.apache.polygene.runtime.composite.SideEffectsModel;
+import org.apache.polygene.runtime.composite.StateModel;
+import org.apache.polygene.runtime.composite.ValueConstraintsInstance;
+import org.apache.polygene.runtime.composite.ValueConstraintsModel;
+import org.apache.polygene.runtime.injection.Dependencies;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.property.PropertiesModel;
+import org.apache.polygene.runtime.property.PropertyModel;
+
+import static java.util.stream.Stream.concat;
+import static org.apache.polygene.api.util.Annotations.isType;
+import static org.apache.polygene.api.util.Annotations.typeHasAnnotation;
+import static org.apache.polygene.api.util.Classes.classHierarchy;
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+import static org.apache.polygene.api.util.Classes.isAssignableFrom;
+import static org.apache.polygene.api.util.Classes.typeOf;
+import static org.apache.polygene.api.util.Classes.typesOf;
+import static org.apache.polygene.api.util.Classes.wrapperClass;
+
+/**
+ * Declaration of a Composite.
+ */
+public abstract class CompositeAssemblyImpl
+    implements HasTypes
+{
+    protected List<Class<?>> concerns = new ArrayList<>();
+    protected List<Class<?>> sideEffects = new ArrayList<>();
+    protected List<Class<?>> mixins = new ArrayList<>();
+    protected List<Class<?>> types = new ArrayList<>();
+    protected MetaInfo metaInfo = new MetaInfo();
+    protected Visibility visibility = Visibility.module;
+
+    protected boolean immutable;
+    protected PropertiesModel propertiesModel;
+    protected StateModel stateModel;
+    protected MixinsModel mixinsModel;
+    protected CompositeMethodsModel compositeMethodsModel;
+    private AssemblyHelper helper;
+    protected StateDeclarations stateDeclarations;
+
+    protected Set<String> registeredStateNames = new HashSet<>();
+
+    public CompositeAssemblyImpl( Class<?> mainType )
+    {
+        types.add( mainType );
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return types.stream();
+    }
+
+    protected StateModel createStateModel()
+    {
+        return new StateModel( propertiesModel );
+    }
+
+    protected MixinsModel createMixinsModel()
+    {
+        return new MixinsModel();
+    }
+
+    protected void buildComposite( AssemblyHelper helper,
+                                   StateDeclarations stateDeclarations
+    )
+    {
+        this.stateDeclarations = stateDeclarations;
+        this.helper = helper;
+        for( Class<?> compositeType : types )
+        {
+            metaInfo = new MetaInfo( metaInfo ).withAnnotations( compositeType );
+            addAnnotationsMetaInfo( compositeType, metaInfo );
+        }
+
+        immutable = metaInfo.get( Immutable.class ) != null;
+        propertiesModel = new PropertiesModel();
+        stateModel = createStateModel();
+        mixinsModel = createMixinsModel();
+//        compositeMethodsModel = new CompositeMethodsModel();
+        compositeMethodsModel = new CompositeMethodsModel( mixinsModel );
+
+        // Implement composite methods
+        List<Class<?>> constraintClasses = toList( constraintDeclarations( getAllTypes() ) );
+        List<Class<?>> concernClasses = toList( concat( concerns.stream(), concernDeclarations( getAllTypes() ) ) );
+        List<Class<?>> sideEffectClasses = toList( concat( sideEffects.stream(), sideEffectDeclarations( getAllTypes() ) ) );
+        List<Class<?>> mixinClasses = toList( concat( mixins.stream(), mixinDeclarations( getAllTypes() ) ) );
+        //noinspection unchecked
+        implementMixinType( types,
+                            constraintClasses,
+                            concernClasses,
+                            sideEffectClasses,
+                            mixinClasses
+        );
+
+        // Add state from methods and fields
+        //noinspection unchecked
+        addState( constraintClasses );
+    }
+
+    private List<Class<?>> toList( Stream<Class<?>> stream )
+    {
+        return stream.collect( Collectors.toList() );
+    }
+
+    protected void addAnnotationsMetaInfo( Class<?> type, MetaInfo compositeMetaInfo )
+    {
+        Class[] declaredInterfaces = type.getInterfaces();
+        for( int i = declaredInterfaces.length - 1; i >= 0; i-- )
+        {
+            addAnnotationsMetaInfo( declaredInterfaces[ i ], compositeMetaInfo );
+        }
+        compositeMetaInfo.withAnnotations( type );
+    }
+
+    protected void implementMixinType( List<? extends Class<?>> types,
+                                       List<Class<?>> constraintClasses,
+                                       List<Class<?>> concernClasses,
+                                       List<Class<?>> sideEffectClasses,
+                                       List<Class<?>> mixinClasses
+    )
+    {
+        Set<Class<?>> thisDependencies = new HashSet<>();
+        types.forEach( mixinType -> {
+            for( Method method : mixinType.getMethods() )
+            {
+                if( !compositeMethodsModel.isImplemented( method )
+                    && !Proxy.class.equals( method.getDeclaringClass().getSuperclass() )
+                    && !Proxy.class.equals( method.getDeclaringClass() )
+                    && !Modifier.isStatic( method.getModifiers() ) )
+                {
+                    MixinModel mixinModel = implementMethod( method, mixinClasses );
+                    ConcernsModel concernsModel = concernsFor(
+                        method,
+                        mixinModel.mixinClass(),
+                        concat( concernDeclarations( mixinModel.mixinClass() ),
+                                concernClasses.stream() )
+                    );
+                    SideEffectsModel sideEffectsModel = sideEffectsFor(
+                        method,
+                        mixinModel.mixinClass(),
+                        concat( sideEffectDeclarations( mixinModel.mixinClass() ),
+                                sideEffectClasses.stream() )
+                    );
+                    method.setAccessible( true );
+                    ConstraintsModel constraints = constraintsFor(
+                        method,
+                        toList( concat( constraintDeclarations( mixinModel.mixinClass() ),
+                                        constraintClasses.stream() ) )
+                    );
+                    CompositeMethodModel methodComposite = new CompositeMethodModel(
+                        method,
+                        constraints,
+                        concernsModel,
+                        sideEffectsModel,
+                        mixinsModel
+                    );
+
+                    Stream<? extends Dependencies> source = Stream.of( methodComposite, mixinModel );
+                    source.flatMap( Dependencies::dependencies )
+                          .filter( new DependencyModel.ScopeSpecification( This.class ) )
+                          .map( DependencyModel::rawInjectionType )
+                          .forEach( thisDependencies::add );
+
+                    interfacesOf( mixinModel.mixinClass() )
+                        .map( Classes.RAW_CLASS )
+                        .filter( clazz -> Stream.of( Initializable.class, Lifecycle.class, InvocationHandler.class )
+                                                .noneMatch( c -> c.equals( clazz ) ) )
+                        .forEach( thisDependencies::add );
+
+                    compositeMethodsModel.addMethod( methodComposite );
+                }
+            }
+            // Add type to set of mixin types
+            mixinsModel.addMixinType( mixinType );
+        } );
+
+        // Implement all @This dependencies that were found
+        thisDependencies.forEach( thisDependency -> {
+            // Add additional declarations from the @This type
+            Stream<Class<?>> typeConstraintClasses = concat(
+                constraintClasses.stream(),
+                constraintDeclarations( thisDependency ) );
+            Stream<Class<?>> typeConcernClasses = concat(
+                concernClasses.stream(),
+                concernDeclarations( thisDependency ) );
+            Stream<Class<?>> typeSideEffectClasses = concat(
+                sideEffectClasses.stream(),
+                sideEffectDeclarations( thisDependency ) );
+            Stream<Class<?>> typeMixinClasses = concat(
+                mixinClasses.stream(),
+                mixinDeclarations( thisDependency ) );
+            List<? extends Class<?>> singleton = Collections.singletonList( thisDependency );
+            implementMixinType( singleton,
+                                toList( typeConstraintClasses ),
+                                toList( typeConcernClasses ),
+                                toList( typeSideEffectClasses ),
+                                toList( typeMixinClasses )
+            );
+        } );
+    }
+
+    @SuppressWarnings( "raw" )
+    protected MixinModel implementMethod( Method method, List<Class<?>> mixinDeclarations )
+    {
+        MixinModel implementationModel = mixinsModel.mixinFor( method );
+        if( implementationModel != null )
+        {
+            return implementationModel;
+        }
+        Class mixinClass = findTypedImplementation( method, mixinDeclarations.stream() );
+        if( mixinClass != null )
+        {
+            return implementMethodWithClass( method, mixinClass );
+        }
+
+        // Check generic implementations
+        mixinClass = findGenericImplementation( method, mixinDeclarations.stream() );
+        if( mixinClass != null )
+        {
+            return implementMethodWithClass( method, mixinClass );
+        }
+
+        throw new InvalidCompositeException( "No implementation found for method \n    " + method.toGenericString()
+                                             + "\nin\n    " + types );
+    }
+
+    private Class<?> findTypedImplementation( final Method method, Stream<Class<?>> mixins )
+    {
+        // Check if mixinClass implements the method. If so, check if the mixinClass is generic or if the filter passes.
+        // If a mixinClass is both generic AND non-generic at the same time, then the filter applies to the non-generic
+        // side only.
+        Predicate<Class<?>> appliesToSpec = item -> helper.appliesTo( item, method, types, item );
+        return mixins.filter( isAssignableFrom( method.getDeclaringClass() )
+                                  .and( Genericpredicate.INSTANCE.or( appliesToSpec ) ) )
+                     .findFirst().orElse( null );
+    }
+
+    private Class<?> findGenericImplementation( final Method method, Stream<Class<?>> mixins )
+    {
+        // Check if mixinClass is generic and the applies-to filter passes
+        Predicate<Class<?>> appliesToSpec = item -> helper.appliesTo( item, method, types, item );
+        return mixins.filter( Genericpredicate.INSTANCE.and( appliesToSpec ) ).findFirst().orElse( null );
+    }
+
+    private MixinModel implementMethodWithClass( Method method, Class mixinClass )
+    {
+        MixinModel mixinModel = mixinsModel.getMixinModel( mixinClass );
+        if( mixinModel == null )
+        {
+            mixinModel = helper.getMixinModel( mixinClass );
+            mixinsModel.addMixinModel( mixinModel );
+        }
+
+        mixinsModel.addMethodMixin( method, mixinModel );
+
+        return mixinModel;
+    }
+
+    protected void addState( final List<Class<?>> constraintClasses )
+    {
+        // Add method state
+        compositeMethodsModel.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
+        {
+            @Override
+            public boolean visitEnter( Object visited )
+                throws RuntimeException
+            {
+                if( visited instanceof CompositeMethodModel )
+                {
+                    CompositeMethodModel methodModel = (CompositeMethodModel) visited;
+                    if( methodModel.method().getParameterTypes().length == 0 )
+                    {
+                        addStateFor( methodModel.method(), constraintClasses );
+                    }
+
+                    return false;
+                }
+
+                return super.visitEnter( visited );
+            }
+        } );
+
+        // Add field state
+        mixinsModel.accept( new HierarchicalVisitorAdapter<Object, Object, RuntimeException>()
+        {
+            @Override
+            public boolean visitEnter( Object visited )
+                throws RuntimeException
+            {
+                if( visited instanceof MixinModel )
+                {
+                    MixinModel model = (MixinModel) visited;
+                    Consumer<Field> addState = field -> addStateFor( field, constraintClasses );
+                    Fields.FIELDS_OF.apply( model.mixinClass() )
+                        .filter( Annotations.hasAnnotation( State.class ) )
+                        .forEach( addState );
+                    return false;
+                }
+                return super.visitEnter( visited );
+            }
+        } );
+    }
+
+    protected void addStateFor( AccessibleObject accessor, List<Class<?>> constraintClasses )
+    {
+        String stateName = QualifiedName.fromAccessor( accessor ).name();
+
+        if( registeredStateNames.contains( stateName ) )
+        {
+            return; // Skip already registered names
+        }
+
+        Class<?> accessorType = Classes.RAW_CLASS.apply( typeOf( accessor ) );
+        if( Property.class.isAssignableFrom( accessorType ) )
+        {
+            propertiesModel.addProperty( newPropertyModel( accessor, constraintClasses ) );
+            registeredStateNames.add( stateName );
+        }
+        else if( Association.class.isAssignableFrom( accessorType ) )
+        {
+            associationsModel().addAssociation( newAssociationModel( accessor, constraintClasses ) );
+            registeredStateNames.add( stateName );
+        }
+        else if( ManyAssociation.class.isAssignableFrom( accessorType ) )
+        {
+            manyAssociationsModel().addManyAssociation( newManyAssociationModel( accessor, constraintClasses ) );
+            registeredStateNames.add( stateName );
+        }
+        else if( NamedAssociation.class.isAssignableFrom( accessorType ) )
+        {
+            namedAssociationsModel().addNamedAssociation( newNamedAssociationModel( accessor, constraintClasses ) );
+            registeredStateNames.add( stateName );
+        }
+    }
+
+    protected AssociationsModel associationsModel()
+    {
+        return null;
+    }
+
+    protected ManyAssociationsModel manyAssociationsModel()
+    {
+        return null;
+    }
+
+    protected NamedAssociationsModel namedAssociationsModel()
+    {
+        return null;
+    }
+
+    protected PropertyModel newPropertyModel( AccessibleObject accessor,
+                                              List<Class<?>> constraintClasses
+    )
+    {
+        List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
+        boolean optional = annotations.stream().anyMatch( isType( Optional.class ) );
+        ValueConstraintsModel valueConstraintsModel = constraintsFor(
+            annotations.stream(),
+            GenericPropertyInfo.propertyTypeOf( accessor ),
+            ( (Member) accessor ).getName(),
+            optional,
+            constraintClasses,
+            accessor );
+        ValueConstraintsInstance valueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            valueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
+        UseDefaults useDefaultsDeclaration = metaInfo.get( UseDefaults.class );
+        Object initialValue = stateDeclarations.initialValueOf( accessor );
+        if( initialValue == null && useDefaultsDeclaration != null )
+        {
+            initialValue = useDefaultsDeclaration.value();
+        }
+        boolean useDefaults = useDefaultsDeclaration != null || stateDeclarations.useDefaults( accessor );
+        boolean immutable = this.immutable || metaInfo.get( Immutable.class ) != null;
+        return new PropertyModel(
+            accessor,
+            immutable,
+            useDefaults,
+            valueConstraintsInstance,
+            metaInfo,
+            initialValue
+        );
+    }
+
+    // Model
+    private ConstraintsModel constraintsFor( Method method,
+                                             List<Class<?>> constraintClasses
+    )
+    {
+        List<ValueConstraintsModel> parameterConstraintModels = Collections.emptyList();
+        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+        Type[] parameterTypes = method.getGenericParameterTypes();
+        boolean constrained = false;
+        for( int i = 0; i < parameterAnnotations.length; i++ )
+        {
+            Annotation[] parameterAnnotation = parameterAnnotations[ i ];
+
+            Name nameAnnotation = (Name) Stream.of( parameterAnnotation ).filter( isType( Name.class ) )
+                                               .findFirst().orElse( null );
+            String name = nameAnnotation == null ? "param" + ( i + 1 ) : nameAnnotation.value();
+
+            boolean optional = Stream.of( parameterAnnotation ).filter( isType( Optional.class ) )
+                                     .findFirst().isPresent();
+            ValueConstraintsModel parameterConstraintsModel = constraintsFor(
+                Arrays.stream( parameterAnnotation ),
+                parameterTypes[ i ],
+                name,
+                optional,
+                constraintClasses,
+                method );
+            if( parameterConstraintsModel.isConstrained() )
+            {
+                constrained = true;
+            }
+
+            if( parameterConstraintModels.isEmpty() )
+            {
+                parameterConstraintModels = new ArrayList<>();
+            }
+            parameterConstraintModels.add( parameterConstraintsModel );
+        }
+
+        if( !constrained )
+        {
+            return new ConstraintsModel( Collections.<ValueConstraintsModel>emptyList() );
+        }
+        else
+        {
+            return new ConstraintsModel( parameterConstraintModels );
+        }
+    }
+
+    protected ValueConstraintsModel constraintsFor(
+        Stream<Annotation> constraintAnnotations,
+        Type valueType,
+        String name,
+        boolean optional,
+        Iterable<Class<?>> constraintClasses,
+        AccessibleObject accessor
+    )
+    {
+        valueType = wrapperClass( valueType );
+
+        List<AbstractConstraintModel> constraintModels = new ArrayList<>();
+        List<Annotation> filtered = constraintAnnotations
+            .filter( typeHasAnnotation( ConstraintDeclaration.class ) )
+            .collect( Collectors.toList() );
+
+        // TODO: This massive block below should be cleaned up.
+        nextConstraint:
+        for( Annotation constraintAnnotation : filtered )
+        {
+            // Check composite declarations first
+            Class<? extends Annotation> annotationType = constraintAnnotation.annotationType();
+            for( Class<?> constraint : constraintClasses )
+            {
+                Class<? extends Constraint<?, ?>> constraintType = (Class<? extends Constraint<?, ?>>) constraint;
+                if( helper.appliesTo( constraintType, annotationType, valueType ) )
+                {
+                    constraintModels.add( new ConstraintModel( constraintAnnotation, constraintType ) );
+                    continue nextConstraint;
+                }
+            }
+
+            // Check the annotation itself
+            Constraints constraints = annotationType.getAnnotation( Constraints.class );
+            if( constraints != null )
+            {
+                for( Class<? extends Constraint<?, ?>> constraintClass : constraints.value() )
+                {
+                    if( helper.appliesTo( constraintClass, annotationType, valueType ) )
+                    {
+                        constraintModels.add( new ConstraintModel( constraintAnnotation, constraintClass ) );
+                        continue nextConstraint;
+                    }
+                }
+            }
+
+            // No implementation found!
+            // Check if if it's a composite constraints
+            if( Arrays.stream( annotationType.getAnnotations() )
+                .anyMatch( typeHasAnnotation( ConstraintDeclaration.class ) ) )
+            {
+                ValueConstraintsModel valueConstraintsModel = constraintsFor(
+                    Arrays.stream( annotationType.getAnnotations() ),
+                    valueType,
+                    name,
+                    optional,
+                    constraintClasses,
+                    accessor );
+                CompositeConstraintModel compositeConstraintModel = new CompositeConstraintModel(
+                    constraintAnnotation,
+                    valueConstraintsModel );
+                constraintModels.add( compositeConstraintModel );
+            }
+            else
+            {
+                throw new InvalidCompositeException(
+                    "Cannot find implementation of constraint @"
+                    + annotationType.getSimpleName()
+                    + " for "
+                    + valueType
+                    + " in method "
+                    + ( (Member) accessor ).getName()
+                    + " of composite " + types );
+            }
+        }
+        return new ValueConstraintsModel( constraintModels, name, optional );
+    }
+
+    private ConcernsModel concernsFor( Method method,
+                                       Class<?> mixinClass,
+                                       Stream<Class<?>> concernClasses
+    )
+    {
+        List<ConcernModel> concernsFor = new ArrayList<>();
+        concernClasses.forEach( concern -> {
+            if( helper.appliesTo( concern, method, types, mixinClass ) )
+            {
+                addConcernOrRepositionIfExists( concernsFor, helper.getConcernModel( concern ) );
+            }
+            else
+            {
+                // Lookup method in mixin
+                if( !InvocationHandler.class.isAssignableFrom( mixinClass ) )
+                {
+                    try
+                    {
+                        Method mixinMethod = mixinClass.getMethod( method.getName(), method.getParameterTypes() );
+                        if( helper.appliesTo( concern, mixinMethod, types, mixinClass ) )
+                        {
+                            addConcernOrRepositionIfExists( concernsFor, helper.getConcernModel( concern ) );
+                        }
+                    }
+                    catch( NoSuchMethodException e )
+                    {
+                        // Ignore
+                    }
+                }
+            }
+        } );
+
+        // Check annotations on method that have @Concerns annotations themselves
+        for( Annotation annotation : method.getAnnotations() )
+        {
+            @SuppressWarnings( "raw" )
+            Concerns concerns = annotation.annotationType().getAnnotation( Concerns.class );
+            if( concerns != null )
+            {
+                for( Class<?> concern : concerns.value() )
+                {
+                    if( helper.appliesTo( concern, method, types, mixinClass ) )
+                    {
+                        ConcernModel concernModel = helper.getConcernModel( concern );
+                        addConcernOrRepositionIfExists( concernsFor, concernModel );
+                    }
+                }
+            }
+        }
+
+        if( concernsFor.isEmpty() )
+        {
+            return ConcernsModel.EMPTY_CONCERNS;
+        }
+        else
+        {
+            return new ConcernsModel( concernsFor );
+        }
+    }
+
+    private void addConcernOrRepositionIfExists( List<ConcernModel> concernsFor, ConcernModel concernModel )
+    {
+        // This remove/add is to allow re-ordering of the concerns
+        concernsFor.remove( concernModel );
+        concernsFor.add( concernModel );
+    }
+
+    private SideEffectsModel sideEffectsFor( Method method,
+                                             Class<?> mixinClass,
+                                             Stream<Class<?>> sideEffectClasses
+    )
+    {
+        List<SideEffectModel> sideEffectsFor = new ArrayList<>();
+        sideEffectClasses.forEach( sideEffect -> {
+            SideEffectModel sideEffectModel = helper.getSideEffectModel( sideEffect );
+            if( helper.appliesTo( sideEffect, method, types, mixinClass ) )
+            {
+                addSideEffectOrRepositionIfExists( sideEffectsFor, sideEffectModel );
+            }
+            else
+            {
+                // Lookup method in mixin
+                if( !InvocationHandler.class.isAssignableFrom( mixinClass ) )
+                {
+                    try
+                    {
+                        Method mixinMethod = mixinClass.getMethod( method.getName(), method.getParameterTypes() );
+                        if( helper.appliesTo( sideEffect, mixinMethod, types, mixinClass ) )
+                        {
+                            addSideEffectOrRepositionIfExists( sideEffectsFor, sideEffectModel );
+                        }
+                    }
+                    catch( NoSuchMethodException e )
+                    {
+                        // Ignore
+                    }
+                }
+            }
+        } );
+
+        // Check annotations on method that have @Concerns annotations themselves
+        for( Annotation annotation : method.getAnnotations() )
+        {
+            @SuppressWarnings( "raw" )
+            SideEffects sideEffects = annotation.annotationType().getAnnotation( SideEffects.class );
+            if( sideEffects != null )
+            {
+                for( Class<?> sideEffect : sideEffects.value() )
+                {
+                    if( helper.appliesTo( sideEffect, method, types, mixinClass ) )
+                    {
+                        SideEffectModel sideEffectModel = helper.getSideEffectModel( sideEffect );
+                        addSideEffectOrRepositionIfExists( sideEffectsFor, sideEffectModel );
+                    }
+                }
+            }
+        }
+
+        if( sideEffectsFor.isEmpty() )
+        {
+            return SideEffectsModel.EMPTY_SIDEEFFECTS;
+        }
+        else
+        {
+            return new SideEffectsModel( sideEffectsFor );
+        }
+    }
+
+    private void addSideEffectOrRepositionIfExists( List<SideEffectModel> sideEffectsFor,
+                                                    SideEffectModel sideEffectModel
+    )
+    {
+        // This add/remove is to allow reording of SideEffects.
+        sideEffectsFor.remove( sideEffectModel );
+        sideEffectsFor.add( sideEffectModel );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Stream<Class<?>> constraintDeclarations( Class<?> type )
+    {
+        Stream<? extends Type> types = getTypes( type );
+        return constraintDeclarations( types );
+    }
+
+    private Stream<Class<?>> constraintDeclarations( Stream<? extends Type> types )
+    {
+        return types
+            .filter( mixinType -> Annotations.annotationOn( mixinType, Constraints.class ) != null )
+            .flatMap( mixinType -> Arrays.stream( Annotations.annotationOn( mixinType, Constraints.class ).value() ) );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Stream<Class<?>> concernDeclarations( Class<?> type )
+    {
+        Stream<? extends Type> types = getTypes( type );
+        return concernDeclarations( types );
+    }
+
+    private Stream<Class<?>> concernDeclarations( Stream<? extends Type> types )
+    {
+        return types
+            .filter( mixinType -> Annotations.annotationOn( mixinType, Concerns.class ) != null )
+            .flatMap( new Function<Type, Stream<? extends Class<?>>>()
+            {
+                @Override
+                public Stream<? extends Class<?>> apply( Type mixinType )
+                {
+                    return Arrays.stream( Annotations.annotationOn( mixinType, Concerns.class ).value() );
+                }
+            } );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    protected Stream<Class<?>> sideEffectDeclarations( Class<?> type )
+    {
+        Stream<? extends Type> types = getTypes( type );
+        return sideEffectDeclarations( types );
+    }
+
+    private Stream<Class<?>> sideEffectDeclarations( Stream<? extends Type> types )
+    {
+        return types
+            .filter( mixinType -> Annotations.annotationOn( mixinType, SideEffects.class ) != null )
+            .flatMap( mixinType -> Arrays.stream( Annotations.annotationOn( mixinType, SideEffects.class ).value() ) );
+    }
+
+    protected Stream<Class<?>> mixinDeclarations( Class<?> type )
+    {
+        //Stream<? extends Type> types = typesOf( type );
+        return mixinDeclarations( Stream.of( type ) );
+    }
+
+    private Stream<Class<?>> mixinDeclarations( Stream<? extends Class> types )
+    {
+        return types.flatMap( this::getTypes ).flatMap( Classes::typesOf )
+            .filter( mixinType -> Annotations.annotationOn( mixinType, Mixins.class ) != null )
+            .flatMap( mixinType -> Arrays.stream( Annotations.annotationOn( mixinType, Mixins.class ).value() ) );
+    }
+
+    private Stream<Class> getAllTypes()
+    {
+        return this.types.stream().flatMap( this::getTypes );
+    }
+
+    private Stream<Class> getTypes( Class<?> clazz )
+    {
+        if( clazz.isInterface() )
+        {
+            return typesOf( clazz ).map( Classes.RAW_CLASS );
+        }
+        else
+        {
+            return classHierarchy( clazz ).map( Classes.RAW_CLASS );
+        }
+    }
+
+    public AssociationModel newAssociationModel( AccessibleObject accessor,
+                                                 List<Class<?>> constraintClasses
+    )
+    {
+        List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
+        boolean optional = annotations.stream().anyMatch( isType( Optional.class ) );
+
+        // Constraints for Association references
+        ValueConstraintsModel constraintsModel = constraintsFor( annotations.stream(), GenericAssociationInfo
+            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance valueConstraintsInstance;
+        if( constraintsModel.isConstrained() )
+        {
+            valueConstraintsInstance = constraintsModel.newInstance();
+        }
+        else
+        {
+            valueConstraintsInstance = new ValueConstraintsInstance( Collections.emptyList(), ( (Member) accessor ).getName(), true );
+        }
+
+        // Constraints for the Association itself
+        constraintsModel = constraintsFor( annotations.stream(), Association.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance associationValueConstraintsInstance;
+        if( constraintsModel.isConstrained() )
+        {
+            associationValueConstraintsInstance = constraintsModel.newInstance();
+        }
+        else
+        {
+            associationValueConstraintsInstance = new ValueConstraintsInstance( Collections.emptyList(), ( (Member) accessor ).getName(), true );
+        }
+
+        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
+        return new AssociationModel( accessor, valueConstraintsInstance, associationValueConstraintsInstance, metaInfo );
+    }
+
+    public ManyAssociationModel newManyAssociationModel( AccessibleObject accessor,
+                                                         List<Class<?>> constraintClasses
+    )
+    {
+        List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
+        boolean optional = annotations.stream().anyMatch( isType( Optional.class ) );
+
+        // Constraints for entities in ManyAssociation
+        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations.stream(), GenericAssociationInfo
+            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance valueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            valueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+
+        // Constraints for the ManyAssociation itself
+        valueConstraintsModel = constraintsFor( annotations.stream(), ManyAssociation.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance manyValueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            manyValueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
+        return new ManyAssociationModel( accessor, valueConstraintsInstance, manyValueConstraintsInstance, metaInfo );
+    }
+
+    public NamedAssociationModel newNamedAssociationModel( AccessibleObject accessor,
+                                                           List<Class<?>> constraintClasses
+    )
+    {
+        List<Annotation> annotations = Annotations.findAccessorAndTypeAnnotationsIn( accessor );
+        boolean optional = annotations.stream().anyMatch( isType( Optional.class ) );
+
+        // Constraints for entities in NamedAssociation
+        ValueConstraintsModel valueConstraintsModel = constraintsFor( annotations.stream(), GenericAssociationInfo
+            .associationTypeOf( accessor ), ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance valueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            valueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+
+        // Constraints for the NamedAssociation itself
+        valueConstraintsModel = constraintsFor( annotations.stream(), NamedAssociation.class, ( (Member) accessor ).getName(), optional, constraintClasses, accessor );
+        ValueConstraintsInstance namedValueConstraintsInstance = null;
+        if( valueConstraintsModel.isConstrained() )
+        {
+            namedValueConstraintsInstance = valueConstraintsModel.newInstance();
+        }
+        MetaInfo metaInfo = stateDeclarations.metaInfoFor( accessor );
+        return new NamedAssociationModel( accessor, valueConstraintsInstance, namedValueConstraintsInstance, metaInfo );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationAssemblyImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationAssemblyImpl.java
new file mode 100644
index 0000000..8bbee50
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationAssemblyImpl.java
@@ -0,0 +1,45 @@
+/*
+ *  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.bootstrap;
+
+import java.util.stream.Stream;
+import org.apache.polygene.bootstrap.ConfigurationAssembly;
+
+/**
+ * Declaration of a EntityComposite.
+ */
+public final class ConfigurationAssemblyImpl
+    implements ConfigurationAssembly
+{
+    private ValueAssemblyImpl value;
+    private EntityAssemblyImpl entity;
+
+    public ConfigurationAssemblyImpl( Class<?> mainType )
+    {
+        value = new ValueAssemblyImpl( mainType );
+        entity = new EntityAssemblyImpl( mainType );
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return value.types();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationDeclarationImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationDeclarationImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationDeclarationImpl.java
new file mode 100644
index 0000000..45c71d5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ConfigurationDeclarationImpl.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.bootstrap;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.ConfigurationDeclaration;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Declaration of a Composite. Created by {@link org.apache.polygene.bootstrap.ModuleAssembly#configurations(Class[])}.
+ */
+public final class ConfigurationDeclarationImpl
+    implements ConfigurationDeclaration
+{
+    private final Iterable<EntityAssemblyImpl> entities;
+    private final Iterable<ValueAssemblyImpl> values;
+
+    public ConfigurationDeclarationImpl( Iterable<EntityAssemblyImpl> entities, Iterable<ValueAssemblyImpl> values  )
+    {
+        this.entities = entities;
+        this.values = values;
+    }
+
+    @Override
+    public ConfigurationDeclaration setMetaInfo( Object info )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.metaInfo.set( info );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.metaInfo.set( info );
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration visibleIn( Visibility visibility )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.visibility = visibility;
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.visibility = visibility;
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration withConcerns( Class<?>... concerns )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.concerns.addAll( asList( concerns ) );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.concerns.addAll( asList( concerns ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration withSideEffects( Class<?>... sideEffects )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.sideEffects.addAll( asList( sideEffects ) );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.sideEffects.addAll( asList( sideEffects ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration withMixins( Class<?>... mixins )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.mixins.addAll( asList( mixins ) );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.mixins.addAll( asList( mixins ) );
+        }
+        return this;
+    }
+
+    @Override
+    public ConfigurationDeclaration withTypes( Class<?>... types )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.types.addAll( asList( types ) );
+        }
+        for( ValueAssemblyImpl value : values )
+        {
+            value.types.addAll( asList( types ) );
+        }
+        return 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/bootstrap/EntityAssemblyImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/EntityAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/EntityAssemblyImpl.java
new file mode 100644
index 0000000..605084c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/EntityAssemblyImpl.java
@@ -0,0 +1,121 @@
+/*
+ *  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.bootstrap;
+
+import org.apache.polygene.api.common.InvalidApplicationException;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.bootstrap.AssociationDeclarations;
+import org.apache.polygene.bootstrap.EntityAssembly;
+import org.apache.polygene.bootstrap.ManyAssociationDeclarations;
+import org.apache.polygene.bootstrap.NamedAssociationDeclarations;
+import org.apache.polygene.bootstrap.StateDeclarations;
+import org.apache.polygene.runtime.association.AssociationsModel;
+import org.apache.polygene.runtime.association.ManyAssociationsModel;
+import org.apache.polygene.runtime.association.NamedAssociationsModel;
+import org.apache.polygene.runtime.composite.MixinsModel;
+import org.apache.polygene.runtime.composite.StateModel;
+import org.apache.polygene.runtime.entity.EntityMixinsModel;
+import org.apache.polygene.runtime.entity.EntityModel;
+import org.apache.polygene.runtime.entity.EntityStateModel;
+
+/**
+ * Declaration of a EntityComposite.
+ */
+public final class EntityAssemblyImpl
+    extends CompositeAssemblyImpl
+    implements EntityAssembly
+{
+    private AssociationDeclarations associationDeclarations;
+    private ManyAssociationDeclarations manyAssociationDeclarations;
+    private NamedAssociationDeclarations namedAssociationDeclarations;
+    private AssociationsModel associationsModel;
+    private ManyAssociationsModel manyAssociationsModel;
+    private NamedAssociationsModel namedAssociationsModel;
+
+    public EntityAssemblyImpl( Class<?> entityType )
+    {
+        super( entityType );
+        // The composite must always implement EntityComposite, as a marker interface
+        if( !EntityComposite.class.isAssignableFrom( entityType ) )
+        {
+            types.add( EntityComposite.class );
+        }
+    }
+
+    @Override
+    protected MixinsModel createMixinsModel()
+    {
+        return new EntityMixinsModel();
+    }
+
+    @Override
+    protected AssociationsModel associationsModel()
+    {
+        return associationsModel;
+    }
+
+    @Override
+    protected ManyAssociationsModel manyAssociationsModel()
+    {
+        return manyAssociationsModel;
+    }
+
+    @Override
+    protected NamedAssociationsModel namedAssociationsModel()
+    {
+        return namedAssociationsModel;
+    }
+
+    @Override
+    protected StateModel createStateModel()
+    {
+        return new EntityStateModel( propertiesModel, associationsModel, manyAssociationsModel, namedAssociationsModel );
+    }
+
+    EntityModel newEntityModel(
+        ModuleDescriptor module,
+        StateDeclarations stateDeclarations,
+        AssociationDeclarations associationDecs,
+        ManyAssociationDeclarations manyAssociationDecs,
+        NamedAssociationDeclarations namedAssociationDecs,
+        AssemblyHelper helper
+    )
+    {
+        this.associationDeclarations = associationDecs;
+        this.manyAssociationDeclarations = manyAssociationDecs;
+        this.namedAssociationDeclarations = namedAssociationDecs;
+        try
+        {
+            associationsModel = new AssociationsModel();
+            manyAssociationsModel = new ManyAssociationsModel();
+            namedAssociationsModel = new NamedAssociationsModel();
+            buildComposite( helper, stateDeclarations );
+
+            return new EntityModel( module, types, visibility, metaInfo,
+                                    (EntityMixinsModel) mixinsModel,
+                                    (EntityStateModel) stateModel, compositeMethodsModel );
+        }
+        catch( Exception e )
+        {
+            throw new InvalidApplicationException( "Could not register " + types, e );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/EntityDeclarationImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/EntityDeclarationImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/EntityDeclarationImpl.java
new file mode 100644
index 0000000..ee8adf4
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/EntityDeclarationImpl.java
@@ -0,0 +1,100 @@
+/*
+ *  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.bootstrap;
+
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.bootstrap.EntityDeclaration;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Declaration of a Composite. Created by {@link org.apache.polygene.bootstrap.ModuleAssembly#transients(Class[])}.
+ */
+public final class EntityDeclarationImpl
+    implements EntityDeclaration
+{
+    private final Iterable<EntityAssemblyImpl> entities;
+
+    public EntityDeclarationImpl( Iterable<EntityAssemblyImpl> entities )
+    {
+        this.entities = entities;
+    }
+
+    @Override
+    public EntityDeclaration setMetaInfo( Object info )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.metaInfo.set( info );
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration visibleIn( Visibility visibility )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.visibility = visibility;
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration withConcerns( Class<?>... concerns )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.concerns.addAll( asList( concerns ) );
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration withSideEffects( Class<?>... sideEffects )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.sideEffects.addAll( asList( sideEffects ) );
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration withMixins( Class<?>... mixins )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.mixins.addAll( asList( mixins ) );
+        }
+        return this;
+    }
+
+    @Override
+    public EntityDeclaration withTypes( Class<?>... types )
+    {
+        for( EntityAssemblyImpl entity : entities )
+        {
+            entity.types.addAll( asList( types ) );
+        }
+        return 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/bootstrap/ImplementsMethodAppliesToFilter.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImplementsMethodAppliesToFilter.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImplementsMethodAppliesToFilter.java
new file mode 100644
index 0000000..fd5b04c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImplementsMethodAppliesToFilter.java
@@ -0,0 +1,46 @@
+/*
+ *  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.bootstrap;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import org.apache.polygene.api.common.AppliesToFilter;
+
+/**
+ * JAVADOC
+ */
+final class ImplementsMethodAppliesToFilter
+    implements AppliesToFilter
+{
+    @Override
+    public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
+    {
+        try
+        {
+            return !Modifier.isAbstract( fragmentClass.getMethod( method.getName(), method.getParameterTypes() )
+                                             .getModifiers() );
+        }
+        catch( NoSuchMethodException e )
+        {
+            return false;
+        }
+    }
+}
\ 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/bootstrap/ImportedServiceAssemblyImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImportedServiceAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImportedServiceAssemblyImpl.java
new file mode 100644
index 0000000..c455aed
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImportedServiceAssemblyImpl.java
@@ -0,0 +1,125 @@
+/*
+ *  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.bootstrap;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.common.InvalidApplicationException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.importer.InstanceImporter;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.bootstrap.ImportedServiceAssembly;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+import org.apache.polygene.runtime.service.ImportedServiceModel;
+
+/**
+ * Declaration of an imported Service.
+ *
+ * Created by {@link org.apache.polygene.runtime.bootstrap.ModuleAssemblyImpl#importedServices(Class[])}.
+ */
+public final class ImportedServiceAssemblyImpl
+    implements ImportedServiceAssembly
+{
+    private final Class<?> serviceType;
+    private final ModuleAssemblyImpl moduleAssembly;
+    @SuppressWarnings( "raw" )
+    Class<? extends ServiceImporter> serviceProvider = InstanceImporter.class;
+    String identity;
+    boolean importOnStartup = false;
+    MetaInfo metaInfo = new MetaInfo();
+    Visibility visibility = Visibility.module;
+    List<Class<? extends Activator<?>>> activators = new ArrayList<>();
+
+    public ImportedServiceAssemblyImpl( Class<?> serviceType, ModuleAssemblyImpl moduleAssembly )
+    {
+        this.serviceType = serviceType;
+        this.moduleAssembly = moduleAssembly;
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return Stream.of( serviceType );
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    void addImportedServiceModel( ModuleDescriptor module, List<ImportedServiceModel> serviceModels )
+    {
+        try
+        {
+            Identity id;
+            if( identity == null )
+            {
+                id = generateId( serviceModels, serviceType );
+            }
+            else
+            {
+                id = new StringIdentity( identity );
+            }
+
+            ImportedServiceModel serviceModel = new ImportedServiceModel( module,
+                                                                          serviceType,
+                                                                          visibility,
+                                                                          serviceProvider,
+                                                                          id,
+                                                                          importOnStartup,
+                                                                          new MetaInfo( metaInfo ).withAnnotations( serviceType ),
+                                                                          new ActivatorsModel( activators ),
+                                                                          moduleAssembly.name() );
+            serviceModels.add( serviceModel );
+        }
+        catch( Exception e )
+        {
+            throw new InvalidApplicationException( "Could not register " + serviceType.getName(), e );
+        }
+    }
+
+    @SuppressWarnings( "raw" )
+    private Identity generateId( List<ImportedServiceModel> serviceModels, Class serviceType )
+    {
+        // Find reference that is not yet used
+        int idx = 0;
+        Identity id = new StringIdentity( serviceType.getSimpleName() );
+        boolean invalid;
+        do
+        {
+            invalid = false;
+            for( ImportedServiceModel serviceModel : serviceModels )
+            {
+                if( serviceModel.identity().equals( id ) )
+                {
+                    idx++;
+                    id = new StringIdentity( serviceType.getSimpleName() + "_" + idx );
+                    invalid = true;
+                    break;
+                }
+            }
+        }
+        while( invalid );
+        return id;
+    }
+}
\ 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/bootstrap/ImportedServiceDeclarationImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImportedServiceDeclarationImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImportedServiceDeclarationImpl.java
new file mode 100644
index 0000000..257414e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ImportedServiceDeclarationImpl.java
@@ -0,0 +1,128 @@
+/*
+ *  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.bootstrap;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.qualifier.ServiceTags;
+import org.apache.polygene.bootstrap.ImportedServiceDeclaration;
+
+/**
+ * Declaration of an imported Service.
+ */
+public final class ImportedServiceDeclarationImpl
+    implements ImportedServiceDeclaration
+{
+    private final Iterable<ImportedServiceAssemblyImpl> assemblies;
+
+    public ImportedServiceDeclarationImpl( Iterable<ImportedServiceAssemblyImpl> assemblies )
+    {
+        this.assemblies = assemblies;
+    }
+
+    @Override
+    public ImportedServiceDeclaration importOnStartup()
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.importOnStartup = true;
+        }
+        return this;
+    }
+
+    @Override
+    public ImportedServiceDeclaration visibleIn( Visibility visibility )
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.visibility = visibility;
+        }
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings( "raw" )
+    public ImportedServiceDeclaration importedBy( Class<? extends ServiceImporter> sip )
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.serviceProvider = sip;
+        }
+        return this;
+    }
+
+    @Override
+    public ImportedServiceDeclaration identifiedBy( String identity )
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.identity = identity;
+        }
+        return this;
+    }
+
+    @Override
+    public ImportedServiceDeclaration taggedWith( String... tags )
+    {
+        for( ImportedServiceAssemblyImpl serviceAssembly : assemblies )
+        {
+            ServiceTags previousTags = serviceAssembly.metaInfo.get( ServiceTags.class );
+            if( previousTags != null )
+            {
+                List<String> tagList = new ArrayList<>();
+                Collections.addAll( tagList, previousTags.tags() );
+                Collections.addAll( tagList, tags );
+                serviceAssembly.metaInfo.set( new ServiceTags( tagList.toArray( new String[ tagList.size() ] ) ) );
+            }
+            else
+            {
+                serviceAssembly.metaInfo.set( new ServiceTags( tags ) );
+            }
+        }
+
+        return this;
+    }
+
+    @Override
+    public ImportedServiceDeclaration setMetaInfo( Object serviceAttribute )
+    {
+        for( ImportedServiceAssemblyImpl assembly : assemblies )
+        {
+            assembly.metaInfo.set( serviceAttribute );
+        }
+        return this;
+    }
+
+    @Override
+    @SafeVarargs
+    public final ImportedServiceDeclaration withActivators( Class<? extends Activator<?>>... activators )
+    {
+        for ( ImportedServiceAssemblyImpl serviceAssembly : assemblies ) {
+            serviceAssembly.activators.addAll( Arrays.asList( activators ) );
+        }
+        return this;
+    }
+}
\ No newline at end of file


Mime
View raw message