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/04/14 08:13:18 UTC
[12/34] zest-java git commit: ZEST-132,
ZEST-97 UnitOfWorkFactory as a customizable Service UnitOfWork as a
customizable Transient Class can be a Transient directly,
with itself as both the Composite Type and the Mixin. SideEffects declaratio
http://git-wip-us.apache.org/repos/asf/zest-java/blob/a5be013f/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
index bb9aa65..4bf431f 100644
--- 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
@@ -23,9 +23,7 @@ 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 java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
@@ -42,7 +40,6 @@ 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;
@@ -58,10 +55,8 @@ 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;
@@ -73,13 +68,10 @@ 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;
@@ -90,21 +82,18 @@ 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.spi.structure.ModelModule;
import org.apache.zest.valueserialization.orgjson.OrgJsonValueSerialization;
import static java.util.stream.Stream.concat;
-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.iterable;
import static org.apache.zest.runtime.legacy.Specifications.translate;
@@ -126,15 +115,15 @@ public class ModuleInstance
private final ImportedServicesInstance importedServices;
// Eager instance objects
private final ActivationDelegate activation;
- private final TypeLookup typeLookup;
+ private final TypeLookupImpl 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;
+ private UnitOfWorkFactory uowf;
@SuppressWarnings( "LeakingThisInConstructor" )
public ModuleInstance( ModuleModel moduleModel, LayerInstance layerInstance, TransientsModel transientsModel,
@@ -147,17 +136,16 @@ public class ModuleInstance
layer = layerInstance;
transients = transientsModel;
values = valuesModel;
- objects = objectsModel;
entities = entitiesModel;
services = servicesModel.newInstance( this );
+ objects = objectsModel;
importedServices = importedServicesModel.newInstance( this );
// Eager instance objects
activation = new ActivationDelegate( this );
- typeLookup = new TypeLookup( this );
+ typeLookup = new TypeLookupImpl( this );
queryBuilderFactory = new QueryBuilderFactoryImpl( this );
classLoader = new ModuleClassLoader( this, Thread.currentThread().getContextClassLoader() );
- entityFunction = new EntityFunction( this );
// Activation
services.registerActivationEventListener( activation );
@@ -316,7 +304,7 @@ public class ModuleInstance
}
InjectionContext injectionContext = new InjectionContext( modelModule.module(), UsesInstance.EMPTY_USES.use( uses ) );
- return mixinType.cast( ((ObjectModel) modelModule.model()).newInstance( injectionContext ) );
+ return mixinType.cast( ( (ObjectModel) modelModule.model() ).newInstance( injectionContext ) );
}
@Override
@@ -332,7 +320,7 @@ public class ModuleInstance
}
InjectionContext injectionContext = new InjectionContext( modelModule.module(), UsesInstance.EMPTY_USES.use( uses ) );
- ((ObjectModel) modelModule.model()).inject( injectionContext, instance );
+ ( (ObjectModel) modelModule.model() ).inject( injectionContext, instance );
}
// Implementation of TransientBuilderFactory
@@ -352,7 +340,7 @@ public class ModuleInstance
modelModule.model().state().properties().forEach(
propertyModel ->
{
- Property<?> property = new PropertyInstance<>( ((PropertyModel) propertyModel).getBuilderInfo(),
+ Property<?> property = new PropertyInstance<>( ( (PropertyModel) propertyModel ).getBuilderInfo(),
propertyModel.initialValue( modelModule.module() ) );
properties.put( propertyModel.accessor(), property );
} );
@@ -495,57 +483,6 @@ public class ModuleInstance
}
}
- // 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 )
@@ -617,42 +554,24 @@ public class ModuleInstance
return layer;
}
- public TypeLookup typeLookup()
+ @Override
+ public TypeLookupImpl typeLookup()
{
return typeLookup;
}
- public BiFunction<EntityReference, Type, Object> getEntityFunction()
- {
- return entityFunction;
- }
-
- private static class EntityFunction
- implements BiFunction<EntityReference, Type, Object>
- {
-
- private final UnitOfWorkFactory uowf;
-
- private EntityFunction( UnitOfWorkFactory uowf )
- {
- this.uowf = uowf;
- }
-
- @Override
- public Object apply( EntityReference entityReference, Type type )
- {
- return uowf.currentUnitOfWork().get( RAW_CLASS.apply( type ), entityReference.identity() );
- }
- }
-
public EntityStore entityStore()
{
synchronized( this )
{
if( store == null )
{
- ServiceReference<EntityStore> service = findService( EntityStore.class );
- if( service == null )
+ ServiceReference<EntityStore> service = null;
+ try
+ {
+ service = findService( EntityStore.class );
+ }
+ catch( NoSuchServiceException e )
{
throw new UnitOfWorkException( "No EntityStore service available in module " + name() );
}
@@ -662,6 +581,27 @@ public class ModuleInstance
return store;
}
+ public UnitOfWorkFactory unitOfWorkFactory()
+ {
+ synchronized( this )
+ {
+ if( uowf == null )
+ {
+ ServiceReference<UnitOfWorkFactory> service = null;
+ try
+ {
+ service = findService( UnitOfWorkFactory.class );
+ }
+ catch( NoSuchServiceException e )
+ {
+ throw new UnitOfWorkException( "No UnitOfWorkFactory service available in module " + name() );
+ }
+ uowf = service.get();
+ }
+ }
+ return uowf;
+ }
+
public IdentityGenerator identityGenerator()
{
synchronized( this )
@@ -695,7 +635,7 @@ public class ModuleInstance
return valueSerialization;
}
- /* package */ MetricsProvider metricsProvider()
+ public MetricsProvider metricsProvider()
{
synchronized( this )
{
http://git-wip-us.apache.org/repos/asf/zest-java/blob/a5be013f/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
deleted file mode 100755
index b5303d5..0000000
--- a/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleUnitOfWork.java
+++ /dev/null
@@ -1,769 +0,0 @@
-/*
- * 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 java.util.function.Function;
-import java.util.function.Predicate;
-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.EntityDescriptor;
-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.Iterables;
-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;
-
-/**
- * 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<EntityDescriptor> model = module.typeLookup().lookupEntityModel( type );
-
- if( model == null )
- {
- throw new EntityTypeNotFoundException( type.getName(),
- module.name(),
- module.findVisibleEntityTypes().map( ModelModule.toStringFunction )
- );
- }
-
- 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( model.model().types().findFirst().orElse( null ) );
- }
- EntityBuilder<T> builder;
-
- builder = new EntityBuilderInstance<>( model,
- this,
- uow.getEntityStoreUnitOfWork( entityStore ),
- 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<EntityDescriptor> model = module.typeLookup().lookupEntityModel( type );
-
- if( model == null )
- {
- throw new EntityTypeNotFoundException( type.getName(),
- module.name(),
- module.findVisibleEntityTypes().map( ModelModule.toStringFunction )
- );
- }
-
- EntityStore entityStore = model.module().entityStore();
-
- FunctionStateResolver stateResolver = new FunctionStateResolver(
- propertyFunction, associationFunction, manyAssociationFunction, namedAssociationFunction
- );
-
- if( identity == null )
- {
- // Use identity from StateResolver if available
- PropertyModel identityModel = (PropertyModel) 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( model.model().types().findFirst().orElse( null ));
- }
- }
-
- return new EntityBuilderInstance<>( model,
- this,
- uow.getEntityStoreUnitOfWork( entityStore ),
- identity,
- stateResolver );
- }
-
- @Override
- public <T> T get( Class<T> type, String identity )
- throws EntityTypeNotFoundException, NoSuchEntityException
- {
- Iterable<ModelModule<EntityDescriptor>> models = module.typeLookup().lookupEntityModels( type );
-
- if( !models.iterator().hasNext() )
- {
- throw new EntityTypeNotFoundException( type.getName(),
- module.name(),
- module.findVisibleEntityTypes().map( ModelModule.toStringFunction )
- );
- }
-
- 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<EntityDescriptor> model = new ModelModule<>( compositeInstance.module(), compositeInstance.entityModel() );
- Class<T> type = (Class<T>) compositeInstance.types().findFirst().orElse( null );
- 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,
- Predicate<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,
- Predicate<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,
- Predicate<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 apply( 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 apply( 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> apply( 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> apply( 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 apply( 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 apply( 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> apply( 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> apply( 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;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/a5be013f/core/runtime/src/main/java/org/apache/zest/runtime/structure/TypeLookup.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/structure/TypeLookup.java b/core/runtime/src/main/java/org/apache/zest/runtime/structure/TypeLookup.java
deleted file mode 100755
index 6947b73..0000000
--- a/core/runtime/src/main/java/org/apache/zest/runtime/structure/TypeLookup.java
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- * Copyright (c) 2008-2012, Rickard Öberg.
- * Copyright (c) 2008-2012, Niclas Hedhman.
- * 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.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.WildcardType;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import org.apache.zest.api.common.Visibility;
-import org.apache.zest.api.composite.AmbiguousTypeException;
-import org.apache.zest.api.composite.ModelDescriptor;
-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.NoSuchServiceException;
-import org.apache.zest.api.service.ServiceReference;
-import org.apache.zest.api.type.HasTypes;
-import org.apache.zest.api.value.ValueDescriptor;
-import org.apache.zest.spi.module.ModelModule;
-
-import static java.util.stream.Stream.concat;
-import static org.apache.zest.api.common.Visibility.application;
-import static org.apache.zest.api.common.Visibility.layer;
-import static org.apache.zest.api.common.Visibility.module;
-import static org.apache.zest.api.util.Classes.RAW_CLASS;
-import static org.apache.zest.api.util.Classes.interfacesOf;
-import static org.apache.zest.functional.Iterables.first;
-
-/**
- * Central place for Composite Type lookups.
- */
-public class TypeLookup
-{
-
- // Constructor parameters
- private final ModuleInstance moduleInstance;
- // Eager instance objects
- private final Map<Class<?>, ModelModule<ObjectDescriptor>> objectModels;
- private final Map<Class<?>, ModelModule<TransientDescriptor>> transientModels;
- private final Map<Class<?>, ModelModule<ValueDescriptor>> valueModels;
- private final Map<Class<?>, List<ModelModule<EntityDescriptor>>> allEntityModels;
- private final Map<Class<?>, ModelModule<EntityDescriptor>> unambiguousEntityModels;
- private final Map<Type, ServiceReference<?>> serviceReferences;
- private final Map<Type, List<ServiceReference<?>>> servicesReferences;
-
- /**
- * Create a new TypeLookup bound to the given ModuleInstance.
- *
- * @param moduleInstance ModuleInstance bound to this TypeLookup
- */
- TypeLookup( ModuleInstance moduleInstance )
- {
- // Constructor parameters
- this.moduleInstance = moduleInstance;
-
- // Eager instance objects
- objectModels = new ConcurrentHashMap<>();
- transientModels = new ConcurrentHashMap<>();
- valueModels = new ConcurrentHashMap<>();
- allEntityModels = new ConcurrentHashMap<>();
- unambiguousEntityModels = new ConcurrentHashMap<>();
- serviceReferences = new ConcurrentHashMap<>();
- servicesReferences = new ConcurrentHashMap<>();
- }
-
- /**
- * Lookup first Object Model matching the given Type.
- *
- * <p>First, if Object Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
- * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
- *
- * <p>Second, if Object Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
- * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
- *
- * <p>Type lookup is done lazily and cached.</p>
- *
- * @param type Looked up Type
- *
- * @return First matching Object Model
- */
- ModelModule<ObjectDescriptor> lookupObjectModel( final Class type )
- {
- ModelModule<ObjectDescriptor> model = objectModels.get( type );
- if( model == null )
- {
- List<ModelModule<ObjectDescriptor>> allModels = allObjects().collect( Collectors.toList() );
- model = ambiguityMatching( type, allModels, new ExactTypeMatching<>( type ) );
- if( model == null )
- {
- model = ambiguityMatching( type, allModels, new AssignableFromTypeMatching<>( type ) );
- }
- if( model != null )
- {
- objectModels.put( type, model );
- }
- }
- return model;
- }
-
- /**
- * Lookup first Transient Model matching the given Type.
- *
- * <p>First, if Transient Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
- * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
- *
- * <p>Second, if Transient Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
- * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
- *
- * <p>Type lookup is done lazily and cached.</p>
- *
- * @param type Looked up Type
- *
- * @return First matching Transient Model
- */
- ModelModule<TransientDescriptor> lookupTransientModel( final Class type )
- {
- ModelModule<TransientDescriptor> model = transientModels.get( type );
- if( model == null )
- {
- List<ModelModule<TransientDescriptor>> allModels = allTransients().collect( Collectors.toList() );
- model = ambiguityMatching( type, allModels, new ExactTypeMatching<>( type ) );
- if( model == null )
- {
- model = ambiguityMatching( type, allModels, new AssignableFromTypeMatching<>( type ) );
- }
- if( model != null )
- {
- transientModels.put( type, model );
- }
- }
- return model;
- }
-
- /**
- * Lookup first Value Model matching the given Type.
- *
- * <p>First, if Value Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
- * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
- *
- * <p>Second, if Value Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
- * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
- *
- * <p>Type lookup is done lazily and cached.</p>
- *
- * @param type Looked up Type
- *
- * @return First matching Value Model
- */
- public ModelModule<ValueDescriptor> lookupValueModel( final Class type )
- {
- ModelModule<ValueDescriptor> model = valueModels.get( type );
- if( model == null )
- {
- List<ModelModule<ValueDescriptor>> allModels = allValues().collect( Collectors.toList() );
- model = ambiguityMatching( type, allModels, new ExactTypeMatching<>( type ) );
- if( model == null )
- {
- model = ambiguityMatching( type, allModels, new AssignableFromTypeMatching<>( type ) );
- }
- if( model != null )
- {
- valueModels.put( type, model );
- }
- }
- return model;
- }
-
- /**
- * Lookup first Entity Model matching the given Type.
- *
- * <p>First, if Entity Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
- * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
- *
- * <p>Second, if Entity Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
- * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
- *
- * <p>Type lookup is done lazily and cached.</p>
- *
- * <p><b>Should be used for creational use cases only.</b> For non-creational use cases see
- * {@link #lookupEntityModels(java.lang.Class)}.</p>
- *
- * @param type Looked up Type
- *
- * @return First matching Entity Model
- */
- ModelModule<EntityDescriptor> lookupEntityModel( final Class type )
- {
- ModelModule<EntityDescriptor> model = unambiguousEntityModels.get( type );
-
- if( model == null )
- {
- List<ModelModule<EntityDescriptor>> allModels = allEntities().collect( Collectors.toList() );
- model = ambiguityMatching( type, allModels, new ExactTypeMatching<>( type ) );
- if( model == null )
- {
- model = ambiguityMatching( type, allModels, new AssignableFromTypeMatching<>( type ) );
- }
- if( model != null )
- {
- unambiguousEntityModels.put( type, model );
- }
- }
- return model;
- }
-
- /**
- * Lookup all Entity Models matching the given Type.
- *
- * <p>Returned Iterable contains, in order, Entity Models that: </p>
- *
- * <ul>
- * <li>exactly match the given type, in Visibility then Assembly order ;</li>
- * <li>match a type assignable to the given type, in Visibility then Assembly order.</li>
- * </ul>
- *
- * <p>Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
- * <p>Multiple <b>assignable</b> matches are <b>allowed</b> to enable polymorphic fetches and queries.</p>
- *
- * <p>Type lookup is done lazily and cached.</p>
- *
- * <p><b>Should be used for non-creational use cases only.</b> For creational use cases see
- * {@link #lookupEntityModel(java.lang.Class)}.</p>
- *
- * @param type Looked up Type
- *
- * @return All matching Entity Models
- */
- Iterable<ModelModule<EntityDescriptor>> lookupEntityModels( final Class type )
- {
- List<ModelModule<EntityDescriptor>> result = allEntityModels.get( type );
- if( result == null )
- {
- result = concat(
- allEntities().filter( ref -> new ExactTypeMatching<>( type ).test( ref.model() ) ),
- allEntities().filter( ref -> new AssignableFromTypeMatching<>( type ).test( ref.model() ) )
- ).distinct().collect( Collectors.toList() );
- allEntityModels.put( type, result );
- }
- return result;
- }
-
- /**
- * Lookup first ServiceReference matching the given Type.
- *
- * <p>Type lookup is done lazily and cached.</p>
- *
- * <p>See {@link #lookupServiceReferences(Type)}.</p>
- *
- * @param <T> Service Type
- * @param serviceType Looked up Type
- *
- * @return First matching ServiceReference
- */
- <T> ServiceReference<T> lookupServiceReference( Type serviceType )
- {
- @SuppressWarnings( "unchecked" )
- ServiceReference<T> serviceReference = (ServiceReference<T>) serviceReferences.get( serviceType );
- if( serviceReference == null )
- {
- // Lazily resolve ServiceReference
- serviceReference = first( lookupServiceReferences( serviceType ) );
- if( serviceReference != null )
- {
- serviceReferences.put( serviceType, serviceReference );
- }
- }
-
- if( serviceReference == null )
- {
- throw new NoSuchServiceException( RAW_CLASS.apply( serviceType ).getName(), moduleInstance.name() );
- }
- return serviceReference;
- }
-
- /**
- * Lookup all ServiceReferences matching the given Type.
- *
- * <p>Returned Iterable contains, in order, ServiceReferences that: </p>
- *
- * <ul>
- * <li>exactly match the given type, in Visibility then Assembly order ;</li>
- * <li>match a type assignable to the given type, in Visibility then Assembly order.</li>
- * </ul>
- *
- * <p>Multiple <b>exact</b> matches with the same Visibility are <b>allowed</b> to enable polymorphic lookup/injection.</p>
- * <p>Multiple <b>assignable</b> matches with the same Visibility are <b>allowed</b> for the very same reason.</p>
- *
- * <p>Type lookup is done lazily and cached.</p>
- *
- * @param <T> Service Type
- * @param type Looked up Type
- *
- * @return All matching ServiceReferences
- */
- <T> List<ServiceReference<T>> lookupServiceReferences( final Type type )
- {
- List<ServiceReference<?>> serviceRefs = servicesReferences.get( type );
- if( serviceRefs == null )
- {
- serviceRefs = concat(
- allServices()
- .filter( new ExactTypeMatching<>( type ) ),
- allServices()
- .filter( new AssignableFromTypeMatching<>( type )
- )
- ).distinct().collect( Collectors.toList() );
- servicesReferences.put( type, serviceRefs );
- }
- List<ServiceReference<T>> result = new ArrayList<>();
- //noinspection unchecked
- serviceRefs.forEach( ref -> result.add( (ServiceReference<T>) ref ) );
- return result;
- }
-
- public Stream<Class<?>> allVisibleObjects()
- {
- return allObjects().flatMap( model -> model.model().types() );
- }
-
- private Stream<ModelModule<ObjectDescriptor>> allObjects()
- {
- return concat( moduleInstance.visibleObjects( module ),
- concat(
- moduleInstance.layerInstance().visibleObjects( layer ),
- concat(
- moduleInstance.layerInstance().visibleObjects( application ),
- moduleInstance.layerInstance().usedLayersInstance().visibleObjects()
- )
- )
- );
- }
-
- private Stream<ModelModule<TransientDescriptor>> allTransients()
- {
- return concat( moduleInstance.visibleTransients( module ),
- concat(
- moduleInstance.layerInstance().visibleTransients( layer ),
- concat(
- moduleInstance.layerInstance().visibleTransients( application ),
- moduleInstance.layerInstance().usedLayersInstance().visibleTransients()
- )
- )
- );
- }
-
- private Stream<ModelModule<ValueDescriptor>> allValues()
- {
- return concat( moduleInstance.visibleValues( module ),
- concat(
- moduleInstance.layerInstance().visibleValues( layer ),
- concat(
- moduleInstance.layerInstance().visibleValues( application ),
- moduleInstance.layerInstance().usedLayersInstance().visibleValues()
- )
- )
- );
- }
-
- private Stream<ModelModule<EntityDescriptor>> allEntities()
- {
- return concat( moduleInstance.visibleEntities( module ),
- concat(
- moduleInstance.layerInstance().visibleEntities( layer ),
- concat(
- moduleInstance.layerInstance().visibleEntities( application ),
- moduleInstance.layerInstance().usedLayersInstance().visibleEntities()
- )
- )
- );
- }
-
- private Stream<ServiceReference<?>> allServices()
- {
- return concat( moduleInstance.visibleServices( module ),
- concat(
- moduleInstance.layerInstance().visibleServices( layer ),
- concat(
- moduleInstance.layerInstance().visibleServices( application ),
- moduleInstance.layerInstance().usedLayersInstance().visibleServices()
- )
- )
- );
- }
-
- private <T extends ModelDescriptor> ModelModule<T> ambiguityMatching(
- Class type,
- List<ModelModule<T>> modelModules,
- TypeMatching<T> matching
- )
- {
- List<ModelModule<T>> models = modelModules.stream()
- .filter( ref -> matching.test( ref.model() ) )
- .filter( new SameVisibility<>() )
- .distinct()
- .collect( Collectors.toList() );
-
- if( models.size() > 1 )
- {
- throw new AmbiguousTypeException( "More than one type matches " + type.getName() + ": " + models + "]" );
- }
- if( models.isEmpty() )
- {
- return null;
- }
- return models.get( 0 );
- }
-
- private static abstract class TypeMatching<T extends HasTypes>
- implements Predicate<T>
- {
- protected final Type lookedUpType;
-
- protected TypeMatching( Type lookedUpType )
- {
- this.lookedUpType = lookedUpType;
- }
-
- @Override
- public final boolean test( T model )
- {
- if( lookedUpType instanceof Class )
- {
- return model.types().anyMatch( checkMatch( lookedUpType ) );
- }
- else
- {
- if( lookedUpType instanceof ParameterizedType )
- {
- // Foo<Bar> check
- // First check Foo
- ParameterizedType parameterizedType = (ParameterizedType) lookedUpType;
- Type rawType = parameterizedType.getRawType();
- if( !model.types().anyMatch( checkMatch( rawType ) ) )
- {
- return false;
- }
- // Then check Bar
- return interfacesOf( model.types() ).anyMatch( intf -> intf.equals( lookedUpType ) );
- }
- else if( lookedUpType instanceof WildcardType )
- {
- return true;
- }
- return false;
- }
- }
-
- protected abstract Predicate<Type> checkMatch( Type matchTo );
- }
-
- private static final class ExactTypeMatching<T extends HasTypes> extends TypeMatching<T>
- {
- private ExactTypeMatching( Type lookedUpType )
- {
- super( lookedUpType );
- }
-
- protected Predicate<Type> checkMatch( Type matchTo )
- {
- return matchTo::equals;
- }
- }
-
- private static final class AssignableFromTypeMatching<T extends HasTypes> extends TypeMatching<T>
- {
- private AssignableFromTypeMatching( Type lookedUpType )
- {
- super( lookedUpType );
- }
-
- protected Predicate<Type> checkMatch( Type matchTo )
- {
- // TODO; what to do if there is ParameterizedType here?? Now set to ClassCastException and see if anything surfaces
-// if( matchTo instanceof Class )
- {
- Class<?> clazz = (Class<?>) matchTo;
- return candidate ->
- !candidate.equals( matchTo ) && clazz.isAssignableFrom( (Class<?>) candidate );
- }
-// return candidate -> candidate.equals( matchTo );
- }
- }
-
- /**
- * This Predicate will filter out all Models that doesn't have the same visisbility as the first one.
- */
- private class SameVisibility<T extends ModelDescriptor>
- implements Predicate<ModelModule<T>>
- {
- private Visibility current = null;
-
- @Override
- public boolean test( ModelModule<T> model )
- {
- if( current == null )
- {
- current = model.model().visibility();
- return true;
- }
- return current == model.model().visibility();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/a5be013f/core/runtime/src/main/java/org/apache/zest/runtime/structure/TypeLookupImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/structure/TypeLookupImpl.java b/core/runtime/src/main/java/org/apache/zest/runtime/structure/TypeLookupImpl.java
new file mode 100755
index 0000000..7835aaa
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/structure/TypeLookupImpl.java
@@ -0,0 +1,538 @@
+/*
+ * Copyright (c) 2008-2012, Rickard Öberg.
+ * Copyright (c) 2008-2012, Niclas Hedhman.
+ * 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.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.api.composite.AmbiguousTypeException;
+import org.apache.zest.api.composite.ModelDescriptor;
+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.NoSuchServiceException;
+import org.apache.zest.api.service.ServiceReference;
+import org.apache.zest.api.type.HasTypes;
+import org.apache.zest.api.value.ValueDescriptor;
+import org.apache.zest.spi.structure.ModelModule;
+import org.apache.zest.spi.structure.TypeLookup;
+
+import static java.util.stream.Stream.concat;
+import static org.apache.zest.api.common.Visibility.application;
+import static org.apache.zest.api.common.Visibility.layer;
+import static org.apache.zest.api.common.Visibility.module;
+import static org.apache.zest.api.util.Classes.RAW_CLASS;
+import static org.apache.zest.api.util.Classes.interfacesOf;
+import static org.apache.zest.functional.Iterables.first;
+
+/**
+ * Central place for Composite Type lookups.
+ */
+public class TypeLookupImpl
+ implements TypeLookup
+{
+
+ // Constructor parameters
+ private final ModuleInstance moduleInstance;
+ // Eager instance objects
+ private final Map<Class<?>, ModelModule<ObjectDescriptor>> objectModels;
+ private final Map<Class<?>, ModelModule<TransientDescriptor>> transientModels;
+ private final Map<Class<?>, ModelModule<ValueDescriptor>> valueModels;
+ private final Map<Class<?>, List<ModelModule<EntityDescriptor>>> allEntityModels;
+ private final Map<Class<?>, ModelModule<EntityDescriptor>> unambiguousEntityModels;
+ private final Map<Type, ServiceReference<?>> serviceReferences;
+ private final Map<Type, List<ServiceReference<?>>> servicesReferences;
+
+ /**
+ * Create a new TypeLookup bound to the given ModuleInstance.
+ *
+ * @param moduleInstance ModuleInstance bound to this TypeLookup
+ */
+ TypeLookupImpl( ModuleInstance moduleInstance )
+ {
+ // Constructor parameters
+ this.moduleInstance = moduleInstance;
+
+ // Eager instance objects
+ objectModels = new ConcurrentHashMap<>();
+ transientModels = new ConcurrentHashMap<>();
+ valueModels = new ConcurrentHashMap<>();
+ allEntityModels = new ConcurrentHashMap<>();
+ unambiguousEntityModels = new ConcurrentHashMap<>();
+ serviceReferences = new ConcurrentHashMap<>();
+ servicesReferences = new ConcurrentHashMap<>();
+ }
+
+ /**
+ * Lookup first Object Model matching the given Type.
+ *
+ * <p>First, if Object Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
+ * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+ *
+ * <p>Second, if Object Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
+ * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+ *
+ * <p>Type lookup is done lazily and cached.</p>
+ *
+ * @param type Looked up Type
+ *
+ * @return First matching Object Model
+ */
+ ModelModule<ObjectDescriptor> lookupObjectModel( final Class type )
+ {
+ ModelModule<ObjectDescriptor> model = objectModels.get( type );
+ if( model == null )
+ {
+ List<ModelModule<ObjectDescriptor>> allModels = allObjects().collect( Collectors.toList() );
+ model = ambiguityMatching( type, allModels, new ExactTypeMatching<>( type ) );
+ if( model == null )
+ {
+ model = ambiguityMatching( type, allModels, new AssignableFromTypeMatching<>( type ) );
+ }
+ if( model != null )
+ {
+ objectModels.put( type, model );
+ }
+ }
+ return model;
+ }
+
+ /**
+ * Lookup first Transient Model matching the given Type.
+ *
+ * <p>First, if Transient Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
+ * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+ *
+ * <p>Second, if Transient Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
+ * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+ *
+ * <p>Type lookup is done lazily and cached.</p>
+ *
+ * @param type Looked up Type
+ *
+ * @return First matching Transient Model
+ */
+ ModelModule<TransientDescriptor> lookupTransientModel( final Class type )
+ {
+ ModelModule<TransientDescriptor> model = transientModels.get( type );
+ if( model == null )
+ {
+ List<ModelModule<TransientDescriptor>> allModels = allTransients().collect( Collectors.toList() );
+ model = ambiguityMatching( type, allModels, new ExactTypeMatching<>( type ) );
+ if( model == null )
+ {
+ model = ambiguityMatching( type, allModels, new AssignableFromTypeMatching<>( type ) );
+ }
+ if( model != null )
+ {
+ transientModels.put( type, model );
+ }
+ }
+ return model;
+ }
+
+ /**
+ * Lookup first Value Model matching the given Type.
+ *
+ * <p>First, if Value Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
+ * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+ *
+ * <p>Second, if Value Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
+ * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+ *
+ * <p>Type lookup is done lazily and cached.</p>
+ *
+ * @param type Looked up Type
+ *
+ * @return First matching Value Model
+ */
+ public ModelModule<ValueDescriptor> lookupValueModel( final Class type )
+ {
+ ModelModule<ValueDescriptor> model = valueModels.get( type );
+ if( model == null )
+ {
+ List<ModelModule<ValueDescriptor>> allModels = allValues().collect( Collectors.toList() );
+ model = ambiguityMatching( type, allModels, new ExactTypeMatching<>( type ) );
+ if( model == null )
+ {
+ model = ambiguityMatching( type, allModels, new AssignableFromTypeMatching<>( type ) );
+ }
+ if( model != null )
+ {
+ valueModels.put( type, model );
+ }
+ }
+ return model;
+ }
+
+ /**
+ * Lookup first Entity Model matching the given Type.
+ *
+ * <p>First, if Entity Models exactly match the given type, the closest one (Visibility then Assembly order) is returned.
+ * Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+ *
+ * <p>Second, if Entity Models match a type assignable to the given type, the closest one (Visibility then Assembly order) is returned.
+ * Multiple <b>assignable</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+ *
+ * <p>Type lookup is done lazily and cached.</p>
+ *
+ * <p><b>Should be used for creational use cases only.</b> For non-creational use cases see
+ * {@link #lookupEntityModels(java.lang.Class)}.</p>
+ *
+ * @param type Looked up Type
+ *
+ * @return First matching Entity Model
+ */
+ @Override
+ public ModelModule<EntityDescriptor> lookupEntityModel( final Class type )
+ {
+ ModelModule<EntityDescriptor> model = unambiguousEntityModels.get( type );
+
+ if( model == null )
+ {
+ List<ModelModule<EntityDescriptor>> allModels = allEntities().collect( Collectors.toList() );
+ model = ambiguityMatching( type, allModels, new ExactTypeMatching<>( type ) );
+ if( model == null )
+ {
+ model = ambiguityMatching( type, allModels, new AssignableFromTypeMatching<>( type ) );
+ }
+ if( model != null )
+ {
+ unambiguousEntityModels.put( type, model );
+ }
+ }
+ return model;
+ }
+
+ /**
+ * Lookup all Entity Models matching the given Type.
+ *
+ * <p>Returned Iterable contains, in order, Entity Models that: </p>
+ *
+ * <ul>
+ * <li>exactly match the given type, in Visibility then Assembly order ;</li>
+ * <li>match a type assignable to the given type, in Visibility then Assembly order.</li>
+ * </ul>
+ *
+ * <p>Multiple <b>exact</b> matches with the same Visibility are <b>forbidden</b> and result in an AmbiguousTypeException.</p>
+ * <p>Multiple <b>assignable</b> matches are <b>allowed</b> to enable polymorphic fetches and queries.</p>
+ *
+ * <p>Type lookup is done lazily and cached.</p>
+ *
+ * <p><b>Should be used for non-creational use cases only.</b> For creational use cases see
+ * {@link #lookupEntityModel(java.lang.Class)}.</p>
+ *
+ * @param type Looked up Type
+ *
+ * @return All matching Entity Models
+ */
+ @Override
+ public Iterable<ModelModule<EntityDescriptor>> lookupEntityModels( final Class type )
+ {
+ List<ModelModule<EntityDescriptor>> result = allEntityModels.get( type );
+ if( result == null )
+ {
+ result = concat(
+ allEntities().filter( ref -> new ExactTypeMatching<>( type ).test( ref.model() ) ),
+ allEntities().filter( ref -> new AssignableFromTypeMatching<>( type ).test( ref.model() ) )
+ ).distinct().collect( Collectors.toList() );
+ allEntityModels.put( type, result );
+ }
+ return result;
+ }
+
+ /**
+ * Lookup first ServiceReference matching the given Type.
+ *
+ * <p>Type lookup is done lazily and cached.</p>
+ *
+ * <p>See {@link #lookupServiceReferences(Type)}.</p>
+ *
+ * @param <T> Service Type
+ * @param serviceType Looked up Type
+ *
+ * @return First matching ServiceReference
+ */
+ @Override
+ public <T> ServiceReference<T> lookupServiceReference( Type serviceType )
+ {
+ @SuppressWarnings( "unchecked" )
+ ServiceReference<T> serviceReference = (ServiceReference<T>) serviceReferences.get( serviceType );
+ if( serviceReference == null )
+ {
+ // Lazily resolve ServiceReference
+ serviceReference = first( lookupServiceReferences( serviceType ) );
+ if( serviceReference != null )
+ {
+ serviceReferences.put( serviceType, serviceReference );
+ }
+ }
+
+ if( serviceReference == null )
+ {
+ throw new NoSuchServiceException( RAW_CLASS.apply( serviceType ).getName(), moduleInstance.name() );
+ }
+ return serviceReference;
+ }
+
+ /**
+ * Lookup all ServiceReferences matching the given Type.
+ *
+ * <p>Returned Iterable contains, in order, ServiceReferences that: </p>
+ *
+ * <ul>
+ * <li>exactly match the given type, in Visibility then Assembly order ;</li>
+ * <li>match a type assignable to the given type, in Visibility then Assembly order.</li>
+ * </ul>
+ *
+ * <p>Multiple <b>exact</b> matches with the same Visibility are <b>allowed</b> to enable polymorphic lookup/injection.</p>
+ * <p>Multiple <b>assignable</b> matches with the same Visibility are <b>allowed</b> for the very same reason.</p>
+ *
+ * <p>Type lookup is done lazily and cached.</p>
+ *
+ * @param <T> Service Type
+ * @param type Looked up Type
+ *
+ * @return All matching ServiceReferences
+ */
+ @Override
+ public <T> List<ServiceReference<T>> lookupServiceReferences( final Type type )
+ {
+ List<ServiceReference<?>> serviceRefs = servicesReferences.get( type );
+ if( serviceRefs == null )
+ {
+ serviceRefs = concat(
+ allServices()
+ .filter( new ExactTypeMatching<>( type ) ),
+ allServices()
+ .filter( new AssignableFromTypeMatching<>( type )
+ )
+ ).distinct().collect( Collectors.toList() );
+ servicesReferences.put( type, serviceRefs );
+ }
+ List<ServiceReference<T>> result = new ArrayList<>();
+ //noinspection unchecked
+ serviceRefs.forEach( ref -> result.add( (ServiceReference<T>) ref ) );
+ return result;
+ }
+
+ @Override
+ public Stream<Class<?>> allVisibleObjects()
+ {
+ return allObjects().flatMap( model -> model.model().types() );
+ }
+
+ @Override
+ public Stream<ModelModule<ObjectDescriptor>> allObjects()
+ {
+ return concat( moduleInstance.visibleObjects( module ),
+ concat(
+ moduleInstance.layerInstance().visibleObjects( layer ),
+ concat(
+ moduleInstance.layerInstance().visibleObjects( application ),
+ moduleInstance.layerInstance().usedLayersInstance().visibleObjects()
+ )
+ )
+ );
+ }
+
+ @Override
+ public Stream<ModelModule<TransientDescriptor>> allTransients()
+ {
+ return concat( moduleInstance.visibleTransients( module ),
+ concat(
+ moduleInstance.layerInstance().visibleTransients( layer ),
+ concat(
+ moduleInstance.layerInstance().visibleTransients( application ),
+ moduleInstance.layerInstance().usedLayersInstance().visibleTransients()
+ )
+ )
+ );
+ }
+
+ @Override
+ public Stream<ModelModule<ValueDescriptor>> allValues()
+ {
+ return concat( moduleInstance.visibleValues( module ),
+ concat(
+ moduleInstance.layerInstance().visibleValues( layer ),
+ concat(
+ moduleInstance.layerInstance().visibleValues( application ),
+ moduleInstance.layerInstance().usedLayersInstance().visibleValues()
+ )
+ )
+ );
+ }
+
+ @Override
+ public Stream<ModelModule<EntityDescriptor>> allEntities()
+ {
+ return concat( moduleInstance.visibleEntities( module ),
+ concat(
+ moduleInstance.layerInstance().visibleEntities( layer ),
+ concat(
+ moduleInstance.layerInstance().visibleEntities( application ),
+ moduleInstance.layerInstance().usedLayersInstance().visibleEntities()
+ )
+ )
+ );
+ }
+
+ @Override
+ public Stream<ServiceReference<?>> allServices()
+ {
+ return concat( moduleInstance.visibleServices( module ),
+ concat(
+ moduleInstance.layerInstance().visibleServices( layer ),
+ concat(
+ moduleInstance.layerInstance().visibleServices( application ),
+ moduleInstance.layerInstance().usedLayersInstance().visibleServices()
+ )
+ )
+ );
+ }
+
+ private <T extends ModelDescriptor> ModelModule<T> ambiguityMatching(
+ Class type,
+ List<ModelModule<T>> modelModules,
+ TypeMatching<T> matching
+ )
+ {
+ List<ModelModule<T>> models = modelModules.stream()
+ .filter( ref -> matching.test( ref.model() ) )
+ .filter( new SameVisibility<>() )
+ .distinct()
+ .collect( Collectors.toList() );
+
+ if( models.size() > 1 )
+ {
+ throw new AmbiguousTypeException( "More than one type matches " + type.getName() + ": " + models + "]" );
+ }
+ if( models.isEmpty() )
+ {
+ return null;
+ }
+ return models.get( 0 );
+ }
+
+ private static abstract class TypeMatching<T extends HasTypes>
+ implements Predicate<T>
+ {
+ protected final Type lookedUpType;
+
+ protected TypeMatching( Type lookedUpType )
+ {
+ this.lookedUpType = lookedUpType;
+ }
+
+ @Override
+ public final boolean test( T model )
+ {
+ if( lookedUpType instanceof Class )
+ {
+ return model.types().anyMatch( checkMatch( lookedUpType ) );
+ }
+ else
+ {
+ if( lookedUpType instanceof ParameterizedType )
+ {
+ // Foo<Bar> check
+ // First check Foo
+ ParameterizedType parameterizedType = (ParameterizedType) lookedUpType;
+ Type rawType = parameterizedType.getRawType();
+ if( !model.types().anyMatch( checkMatch( rawType ) ) )
+ {
+ return false;
+ }
+ // Then check Bar
+ return interfacesOf( model.types() ).anyMatch( intf -> intf.equals( lookedUpType ) );
+ }
+ else if( lookedUpType instanceof WildcardType )
+ {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ protected abstract Predicate<Type> checkMatch( Type matchTo );
+ }
+
+ private static final class ExactTypeMatching<T extends HasTypes> extends TypeMatching<T>
+ {
+ private ExactTypeMatching( Type lookedUpType )
+ {
+ super( lookedUpType );
+ }
+
+ protected Predicate<Type> checkMatch( Type matchTo )
+ {
+ return matchTo::equals;
+ }
+ }
+
+ private static final class AssignableFromTypeMatching<T extends HasTypes> extends TypeMatching<T>
+ {
+ private AssignableFromTypeMatching( Type lookedUpType )
+ {
+ super( lookedUpType );
+ }
+
+ protected Predicate<Type> checkMatch( Type matchTo )
+ {
+ // TODO; what to do if there is ParameterizedType here?? Now set to ClassCastException and see if anything surfaces
+// if( matchTo instanceof Class )
+ {
+ Class<?> clazz = (Class<?>) matchTo;
+ return candidate ->
+ !candidate.equals( matchTo ) && clazz.isAssignableFrom( (Class<?>) candidate );
+ }
+// return candidate -> candidate.equals( matchTo );
+ }
+ }
+
+ /**
+ * This Predicate will filter out all Models that doesn't have the same visisbility as the first one.
+ */
+ private class SameVisibility<T extends ModelDescriptor>
+ implements Predicate<ModelModule<T>>
+ {
+ private Visibility current = null;
+
+ @Override
+ public boolean test( ModelModule<T> model )
+ {
+ if( current == null )
+ {
+ current = model.model().visibility();
+ return true;
+ }
+ return current == model.model().visibility();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/a5be013f/core/runtime/src/main/java/org/apache/zest/runtime/structure/UsedLayersInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/structure/UsedLayersInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/structure/UsedLayersInstance.java
index 5a9bc94..ebf4b9c 100644
--- a/core/runtime/src/main/java/org/apache/zest/runtime/structure/UsedLayersInstance.java
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/structure/UsedLayersInstance.java
@@ -17,13 +17,12 @@ package org.apache.zest.runtime.structure;
import java.util.List;
import java.util.stream.Stream;
import org.apache.zest.api.common.Visibility;
-import org.apache.zest.api.composite.ModelDescriptor;
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.value.ValueDescriptor;
-import org.apache.zest.spi.module.ModelModule;
+import org.apache.zest.spi.structure.ModelModule;
/**
* JAVADOC
http://git-wip-us.apache.org/repos/asf/zest-java/blob/a5be013f/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/EntityBuilderInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/EntityBuilderInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/EntityBuilderInstance.java
index 425e851..ed8d137 100755
--- a/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/EntityBuilderInstance.java
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/EntityBuilderInstance.java
@@ -25,8 +25,7 @@ import org.apache.zest.api.entity.LifecycleException;
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.spi.module.ModelModule;
-import org.apache.zest.runtime.structure.ModuleUnitOfWork;
+import org.apache.zest.spi.structure.ModelModule;
import org.apache.zest.spi.entity.EntityState;
import org.apache.zest.spi.entitystore.EntityStoreUnitOfWork;
import org.apache.zest.spi.module.ModuleSpi;
http://git-wip-us.apache.org/repos/asf/zest-java/blob/a5be013f/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/EntityFunction.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/EntityFunction.java b/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/EntityFunction.java
new file mode 100644
index 0000000..a7524db
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/EntityFunction.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.zest.runtime.unitofwork;
+
+import java.lang.reflect.Type;
+import java.util.function.BiFunction;
+import org.apache.zest.api.entity.EntityReference;
+import org.apache.zest.api.unitofwork.UnitOfWorkFactory;
+
+import static org.apache.zest.api.util.Classes.RAW_CLASS;
+
+public class EntityFunction
+ implements BiFunction<EntityReference, Type, Object>
+{
+
+ private final UnitOfWorkFactory uowf;
+
+ public EntityFunction( UnitOfWorkFactory uowf )
+ {
+ this.uowf = uowf;
+ }
+
+ @Override
+ public Object apply( EntityReference entityReference, Type type )
+ {
+ return uowf.currentUnitOfWork().get( RAW_CLASS.apply( type ), entityReference.identity() );
+ }
+}