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:45 UTC
[09/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/injection/provider/InjectionProviderFactoryStrategy.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderFactoryStrategy.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderFactoryStrategy.java
new file mode 100644
index 0000000..38bc5ba
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InjectionProviderFactoryStrategy.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.injection.provider;
+
+import java.lang.annotation.Annotation;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.composite.InvalidValueCompositeException;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.concern.internal.ConcernFor;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.injection.scope.Uses;
+import org.apache.polygene.api.sideeffect.internal.SideEffectFor;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class InjectionProviderFactoryStrategy
+ implements InjectionProviderFactory
+{
+ private final Map<Class<? extends Annotation>, InjectionProviderFactory> generalProviderFactories = new HashMap<>();
+ private final Map<Class<? extends Annotation>, InjectionProviderFactory> valuesProviderFactories = new HashMap<>();
+ private MetaInfo metaInfo;
+
+ public InjectionProviderFactoryStrategy( MetaInfo metaInfo )
+ {
+ this.metaInfo = metaInfo;
+ valuesProviderFactories.put( This.class, new ThisInjectionProviderFactory() );
+ ModifiesInjectionProviderFactory modifiesInjectionProviderFactory = new ModifiesInjectionProviderFactory();
+ valuesProviderFactories.put( ConcernFor.class, modifiesInjectionProviderFactory );
+ valuesProviderFactories.put( SideEffectFor.class, modifiesInjectionProviderFactory );
+ valuesProviderFactories.put( State.class, new StateInjectionProviderFactory() );
+
+ valuesProviderFactories.put( Structure.class, new CachingInjectionProviderFactoryDecorator( new StructureInjectionProviderFactory() ) );
+ valuesProviderFactories.put( Service.class, new CachingInjectionProviderFactoryDecorator( new ServiceInjectionProviderFactory() ) );
+ generalProviderFactories.put( Invocation.class, new InvocationInjectionProviderFactory() );
+ generalProviderFactories.put( Uses.class, new UsesInjectionProviderFactory() );
+ }
+
+ @Override
+ public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+ throws InvalidInjectionException
+ {
+ Class<? extends Annotation> injectionAnnotationType = dependencyModel.injectionAnnotation().annotationType();
+ InjectionProviderFactory factory1 = generalProviderFactories.get( injectionAnnotationType );
+ InjectionProviderFactory factory2 = valuesProviderFactories.get( injectionAnnotationType );
+ if( factory1 == null && factory2 == null )
+ {
+ InjectionProviderFactory factory = metaInfo.get( InjectionProviderFactory.class );
+ if( factory != null )
+ {
+ return factory.newInjectionProvider( resolution, dependencyModel );
+ }
+ else
+ {
+ throw new InvalidInjectionException( "Unknown injection annotation @" + injectionAnnotationType.getSimpleName() );
+ }
+ }
+ ModelDescriptor composite = resolution.model();
+ Class<?> compositeType = composite.types().findFirst().orElse( null );
+ if( factory1 != null && ValueComposite.class.isAssignableFrom( compositeType ) )
+ {
+ throw new InvalidValueCompositeException( "@" + injectionAnnotationType.getSimpleName() + " is not allowed in ValueComposites: " + compositeType );
+ }
+
+ InjectionProviderFactory factory;
+ if( factory1 == null )
+ {
+ factory = factory2;
+ }
+ else
+ {
+ factory = factory1;
+ }
+ return factory.newInjectionProvider( resolution, dependencyModel );
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InvocationInjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InvocationInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InvocationInjectionProviderFactory.java
new file mode 100644
index 0000000..90e2987
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/InvocationInjectionProviderFactory.java
@@ -0,0 +1,118 @@
+/*
+ * 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.injection.provider;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.composite.CompositeMethodModel;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class InvocationInjectionProviderFactory
+ implements InjectionProviderFactory
+{
+ @Override
+ @SuppressWarnings( "raw" )
+ public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+ throws InvalidInjectionException
+ {
+ Class injectionClass = Classes.RAW_CLASS.apply( dependencyModel.injectionType() );
+ if( injectionClass.equals( Method.class ) ||
+ injectionClass.equals( AnnotatedElement.class ) ||
+ injectionClass.equals( Iterable.class ) ||
+ Annotation.class.isAssignableFrom( injectionClass ) )
+ {
+ return new InvocationDependencyResolution( resolution, dependencyModel );
+ }
+ else
+ {
+ String injectedTo = dependencyModel.injectedClass().getName();
+ throw new InvalidInjectionException( "Invalid injection type " + injectionClass + " in " + injectedTo );
+ }
+ }
+
+ private static class InvocationDependencyResolution
+ implements InjectionProvider
+ {
+ private final Resolution resolution;
+ private final DependencyModel dependencyModel;
+
+ private InvocationDependencyResolution( Resolution resolution, DependencyModel dependencyModel )
+ {
+ this.resolution = resolution;
+ this.dependencyModel = dependencyModel;
+ }
+
+ @Override
+ @SuppressWarnings( {"raw", "unchecked"} )
+ public Object provideInjection( InjectionContext context )
+ throws InjectionProviderException
+ {
+ Class injectionClass = Classes.RAW_CLASS.apply( dependencyModel.injectionType() );
+ final CompositeMethodModel methodModel = resolution.method();
+ if( injectionClass.equals( Method.class ) )
+ {
+ return methodModel.method();
+ }
+
+ final AnnotatedElement annotatedElement = methodModel.annotatedElement();
+ if( injectionClass.equals( AnnotatedElement.class ) )
+ {
+ return annotatedElement;
+ }
+ final Annotation annotation = annotatedElement.getAnnotation( injectionClass );
+ if( annotation != null )
+ {
+ return annotation;
+ }
+ if( dependencyModel.injectionType() instanceof Class<?> )
+ {
+ return annotatedElement.getAnnotation( (Class<Annotation>) dependencyModel.injectionType() );
+ }
+ if( dependencyModel.injectionType() instanceof ParameterizedType )
+ {
+ ParameterizedType injectionType = (ParameterizedType) dependencyModel.injectionType();
+ Type rawType = injectionType.getRawType();
+ Type[] actualTypeArguments = injectionType.getActualTypeArguments();
+ boolean isAnIterable = rawType.equals( Iterable.class );
+ boolean haveOneGenericType = actualTypeArguments.length == 1;
+ boolean thatIsOfTypeMethod = actualTypeArguments[ 0 ].equals( Method.class );
+ if( isAnIterable && haveOneGenericType && thatIsOfTypeMethod )
+ {
+ Class<?> injectedClass = dependencyModel.injectedClass();
+ Iterable<Method> result = methodModel.invocationsFor( injectedClass );
+ return result;
+ }
+ }
+ return null;
+ }
+ }
+}
\ 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/injection/provider/ModifiesInjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ModifiesInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ModifiesInjectionProviderFactory.java
new file mode 100644
index 0000000..b0f662b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ModifiesInjectionProviderFactory.java
@@ -0,0 +1,71 @@
+/*
+ * 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.injection.provider;
+
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class ModifiesInjectionProviderFactory
+ implements InjectionProviderFactory
+{
+ @Override
+ public InjectionProvider newInjectionProvider( Resolution bindingContext, DependencyModel dependencyModel )
+ throws InvalidInjectionException
+ {
+ if( bindingContext.model() instanceof CompositeDescriptor )
+ {
+ Class<?> type = Classes.RAW_CLASS.apply( dependencyModel.injectionType() );
+ if( type.isAssignableFrom( dependencyModel.injectedClass() ) )
+ {
+ return new ModifiedInjectionProvider();
+ }
+ else
+ {
+ throw new InvalidInjectionException( "Composite " + bindingContext.model() + " does not implement @ConcernFor type " + type
+ .getName() + " in modifier " + dependencyModel.injectedClass().getName() );
+ }
+ }
+ else
+ {
+ throw new InvalidInjectionException( "The class " + dependencyModel.injectedClass()
+ .getName() + " is not a modifier" );
+ }
+ }
+
+ private static class ModifiedInjectionProvider
+ implements InjectionProvider
+ {
+ @Override
+ public Object provideInjection( InjectionContext context )
+ throws InjectionProviderException
+ {
+ return context.next();
+ }
+ }
+}
\ 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/injection/provider/ServiceInjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ServiceInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ServiceInjectionProviderFactory.java
new file mode 100644
index 0000000..f3dc70c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ServiceInjectionProviderFactory.java
@@ -0,0 +1,224 @@
+/*
+ * 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.injection.provider;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.service.NoSuchServiceException;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.service.qualifier.Qualifier;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+import static java.util.stream.Collectors.toCollection;
+import static org.apache.polygene.api.util.Annotations.typeHasAnnotation;
+
+public final class ServiceInjectionProviderFactory
+ implements InjectionProviderFactory
+{
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+ throws InvalidInjectionException
+ {
+ // TODO This could be changed to allow multiple @Qualifier annotations
+ Annotation qualifierAnnotation = Stream.of( dependencyModel.annotations() )
+ .filter( typeHasAnnotation( Qualifier.class ) )
+ .findFirst().orElse( null );
+ Predicate<ServiceReference<?>> serviceQualifier = null;
+ if( qualifierAnnotation != null )
+ {
+ Qualifier qualifier = qualifierAnnotation.annotationType().getAnnotation( Qualifier.class );
+ try
+ {
+ serviceQualifier = qualifier.value().newInstance().qualifier( qualifierAnnotation );
+ }
+ catch( Exception e )
+ {
+ throw new InvalidInjectionException( "Could not instantiate qualifier serviceQualifier", e );
+ }
+ }
+
+ if( dependencyModel.rawInjectionType().equals( Iterable.class ) )
+ {
+ Type iterableType = ( (ParameterizedType) dependencyModel.injectionType() ).getActualTypeArguments()[ 0 ];
+ if( Classes.RAW_CLASS.apply( iterableType ).equals( ServiceReference.class ) )
+ {
+ // @Service Iterable<ServiceReference<MyService<Foo>> serviceRefs
+ Type serviceType = ( (ParameterizedType) iterableType ).getActualTypeArguments()[ 0 ];
+
+ return new IterableServiceReferenceProvider( serviceType, serviceQualifier );
+ }
+ else
+ {
+ // @Service Iterable<MyService<Foo>> services
+ return new IterableServiceProvider( iterableType, serviceQualifier );
+ }
+ }
+ else if( dependencyModel.rawInjectionType().equals( ServiceReference.class ) )
+ {
+ // @Service ServiceReference<MyService<Foo>> serviceRef
+ Type referencedType = ( (ParameterizedType) dependencyModel.injectionType() ).getActualTypeArguments()[ 0 ];
+ return new ServiceReferenceProvider( referencedType, serviceQualifier );
+ }
+ else
+ {
+ // @Service MyService<Foo> service
+ return new ServiceProvider( dependencyModel.injectionType(), serviceQualifier );
+ }
+ }
+
+ private static class IterableServiceReferenceProvider
+ extends ServiceInjectionProvider
+ {
+ private IterableServiceReferenceProvider( Type serviceType, Predicate<ServiceReference<?>> serviceQualifier )
+ {
+ super( serviceType, serviceQualifier );
+ }
+
+ @Override
+ public synchronized Object provideInjection( InjectionContext context )
+ throws InjectionProviderException
+ {
+ return getServiceReferences( context ).collect( toCollection( ArrayList::new ) );
+ }
+ }
+
+ private static class IterableServiceProvider
+ extends ServiceInjectionProvider
+ implements Function<ServiceReference<?>, Object>
+ {
+ private IterableServiceProvider( Type serviceType, Predicate<ServiceReference<?>> serviceQualifier )
+ {
+ super( serviceType, serviceQualifier );
+ }
+
+ @Override
+ public synchronized Object provideInjection( final InjectionContext context )
+ throws InjectionProviderException
+ {
+ return getServiceReferences( context ).map( ServiceReference::get )
+ .collect( toCollection( ArrayList::new ) );
+ }
+
+ @Override
+ public Object apply( ServiceReference<?> objectServiceReference )
+ {
+ return objectServiceReference.get();
+ }
+ }
+
+ private static class ServiceReferenceProvider
+ extends ServiceInjectionProvider
+ {
+ ServiceReferenceProvider( Type serviceType, Predicate<ServiceReference<?>> qualifier )
+ {
+ super( serviceType, qualifier );
+ }
+
+ @Override
+ public synchronized Object provideInjection( InjectionContext context )
+ throws InjectionProviderException
+ {
+ return getServiceReference( context );
+ }
+ }
+
+ private static class ServiceProvider
+ extends ServiceInjectionProvider
+ {
+ ServiceProvider( Type serviceType, Predicate<ServiceReference<?>> qualifier )
+ {
+ super( serviceType, qualifier );
+ }
+
+ @Override
+ public synchronized Object provideInjection( InjectionContext context )
+ throws InjectionProviderException
+ {
+ ServiceReference<?> ref = getServiceReference( context );
+
+ if( ref != null )
+ {
+ return ref.get();
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+
+ public abstract static class ServiceInjectionProvider
+ implements InjectionProvider
+ {
+ private final Type serviceType;
+ private final Predicate<ServiceReference<?>> serviceQualifier;
+
+ private ServiceInjectionProvider( Type serviceType, Predicate<ServiceReference<?>> serviceQualifier )
+ {
+ this.serviceType = serviceType;
+ this.serviceQualifier = serviceQualifier;
+ }
+
+ protected ServiceReference<Object> getServiceReference( InjectionContext context )
+ {
+ try
+ {
+ if( serviceQualifier == null )
+ {
+ return context.module().instance().findService( serviceType );
+ }
+ else
+ {
+ return context.module().instance().findServices( serviceType )
+ .filter( serviceQualifier ).findFirst().orElse( null );
+ }
+ }
+ catch( NoSuchServiceException e )
+ {
+ return null;
+ }
+ }
+
+ protected Stream<ServiceReference<Object>> getServiceReferences( final InjectionContext context )
+ {
+ if( serviceQualifier == null )
+ {
+ return context.module().instance().findServices( serviceType );
+ }
+ else
+ {
+ return context.module().instance().findServices( serviceType ).filter( serviceQualifier );
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StateInjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StateInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StateInjectionProviderFactory.java
new file mode 100644
index 0000000..3a3a80e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StateInjectionProviderFactory.java
@@ -0,0 +1,273 @@
+/*
+ * 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.injection.provider;
+
+import org.apache.polygene.api.association.AbstractAssociation;
+import org.apache.polygene.api.association.Association;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.AssociationStateDescriptor;
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.composite.StateDescriptor;
+import org.apache.polygene.api.composite.StatefulCompositeDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.injection.scope.State;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.entity.EntityInstance;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class StateInjectionProviderFactory
+ implements InjectionProviderFactory
+{
+ @Override
+ public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+ throws InvalidInjectionException
+ {
+ if( StateHolder.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+ {
+ // @State StateHolder properties;
+ return new StateInjectionProvider();
+ }
+ else if( UnitOfWork.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+ {
+ if( !( resolution.model() instanceof EntityDescriptor ) )
+ {
+ throw new InvalidInjectionException( "Only EntityComposites can be injected with '@State UnitOfWork'" );
+ }
+ return new UnitOfWorkInjectionProvider();
+ }
+ else if( Property.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+ {
+ // @State Property<String> name;
+ StateDescriptor descriptor;
+ descriptor = ( (StatefulCompositeDescriptor) resolution.model() ).state();
+
+ State annotation = (State) dependencyModel.injectionAnnotation();
+ String name;
+ if( annotation.value().isEmpty() )
+ {
+ name = resolution.field().getName();
+ }
+ else
+ {
+ name = annotation.value();
+ }
+
+ PropertyDescriptor propertyDescriptor = descriptor.findPropertyModelByName( name );
+ return new PropertyInjectionProvider( propertyDescriptor );
+ }
+ else if( Association.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+ {
+ // @State Association<MyEntity> name;
+ AssociationStateDescriptor descriptor = ( (EntityDescriptor) resolution.model() ).state();
+ State annotation = (State) dependencyModel.injectionAnnotation();
+ String name;
+ if( annotation.value().isEmpty() )
+ {
+ name = resolution.field().getName();
+ }
+ else
+ {
+ name = annotation.value();
+ }
+ AssociationDescriptor model = descriptor.getAssociationByName( name );
+ return new AssociationInjectionProvider( model );
+ }
+ else if( ManyAssociation.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+ {
+ // @State ManyAssociation<MyEntity> name;
+ AssociationStateDescriptor descriptor = ( (EntityDescriptor) resolution.model() ).state();
+ State annotation = (State) dependencyModel.injectionAnnotation();
+ String name;
+ if( annotation.value().isEmpty() )
+ {
+ name = resolution.field().getName();
+ }
+ else
+ {
+ name = annotation.value();
+ }
+ AssociationDescriptor model = descriptor.getManyAssociationByName( name );
+ return new ManyAssociationInjectionProvider( model );
+ }
+ else if( NamedAssociation.class.isAssignableFrom( dependencyModel.rawInjectionType() ) )
+ {
+ // @State NamedAssociation<MyEntity> name;
+ AssociationStateDescriptor descriptor = ( (EntityDescriptor) resolution.model() ).state();
+ State annotation = (State) dependencyModel.injectionAnnotation();
+ String name;
+ if( annotation.value().isEmpty() )
+ {
+ name = resolution.field().getName();
+ }
+ else
+ {
+ name = annotation.value();
+ }
+ AssociationDescriptor model = descriptor.getNamedAssociationByName( name );
+ return new NamedAssociationInjectionProvider( model );
+ }
+
+ throw new InjectionProviderException( "Injected value has invalid type" );
+ }
+
+ private static class PropertyInjectionProvider
+ implements InjectionProvider
+ {
+ private final PropertyDescriptor propertyDescriptor;
+
+ private PropertyInjectionProvider( PropertyDescriptor propertyDescriptor )
+ {
+ this.propertyDescriptor = propertyDescriptor;
+ }
+
+ @Override
+ public Object provideInjection( InjectionContext context )
+ throws InjectionProviderException
+ {
+ Property<?> value = context.state().propertyFor( propertyDescriptor.accessor() );
+ if( value != null )
+ {
+ return value;
+ }
+ else
+ {
+ throw new InjectionProviderException( "Non-optional property " + propertyDescriptor + " had no value" );
+ }
+ }
+ }
+
+ private static class AssociationInjectionProvider
+ implements InjectionProvider
+ {
+ private final AssociationDescriptor associationDescriptor;
+
+ private AssociationInjectionProvider( AssociationDescriptor associationDescriptor )
+ {
+ this.associationDescriptor = associationDescriptor;
+ }
+
+ @Override
+ public Object provideInjection( InjectionContext context )
+ throws InjectionProviderException
+ {
+ AbstractAssociation abstractAssociation = ( (AssociationStateHolder) context.state() ).
+ associationFor( associationDescriptor.accessor() );
+ if( abstractAssociation != null )
+ {
+ return abstractAssociation;
+ }
+ else
+ {
+ throw new InjectionProviderException( "Non-optional association " + associationDescriptor.qualifiedName() + " had no association" );
+ }
+ }
+ }
+
+ private static class ManyAssociationInjectionProvider
+ implements InjectionProvider
+ {
+ private final AssociationDescriptor manyAssociationDescriptor;
+
+ private ManyAssociationInjectionProvider( AssociationDescriptor manyAssociationDescriptor )
+ {
+ this.manyAssociationDescriptor = manyAssociationDescriptor;
+ }
+
+ @Override
+ public Object provideInjection( InjectionContext context )
+ throws InjectionProviderException
+ {
+ ManyAssociation<?> abstractAssociation = ( (AssociationStateHolder) context.state() ).
+ manyAssociationFor( manyAssociationDescriptor.accessor() );
+ if( abstractAssociation != null )
+ {
+ return abstractAssociation;
+ }
+ else
+ {
+ throw new InjectionProviderException( "Non-optional association " + manyAssociationDescriptor.qualifiedName() + " had no association" );
+ }
+ }
+ }
+
+ private static class NamedAssociationInjectionProvider
+ implements InjectionProvider
+ {
+ private final AssociationDescriptor namedAssociationDescriptor;
+
+ private NamedAssociationInjectionProvider( AssociationDescriptor namedAssociationDescriptor )
+ {
+ this.namedAssociationDescriptor = namedAssociationDescriptor;
+ }
+
+ @Override
+ public Object provideInjection( InjectionContext context )
+ throws InjectionProviderException
+ {
+ NamedAssociation<?> abstractAssociation = ( (AssociationStateHolder) context.state() ).
+ namedAssociationFor( namedAssociationDescriptor.accessor() );
+ if( abstractAssociation != null )
+ {
+ return abstractAssociation;
+ }
+ else
+ {
+ throw new InjectionProviderException( "Non-optional association " + namedAssociationDescriptor.qualifiedName() + " had no association" );
+ }
+ }
+ }
+
+ static private class StateInjectionProvider
+ implements InjectionProvider
+ {
+ @Override
+ public Object provideInjection( InjectionContext context )
+ throws InjectionProviderException
+ {
+ return context.state();
+ }
+ }
+
+ static private class UnitOfWorkInjectionProvider
+ implements InjectionProvider
+ {
+
+ @Override
+ public Object provideInjection( InjectionContext context )
+ throws InjectionProviderException
+ {
+ return ( (EntityInstance) context.compositeInstance() ).unitOfWork();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StructureInjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StructureInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StructureInjectionProviderFactory.java
new file mode 100644
index 0000000..0d20dab
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/StructureInjectionProviderFactory.java
@@ -0,0 +1,129 @@
+/*
+ * 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.injection.provider;
+
+import java.lang.reflect.Type;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+import org.apache.polygene.runtime.structure.ApplicationInstance;
+
+public final class StructureInjectionProviderFactory
+ implements InjectionProviderFactory
+{
+ @Override
+ public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+ throws InvalidInjectionException
+ {
+ return new StructureInjectionProvider( dependencyModel );
+ }
+
+ private static class StructureInjectionProvider
+ implements InjectionProvider
+ {
+ private final DependencyModel dependencyModel;
+
+ private StructureInjectionProvider( DependencyModel dependencyModel )
+ {
+ this.dependencyModel = dependencyModel;
+ }
+
+ @Override
+ public Object provideInjection( InjectionContext context )
+ throws InjectionProviderException
+ {
+ Type type1 = dependencyModel.injectionType();
+ if( !( type1 instanceof Class ) )
+ {
+ throw new InjectionProviderException( "Type [" + type1 + "] can not be injected from the @Structure injection scope: " + context );
+ }
+ Class clazz = (Class) type1;
+ if( clazz.equals( TransientBuilderFactory.class ) )
+ {
+ return context.module().instance();
+ }
+ else if( clazz.equals( ObjectFactory.class ) )
+ {
+ return context.module().instance();
+ }
+ else if( clazz.equals( ValueBuilderFactory.class ) )
+ {
+ return context.module().instance();
+ }
+ else if( clazz.equals( UnitOfWorkFactory.class ) )
+ {
+ return context.module().instance().unitOfWorkFactory();
+ }
+ else if( clazz.equals( QueryBuilderFactory.class ) )
+ {
+ return context.module().instance();
+ }
+ else if( clazz.equals( ServiceFinder.class ) )
+ {
+ return context.module().instance();
+ }
+ else if( Module.class.isAssignableFrom( clazz ) )
+ {
+ return context.module().instance();
+ }
+ else if( ModuleDescriptor.class.isAssignableFrom( clazz ) )
+ {
+ return context.module();
+ }
+ else if( Layer.class.isAssignableFrom( clazz ) )
+ {
+ return context.module().layer().instance();
+ }
+ else if( LayerDescriptor.class.isAssignableFrom( clazz ) )
+ {
+ return context.module().layer();
+ }
+ else if( Application.class.isAssignableFrom( clazz ) )
+ {
+ return context.module().layer().instance().application();
+ }
+ else if( ApplicationDescriptor.class.isAssignableFrom( clazz ) )
+ {
+ return context.module().layer().instance().application().descriptor();
+ }
+ else if( PolygeneAPI.class.isAssignableFrom( clazz ) )
+ {
+ return (( ApplicationInstance) context.module().layer().instance().application()).runtime();
+ }
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ThisInjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ThisInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ThisInjectionProviderFactory.java
new file mode 100644
index 0000000..161cfbd
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/ThisInjectionProviderFactory.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.runtime.injection.provider;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.composite.ProxyGenerator;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class ThisInjectionProviderFactory
+ implements InjectionProviderFactory
+{
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public InjectionProvider newInjectionProvider( Resolution bindingContext, DependencyModel dependencyModel )
+ throws InvalidInjectionException
+ {
+ if( bindingContext.model() instanceof CompositeDescriptor )
+ {
+ // If Composite type then return real type, otherwise use the specified one
+ final Class<?> thisType = dependencyModel.rawInjectionType();
+
+ Stream<Class<?>> injectionTypes;
+ if( Classes.assignableTypeSpecification( thisType ).test( bindingContext.model() ) )
+ {
+ injectionTypes = bindingContext.model().types();
+ }
+ else
+ {
+ CompositeDescriptor acd = ( (CompositeDescriptor) bindingContext.model() );
+ injectionTypes = acd.mixinTypes().filter( thisType::isAssignableFrom );
+ }
+
+ List<Class<?>> classes = injectionTypes.collect( Collectors.toList() );
+ if( classes.size() == 0 )
+ {
+ throw new InvalidInjectionException( "Composite " + bindingContext.model()
+ + " does not implement @This type " + thisType.getName() + " in fragment "
+ + dependencyModel.injectedClass().getName() );
+ }
+ return new ThisInjectionProvider( classes );
+ }
+ else
+ {
+ throw new InvalidInjectionException( "Object " + dependencyModel.injectedClass() + " may not use @This" );
+ }
+ }
+
+ @SuppressWarnings( { "raw", "unchecked" } )
+ private static class ThisInjectionProvider
+ implements InjectionProvider
+ {
+ Constructor proxyConstructor;
+ private Class[] interfaces;
+
+ private ThisInjectionProvider( List<Class<?>> types )
+ {
+ try
+ {
+ Class proxyClass;
+ Class<?> mainType = types.get( 0 );
+ if( Proxy.class.isAssignableFrom( mainType ) )
+ {
+ proxyClass = mainType;
+ }
+ else
+ {
+ interfaces = types.stream().map( Class.class::cast ).toArray( Class[]::new );
+ proxyClass = ProxyGenerator.createProxyClass( mainType.getClassLoader(), interfaces );
+ }
+
+ proxyConstructor = proxyClass.getConstructor( InvocationHandler.class );
+ }
+ catch( Exception e )
+ {
+ // Ignore
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public Object provideInjection( InjectionContext context )
+ {
+ try
+ {
+ InvocationHandler handler = context.compositeInstance();
+ if( handler == null )
+ {
+ handler = context.proxyHandler();
+ }
+ return proxyConstructor.newInstance( handler );
+ }
+ catch( Exception e )
+ {
+ throw new InjectionProviderException( "Could not instantiate @This proxy", e );
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/UsesInjectionProviderFactory.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/UsesInjectionProviderFactory.java b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/UsesInjectionProviderFactory.java
new file mode 100644
index 0000000..f4549c5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/injection/provider/UsesInjectionProviderFactory.java
@@ -0,0 +1,132 @@
+/*
+ * 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.injection.provider;
+
+import java.lang.reflect.Constructor;
+import org.apache.polygene.api.composite.NoSuchTransientException;
+import org.apache.polygene.api.object.NoSuchObjectException;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.InvalidInjectionException;
+import org.apache.polygene.runtime.composite.UsesInstance;
+import org.apache.polygene.runtime.injection.DependencyModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.injection.InjectionProvider;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.runtime.model.Resolution;
+
+/**
+ * JAVADOC
+ */
+public final class UsesInjectionProviderFactory
+ implements InjectionProviderFactory
+{
+ public UsesInjectionProviderFactory()
+ {
+ }
+
+ @Override
+ public InjectionProvider newInjectionProvider( Resolution resolution, DependencyModel dependencyModel )
+ throws InvalidInjectionException
+ {
+ return new UsesInjectionProvider( dependencyModel );
+ }
+
+ private static class UsesInjectionProvider
+ implements InjectionProvider
+ {
+ private final DependencyModel dependency;
+
+ public UsesInjectionProvider( DependencyModel dependency )
+ {
+ this.dependency = dependency;
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public Object provideInjection( InjectionContext context )
+ throws InjectionProviderException
+ {
+ UsesInstance uses = context.uses();
+
+ Class injectionType = dependency.rawInjectionType();
+ Object usesObject = uses.useForType( injectionType );
+
+ if( usesObject == null && !dependency.optional() )
+ {
+ // No @Uses object provided
+ // Try instantiating a Transient or Object for the given type
+ Module moduleInstance = context.module().instance();
+
+ try
+ {
+ if( context.instance() != null )
+ {
+ uses = uses.use( context.instance() );
+ }
+ usesObject = moduleInstance.newTransient( injectionType, uses.toArray() );
+ }
+ catch( NoSuchTransientException e )
+ {
+ try
+ {
+ usesObject = moduleInstance.newObject( injectionType, uses.toArray() );
+ }
+ catch( NoSuchObjectException e1 )
+ {
+ // Could not instantiate an instance - to try instantiate as plain class
+ try
+ {
+ usesObject = injectionType.newInstance();
+ }
+ catch( Throwable e2 )
+ {
+ // Could not instantiate - try with this as first argument
+ try
+ {
+ Constructor constructor = injectionType.getDeclaredConstructor( context.instance()
+ .getClass() );
+ if( !constructor.isAccessible() )
+ {
+ constructor.setAccessible( true );
+ }
+ usesObject = constructor.newInstance( context.instance() );
+ }
+ catch( Throwable e3 )
+ {
+ // Really can't instantiate it - ignore
+ }
+ }
+ }
+ }
+
+ if( usesObject != null )
+ {
+ context.setUses( context.uses().use( usesObject ) ); // Use this for other injections in same graph
+ }
+
+ return usesObject;
+ }
+ else
+ {
+ return usesObject;
+ }
+ }
+ }
+}
\ 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/internal/Activator.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/internal/Activator.java b/core/runtime/src/main/java/org/apache/polygene/runtime/internal/Activator.java
new file mode 100644
index 0000000..6a0481f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/internal/Activator.java
@@ -0,0 +1,58 @@
+/*
+ * 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.internal;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.apache.polygene.bootstrap.PolygeneRuntime;
+import org.apache.polygene.bootstrap.RuntimeFactory;
+import org.apache.polygene.runtime.PolygeneRuntimeImpl;
+
+/**
+ *
+ */
+public class Activator
+ implements BundleActivator
+{
+ private ServiceRegistration registration;
+
+ @Override
+ public void start( BundleContext bundleContext )
+ throws Exception
+ {
+ RuntimeFactory factory = new RuntimeFactory()
+ {
+ @Override
+ public PolygeneRuntime createRuntime()
+ {
+ return new PolygeneRuntimeImpl();
+ }
+ };
+ registration = bundleContext.registerService( RuntimeFactory.class.getName(), factory, null );
+ }
+
+ @Override
+ public void stop( BundleContext bundleContext )
+ throws Exception
+ {
+ registration.unregister();
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/model/Binder.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/model/Binder.java b/core/runtime/src/main/java/org/apache/polygene/runtime/model/Binder.java
new file mode 100644
index 0000000..c59cc96
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/model/Binder.java
@@ -0,0 +1,32 @@
+/*
+ * 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.model;
+
+import org.apache.polygene.bootstrap.BindingException;
+
+/**
+ * Interface for models that can understand binding of dependencies
+ */
+public interface Binder
+{
+ void bind( Resolution resolution )
+ throws BindingException;
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/model/Resolution.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/model/Resolution.java b/core/runtime/src/main/java/org/apache/polygene/runtime/model/Resolution.java
new file mode 100644
index 0000000..f5ff0f5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/model/Resolution.java
@@ -0,0 +1,92 @@
+/*
+ * 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.model;
+
+import java.lang.reflect.Field;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.runtime.composite.CompositeMethodModel;
+import org.apache.polygene.runtime.structure.ApplicationModel;
+import org.apache.polygene.runtime.structure.LayerModel;
+import org.apache.polygene.runtime.structure.ModuleModel;
+
+/**
+ * JAVADOC
+ */
+public final class Resolution
+{
+ private final ApplicationModel application;
+ private final LayerModel layer;
+ private final ModuleModel module;
+ private final ModelDescriptor modelDescriptor;
+ private final CompositeMethodModel method;
+ private final Field field;
+
+ public Resolution( ApplicationModel application,
+ LayerModel layer,
+ ModuleModel module,
+ ModelDescriptor modelDescriptor,
+ CompositeMethodModel method,
+ Field field
+ )
+ {
+ this.application = application;
+ this.layer = layer;
+ this.module = module;
+ this.modelDescriptor = modelDescriptor;
+ this.method = method;
+ this.field = field;
+ }
+
+ public ApplicationModel application()
+ {
+ return application;
+ }
+
+ public LayerModel layer()
+ {
+ return layer;
+ }
+
+ public ModuleModel module()
+ {
+ return module;
+ }
+
+ public ModelDescriptor model()
+ {
+ return modelDescriptor;
+ }
+
+ public CompositeMethodModel method()
+ {
+ return method;
+ }
+
+ public Field field()
+ {
+ return field;
+ }
+
+ public Resolution forField( final Field injectedField )
+ {
+ return new Resolution( application, layer, module, modelDescriptor, method, injectedField );
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectModel.java
new file mode 100644
index 0000000..c1a3dbf
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectModel.java
@@ -0,0 +1,158 @@
+/*
+ * 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.object;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.mixin.Initializable;
+import org.apache.polygene.api.mixin.InitializationException;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.runtime.composite.ConstructorsModel;
+import org.apache.polygene.runtime.injection.InjectedFieldsModel;
+import org.apache.polygene.runtime.injection.InjectedMethodsModel;
+import org.apache.polygene.runtime.injection.InjectionContext;
+
+/**
+ * JAVADOC
+ */
+public final class ObjectModel
+ implements ObjectDescriptor, VisitableHierarchy<Object, Object>
+{
+ private final ModuleDescriptor module;
+ private final Class<?> objectType;
+ private final Visibility visibility;
+ private final MetaInfo metaInfo;
+ private final ConstructorsModel constructorsModel;
+ private final InjectedFieldsModel injectedFieldsModel;
+ private final InjectedMethodsModel injectedMethodsModel;
+
+ public ObjectModel( ModuleDescriptor module,
+ Class<?> objectType,
+ Visibility visibility,
+ MetaInfo metaInfo
+ )
+ {
+ this.module = module;
+ this.objectType = objectType;
+ this.visibility = visibility;
+ this.metaInfo = metaInfo;
+
+ constructorsModel = new ConstructorsModel( objectType );
+ injectedFieldsModel = new InjectedFieldsModel( objectType );
+ injectedMethodsModel = new InjectedMethodsModel( objectType );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public Stream<Class<?>> types()
+ {
+ return Stream.of( objectType );
+ }
+
+ @Override
+ public Visibility visibility()
+ {
+ return visibility;
+ }
+
+ @Override
+ public ModuleDescriptor module()
+ {
+ return module;
+ }
+
+ @Override
+ public <T> T metaInfo( Class<T> infoType )
+ {
+ return metaInfo.get( infoType );
+ }
+
+ @Override
+ public boolean isAssignableTo( Class<?> type )
+ {
+ return type.isAssignableFrom( objectType );
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ if( visitor.visitEnter( this ) )
+ {
+ if( constructorsModel.accept( visitor ) )
+ {
+ if( injectedFieldsModel.accept( visitor ) )
+ {
+ injectedMethodsModel.accept( visitor );
+ }
+ }
+ }
+ return visitor.visitLeave( this );
+ }
+
+ public Object newInstance( InjectionContext injectionContext )
+ {
+ Object instance;
+ try
+ {
+ instance = constructorsModel.newInstance( injectionContext );
+ injectionContext = new InjectionContext( injectionContext.module(), injectionContext.uses(), instance );
+ injectedFieldsModel.inject( injectionContext, instance );
+ injectedMethodsModel.inject( injectionContext, instance );
+ }
+ catch( Exception e )
+ {
+ throw new ConstructionException( "Could not instantiate " + objectType.getName(), e );
+ }
+
+ if( instance instanceof Initializable )
+ {
+ try
+ {
+ ( (Initializable) instance ).initialize();
+ }
+ catch( Exception e )
+ {
+ String message = "Unable to initialize " + objectType;
+ throw new ConstructionException( new InitializationException( message, e ) );
+ }
+ }
+
+ return instance;
+ }
+
+ public void inject( InjectionContext injectionContext, Object instance )
+ {
+ injectedFieldsModel.inject( injectionContext, instance );
+ injectedMethodsModel.inject( injectionContext, instance );
+ }
+
+ @Override
+ public String toString()
+ {
+ return objectType.getName();
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectsModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectsModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectsModel.java
new file mode 100644
index 0000000..84d2c11
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/object/ObjectsModel.java
@@ -0,0 +1,62 @@
+/*
+ * 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.object;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public class ObjectsModel
+ implements VisitableHierarchy<Object, Object>
+{
+ private final List<ObjectModel> objectModels;
+
+ public ObjectsModel( List<ObjectModel> objectModels )
+ {
+ this.objectModels = objectModels;
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ if( visitor.visitEnter( this ) )
+ {
+ for( ObjectModel objectModel : objectModels )
+ {
+ if( !objectModel.accept( visitor ) )
+ {
+ break;
+ }
+ }
+ }
+ return visitor.visitLeave( this );
+ }
+
+ public Stream<ObjectModel> models()
+ {
+ return objectModels.stream();
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/package.html
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/package.html b/core/runtime/src/main/java/org/apache/polygene/runtime/package.html
new file mode 100644
index 0000000..1ed6d55
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/package.html
@@ -0,0 +1,24 @@
+<!--
+ ~ 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.
+ ~
+ ~
+ -->
+<html>
+ <body>
+ <h2>Apache Polygene\u2122 Runtime.</h2>
+ </body>
+</html>
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertiesModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertiesModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertiesModel.java
new file mode 100644
index 0000000..cfcfcb5
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertiesModel.java
@@ -0,0 +1,107 @@
+/*
+ * 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.property;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * Base class for properties model
+ */
+public class PropertiesModel
+ implements VisitableHierarchy<Object, Object>
+{
+ protected final Map<AccessibleObject, PropertyModel> mapAccessiblePropertyModel = new LinkedHashMap<>();
+
+ public PropertiesModel()
+ {
+ }
+
+ public void addProperty( PropertyModel property )
+ {
+ mapAccessiblePropertyModel.put( property.accessor(), property );
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ if( visitor.visitEnter( this ) )
+ {
+ for( PropertyModel propertyModel : mapAccessiblePropertyModel.values() )
+ {
+ if( !propertyModel.accept( visitor ) )
+ {
+ break;
+ }
+ }
+ }
+
+ return visitor.visitLeave( this );
+ }
+
+ public Stream<PropertyModel> properties()
+ {
+ return mapAccessiblePropertyModel.values().stream();
+ }
+
+ public PropertyModel getProperty( AccessibleObject accessor )
+ {
+ PropertyModel propertyModel = mapAccessiblePropertyModel.get( accessor );
+ if( propertyModel == null )
+ {
+ throw new IllegalArgumentException( "No property found with name: " + ( (Member) accessor ).getName() );
+ }
+
+ return propertyModel;
+ }
+
+ public PropertyModel getPropertyByName( String name )
+ throws IllegalArgumentException
+ {
+ for( PropertyModel propertyModel : mapAccessiblePropertyModel.values() )
+ {
+ if( propertyModel.qualifiedName().name().equals( name ) )
+ {
+ return propertyModel;
+ }
+ }
+ throw new IllegalArgumentException( "No property found with name: " + name );
+ }
+
+ public PropertyModel getPropertyByQualifiedName( QualifiedName name )
+ throws IllegalArgumentException
+ {
+ for( PropertyModel propertyModel : mapAccessiblePropertyModel.values() )
+ {
+ if( propertyModel.qualifiedName().equals( name ) )
+ {
+ return propertyModel;
+ }
+ }
+ throw new IllegalArgumentException( "No property found with qualified name: " + name );
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInfo.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInfo.java b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInfo.java
new file mode 100644
index 0000000..fa8e1e6
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInfo.java
@@ -0,0 +1,37 @@
+/*
+ * 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.property;
+
+import java.lang.reflect.Type;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.runtime.composite.ConstraintsCheck;
+
+/**
+ * TODO
+ */
+public interface PropertyInfo
+ extends ConstraintsCheck
+{
+ boolean isImmutable();
+
+ QualifiedName qualifiedName();
+
+ Type type();
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInstance.java
new file mode 100644
index 0000000..72d39cb
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyInstance.java
@@ -0,0 +1,326 @@
+/*
+ * 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.property;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.property.PropertyWrapper;
+import org.apache.polygene.api.type.CollectionType;
+import org.apache.polygene.api.type.MapType;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.runtime.value.ValueInstance;
+
+/**
+ * {@code PropertyInstance} represents a property.
+ */
+public class PropertyInstance<T>
+ implements Property<T>
+{
+ protected volatile T value;
+ protected PropertyInfo model;
+
+ /**
+ * Construct an instance of {@code PropertyInstance} with the specified arguments.
+ *
+ * @param model The property model. This argument must not be {@code null}.
+ * @param aValue The property value.
+ */
+ public PropertyInstance( PropertyInfo model, T aValue )
+ {
+ this.model = model;
+ value = aValue;
+ }
+
+ public PropertyInfo propertyInfo()
+ {
+ return model;
+ }
+
+ /**
+ * @param model The property model. This argument must not be {@code null}.
+ */
+ public void setPropertyInfo( PropertyInfo model )
+ {
+ this.model = model;
+ }
+
+ /**
+ * Returns this property value.
+ *
+ * @return This property value.
+ */
+ @Override
+ public T get()
+ {
+ return value;
+ }
+
+ /**
+ * Sets this property value.
+ *
+ * @param aNewValue The new value.
+ */
+ @Override
+ public void set( T aNewValue )
+ {
+ if( model.isImmutable() )
+ {
+ throw new IllegalStateException( "Property [" + model.qualifiedName() + "] is immutable." );
+ }
+
+ model.checkConstraints( aNewValue );
+
+ value = aNewValue;
+ }
+
+ /**
+ * Perform equals with {@code o} argument.
+ * <p>
+ * The definition of equals() for the Property is that if both the state and descriptor are equal,
+ * then the properties 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 || getClass() != o.getClass() )
+ {
+ return false;
+ }
+
+ Property<?> that = (Property<?>) o;
+ // Unwrap if needed
+ while( that instanceof PropertyWrapper )
+ {
+ that = ( (PropertyWrapper) that ).next();
+ }
+ // Descriptor equality
+ PropertyDescriptor thatDescriptor = (PropertyDescriptor) ( (PropertyInstance) that ).propertyInfo();
+ if( !model.equals( thatDescriptor ) )
+ {
+ return false;
+ }
+ // State equality
+ T value = get();
+ if( value == null )
+ {
+ return that.get() == null;
+ }
+ return value.equals( that.get() );
+ }
+
+ /**
+ * Calculate hash code.
+ *
+ * @return the hashcode of this instance.
+ */
+ @Override
+ public int hashCode()
+ {
+ int hash = model.hashCode() * 19; // Descriptor
+ T value = get();
+ if( value != null )
+ {
+ hash += value.hashCode() * 13; // State
+ }
+ return hash;
+ }
+
+ /**
+ * Returns the value as string.
+ *
+ * @return The value as string.
+ */
+ @Override
+ public String toString()
+ {
+ Object value = get();
+ return value == null ? "" : value.toString();
+ }
+
+ @SuppressWarnings( {"raw", "unchecked"} )
+ public void prepareToBuild( PropertyModel propertyDescriptor )
+ {
+ // Check if state has to be modified
+ model = propertyDescriptor.getBuilderInfo();
+ if( propertyDescriptor.valueType() instanceof ValueCompositeType )
+ {
+ Object value = get();
+ if( value != null )
+ {
+ ValueInstance.valueInstanceOf( (ValueComposite) value ).prepareToBuild();
+ }
+ }
+ else if( propertyDescriptor.valueType() instanceof CollectionType )
+ {
+ Object value = get();
+
+ if( value != null )
+ {
+ if( value instanceof List )
+ {
+ value = new ArrayList( (Collection) value );
+ }
+ else if( value instanceof Set )
+ {
+ value = new LinkedHashSet( (Collection) value );
+ }
+
+ // Check if items are Values
+ CollectionType collection = (CollectionType) propertyDescriptor.valueType();
+ if( collection.collectedType() instanceof ValueCompositeType )
+ {
+ Collection coll = (Collection) value;
+ for( Object instance : coll )
+ {
+ ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareToBuild();
+ }
+ }
+
+ set( (T) value );
+ }
+ }
+ else if( propertyDescriptor.valueType() instanceof MapType )
+ {
+ Object value = get();
+
+ if( value != null )
+ {
+ Map map = new LinkedHashMap( (Map) value );
+
+ // Check if keys/values are Values
+ MapType mapType = (MapType) propertyDescriptor.valueType();
+ if( mapType.keyType() instanceof ValueCompositeType )
+ {
+ for( Object instance : map.keySet() )
+ {
+ ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareToBuild();
+ }
+ }
+ if( mapType.valueType() instanceof ValueCompositeType )
+ {
+ for( Object instance : map.values() )
+ {
+ ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareToBuild();
+ }
+ }
+
+ set( (T) value );
+ }
+ }
+ }
+
+ @SuppressWarnings( {"raw", "unchecked"} )
+ public void prepareBuilderState( PropertyModel propertyDescriptor )
+ {
+ // Check if state has to be modified
+ if( propertyDescriptor.valueType() instanceof ValueCompositeType )
+ {
+ Object value = get();
+ if( value != null )
+ {
+ ValueInstance.valueInstanceOf( (ValueComposite) value ).prepareBuilderState();
+ }
+ }
+ else if( propertyDescriptor.valueType() instanceof CollectionType )
+ {
+ T value = get();
+ if( value != null )
+ {
+ if( propertyDescriptor.isImmutable() )
+ {
+ if( value instanceof List )
+ {
+ value = (T) Collections.unmodifiableList( (List<? extends Object>) value );
+ }
+ else if( value instanceof Set )
+ {
+ value = (T) Collections.unmodifiableSet( (Set<? extends Object>) value );
+ }
+ else
+ {
+ value = (T) Collections.unmodifiableCollection( (Collection<? extends Object>) value );
+ }
+
+ this.value = value;
+ }
+
+ CollectionType collection = (CollectionType) propertyDescriptor.valueType();
+ if( collection.collectedType() instanceof ValueCompositeType )
+ {
+ Collection coll = (Collection) value;
+ for( Object instance : coll )
+ {
+ ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareBuilderState();
+ }
+ }
+ }
+ }
+ else if( propertyDescriptor.valueType() instanceof MapType )
+ {
+ T value = get();
+
+ if( value != null )
+ {
+ MapType mapType = (MapType) propertyDescriptor.valueType();
+ if( mapType.keyType() instanceof ValueCompositeType )
+ {
+ Map map = (Map) value;
+ for( Object instance : map.keySet() )
+ {
+ ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareBuilderState();
+ }
+ }
+ if( mapType.valueType() instanceof ValueCompositeType )
+ {
+ Map map = (Map) value;
+ for( Object instance : map.values() )
+ {
+ ValueInstance.valueInstanceOf( (ValueComposite) instance ).prepareBuilderState();
+ }
+ }
+ if( propertyDescriptor.isImmutable() )
+ {
+ value = (T) Collections.unmodifiableMap( (Map<?, ?>) value );
+ }
+
+ this.value = value;
+ }
+ }
+
+ model = propertyDescriptor;
+ }
+}