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 2015/07/30 21:48:07 UTC
[08/80] [partial] zest-java git commit: First round of changes to
move to org.apache.zest namespace.
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/structure/LayerInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/structure/LayerInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/structure/LayerInstance.java
new file mode 100644
index 0000000..074dccb
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/structure/LayerInstance.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2012, Paul Merlin.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.zest.runtime.structure;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.zest.api.activation.ActivationEventListener;
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.api.activation.PassivationException;
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.api.composite.TransientDescriptor;
+import org.apache.zest.api.entity.EntityDescriptor;
+import org.apache.zest.api.object.ObjectDescriptor;
+import org.apache.zest.api.service.ServiceReference;
+import org.apache.zest.api.structure.Layer;
+import org.apache.zest.api.value.ValueDescriptor;
+import org.apache.zest.functional.Function;
+import org.apache.zest.runtime.activation.ActivationDelegate;
+import org.apache.zest.spi.module.ModelModule;
+
+import static org.apache.zest.functional.Iterables.flattenIterables;
+import static org.apache.zest.functional.Iterables.map;
+
+/**
+ * Instance of a Zest application layer. Contains a list of modules which are managed by this layer.
+ */
+public class LayerInstance
+ implements Layer
+{
+
+ // Constructor parameters
+ private final LayerModel layerModel;
+ private final ApplicationInstance applicationInstance;
+ private final UsedLayersInstance usedLayersInstance;
+ // Eager instance objects
+ private final ActivationDelegate activation;
+ private final List<ModuleInstance> moduleInstances;
+
+ public LayerInstance( LayerModel model,
+ ApplicationInstance applicationInstance,
+ UsedLayersInstance usedLayersInstance
+ )
+ {
+ // Constructor parameters
+ this.layerModel = model;
+ this.applicationInstance = applicationInstance;
+ this.usedLayersInstance = usedLayersInstance;
+
+ // Eager instance objects
+ activation = new ActivationDelegate( this );
+ moduleInstances = new ArrayList<>();
+ }
+
+ @Override
+ public String toString()
+ {
+ return layerModel.toString();
+ }
+
+ // Implementation of Layer
+ @Override
+ public String name()
+ {
+ return layerModel.name();
+ }
+
+ // Implementation of MetaInfoHolder
+ @Override
+ public <T> T metaInfo( Class<T> infoType )
+ {
+ return layerModel.metaInfo( infoType );
+ }
+
+ // Implementation of Activation
+ @Override
+ public void activate()
+ throws ActivationException
+ {
+ activation.activate( layerModel.newActivatorsInstance(), moduleInstances );
+ }
+
+ @Override
+ public void passivate()
+ throws PassivationException
+ {
+ activation.passivate();
+ }
+
+ @Override
+ public void registerActivationEventListener( ActivationEventListener listener )
+ {
+ activation.registerActivationEventListener( listener );
+ }
+
+ @Override
+ public void deregisterActivationEventListener( ActivationEventListener listener )
+ {
+ activation.deregisterActivationEventListener( listener );
+ }
+
+ // Other methods
+ /* package */ void addModule( ModuleInstance module )
+ {
+ module.registerActivationEventListener( activation );
+ moduleInstances.add( module );
+ }
+
+ /* package */ LayerModel model()
+ {
+ return layerModel;
+ }
+
+ public ApplicationInstance applicationInstance()
+ {
+ return applicationInstance;
+ }
+
+ /* package */ UsedLayersInstance usedLayersInstance()
+ {
+ return usedLayersInstance;
+ }
+
+ /* package */ Iterable<ModelModule<ObjectDescriptor>> visibleObjects( final Visibility visibility )
+ {
+ return flattenIterables( map( new Function<ModuleInstance, Iterable<ModelModule<ObjectDescriptor>>>()
+ {
+
+ @Override
+ public Iterable<ModelModule<ObjectDescriptor>> map( ModuleInstance moduleInstance )
+ {
+ return moduleInstance.visibleObjects( visibility );
+ }
+ }, moduleInstances ) );
+ }
+
+ /* package */ Iterable<ModelModule<TransientDescriptor>> visibleTransients( final Visibility visibility )
+ {
+ return flattenIterables( map( new Function<ModuleInstance, Iterable<ModelModule<TransientDescriptor>>>()
+ {
+
+ @Override
+ public Iterable<ModelModule<TransientDescriptor>> map( ModuleInstance moduleInstance )
+ {
+ return moduleInstance.visibleTransients( visibility );
+ }
+ }, moduleInstances ) );
+ }
+
+ /* package */ Iterable<ModelModule<EntityDescriptor>> visibleEntities( final Visibility visibility )
+ {
+ return flattenIterables( map( new Function<ModuleInstance, Iterable<ModelModule<EntityDescriptor>>>()
+ {
+
+ @Override
+ public Iterable<ModelModule<EntityDescriptor>> map( ModuleInstance moduleInstance )
+ {
+ return moduleInstance.visibleEntities( visibility );
+ }
+ }, moduleInstances ) );
+ }
+
+ /* package */ Iterable<ModelModule<ValueDescriptor>> visibleValues( final Visibility visibility )
+ {
+ return flattenIterables( map( new Function<ModuleInstance, Iterable<ModelModule<ValueDescriptor>>>()
+ {
+
+ @Override
+ public Iterable<ModelModule<ValueDescriptor>> map( ModuleInstance moduleInstance )
+ {
+ return moduleInstance.visibleValues( visibility );
+ }
+ }, moduleInstances ) );
+ }
+
+ /* package */ Iterable<ServiceReference<?>> visibleServices( final Visibility visibility )
+ {
+ return flattenIterables( map( new Function<ModuleInstance, Iterable<ServiceReference<?>>>()
+ {
+
+ @Override
+ public Iterable<ServiceReference<?>> map( ModuleInstance moduleInstance )
+ {
+ return moduleInstance.visibleServices( visibility );
+ }
+ }, moduleInstances ) );
+ }
+
+ /* package */ ModuleInstance findModule( String moduleName )
+ {
+ for( ModuleInstance moduleInstance : moduleInstances )
+ {
+ if( moduleInstance.model().name().equals( moduleName ) )
+ {
+ return moduleInstance;
+ }
+ }
+
+ throw new IllegalArgumentException( "No such module:" + moduleName );
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/structure/LayerModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/structure/LayerModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/structure/LayerModel.java
new file mode 100644
index 0000000..8592122
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/structure/LayerModel.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
+ * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.zest.runtime.structure;
+
+import java.util.List;
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.api.common.MetaInfo;
+import org.apache.zest.api.structure.Layer;
+import org.apache.zest.api.structure.LayerDescriptor;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.VisitableHierarchy;
+import org.apache.zest.runtime.activation.ActivatorsInstance;
+import org.apache.zest.runtime.activation.ActivatorsModel;
+
+/**
+ * JAVADOC
+ */
+public final class LayerModel
+ implements LayerDescriptor, VisitableHierarchy<Object, Object>
+{
+ // Model
+ private final String name;
+ private final MetaInfo metaInfo;
+ private final UsedLayersModel usedLayersModel;
+ private final ActivatorsModel<Layer> activatorsModel;
+ private final List<ModuleModel> modules;
+
+ public LayerModel( String name,
+ MetaInfo metaInfo,
+ UsedLayersModel usedLayersModel,
+ ActivatorsModel<Layer> activatorsModel,
+ List<ModuleModel> modules
+ )
+ {
+ this.name = name;
+ this.metaInfo = metaInfo;
+ this.usedLayersModel = usedLayersModel;
+ this.activatorsModel = activatorsModel;
+ this.modules = modules;
+ }
+
+ @Override
+ public String name()
+ {
+ return name;
+ }
+
+ public <T> T metaInfo( Class<T> infoType )
+ {
+ return metaInfo.get( infoType );
+ }
+
+ public Iterable<ModuleModel> modules()
+ {
+ return modules;
+ }
+
+ @Override
+ public UsedLayersModel usedLayers()
+ {
+ return usedLayersModel;
+ }
+
+ public ActivatorsInstance<Layer> newActivatorsInstance()
+ throws ActivationException
+ {
+ return new ActivatorsInstance<>( activatorsModel.newInstances() );
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+ throws ThrowableType
+ {
+ if( modelVisitor.visitEnter( this ) )
+ {
+ if( activatorsModel.accept( modelVisitor ) )
+ {
+ for( ModuleModel module : modules )
+ {
+ if( !module.accept( modelVisitor ) )
+ {
+ break;
+ }
+ }
+ }
+ }
+ return modelVisitor.visitLeave( this );
+ }
+
+ // Context
+ public LayerInstance newInstance( ApplicationInstance applicationInstance, UsedLayersInstance usedLayerInstance )
+ {
+ LayerInstance layerInstance = new LayerInstance( this, applicationInstance, usedLayerInstance );
+ for( ModuleModel module : modules )
+ {
+ ModuleInstance moduleInstance = module.newInstance( layerInstance );
+ layerInstance.addModule( moduleInstance );
+ }
+
+ return layerInstance;
+ }
+
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleInstance.java
new file mode 100644
index 0000000..0a110e4
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleInstance.java
@@ -0,0 +1,873 @@
+/*
+ * Copyright (c) 2008-2012, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2012, Kent Sølvsten. All Rights Reserved.
+ * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
+ * Copyright (c) 2012-2015, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.zest.runtime.structure;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.zest.api.activation.Activation;
+import org.apache.zest.api.activation.ActivationEventListener;
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.api.activation.PassivationException;
+import org.apache.zest.api.association.AssociationDescriptor;
+import org.apache.zest.api.common.ConstructionException;
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.api.composite.AmbiguousTypeException;
+import org.apache.zest.api.composite.Composite;
+import org.apache.zest.api.composite.ModelDescriptor;
+import org.apache.zest.api.composite.NoSuchTransientException;
+import org.apache.zest.api.composite.TransientBuilder;
+import org.apache.zest.api.composite.TransientDescriptor;
+import org.apache.zest.api.entity.EntityComposite;
+import org.apache.zest.api.entity.EntityDescriptor;
+import org.apache.zest.api.entity.EntityReference;
+import org.apache.zest.api.entity.IdentityGenerator;
+import org.apache.zest.api.metrics.MetricsProvider;
+import org.apache.zest.api.object.NoSuchObjectException;
+import org.apache.zest.api.object.ObjectDescriptor;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.api.property.PropertyDescriptor;
+import org.apache.zest.api.query.QueryBuilder;
+import org.apache.zest.api.query.QueryBuilderFactory;
+import org.apache.zest.api.service.NoSuchServiceException;
+import org.apache.zest.api.service.ServiceDescriptor;
+import org.apache.zest.api.service.ServiceReference;
+import org.apache.zest.api.structure.Module;
+import org.apache.zest.api.unitofwork.UnitOfWork;
+import org.apache.zest.api.unitofwork.UnitOfWorkException;
+import org.apache.zest.api.unitofwork.UnitOfWorkFactory;
+import org.apache.zest.api.usecase.Usecase;
+import org.apache.zest.api.util.NullArgumentException;
+import org.apache.zest.api.value.NoSuchValueException;
+import org.apache.zest.api.value.ValueBuilder;
+import org.apache.zest.api.value.ValueComposite;
+import org.apache.zest.api.value.ValueDescriptor;
+import org.apache.zest.api.value.ValueSerialization;
+import org.apache.zest.api.value.ValueSerializationException;
+import org.apache.zest.functional.Function;
+import org.apache.zest.functional.Function2;
+import org.apache.zest.functional.Specification;
+import org.apache.zest.functional.Specifications;
+import org.apache.zest.runtime.activation.ActivationDelegate;
+import org.apache.zest.runtime.composite.FunctionStateResolver;
+import org.apache.zest.runtime.composite.StateResolver;
+import org.apache.zest.runtime.composite.TransientBuilderInstance;
+import org.apache.zest.runtime.composite.TransientModel;
+import org.apache.zest.runtime.composite.TransientStateInstance;
+import org.apache.zest.runtime.composite.TransientsModel;
+import org.apache.zest.runtime.composite.UsesInstance;
+import org.apache.zest.runtime.entity.EntitiesModel;
+import org.apache.zest.runtime.entity.EntityInstance;
+import org.apache.zest.runtime.entity.EntityModel;
+import org.apache.zest.runtime.injection.InjectionContext;
+import org.apache.zest.runtime.object.ObjectModel;
+import org.apache.zest.runtime.object.ObjectsModel;
+import org.apache.zest.runtime.property.PropertyInstance;
+import org.apache.zest.runtime.property.PropertyModel;
+import org.apache.zest.runtime.query.QueryBuilderFactoryImpl;
+import org.apache.zest.runtime.service.ImportedServicesInstance;
+import org.apache.zest.runtime.service.ImportedServicesModel;
+import org.apache.zest.runtime.service.ServicesInstance;
+import org.apache.zest.runtime.service.ServicesModel;
+import org.apache.zest.runtime.unitofwork.UnitOfWorkInstance;
+import org.apache.zest.runtime.value.ValueBuilderInstance;
+import org.apache.zest.runtime.value.ValueBuilderWithPrototype;
+import org.apache.zest.runtime.value.ValueBuilderWithState;
+import org.apache.zest.runtime.value.ValueInstance;
+import org.apache.zest.runtime.value.ValueModel;
+import org.apache.zest.runtime.value.ValuesModel;
+import org.apache.zest.spi.entitystore.EntityStore;
+import org.apache.zest.spi.metrics.MetricsProviderAdapter;
+import org.apache.zest.spi.module.ModelModule;
+import org.apache.zest.spi.module.ModuleSpi;
+import org.apache.zest.valueserialization.orgjson.OrgJsonValueSerialization;
+
+import static org.apache.zest.api.util.Classes.RAW_CLASS;
+import static org.apache.zest.api.util.Classes.modelTypeSpecification;
+import static org.apache.zest.functional.Iterables.cast;
+import static org.apache.zest.functional.Iterables.filter;
+import static org.apache.zest.functional.Iterables.first;
+import static org.apache.zest.functional.Iterables.flatten;
+import static org.apache.zest.functional.Iterables.iterable;
+import static org.apache.zest.functional.Iterables.map;
+import static org.apache.zest.functional.Iterables.toList;
+
+/**
+ * Instance of a Zest Module. Contains the various composites for this Module.
+ */
+public class ModuleInstance
+ implements Module, ModuleSpi, Activation
+{
+ // Constructor parameters
+ private final ModuleModel model;
+ private final LayerInstance layer;
+ private final TransientsModel transients;
+ private final ValuesModel values;
+ private final ObjectsModel objects;
+ private final EntitiesModel entities;
+ private final ServicesInstance services;
+ private final ImportedServicesInstance importedServices;
+ // Eager instance objects
+ private final ActivationDelegate activation;
+ private final TypeLookup typeLookup;
+ private final QueryBuilderFactory queryBuilderFactory;
+ private final ClassLoader classLoader;
+ private final EntityFunction entityFunction;
+ // Lazy assigned on accessors
+ private EntityStore store;
+ private IdentityGenerator generator;
+ private ValueSerialization valueSerialization;
+ private MetricsProvider metrics;
+
+ @SuppressWarnings( "LeakingThisInConstructor" )
+ public ModuleInstance( ModuleModel moduleModel, LayerInstance layerInstance, TransientsModel transientsModel,
+ EntitiesModel entitiesModel, ObjectsModel objectsModel, ValuesModel valuesModel,
+ ServicesModel servicesModel, ImportedServicesModel importedServicesModel
+ )
+ {
+ // Constructor parameters
+ model = moduleModel;
+ layer = layerInstance;
+ transients = transientsModel;
+ values = valuesModel;
+ objects = objectsModel;
+ entities = entitiesModel;
+ services = servicesModel.newInstance( this );
+ importedServices = importedServicesModel.newInstance( this );
+
+ // Eager instance objects
+ activation = new ActivationDelegate( this );
+ typeLookup = new TypeLookup( this );
+ queryBuilderFactory = new QueryBuilderFactoryImpl( this );
+ classLoader = new ModuleClassLoader( this, Thread.currentThread().getContextClassLoader() );
+ entityFunction = new EntityFunction( this );
+
+ // Activation
+ services.registerActivationEventListener( activation );
+ importedServices.registerActivationEventListener( activation );
+ }
+
+ @Override
+ public String toString()
+ {
+ return model.toString();
+ }
+
+ // Implementation of Module
+ @Override
+ public String name()
+ {
+ return model.name();
+ }
+
+ @Override
+ public ClassLoader classLoader()
+ {
+ return classLoader;
+ }
+
+ @Override
+ public EntityDescriptor entityDescriptor( String name )
+ {
+ try
+ {
+ Class<?> type = classLoader().loadClass( name );
+ ModelModule<EntityModel> entityModel = typeLookup.lookupEntityModel( type );
+ if( entityModel == null )
+ {
+ return null;
+ }
+ return entityModel.model();
+ }
+ catch( ClassNotFoundException e )
+ {
+ return null;
+ }
+ }
+
+ @Override
+ public ObjectDescriptor objectDescriptor( String typeName )
+ {
+ try
+ {
+ Class<?> type = classLoader().loadClass( typeName );
+ ModelModule<ObjectModel> objectModel = typeLookup.lookupObjectModel( type );
+ if( objectModel == null )
+ {
+ return null;
+ }
+ return objectModel.model();
+ }
+ catch( ClassNotFoundException e )
+ {
+ return null;
+ }
+ }
+
+ @Override
+ public TransientDescriptor transientDescriptor( String name )
+ {
+ try
+ {
+ Class<?> type = classLoader().loadClass( name );
+ ModelModule<TransientModel> transientModel = typeLookup.lookupTransientModel( type );
+ if( transientModel == null )
+ {
+ return null;
+ }
+ return transientModel.model();
+ }
+ catch( ClassNotFoundException e )
+ {
+ return null;
+ }
+ }
+
+ @Override
+ public ValueDescriptor valueDescriptor( String name )
+ {
+ try
+ {
+ Class<?> type = classLoader().loadClass( name );
+ ModelModule<ValueModel> valueModel = typeLookup.lookupValueModel( type );
+ if( valueModel == null )
+ {
+ return null;
+ }
+ return valueModel.model();
+ }
+ catch( ClassNotFoundException e )
+ {
+ return null;
+ }
+ }
+
+ // Implementation of MetaInfoHolder
+ @Override
+ public <T> T metaInfo( Class<T> infoType )
+ {
+ return model.metaInfo( infoType );
+ }
+
+ // Implementation of ObjectFactory
+ @Override
+ public <T> T newObject( Class<T> mixinType, Object... uses )
+ throws NoSuchObjectException
+ {
+ NullArgumentException.validateNotNull( "mixinType", mixinType );
+ ModelModule<ObjectModel> modelModule = typeLookup.lookupObjectModel( mixinType );
+
+ if( modelModule == null )
+ {
+ throw new NoSuchObjectException( mixinType.getName(), name() );
+ }
+
+ InjectionContext injectionContext = new InjectionContext( modelModule.module(), UsesInstance.EMPTY_USES.use( uses ) );
+ return mixinType.cast( modelModule.model().newInstance( injectionContext ) );
+ }
+
+ @Override
+ public void injectTo( Object instance, Object... uses )
+ throws ConstructionException
+ {
+ NullArgumentException.validateNotNull( "instance", instance );
+ ModelModule<ObjectModel> modelModule = typeLookup.lookupObjectModel( instance.getClass() );
+
+ if( modelModule == null )
+ {
+ throw new NoSuchObjectException( instance.getClass().getName(), name() );
+ }
+
+ InjectionContext injectionContext = new InjectionContext( modelModule.module(), UsesInstance.EMPTY_USES.use( uses ) );
+ modelModule.model().inject( injectionContext, instance );
+ }
+
+ // Implementation of TransientBuilderFactory
+ @Override
+ public <T> TransientBuilder<T> newTransientBuilder( Class<T> mixinType )
+ throws NoSuchTransientException
+ {
+ NullArgumentException.validateNotNull( "mixinType", mixinType );
+ ModelModule<TransientModel> modelModule = typeLookup.lookupTransientModel( mixinType );
+
+ if( modelModule == null )
+ {
+ throw new NoSuchTransientException( mixinType.getName(), name() );
+ }
+
+ Map<AccessibleObject, Property<?>> properties = new HashMap<>();
+ for( PropertyModel propertyModel : modelModule.model().state().properties() )
+ {
+ Property<?> property = new PropertyInstance<>( propertyModel.getBuilderInfo(),
+ propertyModel.initialValue( modelModule.module() ) );
+ properties.put( propertyModel.accessor(), property );
+ }
+
+ TransientStateInstance state = new TransientStateInstance( properties );
+
+ return new TransientBuilderInstance<>( modelModule, state, UsesInstance.EMPTY_USES );
+ }
+
+ @Override
+ public <T> T newTransient( final Class<T> mixinType, Object... uses )
+ throws NoSuchTransientException, ConstructionException
+ {
+ return newTransientBuilder( mixinType ).use( uses ).newInstance();
+ }
+
+ // Implementation of ValueBuilderFactory
+ @Override
+ public <T> T newValue( Class<T> mixinType )
+ throws NoSuchValueException, ConstructionException
+ {
+ return newValueBuilder( mixinType ).newInstance();
+ }
+
+ @Override
+ public <T> ValueBuilder<T> newValueBuilder( Class<T> mixinType )
+ throws NoSuchValueException
+ {
+ NullArgumentException.validateNotNull( "mixinType", mixinType );
+ ModelModule<ValueModel> compositeModelModule = typeLookup.lookupValueModel( mixinType );
+
+ if( compositeModelModule == null )
+ {
+ throw new NoSuchValueException( mixinType.getName(), name() );
+ }
+
+ StateResolver stateResolver = new InitialStateResolver( compositeModelModule.module() );
+ return new ValueBuilderInstance<>( compositeModelModule, this, stateResolver );
+ }
+
+ @Override
+ public <T> ValueBuilder<T> newValueBuilderWithState( Class<T> mixinType,
+ Function<PropertyDescriptor, Object> propertyFunction,
+ Function<AssociationDescriptor, EntityReference> associationFunction,
+ Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
+ Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction
+ )
+ {
+ NullArgumentException.validateNotNull( "propertyFunction", propertyFunction );
+ NullArgumentException.validateNotNull( "associationFunction", associationFunction );
+ NullArgumentException.validateNotNull( "manyAssociationFunction", manyAssociationFunction );
+ NullArgumentException.validateNotNull( "namedAssociationFunction", namedAssociationFunction );
+
+ ModelModule<ValueModel> compositeModelModule = typeLookup.lookupValueModel( mixinType );
+
+ if( compositeModelModule == null )
+ {
+ throw new NoSuchValueException( mixinType.getName(), name() );
+ }
+
+ StateResolver stateResolver = new FunctionStateResolver(
+ propertyFunction, associationFunction, manyAssociationFunction, namedAssociationFunction
+ );
+ return new ValueBuilderWithState<>( compositeModelModule, this, stateResolver );
+ }
+
+ private static class InitialStateResolver
+ implements StateResolver
+ {
+ private final Module module;
+
+ private InitialStateResolver( Module module )
+ {
+ this.module = module;
+ }
+
+ @Override
+ public Object getPropertyState( PropertyDescriptor propertyDescriptor )
+ {
+ return propertyDescriptor.initialValue( module );
+ }
+
+ @Override
+ public EntityReference getAssociationState( AssociationDescriptor associationDescriptor )
+ {
+ return null;
+ }
+
+ @Override
+ public List<EntityReference> getManyAssociationState( AssociationDescriptor associationDescriptor )
+ {
+ return new ArrayList<>();
+ }
+
+ @Override
+ public Map<String, EntityReference> getNamedAssociationState( AssociationDescriptor associationDescriptor )
+ {
+ return new HashMap<>();
+ }
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> ValueBuilder<T> newValueBuilderWithPrototype( T prototype )
+ {
+ NullArgumentException.validateNotNull( "prototype", prototype );
+
+ ValueInstance valueInstance = ValueInstance.valueInstanceOf( (ValueComposite) prototype );
+ Class<Composite> valueType = (Class<Composite>) first( valueInstance.types() );
+
+ ModelModule<ValueModel> modelModule = typeLookup.lookupValueModel( valueType );
+
+ if( modelModule == null )
+ {
+ throw new NoSuchValueException( valueType.getName(), name() );
+ }
+
+ return new ValueBuilderWithPrototype<>( modelModule, this, prototype );
+ }
+
+ @Override
+ public <T> T newValueFromSerializedState( Class<T> mixinType, String serializedState )
+ throws NoSuchValueException, ConstructionException
+ {
+ NullArgumentException.validateNotNull( "mixinType", mixinType );
+ ModelModule<ValueModel> modelModule = typeLookup.lookupValueModel( mixinType );
+
+ if( modelModule == null )
+ {
+ throw new NoSuchValueException( mixinType.getName(), name() );
+ }
+
+ try
+ {
+ return valueSerialization().deserialize( modelModule.model().valueType(), serializedState );
+ }
+ catch( ValueSerializationException ex )
+ {
+ throw new ConstructionException( "Could not create value from serialized state", ex );
+ }
+ }
+
+ // Implementation of UnitOfWorkFactory
+ @Override
+ public UnitOfWork newUnitOfWork()
+ {
+ return newUnitOfWork( Usecase.DEFAULT );
+ }
+
+ @Override
+ public UnitOfWork newUnitOfWork( long currentTime )
+ {
+ return newUnitOfWork( Usecase.DEFAULT, currentTime );
+ }
+
+ @Override
+ public UnitOfWork newUnitOfWork( Usecase usecase )
+ {
+ return newUnitOfWork( usecase == null ? Usecase.DEFAULT : usecase, System.currentTimeMillis() );
+ }
+
+ @Override
+ public UnitOfWork newUnitOfWork( Usecase usecase, long currentTime )
+ {
+ UnitOfWorkInstance unitOfWorkInstance = new UnitOfWorkInstance( usecase, currentTime, metricsProvider() );
+ return new ModuleUnitOfWork( ModuleInstance.this, unitOfWorkInstance );
+ }
+
+ @Override
+ public boolean isUnitOfWorkActive()
+ {
+ Stack<UnitOfWorkInstance> stack = UnitOfWorkInstance.getCurrent();
+ return !stack.isEmpty();
+ }
+
+ @Override
+ public UnitOfWork currentUnitOfWork()
+ {
+ Stack<UnitOfWorkInstance> stack = UnitOfWorkInstance.getCurrent();
+ if( stack.size() == 0 )
+ {
+ throw new IllegalStateException( "No current UnitOfWork active" );
+ }
+ return new ModuleUnitOfWork( ModuleInstance.this, stack.peek() );
+ }
+
+ @Override
+ public UnitOfWork getUnitOfWork( EntityComposite entity )
+ {
+ EntityInstance instance = EntityInstance.entityInstanceOf( entity );
+ return instance.unitOfWork();
+ }
+
+ // Implementation of QueryBuilderFactory
+ @Override
+ public <T> QueryBuilder<T> newQueryBuilder( final Class<T> resultType )
+ {
+ return queryBuilderFactory.newQueryBuilder( resultType );
+ }
+
+ // Implementation of ServiceFinder
+ @Override
+ public <T> ServiceReference<T> findService( Class<T> serviceType )
+ {
+ return typeLookup.lookupServiceReference( (Type) serviceType );
+ }
+
+ @Override
+ public <T> ServiceReference<T> findService( Type serviceType )
+ {
+ return typeLookup.lookupServiceReference( serviceType );
+ }
+
+ @Override
+ public <T> Iterable<ServiceReference<T>> findServices( Class<T> serviceType )
+ {
+ return typeLookup.lookupServiceReferences( (Type) serviceType );
+ }
+
+ @Override
+ public <T> Iterable<ServiceReference<T>> findServices( Type serviceType )
+ {
+ return typeLookup.lookupServiceReferences( serviceType );
+ }
+
+ // Implementation of Activation
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public void activate()
+ throws ActivationException
+ {
+ activation.activate( model.newActivatorsInstance(), iterable( services, importedServices ) );
+ }
+
+ @Override
+ public void passivate()
+ throws PassivationException
+ {
+ activation.passivate();
+ }
+
+ @Override
+ public void registerActivationEventListener( ActivationEventListener listener )
+ {
+ activation.registerActivationEventListener( listener );
+ }
+
+ @Override
+ public void deregisterActivationEventListener( ActivationEventListener listener )
+ {
+ activation.deregisterActivationEventListener( listener );
+ }
+
+ // Other methods
+ /* package */ ModuleModel model()
+ {
+ return model;
+ }
+
+ public LayerInstance layerInstance()
+ {
+ return layer;
+ }
+
+ public TypeLookup typeLookup()
+ {
+ return typeLookup;
+ }
+
+ public Function2<EntityReference, Type, Object> getEntityFunction()
+ {
+ return entityFunction;
+ }
+
+ private static class EntityFunction
+ implements Function2<EntityReference, Type, Object>
+ {
+
+ private final UnitOfWorkFactory uowf;
+
+ private EntityFunction( UnitOfWorkFactory uowf )
+ {
+ this.uowf = uowf;
+ }
+
+ @Override
+ public Object map( EntityReference entityReference, Type type )
+ {
+ return uowf.currentUnitOfWork().get( RAW_CLASS.map( type ), entityReference.identity() );
+ }
+ }
+
+ public EntityStore entityStore()
+ {
+ synchronized( this )
+ {
+ if( store == null )
+ {
+ ServiceReference<EntityStore> service = findService( EntityStore.class );
+ if( service == null )
+ {
+ throw new UnitOfWorkException( "No EntityStore service available in module " + name() );
+ }
+ store = service.get();
+ }
+ }
+ return store;
+ }
+
+ public IdentityGenerator identityGenerator()
+ {
+ synchronized( this )
+ {
+ if( generator == null )
+ {
+ ServiceReference<IdentityGenerator> service = findService( IdentityGenerator.class );
+ generator = service.get();
+ }
+ return generator;
+ }
+ }
+
+ public ValueSerialization valueSerialization()
+ {
+ synchronized( this )
+ {
+ if( valueSerialization == null )
+ {
+ try
+ {
+ ServiceReference<ValueSerialization> service = findService( ValueSerialization.class );
+ valueSerialization = service.get();
+ }
+ catch( NoSuchServiceException e )
+ {
+ valueSerialization = new OrgJsonValueSerialization( layer.applicationInstance(), this, this );
+ }
+ }
+ }
+ return valueSerialization;
+ }
+
+ /* package */ MetricsProvider metricsProvider()
+ {
+ synchronized( this )
+ {
+ if( metrics == null )
+ {
+ try
+ {
+ ServiceReference<MetricsProvider> service = findService( MetricsProvider.class );
+ metrics = service.get();
+ }
+ catch( NoSuchServiceException e )
+ {
+ metrics = new MetricsProviderAdapter();
+ }
+ }
+ }
+ return metrics;
+ }
+
+ public Iterable<ModelModule<ObjectDescriptor>> visibleObjects( Visibility visibility )
+ {
+ return map( ModelModule.<ObjectDescriptor>modelModuleFunction( this ),
+ filter( new VisibilitySpecification( visibility ), objects.models() ) );
+ }
+
+ public Iterable<ModelModule<TransientDescriptor>> visibleTransients( Visibility visibility )
+ {
+ return map( ModelModule.<TransientDescriptor>modelModuleFunction( this ),
+ filter( new VisibilitySpecification( visibility ), transients.models() ) );
+ }
+
+ public Iterable<ModelModule<EntityDescriptor>> visibleEntities( Visibility visibility )
+ {
+ return map( ModelModule.<EntityDescriptor>modelModuleFunction( this ),
+ filter( new VisibilitySpecification( visibility ), entities.models() ) );
+ }
+
+ public Iterable<ModelModule<ValueDescriptor>> visibleValues( Visibility visibility )
+ {
+ return map( ModelModule.<ValueDescriptor>modelModuleFunction( this ),
+ filter( new VisibilitySpecification( visibility ), values.models() ) );
+ }
+
+ public Iterable<ServiceReference<?>> visibleServices( Visibility visibility )
+ {
+ return flatten( services.visibleServices( visibility ),
+ importedServices.visibleServices( visibility ) );
+ }
+
+ // Module ClassLoader
+ private static class ModuleClassLoader
+ extends ClassLoader
+ {
+
+ private final ModuleInstance moduleInstance;
+ private final Map<String, Class<?>> classes = new ConcurrentHashMap<>();
+
+ private ModuleClassLoader( ModuleInstance moduleInstance, ClassLoader classLoader )
+ {
+ super( classLoader );
+ this.moduleInstance = moduleInstance;
+ }
+
+ @Override
+ protected Class<?> findClass( String name )
+ throws ClassNotFoundException
+ {
+ Class<?> clazz = classes.get( name );
+ if( clazz == null )
+ {
+ Specification<ModelDescriptor> modelTypeSpecification = modelTypeSpecification( name );
+ Specification<ModelModule<ModelDescriptor>> translate = Specifications.translate( ModelModule.modelFunction(), modelTypeSpecification );
+ // Check module
+ {
+ Iterable<ModelModule<ModelDescriptor>> i = cast( flatten(
+ cast( moduleInstance.visibleObjects( Visibility.module ) ),
+ cast( moduleInstance.visibleEntities( Visibility.module ) ),
+ cast( moduleInstance.visibleTransients( Visibility.module ) ),
+ cast( moduleInstance.visibleValues( Visibility.module ) ) ) );
+
+ Iterable<ModelModule<ModelDescriptor>> moduleModels = filter( translate, i );
+ Iterator<ModelModule<ModelDescriptor>> iter = moduleModels.iterator();
+ if( iter.hasNext() )
+ {
+ clazz = first( iter.next().model().types() );
+
+ if( iter.hasNext() )
+ {
+ // Ambiguous exception
+ throw new ClassNotFoundException(
+ name,
+ new AmbiguousTypeException(
+ "More than one model matches the classname " + name + ":" + toList( moduleModels )
+ )
+ );
+ }
+ }
+ }
+
+ // Check layer
+ if( clazz == null )
+ {
+ Iterable<ModelModule<ModelDescriptor>> flatten = cast( flatten(
+ cast( moduleInstance.layerInstance().visibleObjects( Visibility.layer ) ),
+ cast( moduleInstance.layerInstance().visibleTransients( Visibility.layer ) ),
+ cast( moduleInstance.layerInstance().visibleEntities( Visibility.layer ) ),
+ cast( moduleInstance.layerInstance().visibleValues( Visibility.layer ) ),
+ cast( moduleInstance.layerInstance().visibleObjects( Visibility.application ) ),
+ cast( moduleInstance.layerInstance().visibleTransients( Visibility.application ) ),
+ cast( moduleInstance.layerInstance().visibleEntities( Visibility.application ) ),
+ cast( moduleInstance.layerInstance().visibleValues( Visibility.application ) ) ) );
+ Iterable<ModelModule<ModelDescriptor>> layerModels = filter( translate, flatten );
+ Iterator<ModelModule<ModelDescriptor>> iter = layerModels.iterator();
+ if( iter.hasNext() )
+ {
+ clazz = first( iter.next().model().types() );
+
+ if( iter.hasNext() )
+ {
+ // Ambiguous exception
+ throw new ClassNotFoundException(
+ name,
+ new AmbiguousTypeException(
+ "More than one model matches the classname " + name + ":" + toList( layerModels ) )
+ );
+ }
+ }
+ }
+
+ // Check used layers
+ if( clazz == null )
+ {
+ Iterable<ModelModule<ModelDescriptor>> flatten = cast( flatten(
+ cast( moduleInstance.layerInstance().usedLayersInstance().visibleObjects() ),
+ cast( moduleInstance.layerInstance().usedLayersInstance().visibleTransients() ),
+ cast( moduleInstance.layerInstance().usedLayersInstance().visibleEntities() ),
+ cast( moduleInstance.layerInstance().usedLayersInstance().visibleValues() ) ) );
+ Iterable<ModelModule<ModelDescriptor>> usedLayersModels = filter( translate, flatten );
+ Iterator<ModelModule<ModelDescriptor>> iter = usedLayersModels.iterator();
+ if( iter.hasNext() )
+ {
+ clazz = first( iter.next().model().types() );
+
+ if( iter.hasNext() )
+ {
+ // Ambiguous exception
+ throw new ClassNotFoundException(
+ name,
+ new AmbiguousTypeException(
+ "More than one model matches the classname " + name + ":" + toList( usedLayersModels )
+ )
+ );
+ }
+ }
+ }
+
+ if( clazz == null )
+ {
+ throw new ClassNotFoundException( name );
+ }
+ classes.put( name, clazz );
+ }
+
+ return clazz;
+ }
+ }
+
+ public Iterable<ModelModule<ValueDescriptor>> findVisibleValueTypes()
+ {
+ return flatten( visibleValues( Visibility.module ),
+ layerInstance().visibleValues( Visibility.layer ),
+ layerInstance().visibleValues( Visibility.application ),
+ layerInstance().usedLayersInstance().visibleValues()
+ );
+ }
+
+ public Iterable<ModelModule<EntityDescriptor>> findVisibleEntityTypes()
+ {
+ return flatten( visibleEntities( Visibility.module ),
+ layerInstance().visibleEntities( Visibility.layer ),
+ layerInstance().visibleEntities( Visibility.application ),
+ layerInstance().usedLayersInstance().visibleEntities()
+ );
+ }
+ public Iterable<ModelModule<TransientDescriptor>> findVisibleTransientTypes()
+ {
+ return flatten( visibleTransients( Visibility.module ),
+ layerInstance().visibleTransients( Visibility.layer ),
+ layerInstance().visibleTransients( Visibility.application ),
+ layerInstance().usedLayersInstance().visibleTransients()
+ );
+ }
+ public Iterable<ModelModule<ServiceDescriptor>> findVisibleServiceTypes()
+ {
+ return flatten( visibleServices( Visibility.module ),
+ layerInstance().visibleServices( Visibility.layer ),
+ layerInstance().visibleServices( Visibility.application ),
+ layerInstance().usedLayersInstance().visibleServices()
+ );
+ }
+ public Iterable<ModelModule<ObjectDescriptor>> findVisibleObjectTypes()
+ {
+ return flatten( visibleObjects( Visibility.module ),
+ layerInstance().visibleObjects( Visibility.layer ),
+ layerInstance().visibleObjects( Visibility.application ),
+ layerInstance().usedLayersInstance().visibleObjects()
+ );
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleModel.java
new file mode 100644
index 0000000..49e3670
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleModel.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
+ * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.zest.runtime.structure;
+
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.api.common.MetaInfo;
+import org.apache.zest.api.structure.Module;
+import org.apache.zest.api.structure.ModuleDescriptor;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.VisitableHierarchy;
+import org.apache.zest.runtime.activation.ActivatorsInstance;
+import org.apache.zest.runtime.activation.ActivatorsModel;
+import org.apache.zest.runtime.composite.TransientsModel;
+import org.apache.zest.runtime.entity.EntitiesModel;
+import org.apache.zest.runtime.object.ObjectsModel;
+import org.apache.zest.runtime.service.ImportedServicesModel;
+import org.apache.zest.runtime.service.ServicesModel;
+import org.apache.zest.runtime.value.ValuesModel;
+
+/**
+ * JAVADOC
+ */
+public class ModuleModel
+ implements ModuleDescriptor, VisitableHierarchy<Object, Object>
+{
+ private final ActivatorsModel<Module> activatorsModel;
+ private final TransientsModel transientsModel;
+ private final EntitiesModel entitiesModel;
+ private final ObjectsModel objectsModel;
+ private final ValuesModel valuesModel;
+ private final ServicesModel servicesModel;
+ private final ImportedServicesModel importedServicesModel;
+
+ private final String name;
+ private final MetaInfo metaInfo;
+
+ public ModuleModel( String name,
+ MetaInfo metaInfo,
+ ActivatorsModel<Module> activatorsModel,
+ TransientsModel transientsModel,
+ EntitiesModel entitiesModel,
+ ObjectsModel objectsModel,
+ ValuesModel valuesModel,
+ ServicesModel servicesModel,
+ ImportedServicesModel importedServicesModel
+ )
+ {
+ this.name = name;
+ this.metaInfo = metaInfo;
+ this.activatorsModel = activatorsModel;
+ this.transientsModel = transientsModel;
+ this.entitiesModel = entitiesModel;
+ this.objectsModel = objectsModel;
+ this.valuesModel = valuesModel;
+ this.servicesModel = servicesModel;
+ this.importedServicesModel = importedServicesModel;
+ }
+
+ @Override
+ public String name()
+ {
+ return name;
+ }
+
+ public <T> T metaInfo( Class<T> infoType )
+ {
+ return metaInfo.get( infoType );
+ }
+
+ public ActivatorsInstance<Module> newActivatorsInstance()
+ throws ActivationException
+ {
+ return new ActivatorsInstance<>( activatorsModel.newInstances() );
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+ throws ThrowableType
+ {
+ if( modelVisitor.visitEnter( this ) )
+ {
+ if( activatorsModel.accept( modelVisitor ) )
+ {
+ if( transientsModel.accept( modelVisitor ) )
+ {
+ if( entitiesModel.accept( modelVisitor ) )
+ {
+ if( servicesModel.accept( modelVisitor ) )
+ {
+ if( importedServicesModel.accept( modelVisitor ) )
+ {
+ if( objectsModel.accept( modelVisitor ) )
+ {
+ valuesModel.accept( modelVisitor );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return modelVisitor.visitLeave( this );
+ }
+
+ // Context
+
+ public ModuleInstance newInstance( LayerInstance layerInstance )
+ {
+ return new ModuleInstance( this, layerInstance, transientsModel, entitiesModel, objectsModel, valuesModel, servicesModel, importedServicesModel );
+ }
+
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleUnitOfWork.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleUnitOfWork.java b/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleUnitOfWork.java
new file mode 100644
index 0000000..f052de2
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleUnitOfWork.java
@@ -0,0 +1,773 @@
+/*
+ * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2013-2015, Niclas Hedhman. All Rights Reserved.
+ * Copyright (c) 2013-2015, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.zest.runtime.structure;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.apache.zest.api.association.AssociationDescriptor;
+import org.apache.zest.api.association.AssociationStateHolder;
+import org.apache.zest.api.common.QualifiedName;
+import org.apache.zest.api.composite.Composite;
+import org.apache.zest.api.entity.EntityBuilder;
+import org.apache.zest.api.entity.EntityComposite;
+import org.apache.zest.api.entity.EntityReference;
+import org.apache.zest.api.entity.Identity;
+import org.apache.zest.api.entity.IdentityGenerator;
+import org.apache.zest.api.entity.LifecycleException;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.api.property.PropertyDescriptor;
+import org.apache.zest.api.property.StateHolder;
+import org.apache.zest.api.query.Query;
+import org.apache.zest.api.query.QueryBuilder;
+import org.apache.zest.api.query.QueryExecutionException;
+import org.apache.zest.api.query.grammar.OrderBy;
+import org.apache.zest.api.service.NoSuchServiceException;
+import org.apache.zest.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.zest.api.unitofwork.EntityTypeNotFoundException;
+import org.apache.zest.api.unitofwork.NoSuchEntityException;
+import org.apache.zest.api.unitofwork.UnitOfWork;
+import org.apache.zest.api.unitofwork.UnitOfWorkCallback;
+import org.apache.zest.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.zest.api.unitofwork.UnitOfWorkFactory;
+import org.apache.zest.api.usecase.Usecase;
+import org.apache.zest.api.util.NullArgumentException;
+import org.apache.zest.api.value.ValueBuilder;
+import org.apache.zest.api.value.ValueComposite;
+import org.apache.zest.functional.Function;
+import org.apache.zest.functional.Iterables;
+import org.apache.zest.functional.Specification;
+import org.apache.zest.runtime.association.AssociationInstance;
+import org.apache.zest.runtime.association.ManyAssociationInstance;
+import org.apache.zest.runtime.association.NamedAssociationInstance;
+import org.apache.zest.runtime.composite.FunctionStateResolver;
+import org.apache.zest.runtime.entity.EntityInstance;
+import org.apache.zest.runtime.entity.EntityModel;
+import org.apache.zest.runtime.property.PropertyModel;
+import org.apache.zest.runtime.unitofwork.EntityBuilderInstance;
+import org.apache.zest.runtime.unitofwork.UnitOfWorkInstance;
+import org.apache.zest.runtime.value.ValueInstance;
+import org.apache.zest.spi.entity.EntityState;
+import org.apache.zest.spi.entity.EntityStatus;
+import org.apache.zest.spi.entity.NamedAssociationState;
+import org.apache.zest.spi.entitystore.EntityStore;
+import org.apache.zest.spi.module.ModelModule;
+import org.apache.zest.spi.query.EntityFinder;
+import org.apache.zest.spi.query.EntityFinderException;
+import org.apache.zest.spi.query.QueryBuilderSPI;
+import org.apache.zest.spi.query.QuerySource;
+
+import static org.apache.zest.api.entity.EntityReference.parseEntityReference;
+import static org.apache.zest.functional.Iterables.first;
+import static org.apache.zest.functional.Iterables.map;
+
+/**
+ * JAVADOC
+ */
+public class ModuleUnitOfWork
+ implements UnitOfWork
+{
+ private static final QualifiedName IDENTITY_STATE_NAME;
+
+ static
+ {
+ try
+ {
+ IDENTITY_STATE_NAME = QualifiedName.fromAccessor( Identity.class.getMethod( "identity" ) );
+ }
+ catch( NoSuchMethodException e )
+ {
+ throw new InternalError( "Zest Core Runtime codebase is corrupted. Contact Zest team: ModuleUnitOfWork" );
+ }
+ }
+
+ private final UnitOfWorkInstance uow;
+ private final ModuleInstance module;
+
+ ModuleUnitOfWork( ModuleInstance module, UnitOfWorkInstance uow )
+ {
+ this.module = module;
+ this.uow = uow;
+ }
+
+ public ModuleInstance module()
+ {
+ return module;
+ }
+
+ public UnitOfWorkInstance instance()
+ {
+ return uow;
+ }
+
+ @Override
+ public UnitOfWorkFactory unitOfWorkFactory()
+ {
+ return module;
+ }
+
+ @Override
+ public long currentTime()
+ {
+ return uow.currentTime();
+ }
+
+ @Override
+ public Usecase usecase()
+ {
+ return uow.usecase();
+ }
+
+ @Override
+ public <T> T metaInfo( Class<T> infoType )
+ {
+ return uow.metaInfo().get( infoType );
+ }
+
+ @Override
+ public void setMetaInfo( Object metaInfo )
+ {
+ uow.metaInfo().set( metaInfo );
+ }
+
+ @Override
+ @SuppressWarnings( { "raw", "unchecked" } )
+ public <T> Query<T> newQuery( QueryBuilder<T> queryBuilder )
+ {
+ QueryBuilderSPI queryBuilderSPI = (QueryBuilderSPI) queryBuilder;
+
+ return queryBuilderSPI.newQuery( new UoWQuerySource( this ) );
+ }
+
+ @Override
+ public <T> T newEntity( Class<T> type )
+ throws EntityTypeNotFoundException, LifecycleException
+ {
+ return newEntity( type, null );
+ }
+
+ @Override
+ public <T> T newEntity( Class<T> type, String identity )
+ throws EntityTypeNotFoundException, LifecycleException
+ {
+ return newEntityBuilder( type, identity ).newInstance();
+ }
+
+ @Override
+ public <T> EntityBuilder<T> newEntityBuilder( Class<T> type )
+ throws EntityTypeNotFoundException
+ {
+ return newEntityBuilder( type, null );
+ }
+
+ @Override
+ public <T> EntityBuilder<T> newEntityBuilder( Class<T> type, String identity )
+ throws EntityTypeNotFoundException
+ {
+ ModelModule<EntityModel> model = module.typeLookup().lookupEntityModel( type );
+
+ if( model == null )
+ {
+ throw new EntityTypeNotFoundException( type.getName(),
+ module.name(),
+ map( ModelModule.toStringFunction,
+ module.findVisibleEntityTypes()
+ ) );
+ }
+
+ EntityStore entityStore = model.module().entityStore();
+
+ // Generate id if necessary
+ if( identity == null )
+ {
+ IdentityGenerator idGen = model.module().identityGenerator();
+ if( idGen == null )
+ {
+ throw new NoSuchServiceException( IdentityGenerator.class.getName(), model.module().name() );
+ }
+ identity = idGen.generate( first( model.model().types() ) );
+ }
+ EntityBuilder<T> builder;
+
+ builder = new EntityBuilderInstance<>( model,
+ this,
+ uow.getEntityStoreUnitOfWork( entityStore, module ),
+ identity );
+ return builder;
+ }
+
+ @Override
+ public <T> EntityBuilder<T> newEntityBuilderWithState(
+ Class<T> type,
+ Function<PropertyDescriptor, Object> propertyFunction,
+ Function<AssociationDescriptor, EntityReference> associationFunction,
+ Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
+ Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction
+ )
+ throws EntityTypeNotFoundException
+ {
+ return newEntityBuilderWithState( type, null,
+ propertyFunction,
+ associationFunction,
+ manyAssociationFunction,
+ namedAssociationFunction );
+ }
+
+ @Override
+ public <T> EntityBuilder<T> newEntityBuilderWithState(
+ Class<T> type, String identity,
+ Function<PropertyDescriptor, Object> propertyFunction,
+ Function<AssociationDescriptor, EntityReference> associationFunction,
+ Function<AssociationDescriptor, Iterable<EntityReference>> manyAssociationFunction,
+ Function<AssociationDescriptor, Map<String, EntityReference>> namedAssociationFunction
+ )
+ throws EntityTypeNotFoundException
+ {
+ NullArgumentException.validateNotNull( "propertyFunction", propertyFunction );
+ NullArgumentException.validateNotNull( "associationFunction", associationFunction );
+ NullArgumentException.validateNotNull( "manyAssociationFunction", manyAssociationFunction );
+ NullArgumentException.validateNotNull( "namedAssociationFunction", namedAssociationFunction );
+
+ ModelModule<EntityModel> model = module.typeLookup().lookupEntityModel( type );
+
+ if( model == null )
+ {
+ throw new EntityTypeNotFoundException( type.getName(),
+ module.name(),
+ map( ModelModule.toStringFunction,
+ module.findVisibleEntityTypes()
+ ) );
+ }
+
+ EntityStore entityStore = model.module().entityStore();
+
+ FunctionStateResolver stateResolver = new FunctionStateResolver(
+ propertyFunction, associationFunction, manyAssociationFunction, namedAssociationFunction
+ );
+
+ if( identity == null )
+ {
+ // Use identity from StateResolver if available
+ PropertyModel identityModel = model.model().state().findPropertyModelByQualifiedName( IDENTITY_STATE_NAME );
+ identity = (String) stateResolver.getPropertyState( identityModel );
+ if( identity == null )
+ {
+ // Generate identity
+ IdentityGenerator idGen = model.module().identityGenerator();
+ if( idGen == null )
+ {
+ throw new NoSuchServiceException( IdentityGenerator.class.getName(), model.module().name() );
+ }
+ identity = idGen.generate( first( model.model().types() ) );
+ }
+ }
+
+ return new EntityBuilderInstance<>( model,
+ this,
+ uow.getEntityStoreUnitOfWork( entityStore, module ),
+ identity,
+ stateResolver );
+ }
+
+ @Override
+ public <T> T get( Class<T> type, String identity )
+ throws EntityTypeNotFoundException, NoSuchEntityException
+ {
+ Iterable<ModelModule<EntityModel>> models = module.typeLookup().lookupEntityModels( type );
+
+ if( !models.iterator().hasNext() )
+ {
+ throw new EntityTypeNotFoundException( type.getName(),
+ module.name(),
+ map( ModelModule.toStringFunction,
+ module.findVisibleEntityTypes()
+ ) );
+ }
+
+ return uow.get( parseEntityReference( identity ), this, models, type );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> T get( T entity )
+ throws EntityTypeNotFoundException
+ {
+ EntityComposite entityComposite = (EntityComposite) entity;
+ EntityInstance compositeInstance = EntityInstance.entityInstanceOf( entityComposite );
+ ModelModule<EntityModel> model = new ModelModule<>( compositeInstance.module(), compositeInstance.entityModel() );
+ Class<T> type = (Class<T>) first( compositeInstance.types() );
+ return uow.get( compositeInstance.identity(), this, Collections.singletonList( model ), type );
+ }
+
+ @Override
+ public void remove( Object entity )
+ throws LifecycleException
+ {
+ uow.checkOpen();
+
+ EntityComposite entityComposite = (EntityComposite) entity;
+
+ EntityInstance compositeInstance = EntityInstance.entityInstanceOf( entityComposite );
+
+ if( compositeInstance.status() == EntityStatus.NEW )
+ {
+ compositeInstance.remove( this );
+ uow.remove( compositeInstance.identity() );
+ }
+ else if( compositeInstance.status() == EntityStatus.LOADED || compositeInstance.status() == EntityStatus.UPDATED )
+ {
+ compositeInstance.remove( this );
+ }
+ else
+ {
+ throw new NoSuchEntityException( compositeInstance.identity(), compositeInstance.types(), usecase() );
+ }
+ }
+
+ @SuppressWarnings( "DuplicateThrows" )
+ @Override
+ public void complete()
+ throws UnitOfWorkCompletionException, ConcurrentEntityModificationException
+ {
+ uow.complete();
+ }
+
+ @Override
+ public void discard()
+ {
+ uow.discard();
+ }
+
+ @Override
+ public void close()
+ {
+ discard();
+ }
+
+ @Override
+ public boolean isOpen()
+ {
+ return uow.isOpen();
+ }
+
+ @Override
+ public boolean isPaused()
+ {
+ return uow.isPaused();
+ }
+
+ @Override
+ public void pause()
+ {
+ uow.pause();
+ }
+
+ @Override
+ public void resume()
+ {
+ uow.resume();
+ }
+
+ @Override
+ public void addUnitOfWorkCallback( UnitOfWorkCallback callback )
+ {
+ uow.addUnitOfWorkCallback( callback );
+ }
+
+ @Override
+ public void removeUnitOfWorkCallback( UnitOfWorkCallback callback )
+ {
+ uow.removeUnitOfWorkCallback( callback );
+ }
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if( this == o )
+ {
+ return true;
+ }
+ if( o == null || getClass() != o.getClass() )
+ {
+ return false;
+ }
+
+ ModuleUnitOfWork that = (ModuleUnitOfWork) o;
+
+ return uow.equals( that.uow );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return uow.hashCode();
+ }
+
+ @Override
+ public String toString()
+ {
+ return uow.toString();
+ }
+
+ public void addEntity( EntityInstance instance )
+ {
+ uow.addEntity( instance );
+ }
+
+ @Override
+ public <T extends Identity> T toValue( Class<T> primaryType, T entityComposite )
+ {
+ Function<PropertyDescriptor, Object> propertyFunction = new ToValuePropertyMappingFunction( entityComposite );
+ Function<AssociationDescriptor, EntityReference> assocationFunction = new ToValueAssociationMappingFunction<>( entityComposite );
+ Function<AssociationDescriptor, Iterable<EntityReference>> manyAssocFunction = new ToValueManyAssociationMappingFunction<>( entityComposite );
+ Function<AssociationDescriptor, Map<String, EntityReference>> namedAssocFunction = new ToValueNameAssociationMappingFunction<>( entityComposite );
+
+ @SuppressWarnings( "unchecked" )
+ ValueBuilder<T> builder = module().newValueBuilderWithState(
+ primaryType, propertyFunction, assocationFunction, manyAssocFunction, namedAssocFunction );
+ return builder.newInstance();
+ }
+
+ @Override
+ public <T extends Identity> T toEntity( Class<T> primaryType, T valueComposite )
+ {
+ Function<PropertyDescriptor, Object> propertyFunction = new ToEntityPropertyMappingFunction<>( valueComposite );
+ Function<AssociationDescriptor, EntityReference> assocationFunction = new ToEntityAssociationMappingFunction<>( valueComposite );
+ Function<AssociationDescriptor, Iterable<EntityReference>> manyAssocFunction = new ToEntityManyAssociationMappingFunction<>( valueComposite );
+ Function<AssociationDescriptor, Map<String, EntityReference>> namedAssocFunction = new ToEntityNameAssociationMappingFunction<>( valueComposite );
+
+ String identity = valueComposite.identity().get();
+ try
+ {
+ T entity = get( primaryType, identity );
+ // If successful, then this entity is to by modified.
+ EntityInstance instance = EntityInstance.entityInstanceOf( (EntityComposite) entity );
+ EntityState state = instance.entityState();
+ FunctionStateResolver stateResolver = new FunctionStateResolver( propertyFunction,
+ assocationFunction,
+ manyAssocFunction,
+ namedAssocFunction );
+ EntityModel model = (EntityModel) EntityInstance.entityInstanceOf( (EntityComposite) entity ).descriptor();
+ stateResolver.populateState( model, state );
+ return entity;
+ }
+ catch( NoSuchEntityException e )
+ {
+ EntityBuilder<T> entityBuilder = newEntityBuilderWithState( primaryType,
+ identity,
+ propertyFunction,
+ assocationFunction,
+ manyAssocFunction,
+ namedAssocFunction );
+ return entityBuilder.newInstance();
+ }
+ }
+
+ private static class UoWQuerySource implements QuerySource
+ {
+ private final ModuleUnitOfWork moduleUnitOfWork;
+
+ private UoWQuerySource( ModuleUnitOfWork moduleUnitOfWork )
+ {
+ this.moduleUnitOfWork = moduleUnitOfWork;
+ }
+
+ @Override
+ public <T> T find( Class<T> resultType,
+ Specification<Composite> whereClause,
+ Iterable<OrderBy> orderBySegments,
+ Integer firstResult,
+ Integer maxResults,
+ Map<String, Object> variables
+ )
+ {
+ final EntityFinder entityFinder = moduleUnitOfWork.module().findService( EntityFinder.class ).get();
+
+ try
+ {
+ final EntityReference foundEntity = entityFinder.findEntity( resultType, whereClause, variables == null ? Collections
+ .<String, Object>emptyMap() : variables );
+ if( foundEntity != null )
+ {
+ try
+ {
+ return moduleUnitOfWork.get( resultType, foundEntity.identity() );
+ }
+ catch( NoSuchEntityException e )
+ {
+ return null; // Index is out of sync - entity has been removed
+ }
+ }
+ // No entity was found
+ return null;
+ }
+ catch( EntityFinderException e )
+ {
+ throw new QueryExecutionException( "Finder caused exception", e );
+ }
+ }
+
+ @Override
+ public <T> long count( Class<T> resultType,
+ Specification<Composite> whereClause,
+ Iterable<OrderBy> orderBySegments,
+ Integer firstResult,
+ Integer maxResults,
+ Map<String, Object> variables
+ )
+ {
+ final EntityFinder entityFinder = moduleUnitOfWork.module().findService( EntityFinder.class ).get();
+
+ try
+ {
+ return entityFinder.countEntities( resultType, whereClause, variables == null ? Collections.<String, Object>emptyMap() : variables );
+ }
+ catch( EntityFinderException e )
+ {
+ e.printStackTrace();
+ return 0;
+ }
+ }
+
+ @Override
+ public <T> Iterator<T> iterator( final Class<T> resultType,
+ Specification<Composite> whereClause,
+ Iterable<OrderBy> orderBySegments,
+ Integer firstResult,
+ Integer maxResults,
+ Map<String, Object> variables
+ )
+ {
+ final EntityFinder entityFinder = moduleUnitOfWork.module().findService( EntityFinder.class ).get();
+
+ try
+ {
+ final Iterator<EntityReference> foundEntities = entityFinder.findEntities( resultType,
+ whereClause,
+ Iterables.toArray( OrderBy.class, orderBySegments ),
+ firstResult,
+ maxResults,
+ variables == null ? Collections
+ .<String, Object>emptyMap() : variables )
+ .iterator();
+
+ return new Iterator<T>()
+ {
+ @Override
+ public boolean hasNext()
+ {
+ return foundEntities.hasNext();
+ }
+
+ @Override
+ public T next()
+ {
+ final EntityReference foundEntity = foundEntities.next();
+ try
+ {
+ return moduleUnitOfWork.get( resultType, foundEntity.identity() );
+ }
+ catch( NoSuchEntityException e )
+ {
+ // Index is out of sync - entity has been removed
+ return null;
+ }
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+ catch( EntityFinderException e )
+ {
+ throw new QueryExecutionException( "Query '" + toString() + "' could not be executed", e );
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return "UnitOfWork( " + moduleUnitOfWork.usecase().name() + " )";
+ }
+ }
+
+ private class ToValuePropertyMappingFunction
+ implements Function<PropertyDescriptor, Object>
+ {
+ private Object entity;
+
+ public ToValuePropertyMappingFunction( Object entity )
+ {
+ this.entity = entity;
+ }
+
+ @Override
+ public Object map( PropertyDescriptor propertyDescriptor )
+ {
+ EntityState entityState = EntityInstance.entityInstanceOf( (EntityComposite) entity ).entityState();
+ return entityState.propertyValueOf( propertyDescriptor.qualifiedName() );
+ }
+ }
+
+ private class ToValueAssociationMappingFunction<T>
+ implements Function<AssociationDescriptor, EntityReference>
+ {
+ private final T entity;
+
+ public ToValueAssociationMappingFunction( T entity )
+ {
+ this.entity = entity;
+ }
+
+ @Override
+ public EntityReference map( AssociationDescriptor associationDescriptor )
+ {
+ EntityState entityState = EntityInstance.entityInstanceOf( (EntityComposite) entity ).entityState();
+ return entityState.associationValueOf( associationDescriptor.qualifiedName() );
+ }
+ }
+
+ private class ToValueManyAssociationMappingFunction<T>
+ implements Function<AssociationDescriptor, Iterable<EntityReference>>
+ {
+ private final T entity;
+
+ public ToValueManyAssociationMappingFunction( T entity )
+ {
+ this.entity = entity;
+ }
+
+ @Override
+ public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor )
+ {
+ EntityState entityState = EntityInstance.entityInstanceOf( (EntityComposite) entity ).entityState();
+ return entityState.manyAssociationValueOf( associationDescriptor.qualifiedName() );
+ }
+ }
+
+ private class ToValueNameAssociationMappingFunction<T>
+ implements Function<AssociationDescriptor, Map<String, EntityReference>>
+ {
+ private final T entity;
+
+ public ToValueNameAssociationMappingFunction( T entity )
+ {
+ this.entity = entity;
+ }
+
+ @Override
+ public Map<String, EntityReference> map( AssociationDescriptor associationDescriptor )
+ {
+ Map<String, EntityReference> result = new HashMap<>();
+ EntityState entityState = EntityInstance.entityInstanceOf( (EntityComposite) entity ).entityState();
+ final NamedAssociationState state = entityState.namedAssociationValueOf( associationDescriptor.qualifiedName() );
+ for( String name : state )
+ {
+ result.put( name, state.get( name ) );
+ }
+ return result;
+ }
+ }
+
+ private class ToEntityPropertyMappingFunction<T>
+ implements Function<PropertyDescriptor, Object>
+ {
+ private final T value;
+
+ public ToEntityPropertyMappingFunction( T value )
+ {
+ this.value = value;
+ }
+
+ @Override
+ public Object map( PropertyDescriptor propertyDescriptor )
+ {
+ StateHolder state = ValueInstance.valueInstanceOf( (ValueComposite) value ).state();
+ Property<Object> property = state.propertyFor( propertyDescriptor.accessor() );
+ return property.get();
+ }
+ }
+
+ private class ToEntityAssociationMappingFunction<T>
+ implements Function<AssociationDescriptor, EntityReference>
+ {
+
+ private final T value;
+
+ public ToEntityAssociationMappingFunction( T value )
+ {
+ this.value = value;
+ }
+
+ @Override
+ public EntityReference map( AssociationDescriptor associationDescriptor )
+ {
+ AssociationStateHolder state = ValueInstance.valueInstanceOf( (ValueComposite) value ).state();
+ AssociationInstance<T> association = (AssociationInstance<T>) state.associationFor( associationDescriptor.accessor() );
+ return association.getAssociationState().get();
+ }
+ }
+
+ private class ToEntityManyAssociationMappingFunction<T>
+ implements Function<AssociationDescriptor, Iterable<EntityReference>>
+ {
+
+ private final T value;
+
+ public ToEntityManyAssociationMappingFunction( T valueComposite )
+ {
+ this.value = valueComposite;
+ }
+
+ @Override
+ public Iterable<EntityReference> map( AssociationDescriptor associationDescriptor )
+ {
+ AssociationStateHolder state = ValueInstance.valueInstanceOf( (ValueComposite) value ).state();
+ ManyAssociationInstance<T> association =
+ (ManyAssociationInstance<T>) state.manyAssociationFor( associationDescriptor.accessor() );
+ return association.getManyAssociationState();
+ }
+ }
+
+ private class ToEntityNameAssociationMappingFunction<T>
+ implements Function<AssociationDescriptor, Map<String, EntityReference>>
+ {
+ private final T value;
+
+ public ToEntityNameAssociationMappingFunction( T valueComposite )
+ {
+ this.value = valueComposite;
+ }
+
+ @Override
+ public Map<String, EntityReference> map( AssociationDescriptor associationDescriptor )
+ {
+ AssociationStateHolder state = ValueInstance.valueInstanceOf( (ValueComposite) value ).state();
+ NamedAssociationInstance<T> association =
+ (NamedAssociationInstance<T>) state.namedAssociationFor( associationDescriptor.accessor() );
+ HashMap<String, EntityReference> result = new HashMap<>();
+ for( Map.Entry<String, EntityReference> entry : association.getEntityReferences() )
+ {
+ result.put( entry.getKey(), entry.getValue() );
+ }
+ return result;
+ }
+ }
+}