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:52 UTC
[16/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/association/AssociationInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationInstance.java
new file mode 100644
index 0000000..6d5f6fe
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationInstance.java
@@ -0,0 +1,138 @@
+/*
+ * 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.association;
+
+import java.lang.reflect.Type;
+import java.util.function.BiFunction;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationWrapper;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * Implementation of Association to a single Entity.
+ */
+public final class AssociationInstance<T>
+ extends AbstractAssociationInstance<T>
+ implements Association<T>
+{
+ private Property<EntityReference> associationState;
+
+ public AssociationInstance( AssociationInfo associationInfo,
+ BiFunction<EntityReference, Type, Object> entityFunction,
+ Property<EntityReference> associationState
+ )
+ {
+ super( associationInfo, entityFunction );
+ this.associationState = associationState;
+ }
+
+ // Association implementation
+ @Override
+ public T get()
+ {
+ return getEntity( associationState.get() );
+ }
+
+ @Override
+ public void set( T newValue )
+ throws IllegalArgumentException
+ {
+ checkImmutable();
+ checkType( newValue );
+
+ associationInfo.checkConstraints( newValue );
+
+ // Change association
+ associationState.set( EntityReference.create( ((HasIdentity) newValue ).identity().get()));
+ }
+
+ @Override
+ public EntityReference reference()
+ {
+ return associationState.get();
+ }
+
+ public Property<EntityReference> getAssociationState()
+ {
+ return associationState;
+ }
+
+ @Override
+ public String toString()
+ {
+ if( associationState.get() == null )
+ {
+ return "";
+ }
+ else
+ {
+ return associationState.get().toString();
+ }
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int hash = associationInfo.hashCode() * 39; // Descriptor
+ if( associationState.get() != null )
+ {
+ hash = hash * 997 + associationState.get().hashCode(); // State
+ }
+ return hash;
+ }
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if( this == o )
+ {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() )
+ {
+ return false;
+ }
+ Association<?> that = (Association) o;
+ // Unwrap if needed
+ while( that instanceof AssociationWrapper )
+ {
+ that = ( (AssociationWrapper) that ).next();
+ }
+ // Descriptor equality
+ AssociationInstance<?> thatInstance = (AssociationInstance) that;
+ AssociationDescriptor thatDescriptor = (AssociationDescriptor) thatInstance.associationInfo();
+ if( !associationInfo.equals( thatDescriptor ) )
+ {
+ return false;
+ }
+ // State equality
+ if( associationState.get() != null
+ ? !associationState.get().equals( thatInstance.associationState.get() )
+ : thatInstance.associationState.get() != null )
+ {
+ return false;
+ }
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationModel.java
new file mode 100644
index 0000000..b83021e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationModel.java
@@ -0,0 +1,229 @@
+/*
+ * 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.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.GenericAssociationInfo;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.Aggregated;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.Immutable;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.Visitable;
+import org.apache.polygene.api.util.Visitor;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.runtime.composite.ValueConstraintsInstance;
+import org.apache.polygene.runtime.model.Binder;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * Model for an Association.
+ *
+ * <p>Equality is based on the Association accessor object (associated type and name), not on the QualifiedName.</p>
+ */
+public final class AssociationModel
+ implements AssociationDescriptor, AssociationInfo, Binder, Visitable<AssociationModel>
+{
+ private MetaInfo metaInfo;
+ private Type type;
+ private AccessibleObject accessor;
+ private QualifiedName qualifiedName;
+ private ValueConstraintsInstance constraints;
+ private ValueConstraintsInstance associationConstraints;
+ private boolean queryable;
+ private boolean immutable;
+ private boolean aggregated;
+ private AssociationInfo builderInfo;
+
+ public AssociationModel( AccessibleObject accessor,
+ ValueConstraintsInstance valueConstraintsInstance,
+ ValueConstraintsInstance associationConstraintsInstance,
+ MetaInfo metaInfo
+ )
+ {
+ this.metaInfo = metaInfo;
+ this.constraints = valueConstraintsInstance;
+ this.associationConstraints = associationConstraintsInstance;
+ this.accessor = accessor;
+ initialize();
+ }
+
+ private void initialize()
+ {
+ this.type = GenericAssociationInfo.associationTypeOf( accessor );
+ this.qualifiedName = QualifiedName.fromAccessor( accessor );
+ this.immutable = metaInfo.get( Immutable.class ) != null;
+ this.aggregated = metaInfo.get( Aggregated.class ) != null;
+
+ final Queryable queryable = accessor.getAnnotation( Queryable.class );
+ this.queryable = queryable == null || queryable.value();
+ }
+
+ @Override
+ public <T> T metaInfo( Class<T> infoType )
+ {
+ return metaInfo.get( infoType );
+ }
+
+ @Override
+ public QualifiedName qualifiedName()
+ {
+ return qualifiedName;
+ }
+
+ @Override
+ public Type type()
+ {
+ return type;
+ }
+
+ @Override
+ public boolean isImmutable()
+ {
+ return immutable;
+ }
+
+ @Override
+ public boolean isAggregated()
+ {
+ return aggregated;
+ }
+
+ @Override
+ public AccessibleObject accessor()
+ {
+ return accessor;
+ }
+
+ @Override
+ public boolean queryable()
+ {
+ return queryable;
+ }
+
+ public AssociationInfo getBuilderInfo()
+ {
+ return builderInfo;
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( Visitor<? super AssociationModel, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ return visitor.visit( this );
+ }
+
+ @Override
+ public void checkConstraints( Object value )
+ throws ConstraintViolationException
+ {
+ constraints.checkConstraints( value, accessor );
+ }
+
+ public void checkAssociationConstraints( Association<?> association )
+ throws ConstraintViolationException
+ {
+ associationConstraints.checkConstraints( association, accessor );
+ }
+
+ @Override
+ public void bind( Resolution resolution )
+ throws BindingException
+ {
+ builderInfo = new AssociationInfo()
+ {
+ @Override
+ public boolean isImmutable()
+ {
+ return false;
+ }
+
+ @Override
+ public QualifiedName qualifiedName()
+ {
+ return qualifiedName;
+ }
+
+ @Override
+ public Type type()
+ {
+ return type;
+ }
+
+ @Override
+ public void checkConstraints( Object value )
+ throws ConstraintViolationException
+ {
+ AssociationModel.this.checkConstraints( value );
+ }
+ };
+
+ if( type instanceof TypeVariable )
+ {
+
+ Class mainType = resolution.model().types().findFirst().orElse( null );
+ type = Classes.resolveTypeVariable( (TypeVariable) type, ( (Member) accessor ).getDeclaringClass(), mainType );
+ }
+ }
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if( this == o )
+ {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() )
+ {
+ return false;
+ }
+ AssociationModel that = (AssociationModel) o;
+ return accessor.equals( that.accessor );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return accessor.hashCode();
+ }
+
+ @Override
+ public String toString()
+ {
+ if( accessor instanceof Field )
+ {
+ return ( (Field) accessor ).toGenericString();
+ }
+ else
+ {
+ return ( (Method) accessor ).toGenericString();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationsModel.java
new file mode 100644
index 0000000..aad7d83
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/AssociationsModel.java
@@ -0,0 +1,120 @@
+/*
+ * 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.association;
+
+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.association.Association;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * Model for Associations.
+ */
+public final class AssociationsModel
+ implements VisitableHierarchy<AssociationsModel, AssociationModel>
+{
+ private final Map<AccessibleObject, AssociationModel> mapAccessorAssociationModel = new LinkedHashMap<>();
+
+ public AssociationsModel()
+ {
+ }
+
+ public Stream<AssociationModel> associations()
+ {
+ return mapAccessorAssociationModel.values().stream();
+ }
+
+ public void addAssociation( AssociationModel associationModel )
+ {
+ mapAccessorAssociationModel.put( associationModel.accessor(), associationModel );
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super AssociationsModel, ? super AssociationModel, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ if( visitor.visitEnter( this ) )
+ {
+ for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
+ {
+ if( !associationModel.accept( visitor ) )
+ {
+ break;
+ }
+ }
+ }
+ return visitor.visitLeave( this );
+ }
+
+ public AssociationModel getAssociation( AccessibleObject accessor )
+ throws IllegalArgumentException
+ {
+ AssociationModel associationModel = mapAccessorAssociationModel.get( accessor );
+ if( associationModel == null )
+ {
+ throw new IllegalArgumentException( "No association found with name:" + ( (Member) accessor ).getName() );
+ }
+ return associationModel;
+ }
+
+ public AssociationDescriptor getAssociationByName( String name )
+ throws IllegalArgumentException
+ {
+ for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
+ {
+ if( associationModel.qualifiedName().name().equals( name ) )
+ {
+ return associationModel;
+ }
+ }
+ throw new IllegalArgumentException( "No association found with name:" + name );
+ }
+
+ public AssociationDescriptor getAssociationByQualifiedName( QualifiedName name )
+ throws IllegalArgumentException
+ {
+ for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
+ {
+ if( associationModel.qualifiedName().equals( name ) )
+ {
+ return associationModel;
+ }
+ }
+ throw new IllegalArgumentException( "No association found with qualified name:" + name );
+ }
+
+ public void checkConstraints( AssociationStateHolder state )
+ {
+ for( AssociationModel associationModel : mapAccessorAssociationModel.values() )
+ {
+ Association<Object> association = state.<Object>associationFor( associationModel.accessor() );
+ associationModel.checkAssociationConstraints( association );
+ associationModel.checkConstraints( association.get() );
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationInstance.java
new file mode 100644
index 0000000..b035745
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationInstance.java
@@ -0,0 +1,226 @@
+/*
+ * 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.association;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.function.BiFunction;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.ManyAssociationWrapper;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.util.NullArgumentException;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+
+/**
+ * JAVADOC
+ */
+public class ManyAssociationInstance<T>
+ extends AbstractAssociationInstance<T>
+ implements ManyAssociation<T>
+{
+ private ManyAssociationState manyAssociationState;
+
+ public ManyAssociationInstance( AssociationInfo associationInfo,
+ BiFunction<EntityReference, Type, Object> associationFunction,
+ ManyAssociationState manyAssociationState
+ )
+ {
+ super( associationInfo, associationFunction );
+ this.manyAssociationState = manyAssociationState;
+ }
+
+ @Override
+ public int count()
+ {
+ return manyAssociationState.count();
+ }
+
+ @Override
+ public boolean contains( T entity )
+ {
+ return manyAssociationState.contains( getEntityReference( entity ) );
+ }
+
+ @Override
+ public boolean add( int i, T entity )
+ {
+ NullArgumentException.validateNotNull( "entity", entity );
+ checkImmutable();
+ checkType( entity );
+ associationInfo.checkConstraints( entity );
+ return manyAssociationState.add( i, EntityReference.create( ((HasIdentity) entity ).identity().get()) );
+ }
+
+ @Override
+ public boolean add( T entity )
+ {
+ return add( manyAssociationState.count(), entity );
+ }
+
+ @Override
+ public boolean remove( T entity )
+ {
+ NullArgumentException.validateNotNull( "entity", entity );
+ checkImmutable();
+ checkType( entity );
+
+ return manyAssociationState.remove( EntityReference.create( ((HasIdentity) entity).identity().get() ) );
+ }
+
+ @Override
+ public T get( int i )
+ {
+ return getEntity( manyAssociationState.get( i ) );
+ }
+
+ @Override
+ public List<T> toList()
+ {
+ ArrayList<T> list = new ArrayList<>();
+ for( EntityReference entityReference : manyAssociationState )
+ {
+ list.add( getEntity( entityReference ) );
+ }
+
+ return list;
+ }
+
+ @Override
+ public Set<T> toSet()
+ {
+ Set<T> set = new HashSet<>();
+ for( EntityReference entityReference : manyAssociationState )
+ {
+ set.add( getEntity( entityReference ) );
+ }
+
+ return set;
+ }
+
+ @Override
+ public Stream<EntityReference> references()
+ {
+ return manyAssociationState.stream();
+ }
+
+ @Override
+ public String toString()
+ {
+ return manyAssociationState.toString();
+ }
+
+ @Override
+ public Iterator<T> iterator()
+ {
+ return new ManyAssociationIterator( manyAssociationState.iterator() );
+ }
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if( this == o )
+ {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() )
+ {
+ return false;
+ }
+ ManyAssociation<?> that = (ManyAssociation) o;
+ // Unwrap if needed
+ while( that instanceof ManyAssociationWrapper )
+ {
+ that = ( (ManyAssociationWrapper) that ).next();
+ }
+ // Descriptor equality
+ ManyAssociationInstance<?> thatInstance = (ManyAssociationInstance) that;
+ AssociationDescriptor thatDescriptor = (AssociationDescriptor) thatInstance.associationInfo();
+ if( !associationInfo.equals( thatDescriptor ) )
+ {
+ return false;
+ }
+ // State equality
+ if( manyAssociationState.count() != thatInstance.manyAssociationState.count() )
+ {
+ return false;
+ }
+ for( EntityReference ref : manyAssociationState )
+ {
+ if( !thatInstance.manyAssociationState.contains( ref ) )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int hash = associationInfo.hashCode() * 31; // Descriptor
+ for( EntityReference ref : manyAssociationState )
+ {
+ hash += ref.hashCode() * 7; // State
+ }
+ return hash;
+ }
+
+ public ManyAssociationState getManyAssociationState()
+ {
+ return manyAssociationState;
+ }
+
+ protected class ManyAssociationIterator
+ implements Iterator<T>
+ {
+ private final Iterator<EntityReference> idIterator;
+
+ public ManyAssociationIterator( Iterator<EntityReference> idIterator )
+ {
+ this.idIterator = idIterator;
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return idIterator.hasNext();
+ }
+
+ @Override
+ public T next()
+ {
+ return getEntity( idIterator.next() );
+ }
+
+ @Override
+ public void remove()
+ {
+ checkImmutable();
+ idIterator.remove();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationModel.java
new file mode 100644
index 0000000..e8fd0b6
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationModel.java
@@ -0,0 +1,265 @@
+/*
+ * 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.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.List;
+import java.util.function.BiFunction;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.GenericAssociationInfo;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.constraint.ConstraintViolation;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.Aggregated;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.Immutable;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.Visitable;
+import org.apache.polygene.api.util.Visitor;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.runtime.composite.ValueConstraintsInstance;
+import org.apache.polygene.runtime.model.Binder;
+import org.apache.polygene.runtime.model.Resolution;
+import org.apache.polygene.runtime.unitofwork.ModuleUnitOfWork;
+import org.apache.polygene.runtime.unitofwork.BuilderEntityState;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * Model for a ManyAssociation.
+ *
+ * <p>Equality is based on the ManyAssociation accessor object (associated type and name), not on the QualifiedName.</p>
+ */
+public final class ManyAssociationModel
+ implements AssociationDescriptor, AssociationInfo, Binder, Visitable<ManyAssociationModel>
+{
+ private final ValueConstraintsInstance associationConstraints;
+ private final MetaInfo metaInfo;
+ private Type type;
+ private final AccessibleObject accessor;
+ private QualifiedName qualifiedName;
+ private final ValueConstraintsInstance constraints;
+ private boolean queryable;
+ private boolean immutable;
+ private boolean aggregated;
+ private AssociationInfo builderInfo;
+
+ public ManyAssociationModel( AccessibleObject accessor,
+ ValueConstraintsInstance valueConstraintsInstance,
+ ValueConstraintsInstance associationConstraintsInstance,
+ MetaInfo metaInfo
+ )
+ {
+ this.metaInfo = metaInfo;
+ this.constraints = valueConstraintsInstance;
+ this.associationConstraints = associationConstraintsInstance;
+ this.accessor = accessor;
+ initialize();
+ }
+
+ private void initialize()
+ {
+ this.type = GenericAssociationInfo.associationTypeOf( accessor );
+ this.qualifiedName = QualifiedName.fromAccessor( accessor );
+ this.immutable = metaInfo.get( Immutable.class ) != null;
+ this.aggregated = metaInfo.get( Aggregated.class ) != null;
+
+ final Queryable queryable = accessor.getAnnotation( Queryable.class );
+ this.queryable = queryable == null || queryable.value();
+ }
+
+ @Override
+ public <T> T metaInfo( Class<T> infoType )
+ {
+ return metaInfo.get( infoType );
+ }
+
+ @Override
+ public QualifiedName qualifiedName()
+ {
+ return qualifiedName;
+ }
+
+ @Override
+ public Type type()
+ {
+ return type;
+ }
+
+ @Override
+ public boolean isImmutable()
+ {
+ return immutable;
+ }
+
+ @Override
+ public boolean isAggregated()
+ {
+ return aggregated;
+ }
+
+ @Override
+ public AccessibleObject accessor()
+ {
+ return accessor;
+ }
+
+ @Override
+ public boolean queryable()
+ {
+ return queryable;
+ }
+
+ public AssociationInfo getBuilderInfo()
+ {
+ return builderInfo;
+ }
+
+ public <T> ManyAssociation<T> newInstance( final ModuleUnitOfWork uow, EntityState state )
+ {
+ return new ManyAssociationInstance<>( state instanceof BuilderEntityState ? builderInfo : this, new BiFunction<EntityReference, Type, Object>()
+ {
+ @Override
+ public Object apply( EntityReference entityReference, Type type )
+ {
+ return uow.get( Classes.RAW_CLASS.apply( type ), entityReference.identity() );
+ }
+ }, state.manyAssociationValueOf( qualifiedName ) );
+ }
+
+ @Override
+ public void checkConstraints( Object composite )
+ throws ConstraintViolationException
+ {
+ if( constraints != null )
+ {
+ List<ConstraintViolation> violations = constraints.checkConstraints( composite );
+ if( !violations.isEmpty() )
+ {
+ Stream<Class<?>> empty = Stream.empty();
+ throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
+ }
+ }
+ }
+
+ public void checkAssociationConstraints( ManyAssociation manyAssociation )
+ throws ConstraintViolationException
+ {
+ if( associationConstraints != null )
+ {
+ List<ConstraintViolation> violations = associationConstraints.checkConstraints( manyAssociation );
+ if( !violations.isEmpty() )
+ {
+ Stream<Class<?>> empty = Stream.empty();
+ throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
+ }
+ }
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( Visitor<? super ManyAssociationModel, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ return visitor.visit( this );
+ }
+
+ @Override
+ public void bind( Resolution resolution )
+ throws BindingException
+ {
+ builderInfo = new AssociationInfo()
+ {
+ @Override
+ public boolean isImmutable()
+ {
+ return false;
+ }
+
+ @Override
+ public QualifiedName qualifiedName()
+ {
+ return qualifiedName;
+ }
+
+ @Override
+ public Type type()
+ {
+ return type;
+ }
+
+ @Override
+ public void checkConstraints( Object value )
+ throws ConstraintViolationException
+ {
+ ManyAssociationModel.this.checkConstraints( value );
+ }
+ };
+
+ if( type instanceof TypeVariable )
+ {
+ Class mainType = resolution.model().types().findFirst().orElse( null );
+ type = Classes.resolveTypeVariable( (TypeVariable) type, ( (Member) accessor ).getDeclaringClass(), mainType );
+ }
+ }
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if( this == o )
+ {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() )
+ {
+ return false;
+ }
+
+ ManyAssociationModel that = (ManyAssociationModel) o;
+
+ return accessor.equals( that.accessor );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return accessor.hashCode();
+ }
+
+ @Override
+ public String toString()
+ {
+ if( accessor instanceof Field )
+ {
+ return ( (Field) accessor ).toGenericString();
+ }
+ else
+ {
+ return ( (Method) accessor ).toGenericString();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationsModel.java
new file mode 100644
index 0000000..090b180
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/ManyAssociationsModel.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.association;
+
+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.association.AssociationDescriptor;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.unitofwork.ModuleUnitOfWork;
+import org.apache.polygene.runtime.value.ValueStateInstance;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * Model for ManyAssociations.
+ */
+public final class ManyAssociationsModel
+ implements VisitableHierarchy<ManyAssociationsModel, ManyAssociationModel>
+{
+ private final Map<AccessibleObject, ManyAssociationModel> mapAccessorAssociationModel = new LinkedHashMap<>();
+
+ public ManyAssociationsModel()
+ {
+ }
+
+ public Stream<ManyAssociationModel> manyAssociations()
+ {
+ return mapAccessorAssociationModel.values().stream();
+ }
+
+ public void addManyAssociation( ManyAssociationModel model )
+ {
+ mapAccessorAssociationModel.put( model.accessor(), model );
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super ManyAssociationsModel, ? super ManyAssociationModel, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ if( visitor.visitEnter( this ) )
+ {
+ for( ManyAssociationModel associationModel : mapAccessorAssociationModel.values() )
+ {
+ if( !associationModel.accept( visitor ) )
+ {
+ break;
+ }
+ }
+ }
+ return visitor.visitLeave( this );
+ }
+
+ public <T> ManyAssociation<T> newInstance( AccessibleObject accessor,
+ EntityState entityState,
+ ModuleUnitOfWork uow )
+ {
+ return mapAccessorAssociationModel.get( accessor ).newInstance( uow, entityState );
+ }
+
+ public ManyAssociationModel getManyAssociation( AccessibleObject accessor )
+ throws IllegalArgumentException
+ {
+ ManyAssociationModel manyAssociationModel = mapAccessorAssociationModel.get( accessor );
+ if( manyAssociationModel == null )
+ {
+ throw new IllegalArgumentException( "No many-association found with name:" + ( (Member) accessor ).getName() );
+ }
+ return manyAssociationModel;
+ }
+
+ public AssociationDescriptor getManyAssociationByName( String name )
+ throws IllegalArgumentException
+ {
+ for( ManyAssociationModel associationModel : mapAccessorAssociationModel.values() )
+ {
+ if( associationModel.qualifiedName().name().equals( name ) )
+ {
+ return associationModel;
+ }
+ }
+ throw new IllegalArgumentException( "No many-association found with name:" + name );
+ }
+
+ public AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name )
+ throws IllegalArgumentException
+ {
+ for( ManyAssociationModel associationModel : mapAccessorAssociationModel.values() )
+ {
+ if( associationModel.qualifiedName().equals( name ) )
+ {
+ return associationModel;
+ }
+ }
+ throw new IllegalArgumentException( "No many-association found with qualified name:" + name );
+ }
+
+ public void checkConstraints( ValueStateInstance state )
+ {
+ for( ManyAssociationModel manyAssociationModel : mapAccessorAssociationModel.values() )
+ {
+ manyAssociationModel.checkAssociationConstraints( state.manyAssociationFor( manyAssociationModel.accessor() ) );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationInstance.java
new file mode 100644
index 0000000..05aa878
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationInstance.java
@@ -0,0 +1,192 @@
+/*
+ * 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.association;
+
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.association.NamedAssociationWrapper;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.util.NullArgumentException;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+
+public class NamedAssociationInstance<T>
+ extends AbstractAssociationInstance<T>
+ implements NamedAssociation<T>
+{
+
+ private final NamedAssociationState namedAssociationState;
+
+ public NamedAssociationInstance( AssociationInfo associationInfo,
+ BiFunction<EntityReference, Type, Object> associationFunction,
+ NamedAssociationState namedAssociationState
+ )
+ {
+ super( associationInfo, associationFunction );
+ this.namedAssociationState = namedAssociationState;
+ }
+
+ @Override
+ public Iterator<String> iterator()
+ {
+ return namedAssociationState.iterator();
+ }
+
+ @Override
+ public int count()
+ {
+ return namedAssociationState.count();
+ }
+
+ @Override
+ public boolean containsName( String name )
+ {
+ return namedAssociationState.containsName( name );
+ }
+
+ @Override
+ public boolean put( String name, T entity )
+ {
+ NullArgumentException.validateNotNull( "entity", entity );
+ checkImmutable();
+ checkType( entity );
+ associationInfo.checkConstraints( entity );
+ return namedAssociationState.put( name, EntityReference.create( ((HasIdentity) entity).identity().get() ) );
+ }
+
+ @Override
+ public boolean remove( String name )
+ {
+ checkImmutable();
+ return namedAssociationState.remove( name );
+ }
+
+ @Override
+ public T get( String name )
+ {
+ return getEntity( namedAssociationState.get( name ) );
+ }
+
+ @Override
+ public String nameOf( T entity )
+ {
+ return namedAssociationState.nameOf( getEntityReference( entity ) );
+ }
+
+ @Override
+ public Map<String, T> toMap()
+ {
+ Map<String, T> map = new HashMap<>();
+ for( String name : namedAssociationState )
+ {
+ map.put( name, getEntity( namedAssociationState.get( name ) ) );
+ }
+ return map;
+ }
+
+ @Override
+ public Stream<Map.Entry<String, EntityReference>> references()
+ {
+ return namedAssociationState.stream();
+ }
+
+ @Override
+ public EntityReference referenceOf( String name )
+ {
+ return namedAssociationState.get( name );
+ }
+
+ public Iterable<Map.Entry<String, EntityReference>> getEntityReferences()
+ {
+ return Collections.unmodifiableMap(
+ StreamSupport.stream( namedAssociationState.spliterator(), false )
+ .collect( Collectors.toMap( Function.identity(), namedAssociationState::get ) )
+ ).entrySet();
+ }
+
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if( this == o )
+ {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() )
+ {
+ return false;
+ }
+ NamedAssociation<?> that = (NamedAssociation) o;
+ // Unwrap if needed
+ while( that instanceof NamedAssociationWrapper )
+ {
+ that = ( (NamedAssociationWrapper) that ).next();
+ }
+ // Descriptor equality
+ NamedAssociationInstance<?> thatInstance = (NamedAssociationInstance) that;
+ AssociationDescriptor thatDescriptor = (AssociationDescriptor) thatInstance.associationInfo();
+ if( !associationInfo.equals( thatDescriptor ) )
+ {
+ return false;
+ }
+ // State equality
+ if( namedAssociationState.count() != thatInstance.namedAssociationState.count() )
+ {
+ return false;
+ }
+ for( String name : namedAssociationState )
+ {
+ if( !thatInstance.namedAssociationState.containsName( name ) )
+ {
+ return false;
+ }
+ EntityReference thisReference = namedAssociationState.get( name );
+ EntityReference thatReference = thatInstance.namedAssociationState.get( name );
+ if( !thisReference.equals( thatReference ) )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int hash = associationInfo.hashCode() * 31; // Descriptor
+ for( String name : namedAssociationState )
+ {
+ hash += name.hashCode();
+ hash += namedAssociationState.get( name ).hashCode() * 7; // State
+ }
+ return hash;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationModel.java
new file mode 100644
index 0000000..bfcec63
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationModel.java
@@ -0,0 +1,265 @@
+/*
+ * 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.association;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.List;
+import java.util.function.BiFunction;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.GenericAssociationInfo;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.constraint.ConstraintViolation;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.Aggregated;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.Immutable;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.Visitable;
+import org.apache.polygene.api.util.Visitor;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.runtime.composite.ValueConstraintsInstance;
+import org.apache.polygene.runtime.model.Binder;
+import org.apache.polygene.runtime.model.Resolution;
+import org.apache.polygene.runtime.unitofwork.ModuleUnitOfWork;
+import org.apache.polygene.runtime.unitofwork.BuilderEntityState;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * Model for a NamedAssociation.
+ *
+ * <p>Equality is based on the NamedAssociation accessor object (associated type and name), not on the QualifiedName.</p>
+ */
+public final class NamedAssociationModel
+ implements AssociationDescriptor, AssociationInfo, Binder, Visitable<NamedAssociationModel>
+{
+ private final ValueConstraintsInstance associationConstraints;
+ private final MetaInfo metaInfo;
+ private Type type;
+ private final AccessibleObject accessor;
+ private QualifiedName qualifiedName;
+ private final ValueConstraintsInstance constraints;
+ private boolean queryable;
+ private boolean immutable;
+ private boolean aggregated;
+ private AssociationInfo builderInfo;
+
+ public NamedAssociationModel( AccessibleObject accessor,
+ ValueConstraintsInstance valueConstraintsInstance,
+ ValueConstraintsInstance associationConstraintsInstance,
+ MetaInfo metaInfo
+ )
+ {
+ this.metaInfo = metaInfo;
+ this.constraints = valueConstraintsInstance;
+ this.associationConstraints = associationConstraintsInstance;
+ this.accessor = accessor;
+ initialize();
+ }
+
+ private void initialize()
+ {
+ this.type = GenericAssociationInfo.associationTypeOf( accessor );
+ this.qualifiedName = QualifiedName.fromAccessor( accessor );
+ this.immutable = metaInfo.get( Immutable.class ) != null;
+ this.aggregated = metaInfo.get( Aggregated.class ) != null;
+
+ final Queryable queryable = accessor.getAnnotation( Queryable.class );
+ this.queryable = queryable == null || queryable.value();
+ }
+
+ @Override
+ public <T> T metaInfo( Class<T> infoType )
+ {
+ return metaInfo.get( infoType );
+ }
+
+ @Override
+ public QualifiedName qualifiedName()
+ {
+ return qualifiedName;
+ }
+
+ @Override
+ public Type type()
+ {
+ return type;
+ }
+
+ @Override
+ public boolean isImmutable()
+ {
+ return immutable;
+ }
+
+ @Override
+ public boolean isAggregated()
+ {
+ return aggregated;
+ }
+
+ @Override
+ public AccessibleObject accessor()
+ {
+ return accessor;
+ }
+
+ @Override
+ public boolean queryable()
+ {
+ return queryable;
+ }
+
+ public AssociationInfo getBuilderInfo()
+ {
+ return builderInfo;
+ }
+
+ public <T> NamedAssociation<T> newInstance( final ModuleUnitOfWork uow, EntityState state )
+ {
+ return new NamedAssociationInstance<>( state instanceof BuilderEntityState ? builderInfo : this, new BiFunction<EntityReference, Type, Object>()
+ {
+ @Override
+ public Object apply( EntityReference entityReference, Type type )
+ {
+ return uow.get( Classes.RAW_CLASS.apply( type ), entityReference.identity() );
+ }
+ }, state.namedAssociationValueOf( qualifiedName ) );
+ }
+
+ @Override
+ public void checkConstraints( Object composite )
+ throws ConstraintViolationException
+ {
+ if( constraints != null )
+ {
+ List<ConstraintViolation> violations = constraints.checkConstraints( composite );
+ if( !violations.isEmpty() )
+ {
+ Stream<Class<?>> empty = Stream.empty();
+ throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
+ }
+ }
+ }
+
+ public void checkAssociationConstraints( NamedAssociation association )
+ throws ConstraintViolationException
+ {
+ if( associationConstraints != null )
+ {
+ List<ConstraintViolation> violations = associationConstraints.checkConstraints( association );
+ if( !violations.isEmpty() )
+ {
+ Stream<Class<?>> empty = Stream.empty();
+ throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
+ }
+ }
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( Visitor<? super NamedAssociationModel, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ return visitor.visit( this );
+ }
+
+ @Override
+ public void bind( Resolution resolution )
+ throws BindingException
+ {
+ builderInfo = new AssociationInfo()
+ {
+ @Override
+ public boolean isImmutable()
+ {
+ return false;
+ }
+
+ @Override
+ public QualifiedName qualifiedName()
+ {
+ return qualifiedName;
+ }
+
+ @Override
+ public Type type()
+ {
+ return type;
+ }
+
+ @Override
+ public void checkConstraints( Object value )
+ throws ConstraintViolationException
+ {
+ NamedAssociationModel.this.checkConstraints( value );
+ }
+ };
+
+ if( type instanceof TypeVariable )
+ {
+ Class mainType = resolution.model().types().findFirst().orElse( null );
+ type = Classes.resolveTypeVariable( (TypeVariable) type, ( (Member) accessor ).getDeclaringClass(), mainType );
+ }
+ }
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if( this == o )
+ {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() )
+ {
+ return false;
+ }
+
+ NamedAssociationModel that = (NamedAssociationModel) o;
+
+ return accessor.equals( that.accessor );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return accessor.hashCode();
+ }
+
+ @Override
+ public String toString()
+ {
+ if( accessor instanceof Field )
+ {
+ return ( (Field) accessor ).toGenericString();
+ }
+ else
+ {
+ return ( (Method) accessor ).toGenericString();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationsModel.java
new file mode 100644
index 0000000..513b95a
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/association/NamedAssociationsModel.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.association;
+
+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.association.AssociationDescriptor;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.unitofwork.ModuleUnitOfWork;
+import org.apache.polygene.runtime.value.ValueStateInstance;
+import org.apache.polygene.spi.entity.EntityState;
+
+/**
+ * Model for NamedAssociations.
+ */
+public final class NamedAssociationsModel
+ implements VisitableHierarchy<NamedAssociationsModel, NamedAssociationModel>
+{
+ private final Map<AccessibleObject, NamedAssociationModel> mapAccessorAssociationModel = new LinkedHashMap<>();
+
+ public NamedAssociationsModel()
+ {
+ }
+
+ public Stream<NamedAssociationModel> namedAssociations()
+ {
+ return mapAccessorAssociationModel.values().stream();
+ }
+
+ public void addNamedAssociation( NamedAssociationModel model )
+ {
+ mapAccessorAssociationModel.put( model.accessor(), model );
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super NamedAssociationsModel, ? super NamedAssociationModel, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ if( visitor.visitEnter( this ) )
+ {
+ for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
+ {
+ if( !associationModel.accept( visitor ) )
+ {
+ break;
+ }
+ }
+ }
+ return visitor.visitLeave( this );
+ }
+
+ public <T> NamedAssociation<T> newInstance( AccessibleObject accessor,
+ EntityState entityState,
+ ModuleUnitOfWork uow )
+ {
+ return mapAccessorAssociationModel.get( accessor ).newInstance( uow, entityState );
+ }
+
+ public NamedAssociationModel getNamedAssociation( AccessibleObject accessor )
+ throws IllegalArgumentException
+ {
+ if( false )
+ {
+ return (NamedAssociationModel) getNamedAssociationByName( QualifiedName.fromAccessor( accessor ).name() );
+ }
+ NamedAssociationModel namedAssociationModel = mapAccessorAssociationModel.get( accessor );
+ if( namedAssociationModel == null )
+ {
+ throw new IllegalArgumentException( "No named-association found with name:" + ( (Member) accessor ).getName() );
+ }
+ return namedAssociationModel;
+ }
+
+ public AssociationDescriptor getNamedAssociationByName( String name )
+ throws IllegalArgumentException
+ {
+ for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
+ {
+ if( associationModel.qualifiedName().name().equals( name ) )
+ {
+ return associationModel;
+ }
+ }
+ throw new IllegalArgumentException( "No named-association found with name:" + name );
+ }
+
+ public AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name )
+ throws IllegalArgumentException
+ {
+ for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
+ {
+ if( associationModel.qualifiedName().equals( name ) )
+ {
+ return associationModel;
+ }
+ }
+ throw new IllegalArgumentException( "No named-association found with qualified name:" + name );
+ }
+
+ public void checkConstraints( ValueStateInstance state )
+ {
+ for( NamedAssociationModel associationModel : mapAccessorAssociationModel.values() )
+ {
+ associationModel.checkAssociationConstraints( state.namedAssociationFor( associationModel.accessor() ) );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AndAppliesToFilter.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AndAppliesToFilter.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AndAppliesToFilter.java
new file mode 100644
index 0000000..51e5695
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AndAppliesToFilter.java
@@ -0,0 +1,47 @@
+/*
+ * 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 org.apache.polygene.api.common.AppliesToFilter;
+
+/**
+ * JAVADOC
+ */
+final class AndAppliesToFilter
+ implements AppliesToFilter
+{
+ private final AppliesToFilter left;
+ private final AppliesToFilter right;
+
+ AndAppliesToFilter( AppliesToFilter left, AppliesToFilter right )
+ {
+ this.left = left;
+ this.right = right;
+ }
+
+ @Override
+ public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
+ {
+ return left.appliesTo( method, mixin, compositeType, fragmentClass ) &&
+ right.appliesTo( method, mixin, compositeType, fragmentClass );
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AnnotationAppliesToFilter.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AnnotationAppliesToFilter.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AnnotationAppliesToFilter.java
new file mode 100644
index 0000000..006f24b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/AnnotationAppliesToFilter.java
@@ -0,0 +1,47 @@
+/*
+ * 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 org.apache.polygene.api.common.AppliesToFilter;
+
+/**
+ * JAVADOC
+ */
+final class AnnotationAppliesToFilter
+ implements AppliesToFilter
+{
+ @SuppressWarnings( "raw" )
+ private final Class annotationType;
+
+ @SuppressWarnings( "raw" )
+ AnnotationAppliesToFilter( Class type )
+ {
+ this.annotationType = type;
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public boolean appliesTo( Method method, Class<?> mixin, Class<?> compositeType, Class<?> fragmentClass )
+ {
+ return method.getAnnotation( annotationType ) != null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationAssemblyFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationAssemblyFactoryImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationAssemblyFactoryImpl.java
new file mode 100644
index 0000000..46c8cee
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationAssemblyFactoryImpl.java
@@ -0,0 +1,79 @@
+/*
+ * 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.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationAssemblyFactory;
+import org.apache.polygene.bootstrap.Assembler;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+/**
+ * Factory for ApplicationAssembly.
+ */
+public final class ApplicationAssemblyFactoryImpl
+ implements ApplicationAssemblyFactory
+{
+ @Override
+ public ApplicationAssembly newApplicationAssembly( Assembler assembler )
+ throws AssemblyException
+ {
+ return newApplicationAssembly( new Assembler[][][]{ { { assembler } } } );
+ }
+
+ @Override
+ public ApplicationAssembly newApplicationAssembly( Assembler[][][] assemblers )
+ throws AssemblyException
+ {
+ ApplicationAssembly applicationAssembly = newApplicationAssembly();
+
+ // Build all layers bottom-up
+ LayerAssembly below = null;
+ for( int layer = assemblers.length - 1; layer >= 0; layer-- )
+ {
+ // Create Layer
+ LayerAssembly layerAssembly = applicationAssembly.layer( "Layer " + ( layer + 1 ) );
+ for( int module = 0; module < assemblers[ layer ].length; module++ )
+ {
+ // Create Module
+ ModuleAssembly moduleAssembly = layerAssembly.module( "Module " + ( module + 1 ) );
+ for( Assembler assembler : assemblers[ layer ][ module ] )
+ {
+ // Register Assembler
+ assembler.assemble( moduleAssembly );
+ }
+ }
+ if( below != null )
+ {
+ layerAssembly.uses( below ); // Link layers
+ }
+ below = layerAssembly;
+ }
+ return applicationAssembly;
+ }
+
+ @Override
+ public ApplicationAssembly newApplicationAssembly()
+ {
+ return new ApplicationAssemblyImpl();
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationAssemblyImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationAssemblyImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationAssemblyImpl.java
new file mode 100644
index 0000000..ccc571b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationAssemblyImpl.java
@@ -0,0 +1,157 @@
+/*
+ * 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.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.activation.Activator;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.AssemblyVisitor;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+
+/**
+ * The representation of an entire application. From
+ * this you can set information about the application
+ * and create LayerAssemblies.
+ */
+public final class ApplicationAssemblyImpl
+ implements ApplicationAssembly
+{
+ private final Map<String, LayerAssemblyImpl> layerAssemblies = new LinkedHashMap<>();
+ private String name = "Application";
+ private String version = "1.0"; // Default version
+ private Application.Mode mode;
+ private final MetaInfo metaInfo = new MetaInfo();
+ private final List<Class<? extends Activator<Application>>> activators = new ArrayList<>();
+
+ public ApplicationAssemblyImpl()
+ {
+ mode = Application.Mode.valueOf( System.getProperty( "mode", "production" ) );
+ }
+
+ @Override
+ public LayerAssembly layer( String name )
+ {
+ if( name != null )
+ {
+ LayerAssemblyImpl existing = layerAssemblies.get( name );
+ if( existing != null )
+ {
+ return existing;
+ }
+ }
+ LayerAssemblyImpl layerAssembly = new LayerAssemblyImpl( this, name );
+ layerAssemblies.put( name, layerAssembly );
+ return layerAssembly;
+ }
+
+ @Override
+ public ModuleAssembly module( String layerName, String moduleName )
+ {
+ return layer( layerName ).module( moduleName );
+ }
+
+ @Override
+ public ApplicationAssembly setName( String name )
+ {
+ this.name = name;
+ return this;
+ }
+
+ @Override
+ public ApplicationAssembly setVersion( String version )
+ {
+ this.version = version;
+ return this;
+ }
+
+ @Override
+ public ApplicationAssembly setMode( Application.Mode mode )
+ {
+ this.mode = mode;
+ return this;
+ }
+
+ @Override
+ public ApplicationAssembly setMetaInfo( Object info )
+ {
+ metaInfo.set( info );
+ return this;
+ }
+
+ @Override
+ @SafeVarargs
+ public final ApplicationAssembly withActivators( Class<? extends Activator<Application>>... activators )
+ {
+ this.activators.addAll( Arrays.asList( activators ) );
+ return this;
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> void visit( AssemblyVisitor<ThrowableType> visitor )
+ throws ThrowableType
+ {
+ visitor.visitApplication( this );
+ for( LayerAssemblyImpl layerAssembly : layerAssemblies.values() )
+ {
+ layerAssembly.visit( visitor );
+ }
+ }
+
+ public Collection<LayerAssemblyImpl> layerAssemblies()
+ {
+ return layerAssemblies.values();
+ }
+
+ public List<Class<? extends Activator<Application>>> activators()
+ {
+ return activators;
+ }
+
+ public MetaInfo metaInfo()
+ {
+ return metaInfo;
+ }
+
+ @Override
+ public String name()
+ {
+ return name;
+ }
+
+ public String version()
+ {
+ return version;
+ }
+
+ @Override
+ public Application.Mode mode()
+ {
+ return mode;
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationModelFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationModelFactoryImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationModelFactoryImpl.java
new file mode 100644
index 0000000..a39c521
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/bootstrap/ApplicationModelFactoryImpl.java
@@ -0,0 +1,211 @@
+/*
+ * 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.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.polygene.api.composite.ModelDescriptor;
+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.util.HierarchicalVisitor;
+import org.apache.polygene.bootstrap.ApplicationAssembly;
+import org.apache.polygene.bootstrap.ApplicationModelFactory;
+import org.apache.polygene.bootstrap.AssemblyException;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.bootstrap.LayerAssembly;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+import org.apache.polygene.runtime.composite.CompositeMethodModel;
+import org.apache.polygene.runtime.injection.InjectedFieldModel;
+import org.apache.polygene.runtime.model.Binder;
+import org.apache.polygene.runtime.model.Resolution;
+import org.apache.polygene.runtime.structure.ApplicationModel;
+import org.apache.polygene.runtime.structure.LayerModel;
+import org.apache.polygene.runtime.structure.ModuleModel;
+import org.apache.polygene.runtime.structure.UsedLayersModel;
+
+/**
+ * Factory for Applications.
+ */
+public final class ApplicationModelFactoryImpl
+ implements ApplicationModelFactory
+{
+ @Override
+ public ApplicationDescriptor newApplicationModel( ApplicationAssembly assembly )
+ throws AssemblyException
+ {
+ AssemblyHelper helper = createAssemblyHelper( assembly );
+
+ ApplicationAssemblyImpl applicationAssembly = (ApplicationAssemblyImpl) assembly;
+ ActivatorsModel<Application> applicationActivators = new ActivatorsModel<>( applicationAssembly.activators() );
+ List<LayerModel> layerModels = new ArrayList<>();
+ final ApplicationModel applicationModel = new ApplicationModel( applicationAssembly.name(),
+ applicationAssembly.version(),
+ applicationAssembly.mode(),
+ applicationAssembly.metaInfo(),
+ applicationActivators,
+ layerModels );
+ Map<LayerAssembly, LayerModel> mapAssemblyModel = new HashMap<>();
+ Map<LayerAssembly, List<LayerModel>> mapUsedLayers = new HashMap<>();
+
+ // Build all layers
+ List<LayerAssemblyImpl> layerAssemblies = new ArrayList<>( applicationAssembly.layerAssemblies() );
+ for( LayerAssemblyImpl layerAssembly : layerAssemblies )
+ {
+ List<LayerModel> usedLayers = new ArrayList<>();
+ mapUsedLayers.put( layerAssembly, usedLayers );
+
+ UsedLayersModel usedLayersModel = new UsedLayersModel( usedLayers );
+ List<ModuleModel> moduleModels = new ArrayList<>();
+ String name = layerAssembly.name();
+ if( name == null )
+ {
+ throw new AssemblyException( "Layer must have name set" );
+ }
+ ActivatorsModel<Layer> layerActivators = new ActivatorsModel<>( layerAssembly.activators() );
+ LayerModel layerModel = new LayerModel( name, layerAssembly.metaInfo(), usedLayersModel, layerActivators, moduleModels );
+
+ for( ModuleAssemblyImpl moduleAssembly : layerAssembly.moduleAssemblies() )
+ {
+ moduleModels.add( moduleAssembly.assembleModule( layerModel, helper ) );
+ }
+ mapAssemblyModel.put( layerAssembly, layerModel );
+ layerModels.add( layerModel );
+ }
+
+ // Populate used layer lists
+ for( LayerAssemblyImpl layerAssembly : layerAssemblies )
+ {
+ Set<LayerAssembly> usesLayers = layerAssembly.uses();
+ List<LayerModel> usedLayers = mapUsedLayers.get( layerAssembly );
+ for( LayerAssembly usesLayer : usesLayers )
+ {
+ LayerModel layerModel = mapAssemblyModel.get( usesLayer );
+ usedLayers.add( layerModel );
+ }
+ }
+
+ // Bind model
+ // This will resolve all dependencies
+ try
+ {
+// applicationModel.bind();
+ applicationModel.accept( new BindingVisitor( applicationModel ) );
+ }
+ catch( BindingException e )
+ {
+ throw new AssemblyException( "Unable to bind: " + applicationModel, e );
+ }
+
+ return applicationModel;
+ }
+
+ private AssemblyHelper createAssemblyHelper( ApplicationAssembly assembly )
+ {
+ if( assembly instanceof ApplicationAssemblyImpl )
+ {
+ ApplicationAssemblyImpl impl = (ApplicationAssemblyImpl) assembly;
+ AssemblyHelper helper = impl.metaInfo().get( AssemblyHelper.class );
+ if( helper != null )
+ {
+ return helper;
+ }
+ }
+ return new AssemblyHelper();
+ }
+
+ private static class BindingVisitor
+ implements HierarchicalVisitor<Object, Object, BindingException>
+ {
+ private LayerModel layer;
+ private ModuleModel module;
+ private ModelDescriptor objectDescriptor;
+ private CompositeMethodModel compositeMethodModel;
+
+ private Resolution resolution;
+ private final ApplicationModel applicationModel;
+
+ private BindingVisitor( ApplicationModel applicationModel )
+ {
+ this.applicationModel = applicationModel;
+ }
+
+ @Override
+ public boolean visitEnter( Object visited )
+ throws BindingException
+ {
+ if( visited instanceof Binder )
+ {
+ Binder binder = (Binder) visited;
+ binder.bind( resolution );
+
+ return false;
+ }
+ else if( visited instanceof CompositeMethodModel )
+ {
+ compositeMethodModel = (CompositeMethodModel) visited;
+ resolution = new Resolution( applicationModel, layer, module, objectDescriptor, compositeMethodModel, null );
+ }
+ else if( visited instanceof ModelDescriptor )
+ {
+ objectDescriptor = (ModelDescriptor) visited;
+ resolution = new Resolution( applicationModel, layer, module, objectDescriptor, null, null );
+ }
+ else if( visited instanceof InjectedFieldModel )
+ {
+ InjectedFieldModel fieldModel = (InjectedFieldModel) visited;
+ fieldModel.bind( new Resolution( applicationModel, layer, module,
+ objectDescriptor, compositeMethodModel, fieldModel.field() ) );
+ }
+ else if( visited instanceof ModuleModel )
+ {
+ module = (ModuleModel) visited;
+ }
+ else if( visited instanceof LayerModel )
+ {
+ layer = (LayerModel) visited;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean visitLeave( Object visited )
+ throws BindingException
+ {
+ return true;
+ }
+
+ @Override
+ public boolean visit( Object visited )
+ throws BindingException
+ {
+ if( visited instanceof Binder )
+ {
+ ( (Binder) visited ).bind( resolution );
+ }
+ return true;
+ }
+ }
+}
\ No newline at end of file