You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by ni...@apache.org on 2016/12/17 10:27:41 UTC
[05/81] [abbrv] [partial] zest-java git commit: ZEST-195 ;
Replace all "zest" with "polygene"
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/UnitOfWorkInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/UnitOfWorkInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/UnitOfWorkInstance.java
new file mode 100644
index 0000000..81e4907
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/unitofwork/UnitOfWorkInstance.java
@@ -0,0 +1,510 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.unitofwork;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.metrics.MetricNames;
+import org.apache.polygene.api.metrics.MetricsCounter;
+import org.apache.polygene.api.metrics.MetricsCounterFactory;
+import org.apache.polygene.api.metrics.MetricsProvider;
+import org.apache.polygene.api.metrics.MetricsTimer;
+import org.apache.polygene.api.metrics.MetricsTimerFactory;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.HasTypes;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.NoSuchEntityException;
+import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCallback;
+import org.apache.polygene.api.unitofwork.UnitOfWorkCompletionException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkOptions;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.runtime.entity.EntityInstance;
+import org.apache.polygene.runtime.entity.EntityModel;
+import org.apache.polygene.spi.entity.EntityState;
+import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.entitystore.ConcurrentEntityStateModificationException;
+import org.apache.polygene.spi.entitystore.EntityNotFoundException;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
+import org.apache.polygene.spi.entitystore.StateCommitter;
+import org.apache.polygene.spi.module.ModuleSpi;
+
+import static org.apache.polygene.api.unitofwork.UnitOfWorkCallback.UnitOfWorkStatus.COMPLETED;
+import static org.apache.polygene.api.unitofwork.UnitOfWorkCallback.UnitOfWorkStatus.DISCARDED;
+
+public final class UnitOfWorkInstance
+{
+ private static final ThreadLocal<Stack<UnitOfWorkInstance>> CURRENT = new ThreadLocal<Stack<UnitOfWorkInstance>>()
+ {
+ @Override
+ protected Stack<UnitOfWorkInstance> initialValue()
+ {
+ return new Stack<>();
+ }
+ };
+
+ public static Stack<UnitOfWorkInstance> getCurrent()
+ {
+ return CURRENT.get();
+ }
+
+ private final HashMap<EntityReference, EntityInstance> instanceCache = new HashMap<>();
+ private final HashMap<EntityStore, EntityStoreUnitOfWork> storeUnitOfWork = new HashMap<>();
+ private final ModuleSpi module;
+ private final Usecase usecase;
+ private final Instant currentTime;
+ private final MetricsProvider metrics;
+
+ private boolean open;
+ private boolean paused;
+
+ private MetricsCounter metricsCounter;
+ private MetricsTimer metricsTimer;
+ private MetricsTimer.Context metricsTimerContext;
+ private MetaInfo metaInfo;
+ private List<UnitOfWorkCallback> callbacks;
+
+ public UnitOfWorkInstance(ModuleSpi module, Usecase usecase, Instant currentTime, MetricsProvider metrics )
+ {
+ this.module = module;
+ this.usecase = usecase;
+ this.currentTime = currentTime;
+ this.metrics = metrics;
+
+ this.open = true;
+ getCurrent().push( this );
+ this.paused = false;
+ startCapture();
+ }
+
+ public Instant currentTime()
+ {
+ return currentTime;
+ }
+
+ public EntityStoreUnitOfWork getEntityStoreUnitOfWork( EntityStore store )
+ {
+ EntityStoreUnitOfWork uow = storeUnitOfWork.get( store );
+ if( uow == null )
+ {
+ uow = store.newUnitOfWork( module.descriptor(), usecase, currentTime );
+ storeUnitOfWork.put( store, uow );
+ }
+ return uow;
+ }
+
+ public <T> T get( EntityReference reference,
+ UnitOfWork uow,
+ Iterable<? extends EntityDescriptor> potentialModels,
+ Class<T> mixinType
+ )
+ throws NoSuchEntityTypeException, NoSuchEntityException
+ {
+ checkOpen();
+
+ EntityInstance entityInstance = instanceCache.get( reference );
+ if( entityInstance == null )
+ { // Not yet in cache
+
+ // Check if this is a root UoW, or if no parent UoW knows about this entity
+ EntityState entityState = null;
+ EntityModel model = null;
+ ModuleDescriptor module = null;
+ // Figure out what EntityStore to use
+ for( EntityDescriptor potentialModel : potentialModels )
+ {
+ EntityStore store = ((ModuleSpi) potentialModel.module().instance()).entityStore();
+ EntityStoreUnitOfWork storeUow = getEntityStoreUnitOfWork( store );
+ try
+ {
+ entityState = storeUow.entityStateOf( potentialModel.module(), reference );
+ }
+ catch( EntityNotFoundException e )
+ {
+ continue;
+ }
+
+ // Get the selected model
+ model = (EntityModel) entityState.entityDescriptor();
+ module = potentialModel.module();
+ }
+
+ // Check if model was found
+ if( model == null )
+ {
+ // Check if state was found
+ if( entityState == null )
+ {
+ throw new NoSuchEntityException( reference, mixinType, usecase );
+ }
+ else
+ {
+ throw new NoSuchEntityTypeException( mixinType.getName(), module.name(), module.typeLookup() );
+ }
+ }
+ // Create instance
+ entityInstance = new EntityInstance( uow, model, entityState );
+ instanceCache.put( reference, entityInstance );
+ }
+ else
+ {
+ // Check if it has been removed
+ if( entityInstance.status() == EntityStatus.REMOVED )
+ {
+ throw new NoSuchEntityException( reference, mixinType, usecase );
+ }
+ }
+
+ return entityInstance.proxy();
+ }
+
+ public Usecase usecase()
+ {
+ return usecase;
+ }
+
+ public MetaInfo metaInfo()
+ {
+ if( metaInfo == null )
+ {
+ metaInfo = new MetaInfo();
+ }
+
+ return metaInfo;
+ }
+
+ public void pause()
+ {
+ if( !paused )
+ {
+ paused = true;
+ getCurrent().pop();
+
+ UnitOfWorkOptions unitOfWorkOptions = metaInfo().get( UnitOfWorkOptions.class );
+ if( unitOfWorkOptions == null )
+ {
+ unitOfWorkOptions = usecase().metaInfo( UnitOfWorkOptions.class );
+ }
+
+ if( unitOfWorkOptions != null )
+ {
+ if( unitOfWorkOptions.isPruneOnPause() )
+ {
+ List<EntityReference> prunedInstances = null;
+ for( EntityInstance entityInstance : instanceCache.values() )
+ {
+ if( entityInstance.status() == EntityStatus.LOADED )
+ {
+ if( prunedInstances == null )
+ {
+ prunedInstances = new ArrayList<>();
+ }
+ prunedInstances.add( entityInstance.reference() );
+ }
+ }
+ if( prunedInstances != null )
+ {
+ prunedInstances.forEach( instanceCache::remove );
+ }
+ }
+ }
+ }
+ else
+ {
+ throw new UnitOfWorkException( "Unit of work is not active" );
+ }
+ }
+
+ public void resume()
+ {
+ if( paused )
+ {
+ paused = false;
+ getCurrent().push( this );
+ }
+ else
+ {
+ throw new UnitOfWorkException( "Unit of work has not been paused" );
+ }
+ }
+
+ public void complete()
+ throws UnitOfWorkCompletionException
+ {
+ checkOpen();
+
+ // Copy list so that it cannot be modified during completion
+ List<UnitOfWorkCallback> currentCallbacks = callbacks == null ? null : new ArrayList<>( callbacks );
+
+ // Commit state to EntityStores
+ List<StateCommitter> committers = applyChanges();
+
+ // Check callbacks
+ notifyBeforeCompletion( currentCallbacks );
+
+ // Commit all changes
+ committers.forEach( StateCommitter::commit );
+
+ close();
+
+ // Call callbacks
+ notifyAfterCompletion( currentCallbacks, COMPLETED );
+
+ callbacks = currentCallbacks;
+ }
+
+ public void discard()
+ {
+ if( !isOpen() )
+ {
+ return;
+ }
+ close();
+
+ // Copy list so that it cannot be modified during completion
+ List<UnitOfWorkCallback> currentCallbacks = callbacks == null ? null : new ArrayList<>( callbacks );
+
+ // Call callbacks
+ notifyAfterCompletion( currentCallbacks, DISCARDED );
+ storeUnitOfWork.values().forEach( EntityStoreUnitOfWork::discard );
+ callbacks = currentCallbacks;
+ }
+
+ private void close()
+ {
+ checkOpen();
+
+ if( !isPaused() )
+ {
+ getCurrent().pop();
+ }
+ endCapture();
+ open = false;
+ }
+
+ public boolean isOpen()
+ {
+ return open;
+ }
+
+ public void addUnitOfWorkCallback( UnitOfWorkCallback callback )
+ {
+ if( callbacks == null )
+ {
+ callbacks = new ArrayList<>();
+ }
+
+ callbacks.add( callback );
+ }
+
+ public void removeUnitOfWorkCallback( UnitOfWorkCallback callback )
+ {
+ if( callbacks != null )
+ {
+ callbacks.remove( callback );
+ }
+ }
+
+ public void addEntity( EntityInstance instance )
+ {
+ instanceCache.put( instance.reference(), instance );
+ }
+
+ private List<StateCommitter> applyChanges()
+ throws UnitOfWorkCompletionException
+ {
+ List<StateCommitter> committers = new ArrayList<>();
+ for( EntityStoreUnitOfWork entityStoreUnitOfWork : storeUnitOfWork.values() )
+ {
+ try
+ {
+ StateCommitter committer = entityStoreUnitOfWork.applyChanges();
+ committers.add( committer );
+ }
+ catch( Exception e )
+ {
+ // Cancel all previously prepared stores
+ committers.forEach( StateCommitter::cancel );
+
+ if( e instanceof ConcurrentEntityStateModificationException )
+ {
+ // If we cancelled due to concurrent modification, then create the proper exception for it!
+ ConcurrentEntityStateModificationException mee = (ConcurrentEntityStateModificationException) e;
+ Collection<EntityReference> modifiedEntityIdentities = mee.modifiedEntities();
+ Map<EntityComposite, HasTypes> modifiedEntities = new HashMap<>();
+ for( EntityReference modifiedEntityIdentity : modifiedEntityIdentities )
+ {
+ instanceCache.values().stream()
+ .filter( instance -> instance.reference().equals( modifiedEntityIdentity ) )
+ .forEach( instance -> modifiedEntities.put( instance.<EntityComposite>proxy(), instance ) );
+ }
+ throw new ConcurrentEntityModificationException( modifiedEntities, usecase );
+ }
+ else
+ {
+ throw new UnitOfWorkCompletionException( e );
+ }
+ }
+ }
+ return committers;
+ }
+
+ private void notifyBeforeCompletion( List<UnitOfWorkCallback> callbacks )
+ throws UnitOfWorkCompletionException
+ {
+ // Notify explicitly registered callbacks
+ if( callbacks != null )
+ {
+ callbacks.forEach( UnitOfWorkCallback::beforeCompletion );
+ }
+
+ // Notify entities
+ try
+ {
+ for( EntityInstance instance : instanceCache.values() )
+ {
+ boolean isCallback = instance.proxy() instanceof UnitOfWorkCallback;
+ boolean isNotRemoved = !instance.status().equals( EntityStatus.REMOVED );
+ if( isCallback && isNotRemoved )
+ {
+ UnitOfWorkCallback callback = UnitOfWorkCallback.class.cast( instance.proxy() );
+ callback.beforeCompletion();
+ }
+ }
+ }
+ catch( UnitOfWorkCompletionException e )
+ {
+ throw e;
+ }
+ catch( Exception e )
+ {
+ throw new UnitOfWorkCompletionException( e );
+ }
+ }
+
+ private void notifyAfterCompletion( List<UnitOfWorkCallback> callbacks,
+ final UnitOfWorkCallback.UnitOfWorkStatus status
+ )
+ {
+ if( callbacks != null )
+ {
+ for( UnitOfWorkCallback callback : callbacks )
+ {
+ try
+ {
+ callback.afterCompletion( status );
+ }
+ catch( Exception e )
+ {
+ // Ignore
+ }
+ }
+ }
+
+ // Notify entities
+ try
+ {
+ for( EntityInstance instance : instanceCache.values() )
+ {
+ boolean isCallback = instance.proxy() instanceof UnitOfWorkCallback;
+ boolean isNotRemoved = !instance.status().equals( EntityStatus.REMOVED );
+ if( isCallback && isNotRemoved )
+ {
+ UnitOfWorkCallback callback = UnitOfWorkCallback.class.cast( instance.proxy() );
+ callback.afterCompletion( status );
+ }
+ }
+ }
+ catch( Exception e )
+ {
+ // Ignore
+ }
+ }
+
+ public void checkOpen()
+ {
+ if( !isOpen() )
+ {
+ throw new UnitOfWorkException( "Unit of work has been closed" );
+ }
+ }
+
+ public boolean isPaused()
+ {
+ return paused;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "UnitOfWork " + hashCode() + "(" + usecase + "): entities:" + instanceCache.size();
+ }
+
+ public void remove( EntityReference entityReference )
+ {
+ instanceCache.remove( entityReference );
+ }
+
+ private void startCapture()
+ {
+ getMetricsCounter().increment();
+ metricsTimerContext = getMetricsTimer().start();
+ }
+
+ private void endCapture()
+ {
+ getMetricsCounter().decrement();
+ metricsTimerContext.stop();
+ metricsTimerContext = null;
+ }
+
+ private MetricsCounter getMetricsCounter()
+ {
+ if( metricsCounter == null )
+ {
+ MetricsCounterFactory metricsFactory = metrics.createFactory( MetricsCounterFactory.class );
+ metricsCounter = metricsFactory.createCounter( MetricNames.nameFor( module, UnitOfWork.class, "counter" ) );
+ }
+ return metricsCounter;
+ }
+
+ private MetricsTimer getMetricsTimer()
+ {
+ if( metricsTimer == null )
+ {
+ MetricsTimerFactory metricsFactory = metrics.createFactory( MetricsTimerFactory.class );
+ metricsTimer = metricsFactory.createTimer( MetricNames.nameFor( module, UnitOfWork.class, "timer" ) );
+ }
+ return metricsTimer;
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/value/ManyAssociationValueState.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ManyAssociationValueState.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ManyAssociationValueState.java
new file mode 100644
index 0000000..c386802
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ManyAssociationValueState.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.runtime.value;
+
+import java.util.Iterator;
+import java.util.List;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.spi.entity.ManyAssociationState;
+
+/**
+ * ManyAssociationState implementation for Value composites.
+ */
+public class ManyAssociationValueState
+ implements ManyAssociationState
+{
+ private List<EntityReference> references;
+
+ public ManyAssociationValueState( List<EntityReference> references )
+ {
+ this.references = references;
+ }
+
+ @Override
+ public int count()
+ {
+ return references.size();
+ }
+
+ @Override
+ public boolean contains( EntityReference entityReference )
+ {
+ return references.contains( entityReference );
+ }
+
+ @Override
+ public boolean add( int i, EntityReference entityReference )
+ {
+ if( references.contains( entityReference ) )
+ {
+ return false;
+ }
+
+ references.add( i, entityReference );
+ return true;
+ }
+
+ @Override
+ public boolean remove( EntityReference entity )
+ {
+ boolean removed = references.remove( entity );
+ return removed;
+ }
+
+ @Override
+ public EntityReference get( int i )
+ {
+ return references.get( i );
+ }
+
+ @Override
+ public Iterator<EntityReference> iterator()
+ {
+ final Iterator<EntityReference> iter = references.iterator();
+
+ return new Iterator<EntityReference>()
+ {
+ EntityReference current;
+
+ @Override
+ public boolean hasNext()
+ {
+ return iter.hasNext();
+ }
+
+ @Override
+ public EntityReference next()
+ {
+ current = iter.next();
+ return current;
+ }
+
+ @Override
+ public void remove()
+ {
+ iter.remove();
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/value/NamedAssociationValueState.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/NamedAssociationValueState.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/NamedAssociationValueState.java
new file mode 100644
index 0000000..50c20ca
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/NamedAssociationValueState.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.runtime.value;
+
+import java.util.Iterator;
+import java.util.Map;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.spi.entity.NamedAssociationState;
+
+public class NamedAssociationValueState
+ implements NamedAssociationState
+{
+ private final Map<String, EntityReference> references;
+
+ public NamedAssociationValueState( Map<String, EntityReference> references )
+ {
+ this.references = references;
+ }
+
+ @Override
+ public int count()
+ {
+ return references.size();
+ }
+
+ @Override
+ public boolean containsName( String name )
+ {
+ return references.containsKey( name );
+ }
+
+ @Override
+ public boolean put( String name, EntityReference entityReference )
+ {
+ return references.put( name, entityReference ) != null;
+ }
+
+ @Override
+ public boolean remove( String name )
+ {
+ return references.remove( name ) != null;
+ }
+
+ @Override
+ public EntityReference get( String name )
+ {
+ return references.get( name );
+ }
+
+ @Override
+ public String nameOf( EntityReference entityReference )
+ {
+ for( Map.Entry<String, EntityReference> entry : references.entrySet() )
+ {
+ if( entry.getValue().equals( entityReference ) )
+ {
+ return entry.getKey();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Iterator<String> iterator()
+ {
+ return references.keySet().iterator();
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/value/ReferenceProperty.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ReferenceProperty.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ReferenceProperty.java
new file mode 100644
index 0000000..6dd6d18
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ReferenceProperty.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.runtime.value;
+
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.property.Property;
+
+/**
+ * The reference for an Association
+ */
+public class ReferenceProperty
+ implements Property<EntityReference>
+{
+ EntityReference reference;
+
+ public ReferenceProperty()
+ {
+ }
+
+ public ReferenceProperty( EntityReference reference )
+ {
+ this.reference = reference;
+ }
+
+ @Override
+ public EntityReference get()
+ {
+ return reference;
+ }
+
+ @Override
+ public void set( EntityReference newValue )
+ throws IllegalArgumentException, IllegalStateException
+ {
+ reference = newValue;
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderInstance.java
new file mode 100644
index 0000000..7ecb745
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderInstance.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.runtime.value;
+
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.value.NoSuchValueException;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.composite.StateResolver;
+import org.apache.polygene.runtime.structure.ModuleInstance;
+
+/**
+ * Implementation of ValueBuilder
+ */
+public final class ValueBuilderInstance<T>
+ implements ValueBuilder<T>
+{
+
+ private final ModuleInstance currentModule;
+ private final ValueInstance prototypeInstance;
+
+ public ValueBuilderInstance( ValueDescriptor compositeModel,
+ ModuleInstance currentModule,
+ StateResolver stateResolver
+ )
+ {
+ ValueStateInstance state = new ValueStateInstance( compositeModel, currentModule, stateResolver );
+ ValueModel model = (ValueModel) compositeModel;
+ prototypeInstance = model.newValueInstance( state );
+ prototypeInstance.prepareToBuild();
+ this.currentModule = currentModule;
+ }
+
+ @Override
+ public T prototype()
+ {
+ return prototypeInstance.<T>proxy();
+ }
+
+ @Override
+ public AssociationStateHolder state()
+ {
+ return prototypeInstance.state();
+ }
+
+ @Override
+ public <K> K prototypeFor( Class<K> mixinType )
+ {
+ return prototypeInstance.newProxy( mixinType );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public T newInstance()
+ throws ConstructionException
+ {
+ Class<Composite> valueType = (Class<Composite>) prototypeInstance.types().findFirst().orElse( null );
+
+ ValueDescriptor valueModel = currentModule.typeLookup().lookupValueModel( valueType );
+
+ if( valueModel == null )
+ {
+ throw new NoSuchValueException( valueType.getName(), currentModule.name(), currentModule.typeLookup() );
+ }
+ return new ValueBuilderWithPrototype<>( valueModel, currentModule, prototype() ).newInstance();
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderWithPrototype.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderWithPrototype.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderWithPrototype.java
new file mode 100644
index 0000000..c9a1023
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderWithPrototype.java
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.runtime.value;
+
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.composite.FunctionStateResolver;
+import org.apache.polygene.runtime.composite.MixinModel;
+import org.apache.polygene.runtime.composite.MixinsModel;
+import org.apache.polygene.runtime.composite.StateResolver;
+import org.apache.polygene.runtime.composite.UsesInstance;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.structure.ModuleInstance;
+
+/**
+ * Implementation of ValueBuilder with a prototype supplied
+ */
+public class ValueBuilderWithPrototype<T>
+ implements ValueBuilder<T>
+{
+ private ValueInstance prototypeInstance;
+ private final ValueModel valueModel;
+
+ public ValueBuilderWithPrototype( ValueDescriptor compositeModelModule,
+ ModuleInstance currentModule,
+ T prototype
+ )
+ {
+ valueModel = (ValueModel) compositeModelModule;
+ MixinsModel mixinsModel = valueModel.mixinsModel();
+ Object[] mixins = mixinsModel.newMixinHolder();
+ final ValueStateInstance prototypeState = ValueInstance.valueInstanceOf( (ValueComposite) prototype ).state();
+ StateResolver resolver = new FunctionStateResolver(
+ new PropertyDescriptorFunction( prototypeState ),
+ new AssociationDescriptorEntityReferenceFunction( prototypeState ),
+ new AssociationDescriptorIterableFunction( prototypeState ),
+ new AssociationDescriptorMapFunction( prototypeState )
+ );
+ ValueStateInstance state = new ValueStateInstance( compositeModelModule, currentModule, resolver );
+ ValueInstance valueInstance = new ValueInstance(
+ valueModel,
+ mixins,
+ state
+ );
+
+ int i = 0;
+ InjectionContext injectionContext = new InjectionContext( valueInstance, UsesInstance.EMPTY_USES, state );
+ for( MixinModel mixinModel : mixinsModel.mixinModels() )
+ {
+ mixins[ i++ ] = mixinModel.newInstance( injectionContext );
+ }
+
+ valueInstance.prepareToBuild();
+ this.prototypeInstance = valueInstance;
+ }
+
+ @Override
+ public T prototype()
+ {
+ verifyUnderConstruction();
+ return prototypeInstance.<T>proxy();
+ }
+
+ @Override
+ public AssociationStateHolder state()
+ {
+ verifyUnderConstruction();
+ return prototypeInstance.state();
+ }
+
+ @Override
+ public <K> K prototypeFor( Class<K> mixinType )
+ {
+ verifyUnderConstruction();
+ return prototypeInstance.newProxy( mixinType );
+ }
+
+ @Override
+ public T newInstance()
+ throws ConstructionException
+ {
+ verifyUnderConstruction();
+
+ // Set correct info's (immutable) on the state
+ prototypeInstance.prepareBuilderState();
+
+ // Check that it is valid
+ valueModel.checkConstraints( prototypeInstance.state() );
+
+ try
+ {
+ return prototypeInstance.<T>proxy();
+ }
+ finally
+ {
+ // Invalidate builder
+ prototypeInstance = null;
+ }
+ }
+
+ private void verifyUnderConstruction()
+ {
+ if( prototypeInstance == null )
+ {
+ throw new IllegalStateException( "ValueBuilder instances cannot be reused" );
+ }
+ }
+
+ private static class PropertyDescriptorFunction
+ implements Function<PropertyDescriptor, Object>
+ {
+ private final ValueStateInstance prototypeState;
+
+ public PropertyDescriptorFunction( ValueStateInstance prototypeState )
+ {
+ this.prototypeState = prototypeState;
+ }
+
+ @Override
+ public Object apply( PropertyDescriptor descriptor )
+ {
+ return prototypeState.propertyFor( descriptor.accessor() ).get();
+ }
+ }
+
+ private static class AssociationDescriptorEntityReferenceFunction
+ implements Function<AssociationDescriptor, EntityReference>
+ {
+ private final ValueStateInstance prototypeState;
+
+ public AssociationDescriptorEntityReferenceFunction( ValueStateInstance prototypeState )
+ {
+ this.prototypeState = prototypeState;
+ }
+
+ @Override
+ public EntityReference apply( AssociationDescriptor descriptor )
+ {
+ return prototypeState.associationFor( descriptor.accessor() ).reference();
+ }
+ }
+
+ private static class AssociationDescriptorIterableFunction
+ implements Function<AssociationDescriptor, Stream<EntityReference>>
+ {
+ private final ValueStateInstance prototypeState;
+
+ public AssociationDescriptorIterableFunction( ValueStateInstance prototypeState )
+ {
+ this.prototypeState = prototypeState;
+ }
+
+ @Override
+ public Stream<EntityReference> apply( AssociationDescriptor descriptor )
+ {
+ return prototypeState.manyAssociationFor( descriptor.accessor() ).references();
+ }
+ }
+
+ private static class AssociationDescriptorMapFunction
+ implements Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>>
+ {
+ private final ValueStateInstance prototypeState;
+
+ public AssociationDescriptorMapFunction( ValueStateInstance prototypeState )
+ {
+ this.prototypeState = prototypeState;
+ }
+
+ @Override
+ public Stream<Map.Entry<String, EntityReference>> apply( AssociationDescriptor descriptor )
+ {
+ return prototypeState.namedAssociationFor( descriptor.accessor() ).references();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderWithState.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderWithState.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderWithState.java
new file mode 100644
index 0000000..236e3b9
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueBuilderWithState.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.runtime.value;
+
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.composite.StateResolver;
+import org.apache.polygene.runtime.structure.ModuleInstance;
+
+public class ValueBuilderWithState<T> implements ValueBuilder<T>
+{
+ private final ValueDescriptor model;
+ private ValueInstance prototypeInstance;
+
+ public ValueBuilderWithState( ValueDescriptor compositeModelModule,
+ ModuleInstance currentModule,
+ StateResolver stateResolver )
+ {
+ ValueStateInstance state = new ValueStateInstance( compositeModelModule, currentModule, stateResolver );
+ ValueInstance instance = ((ValueModel) compositeModelModule).newValueInstance( state );
+ instance.prepareToBuild();
+ this.model = compositeModelModule;
+ this.prototypeInstance = instance;
+ }
+
+ @Override
+ public T prototype()
+ {
+ verifyUnderConstruction();
+ return prototypeInstance.<T>proxy();
+ }
+
+ @Override
+ public AssociationStateHolder state()
+ {
+ verifyUnderConstruction();
+ return prototypeInstance.state();
+ }
+
+ @Override
+ public <K> K prototypeFor( Class<K> mixinType )
+ {
+ verifyUnderConstruction();
+
+ return prototypeInstance.newProxy( mixinType );
+ }
+
+ @Override
+ public T newInstance()
+ throws ConstructionException
+ {
+ verifyUnderConstruction();
+
+ // Set correct info's (immutable) on the state
+ prototypeInstance.prepareBuilderState();
+
+ // Check that it is valid
+ ((ValueModel) model).checkConstraints( prototypeInstance.state() );
+
+ try
+ {
+ return prototypeInstance.<T>proxy();
+ }
+ finally
+ {
+ // Invalidate builder
+ prototypeInstance = null;
+ }
+ }
+
+ private void verifyUnderConstruction()
+ {
+ if( prototypeInstance == null )
+ {
+ throw new IllegalStateException( "ValueBuilder instances cannot be reused" );
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueInstance.java
new file mode 100644
index 0000000..12ba7d9
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueInstance.java
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.runtime.value;
+
+import java.lang.reflect.Proxy;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.runtime.composite.MixinsInstance;
+import org.apache.polygene.runtime.composite.TransientInstance;
+import org.apache.polygene.runtime.property.PropertyInstance;
+import org.apache.polygene.spi.module.ModuleSpi;
+
+/**
+ * ValueComposite instance
+ */
+public final class ValueInstance
+ extends TransientInstance
+ implements CompositeInstance, MixinsInstance
+{
+ public static ValueInstance valueInstanceOf( ValueComposite composite )
+ {
+ return (ValueInstance) Proxy.getInvocationHandler( composite );
+ }
+
+ public ValueInstance( ValueModel compositeModel,
+ Object[] mixins,
+ ValueStateInstance state
+ )
+ {
+ super( compositeModel, mixins, state );
+ }
+
+ /**
+ * Perform equals with {@code o} argument.
+ * <p>
+ * The definition of equals() for the Value is that if both the state and descriptor are equal,
+ * then the values are equal.
+ * </p>
+ *
+ * @param o The other object to compare.
+ *
+ * @return Returns a {@code boolean} indicator whether this object is equals the other.
+ */
+ @Override
+ public boolean equals( Object o )
+ {
+ if( this == o )
+ {
+ return true;
+ }
+ if( o == null || !Proxy.isProxyClass( o.getClass() ) )
+ {
+ return false;
+ }
+
+ try
+ {
+ ValueInstance that = (ValueInstance) Proxy.getInvocationHandler( o );
+ // Descriptor equality
+ if( !descriptor().equals( that.descriptor() ) )
+ {
+ return false;
+ }
+ // State equality
+ return state.equals( that.state );
+ }
+ catch( ClassCastException e )
+ {
+ return false;
+ }
+ }
+
+ @Override
+ public ValueStateInstance state()
+ {
+ return (ValueStateInstance) state;
+ }
+
+ @Override
+ public ValueModel descriptor()
+ {
+ return (ValueModel) compositeModel;
+ }
+
+ /**
+ * When a ValueBuilder is about to start, ensure that all state has builder infos, i.e. they are mutable.
+ */
+ public void prepareToBuild()
+ {
+ descriptor().state().properties().forEach( propertyDescriptor -> {
+ PropertyInstance<Object> propertyInstance =
+ (PropertyInstance<Object>) state.propertyFor( propertyDescriptor.accessor() );
+
+ propertyInstance.prepareToBuild( propertyDescriptor );
+ } );
+
+ descriptor().state().associations().forEach( associationDescriptor -> {
+ state().associationFor( associationDescriptor.accessor() )
+ .setAssociationInfo( associationDescriptor.getBuilderInfo() );
+ } );
+
+ descriptor().state().manyAssociations().forEach( associationDescriptor -> {
+ state().manyAssociationFor( associationDescriptor.accessor() )
+ .setAssociationInfo( associationDescriptor.getBuilderInfo() );
+ } );
+
+ descriptor().state().namedAssociations().forEach( associationDescriptor -> {
+ state().namedAssociationFor( associationDescriptor.accessor() )
+ .setAssociationInfo( associationDescriptor.getBuilderInfo() );
+ } );
+ }
+
+ /**
+ * When a ValueBuilder is finished and is about to instantiate a Value, call this to ensure that the state has correct
+ * settings, i.e. is immutable.
+ */
+ public void prepareBuilderState()
+ {
+ descriptor().state().properties().forEach( propertyDescriptor -> {
+ PropertyInstance<Object> propertyInstance =
+ (PropertyInstance<Object>) state.propertyFor( propertyDescriptor.accessor() );
+ propertyInstance.prepareBuilderState( propertyDescriptor );
+ } );
+
+ descriptor().state().associations().forEach( associationDescriptor -> {
+ state().associationFor( associationDescriptor.accessor() ).setAssociationInfo( associationDescriptor );
+ } );
+
+ descriptor().state().manyAssociations().forEach( associationDescriptor -> {
+ state().manyAssociationFor( associationDescriptor.accessor() ).setAssociationInfo( associationDescriptor );
+ } );
+
+ descriptor().state().namedAssociations().forEach( associationDescriptor -> {
+ state().namedAssociationFor( associationDescriptor.accessor() ).setAssociationInfo( associationDescriptor );
+ } );
+ }
+
+ /**
+ * Calculate hash code.
+ *
+ * @return the hashcode of this instance.
+ */
+ @Override
+ public int hashCode()
+ {
+ int hash = compositeModel.hashCode() * 23; // Descriptor
+ return hash + state.hashCode() * 5; // State
+ }
+
+ @Override
+ public String toString()
+ {
+ return ( (ModuleSpi) module().instance() ).valueSerialization().serialize( this.<ValueComposite>proxy() );
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueModel.java
new file mode 100644
index 0000000..2148095
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueModel.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.value;
+
+import java.lang.reflect.Member;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.composite.CompositeMethodsModel;
+import org.apache.polygene.runtime.composite.CompositeModel;
+import org.apache.polygene.runtime.composite.MixinModel;
+import org.apache.polygene.runtime.composite.MixinsModel;
+import org.apache.polygene.runtime.composite.UsesInstance;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.unitofwork.UnitOfWorkInstance;
+
+/**
+ * Model for ValueComposites
+ */
+public final class ValueModel extends CompositeModel
+ implements ValueDescriptor
+{
+ private ValueCompositeType valueType;
+
+ public ValueModel( final ModuleDescriptor module,
+ final List<Class<?>> types,
+ final Visibility visibility,
+ final MetaInfo metaInfo,
+ final MixinsModel mixinsModel,
+ final ValueStateModel stateModel,
+ final CompositeMethodsModel compositeMethodsModel
+ )
+ {
+ super( module, types, visibility, metaInfo, mixinsModel, stateModel, compositeMethodsModel );
+
+ valueType = new ValueCompositeType( this );
+ }
+
+ @Override
+ public ValueCompositeType valueType()
+ {
+ return valueType;
+ }
+
+ @Override
+ public ValueStateModel state()
+ {
+ return (ValueStateModel) super.state();
+ }
+
+ // This method is ONLY called by ValueBuilders
+ void checkConstraints( ValueStateInstance state )
+ throws ConstraintViolationException
+ {
+ stateModel.properties().forEach(
+ propertyModel ->
+ {
+ try
+ {
+ propertyModel.checkConstraints( state.propertyFor( propertyModel.accessor() ).get() );
+ }
+ catch( ConstraintViolationException e )
+ {
+ throw new ConstraintViolationException( "<builder>", propertyModel.valueType()
+ .types(), (Member) propertyModel.accessor(), e.constraintViolations() );
+ }
+ }
+ );
+
+ // IF no UnitOfWork is active, then the Association checks shouldn't be done.
+ if( UnitOfWorkInstance.getCurrent().empty() )
+ {
+ return;
+ }
+ ( (ValueStateModel) stateModel ).associations().forEach(
+ associationModel ->
+ {
+ try
+ {
+ associationModel.checkConstraints( state.associationFor( associationModel.accessor() ).get() );
+ }
+ catch( ConstraintViolationException e )
+ {
+ Stream<? extends Type> types = Classes.interfacesOf( associationModel.type() );
+ throw new ConstraintViolationException( "<builder>", types, (Member) associationModel.accessor(), e.constraintViolations() );
+ }
+ }
+ );
+
+ ( (ValueStateModel) stateModel ).manyAssociations().forEach( associationModel ->
+ associationModel.checkAssociationConstraints( state
+ .manyAssociationFor( associationModel
+ .accessor() ) )
+ );
+
+ ( (ValueStateModel) stateModel ).namedAssociations().forEach( associationModel ->
+ associationModel.checkAssociationConstraints( state
+ .namedAssociationFor( associationModel
+ .accessor() ) )
+ );
+ }
+
+ public ValueInstance newValueInstance( ValueStateInstance state )
+ {
+ Object[] mixins = mixinsModel.newMixinHolder();
+
+ ValueInstance instance = new ValueInstance( this, mixins, state );
+
+ // Instantiate all mixins
+ int i = 0;
+ InjectionContext injectionContext = new InjectionContext( instance, UsesInstance.EMPTY_USES, state );
+ for( MixinModel mixinModel : mixinsModel.mixinModels() )
+ {
+ mixins[ i++ ] = mixinModel.newInstance( injectionContext );
+ }
+
+ // Return
+ return instance;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueStateInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueStateInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueStateInstance.java
new file mode 100644
index 0000000..aab6597
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueStateInstance.java
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.runtime.value;
+
+import java.lang.reflect.AccessibleObject;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.association.AssociationInfo;
+import org.apache.polygene.runtime.association.AssociationInstance;
+import org.apache.polygene.runtime.association.ManyAssociationInstance;
+import org.apache.polygene.runtime.association.NamedAssociationInstance;
+import org.apache.polygene.runtime.composite.StateResolver;
+import org.apache.polygene.runtime.property.PropertyInfo;
+import org.apache.polygene.runtime.property.PropertyInstance;
+import org.apache.polygene.runtime.structure.ModuleInstance;
+import org.apache.polygene.runtime.unitofwork.EntityFunction;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.polygene.api.util.Collectors.toMap;
+
+/**
+ * TODO
+ */
+public final class ValueStateInstance
+ implements AssociationStateHolder
+{
+ private final Map<AccessibleObject, PropertyInstance<?>> properties;
+ private final Map<AccessibleObject, AssociationInstance<?>> associations;
+ private final Map<AccessibleObject, ManyAssociationInstance<?>> manyAssociations;
+ private final Map<AccessibleObject, NamedAssociationInstance<?>> namedAssociations;
+
+ public ValueStateInstance( Map<AccessibleObject, PropertyInstance<?>> properties,
+ Map<AccessibleObject, AssociationInstance<?>> associations,
+ Map<AccessibleObject, ManyAssociationInstance<?>> manyAssociations,
+ Map<AccessibleObject, NamedAssociationInstance<?>> namedAssociations
+ )
+ {
+ this.properties = properties;
+ this.associations = associations;
+ this.manyAssociations = manyAssociations;
+ this.namedAssociations = namedAssociations;
+ }
+
+ public ValueStateInstance( ValueDescriptor compositeModelModule,
+ ModuleInstance currentModule,
+ StateResolver stateResolver
+ )
+ {
+ EntityFunction entityFunction = new EntityFunction( currentModule.unitOfWorkFactory() );
+
+ ValueModel valueModel = (ValueModel) compositeModelModule;
+ this.properties = new LinkedHashMap<>();
+ valueModel.state().properties().forEach( propertyDescriptor -> {
+ PropertyInfo builderInfo = propertyDescriptor.getBuilderInfo();
+ Object value = stateResolver.getPropertyState( propertyDescriptor );
+ PropertyInstance<Object> propertyInstance = new PropertyInstance<>( builderInfo, value );
+ properties.put( propertyDescriptor.accessor(), propertyInstance );
+ } );
+
+ this.associations = new LinkedHashMap<>();
+ valueModel.state().associations().forEach( associationDescriptor -> {
+ AssociationInfo builderInfo = associationDescriptor.getBuilderInfo();
+ EntityReference value = stateResolver.getAssociationState( associationDescriptor );
+ AssociationInstance<Object> associationInstance1 = new AssociationInstance<>(
+ builderInfo,
+ entityFunction,
+ new ReferenceProperty( value ) );
+ associations.put( associationDescriptor.accessor(), associationInstance1 );
+ } );
+
+ this.manyAssociations = new LinkedHashMap<>();
+ valueModel.state().manyAssociations().forEach( associationDescriptor -> {
+ AssociationInfo builderInfo = associationDescriptor.getBuilderInfo();
+ List<EntityReference> value = stateResolver.getManyAssociationState( associationDescriptor )
+ .collect( toList() );
+ ManyAssociationValueState manyAssociationState = new ManyAssociationValueState( value );
+ ManyAssociationInstance<Object> associationInstance = new ManyAssociationInstance<>(
+ builderInfo,
+ entityFunction,
+ manyAssociationState );
+ manyAssociations.put( associationDescriptor.accessor(), associationInstance );
+ } );
+
+ this.namedAssociations = new LinkedHashMap<>();
+ valueModel.state().namedAssociations().forEach( associationDescriptor -> {
+ AssociationInfo builderInfo = associationDescriptor.getBuilderInfo();
+ Map<String, EntityReference> value = stateResolver.getNamedAssociationState( associationDescriptor )
+ .collect( toMap( LinkedHashMap::new ) );
+ NamedAssociationValueState namedAssociationState = new NamedAssociationValueState( value );
+ NamedAssociationInstance<Object> associationInstance = new NamedAssociationInstance<>(
+ builderInfo,
+ entityFunction,
+ namedAssociationState );
+ namedAssociations.put( associationDescriptor.accessor(), associationInstance );
+ } );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> PropertyInstance<T> propertyFor( AccessibleObject accessor )
+ throws IllegalArgumentException
+ {
+ PropertyInstance<T> property = (PropertyInstance<T>) properties.get( accessor );
+
+ if( property == null )
+ {
+ throw new IllegalArgumentException( "No such property:" + accessor );
+ }
+
+ return property;
+ }
+
+ @Override
+ public Stream<PropertyInstance<?>> properties()
+ {
+ return properties.values().stream();
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> AssociationInstance<T> associationFor( AccessibleObject accessor )
+ {
+ AssociationInstance<T> association = (AssociationInstance<T>) associations.get( accessor );
+
+ if( association == null )
+ {
+ throw new IllegalArgumentException( "No such association:" + accessor );
+ }
+
+ return association;
+ }
+
+ @Override
+ public Stream<AssociationInstance<?>> allAssociations()
+ {
+ return associations.values().stream();
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> ManyAssociationInstance<T> manyAssociationFor( AccessibleObject accessor )
+ {
+ ManyAssociationInstance<T> manyAssociation = (ManyAssociationInstance<T>) manyAssociations.get( accessor );
+
+ if( manyAssociation == null )
+ {
+ throw new IllegalArgumentException( "No such many-association:" + accessor );
+ }
+
+ return manyAssociation;
+ }
+
+ @Override
+ public Stream<ManyAssociationInstance<?>> allManyAssociations()
+ {
+ return manyAssociations.values().stream();
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> NamedAssociationInstance<T> namedAssociationFor( AccessibleObject accessor )
+ {
+ NamedAssociationInstance<T> namedAssociation = (NamedAssociationInstance<T>) namedAssociations.get( accessor );
+
+ if( namedAssociation == null )
+ {
+ throw new IllegalArgumentException( "No such named-association:" + accessor );
+ }
+
+ return namedAssociation;
+ }
+
+ @Override
+ public Stream<? extends NamedAssociationInstance<?>> allNamedAssociations()
+ {
+ return namedAssociations.values().stream();
+ }
+
+ @SuppressWarnings( "SimplifiableIfStatement" )
+ @Override
+ public boolean equals( Object obj )
+ {
+ if( !( obj instanceof ValueStateInstance ) )
+ {
+ return false;
+ }
+ ValueStateInstance state = (ValueStateInstance) obj;
+ if( !properties.equals( state.properties ) )
+ {
+ return false;
+ }
+ if( !associations.equals( state.associations ) )
+ {
+ return false;
+ }
+ if( !manyAssociations.equals( state.manyAssociations ) )
+ {
+ return false;
+ }
+ return namedAssociations.equals( state.namedAssociations );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = properties.hashCode();
+ result = 31 * result + associations.hashCode();
+ result = 31 * result + manyAssociations.hashCode();
+ result = 31 * result + namedAssociations.hashCode();
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueStateModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueStateModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueStateModel.java
new file mode 100644
index 0000000..73c6a17
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValueStateModel.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.runtime.value;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateDescriptor;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.association.AssociationModel;
+import org.apache.polygene.runtime.association.AssociationsModel;
+import org.apache.polygene.runtime.association.ManyAssociationModel;
+import org.apache.polygene.runtime.association.ManyAssociationsModel;
+import org.apache.polygene.runtime.association.NamedAssociationModel;
+import org.apache.polygene.runtime.association.NamedAssociationsModel;
+import org.apache.polygene.runtime.composite.StateModel;
+import org.apache.polygene.runtime.property.PropertiesModel;
+
+/**
+ * Model for ValueComposite state.
+ */
+public final class ValueStateModel
+ extends StateModel
+ implements AssociationStateDescriptor
+{
+ private final AssociationsModel associationsModel;
+ private final ManyAssociationsModel manyAssociationsModel;
+ private final NamedAssociationsModel namedAssociationsModel;
+
+ public ValueStateModel( PropertiesModel propertiesModel,
+ AssociationsModel associationsModel,
+ ManyAssociationsModel manyAssociationsModel,
+ NamedAssociationsModel namedAssociationsModel
+ )
+ {
+ super( propertiesModel );
+ this.associationsModel = associationsModel;
+ this.manyAssociationsModel = manyAssociationsModel;
+ this.namedAssociationsModel = namedAssociationsModel;
+ }
+
+ @Override
+ public AssociationDescriptor getAssociationByName( String name )
+ {
+ return associationsModel.getAssociationByName( name );
+ }
+
+ @Override
+ public AssociationDescriptor getAssociationByQualifiedName( QualifiedName name )
+ {
+ return associationsModel.getAssociationByQualifiedName( name );
+ }
+
+ @Override
+ public AssociationDescriptor getManyAssociationByName( String name )
+ {
+ return manyAssociationsModel.getManyAssociationByName( name );
+ }
+
+ @Override
+ public AssociationDescriptor getManyAssociationByQualifiedName( QualifiedName name )
+ {
+ return manyAssociationsModel.getManyAssociationByQualifiedName( name );
+ }
+
+ @Override
+ public AssociationDescriptor getNamedAssociationByName( String name )
+ {
+ return namedAssociationsModel.getNamedAssociationByName( name );
+ }
+
+ @Override
+ public AssociationDescriptor getNamedAssociationByQualifiedName( QualifiedName name )
+ {
+ return namedAssociationsModel.getNamedAssociationByQualifiedName( name );
+ }
+
+ @Override
+ public Stream<AssociationModel> associations()
+ {
+ return associationsModel.associations();
+ }
+
+ @Override
+ public Stream<ManyAssociationModel> manyAssociations()
+ {
+ return manyAssociationsModel.manyAssociations();
+ }
+
+ @Override
+ public Stream<NamedAssociationModel> namedAssociations()
+ {
+ return namedAssociationsModel.namedAssociations();
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ if( visitor.visitEnter( this ) )
+ {
+ if( ( (VisitableHierarchy<Object, Object>) propertiesModel ).accept( visitor ) )
+ {
+ if( ( (VisitableHierarchy<AssociationsModel, AssociationModel>) associationsModel ).accept( visitor ) )
+ {
+ if( ( (VisitableHierarchy<ManyAssociationsModel, ManyAssociationModel>) manyAssociationsModel ).accept( visitor ) )
+ {
+ ( (VisitableHierarchy<NamedAssociationsModel, NamedAssociationModel>) namedAssociationsModel ).accept( visitor );
+ }
+ }
+ }
+ }
+ return visitor.visitLeave( this );
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValuesModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValuesModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValuesModel.java
new file mode 100644
index 0000000..caa875b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/value/ValuesModel.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.runtime.value;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.api.value.ValueDescriptor;
+
+/**
+ * JAVADOC
+ */
+public final class ValuesModel
+ implements VisitableHierarchy<Object, Object>
+{
+ private final List<ValueModel> valueModels;
+
+ public ValuesModel( List<ValueModel> valueModels )
+ {
+ this.valueModels = valueModels;
+ }
+
+ public Stream<ValueModel> models()
+ {
+ return valueModels.stream();
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ if( visitor.visitEnter( this ) )
+ {
+ for( ValueModel valueModel : valueModels )
+ {
+ if( !valueModel.accept( visitor ) )
+ {
+ break;
+ }
+ }
+ }
+ return visitor.visitLeave( this );
+ }
+
+ public Stream<? extends ValueDescriptor> stream()
+ {
+ return valueModels.stream();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/zest/runtime/ZestRuntimeImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/ZestRuntimeImpl.java b/core/runtime/src/main/java/org/apache/zest/runtime/ZestRuntimeImpl.java
deleted file mode 100644
index 269496c..0000000
--- a/core/runtime/src/main/java/org/apache/zest/runtime/ZestRuntimeImpl.java
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * 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;
-
-import java.lang.reflect.InvocationHandler;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.stream.Stream;
-import org.apache.zest.api.PolygeneAPI;
-import org.apache.zest.api.association.AbstractAssociation;
-import org.apache.zest.api.association.Association;
-import org.apache.zest.api.association.AssociationDescriptor;
-import org.apache.zest.api.association.AssociationStateHolder;
-import org.apache.zest.api.association.AssociationWrapper;
-import org.apache.zest.api.association.ManyAssociation;
-import org.apache.zest.api.association.ManyAssociationWrapper;
-import org.apache.zest.api.association.NamedAssociation;
-import org.apache.zest.api.association.NamedAssociationWrapper;
-import org.apache.zest.api.composite.Composite;
-import org.apache.zest.api.composite.CompositeDescriptor;
-import org.apache.zest.api.composite.CompositeInstance;
-import org.apache.zest.api.composite.ModelDescriptor;
-import org.apache.zest.api.composite.TransientComposite;
-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.property.Property;
-import org.apache.zest.api.property.PropertyDescriptor;
-import org.apache.zest.api.property.PropertyWrapper;
-import org.apache.zest.api.property.StateHolder;
-import org.apache.zest.api.service.ServiceComposite;
-import org.apache.zest.api.service.ServiceDescriptor;
-import org.apache.zest.api.service.ServiceReference;
-import org.apache.zest.api.structure.ModuleDescriptor;
-import org.apache.zest.api.unitofwork.UnitOfWork;
-import org.apache.zest.api.value.ValueComposite;
-import org.apache.zest.api.value.ValueDescriptor;
-import org.apache.zest.bootstrap.ApplicationAssemblyFactory;
-import org.apache.zest.bootstrap.ApplicationModelFactory;
-import org.apache.zest.bootstrap.PolygeneRuntime;
-import org.apache.zest.runtime.association.AbstractAssociationInstance;
-import org.apache.zest.runtime.bootstrap.ApplicationAssemblyFactoryImpl;
-import org.apache.zest.runtime.bootstrap.ApplicationModelFactoryImpl;
-import org.apache.zest.runtime.composite.ProxyReferenceInvocationHandler;
-import org.apache.zest.runtime.composite.TransientInstance;
-import org.apache.zest.runtime.entity.EntityInstance;
-import org.apache.zest.runtime.property.PropertyInstance;
-import org.apache.zest.runtime.service.ImportedServiceReferenceInstance;
-import org.apache.zest.runtime.service.ServiceInstance;
-import org.apache.zest.runtime.service.ServiceReferenceInstance;
-import org.apache.zest.runtime.unitofwork.ModuleUnitOfWork;
-import org.apache.zest.runtime.value.ValueInstance;
-import org.apache.zest.spi.PolygeneSPI;
-import org.apache.zest.spi.entity.EntityState;
-
-import static java.lang.reflect.Proxy.getInvocationHandler;
-import static org.apache.zest.runtime.composite.TransientInstance.compositeInstanceOf;
-
-/**
- * Incarnation of Polygene.
- */
-public final class PolygeneRuntimeImpl
- implements PolygeneSPI, PolygeneRuntime
-{
- private final ApplicationAssemblyFactory applicationAssemblyFactory;
- private final ApplicationModelFactory applicationModelFactory;
-
- public PolygeneRuntimeImpl()
- {
- applicationAssemblyFactory = new ApplicationAssemblyFactoryImpl();
- applicationModelFactory = new ApplicationModelFactoryImpl();
- }
-
- @Override
- public ApplicationAssemblyFactory applicationAssemblyFactory()
- {
- return applicationAssemblyFactory;
- }
-
- @Override
- public ApplicationModelFactory applicationModelFactory()
- {
- return applicationModelFactory;
- }
-
- @Override
- public PolygeneAPI api()
- {
- return this;
- }
-
- @Override
- public PolygeneSPI spi()
- {
- return this;
- }
-
- // API
-
- @Override
- @SuppressWarnings( "unchecked" )
- public <T> T dereference( T composite )
- {
- InvocationHandler handler = getInvocationHandler( composite );
- if( handler instanceof ProxyReferenceInvocationHandler )
- {
- return (T) ( (ProxyReferenceInvocationHandler) handler ).proxy();
- }
- if( handler instanceof CompositeInstance )
- {
- return composite;
- }
- return null;
- }
-
- @Override
- public ModuleDescriptor moduleOf( Object compositeOrServiceReferenceOrUow )
- {
- if( compositeOrServiceReferenceOrUow instanceof TransientComposite )
- {
- TransientComposite composite = (TransientComposite) compositeOrServiceReferenceOrUow;
- return TransientInstance.compositeInstanceOf( composite ).module();
- }
- else if( compositeOrServiceReferenceOrUow instanceof EntityComposite )
- {
- EntityComposite composite = (EntityComposite) compositeOrServiceReferenceOrUow;
- return EntityInstance.entityInstanceOf( composite ).module();
- }
- else if( compositeOrServiceReferenceOrUow instanceof ValueComposite )
- {
- ValueComposite composite = (ValueComposite) compositeOrServiceReferenceOrUow;
- return ValueInstance.valueInstanceOf( composite ).module();
- }
- else if( compositeOrServiceReferenceOrUow instanceof ServiceComposite )
- {
- ServiceComposite composite = (ServiceComposite) compositeOrServiceReferenceOrUow;
- InvocationHandler handler = getInvocationHandler( composite );
- if( handler instanceof ServiceInstance )
- {
- return ( (ServiceInstance) handler ).module();
- }
- return ( (ServiceReferenceInstance.ServiceInvocationHandler) handler ).module();
- }
- else if( compositeOrServiceReferenceOrUow instanceof UnitOfWork )
- {
- ModuleUnitOfWork unitOfWork = (ModuleUnitOfWork) compositeOrServiceReferenceOrUow;
- return unitOfWork.module();
- }
- else if( compositeOrServiceReferenceOrUow instanceof ServiceReferenceInstance )
- {
- ServiceReferenceInstance<?> reference = (ServiceReferenceInstance<?>) compositeOrServiceReferenceOrUow;
- return reference.module();
- }
- else if( compositeOrServiceReferenceOrUow instanceof ImportedServiceReferenceInstance )
- {
- ImportedServiceReferenceInstance<?> importedServiceReference
- = (ImportedServiceReferenceInstance<?>) compositeOrServiceReferenceOrUow;
- return importedServiceReference.module();
- }
- throw new IllegalArgumentException( "Wrong type. Must be one of "
- + Arrays.asList( TransientComposite.class, ValueComposite.class,
- ServiceComposite.class, ServiceReference.class,
- UnitOfWork.class ) );
- }
-
- @Override
- public ModelDescriptor modelDescriptorFor( Object compositeOrServiceReference )
- {
- if( compositeOrServiceReference instanceof TransientComposite )
- {
- TransientComposite composite = (TransientComposite) compositeOrServiceReference;
- return TransientInstance.compositeInstanceOf( composite ).descriptor();
- }
- else if( compositeOrServiceReference instanceof EntityComposite )
- {
- EntityComposite composite = (EntityComposite) compositeOrServiceReference;
- return EntityInstance.entityInstanceOf( composite ).descriptor();
- }
- else if( compositeOrServiceReference instanceof ValueComposite )
- {
- ValueComposite composite = (ValueComposite) compositeOrServiceReference;
- return ValueInstance.valueInstanceOf( composite ).descriptor();
- }
- else if( compositeOrServiceReference instanceof ServiceComposite )
- {
- ServiceComposite composite = (ServiceComposite) compositeOrServiceReference;
- InvocationHandler handler = getInvocationHandler( composite );
- if( handler instanceof ServiceInstance )
- {
- return ( (ServiceInstance) handler ).descriptor();
- }
- return ( (ServiceReferenceInstance.ServiceInvocationHandler) handler ).descriptor();
- }
- else if( compositeOrServiceReference instanceof ServiceReferenceInstance )
- {
- ServiceReferenceInstance<?> reference = (ServiceReferenceInstance<?>) compositeOrServiceReference;
- return reference.serviceDescriptor();
- }
- else if( compositeOrServiceReference instanceof ImportedServiceReferenceInstance )
- {
- ImportedServiceReferenceInstance<?> importedServiceReference
- = (ImportedServiceReferenceInstance<?>) compositeOrServiceReference;
- return importedServiceReference.serviceDescriptor();
- }
- throw new IllegalArgumentException( "Wrong type. Must be one of "
- + Arrays.asList( TransientComposite.class, ValueComposite.class,
- ServiceComposite.class, ServiceReference.class ) );
- }
-
- @Override
- public CompositeDescriptor compositeDescriptorFor( Object compositeOrServiceReference )
- {
- return (CompositeDescriptor) modelDescriptorFor( compositeOrServiceReference );
- }
-
- // Descriptors
-
- @Override
- public TransientDescriptor transientDescriptorFor( Object transsient )
- {
- if( transsient instanceof TransientComposite )
- {
- TransientInstance transientInstance = compositeInstanceOf( (Composite) transsient );
- return (TransientDescriptor) transientInstance.descriptor();
- }
- throw new IllegalArgumentException( "Wrong type. Must be subtype of " + TransientComposite.class );
- }
-
- @Override
- public StateHolder stateOf( TransientComposite composite )
- {
- return TransientInstance.compositeInstanceOf( composite ).state();
- }
-
- @Override
- public EntityDescriptor entityDescriptorFor( Object entity )
- {
- if( entity instanceof EntityComposite )
- {
- EntityInstance entityInstance = (EntityInstance) getInvocationHandler( entity );
- return entityInstance.entityModel();
- }
- throw new IllegalArgumentException( "Wrong type. Must be subtype of " + EntityComposite.class );
- }
-
- @Override
- public AssociationStateHolder stateOf( EntityComposite composite )
- {
- return EntityInstance.entityInstanceOf( composite ).state();
- }
-
- @Override
- public ValueDescriptor valueDescriptorFor( Object value )
- {
- if( value instanceof ValueComposite )
- {
- ValueInstance valueInstance = ValueInstance.valueInstanceOf( (ValueComposite) value );
- return valueInstance.descriptor();
- }
- throw new IllegalArgumentException( "Wrong type. Must be subtype of " + ValueComposite.class );
- }
-
- @Override
- public AssociationStateHolder stateOf( ValueComposite composite )
- {
- return ValueInstance.valueInstanceOf( composite ).state();
- }
-
- @Override
- public ServiceDescriptor serviceDescriptorFor( Object service )
- {
- if( service instanceof ServiceReferenceInstance )
- {
- ServiceReferenceInstance<?> ref = (ServiceReferenceInstance<?>) service;
- return ref.serviceDescriptor();
- }
- if( service instanceof ServiceComposite )
- {
- ServiceComposite composite = (ServiceComposite) service;
- return (ServiceDescriptor) ServiceInstance.serviceInstanceOf( composite ).descriptor();
- }
- throw new IllegalArgumentException( "Wrong type. Must be subtype of "
- + ServiceComposite.class + " or " + ServiceReference.class );
- }
-
- @Override
- public PropertyDescriptor propertyDescriptorFor( Property<?> property )
- {
- while( property instanceof PropertyWrapper )
- {
- property = ( (PropertyWrapper) property ).next();
- }
-
- return (PropertyDescriptor) ( (PropertyInstance<?>) property ).propertyInfo();
- }
-
- @Override
- public AssociationDescriptor associationDescriptorFor( AbstractAssociation association )
- {
- while( association instanceof AssociationWrapper )
- {
- association = ( (AssociationWrapper) association ).next();
- }
-
- while( association instanceof ManyAssociationWrapper )
- {
- association = ( (ManyAssociationWrapper) association ).next();
- }
-
- while( association instanceof NamedAssociationWrapper )
- {
- association = ( (NamedAssociationWrapper) association ).next();
- }
-
- return (AssociationDescriptor) ( (AbstractAssociationInstance) association ).associationInfo();
- }
-
- // SPI
- @Override
- public EntityState entityStateOf( EntityComposite composite )
- {
- return EntityInstance.entityInstanceOf( composite ).entityState();
- }
-
- @Override
- public EntityReference entityReferenceOf( Association<?> assoc )
- {
- return assoc.reference();
- }
-
- @Override
- public Stream<EntityReference> entityReferencesOf( ManyAssociation<?> assoc )
- {
- return assoc.references();
- }
-
- @Override
- public Stream<Map.Entry<String, EntityReference>> entityReferencesOf( NamedAssociation<?> assoc )
- {
- return assoc.references();
- }
-}