You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by ni...@apache.org on 2015/07/30 21:48:08 UTC
[09/80] [partial] zest-java git commit: First round of changes to
move to org.apache.zest namespace.
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/query/IterableQuerySource.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/query/IterableQuerySource.java b/core/runtime/src/main/java/org/apache/zest/runtime/query/IterableQuerySource.java
new file mode 100644
index 0000000..41ec961
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/query/IterableQuerySource.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.zest.runtime.query;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.apache.zest.api.composite.Composite;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.api.query.grammar.OrderBy;
+import org.apache.zest.api.util.Classes;
+import org.apache.zest.functional.Iterables;
+import org.apache.zest.functional.Specification;
+import org.apache.zest.functional.Specifications;
+import org.apache.zest.spi.query.QuerySource;
+
+/**
+ * JAVADOC
+ */
+public class IterableQuerySource
+ implements QuerySource
+{
+ private final Iterable iterable;
+
+ /**
+ * Constructor.
+ *
+ * @param iterable iterable
+ */
+ @SuppressWarnings( "raw" )
+ IterableQuerySource( final Iterable iterable )
+ {
+ this.iterable = iterable;
+ }
+
+ @Override
+ public <T> T find( Class<T> resultType,
+ Specification<Composite> whereClause,
+ Iterable<OrderBy> orderBySegments,
+ Integer firstResult,
+ Integer maxResults,
+ Map<String, Object> variables
+ )
+ {
+ final Iterator<T> iterator = iterator( resultType, whereClause, orderBySegments, firstResult, maxResults, variables );
+ if( iterator.hasNext() )
+ {
+ return iterator.next();
+ }
+ return null;
+ }
+
+ @Override
+ public <T> long count( Class<T> resultType,
+ Specification<Composite> whereClause,
+ Iterable<OrderBy> orderBySegments,
+ Integer firstResult,
+ Integer maxResults,
+ Map<String, Object> variables
+ )
+ {
+ return list( resultType, whereClause, orderBySegments, firstResult, maxResults, variables ).size();
+ }
+
+ @Override
+ public <T> Iterator<T> iterator( Class<T> resultType,
+ Specification<Composite> whereClause,
+ Iterable<OrderBy> orderBySegments,
+ Integer firstResult,
+ Integer maxResults,
+ Map<String, Object> variables
+ )
+ {
+ return list( resultType, whereClause, orderBySegments, firstResult, maxResults, variables ).iterator();
+ }
+
+ @SuppressWarnings( {"raw", "unchecked"} )
+ private <T> List<T> list( Class<T> resultType,
+ Specification<Composite> whereClause,
+ Iterable<OrderBy> orderBySegments,
+ Integer firstResult,
+ Integer maxResults,
+ Map<String, Object> variables
+ )
+ {
+ // Ensure it's a list first
+ List<T> list = filter( resultType, whereClause );
+
+ // Order list
+ if( orderBySegments != null )
+ {
+ // Sort it
+ Collections.sort( list, new OrderByComparator( orderBySegments ) );
+ }
+
+ // Cut results
+ if( firstResult != null )
+ {
+ if( firstResult > list.size() )
+ {
+ return Collections.emptyList();
+ }
+
+ int toIdx;
+ if( maxResults != null )
+ {
+ toIdx = Math.min( firstResult + maxResults, list.size() );
+ }
+ else
+ {
+ toIdx = list.size();
+ }
+
+ list = list.subList( firstResult, toIdx );
+ }
+ else
+ {
+ int toIdx;
+ if( maxResults != null )
+ {
+ toIdx = Math.min( maxResults, list.size() );
+ }
+ else
+ {
+ toIdx = list.size();
+ }
+
+ list = list.subList( 0, toIdx );
+ }
+
+ return list;
+ }
+
+ @SuppressWarnings( {"raw", "unchecked"} )
+ private <T> List<T> filter( Class<T> resultType, Specification whereClause )
+ {
+ if( whereClause == null )
+ {
+ return Iterables.toList( Iterables.filter( Classes.instanceOf( resultType ), iterable ) );
+ }
+ else
+ {
+ return Iterables.toList( Iterables.filter( Specifications.and( Classes.instanceOf( resultType ), whereClause ), iterable ) );
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return "IterableQuerySource{" + iterable + '}';
+ }
+
+ private static class OrderByComparator<T extends Composite>
+ implements Comparator<T>
+ {
+
+ private final Iterable<OrderBy> orderBySegments;
+
+ private OrderByComparator( Iterable<OrderBy> orderBySegments )
+ {
+ this.orderBySegments = orderBySegments;
+ }
+
+ @Override
+ @SuppressWarnings( {"raw", "unchecked"} )
+ public int compare( T o1, T o2 )
+ {
+ for( OrderBy orderBySegment : orderBySegments )
+ {
+ try
+ {
+ final Property prop1 = orderBySegment.property().map( o1 );
+ final Property prop2 = orderBySegment.property().map( o2 );
+ if( prop1 == null || prop2 == null )
+ {
+ if( prop1 == null && prop2 == null )
+ {
+ return 0;
+ }
+ else if( prop1 != null )
+ {
+ return 1;
+ }
+ return -1;
+ }
+ final Object value1 = prop1.get();
+ final Object value2 = prop2.get();
+ if( value1 == null || value2 == null )
+ {
+ if( value1 == null && value2 == null )
+ {
+ return 0;
+ }
+ else if( value1 != null )
+ {
+ return 1;
+ }
+ return -1;
+ }
+ if( value1 instanceof Comparable )
+ {
+ int result = ( (Comparable) value1 ).compareTo( value2 );
+ if( result != 0 )
+ {
+ if( orderBySegment.order() == OrderBy.Order.ASCENDING )
+ {
+ return result;
+ }
+ else
+ {
+ return -result;
+ }
+ }
+ }
+ }
+ catch( Exception e )
+ {
+ return 0;
+ }
+ }
+
+ return 0;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/query/QueryBuilderFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/query/QueryBuilderFactoryImpl.java b/core/runtime/src/main/java/org/apache/zest/runtime/query/QueryBuilderFactoryImpl.java
new file mode 100644
index 0000000..8bc93b3
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/query/QueryBuilderFactoryImpl.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2007-2009 Niclas Hedhman.
+ * Copyright 2008 Alin Dreghiciu.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zest.runtime.query;
+
+import org.apache.zest.api.query.NotQueryableException;
+import org.apache.zest.api.query.QueryBuilder;
+import org.apache.zest.api.query.QueryBuilderFactory;
+import org.apache.zest.api.service.NoSuchServiceException;
+import org.apache.zest.api.service.ServiceFinder;
+import org.apache.zest.api.service.ServiceReference;
+import org.apache.zest.api.util.NullArgumentException;
+import org.apache.zest.spi.query.EntityFinder;
+
+/**
+ * Default implementation of {@link QueryBuilderFactory}
+ */
+public final class QueryBuilderFactoryImpl
+ implements QueryBuilderFactory
+{
+ private ServiceFinder finder;
+
+ /**
+ * Constructor.
+ *
+ * @param finder The ServiceFinder of the Module this QueryBuilderFactory belongs to.
+ */
+ public QueryBuilderFactoryImpl( ServiceFinder finder )
+ {
+ NullArgumentException.validateNotNull( "ServiceFinder", finder );
+ this.finder = finder;
+ }
+
+ /**
+ * @see QueryBuilderFactory#newQueryBuilder(Class)
+ */
+ @Override
+ public <T> QueryBuilder<T> newQueryBuilder( final Class<T> resultType )
+ {
+ NotQueryableException.throwIfNotQueryable( resultType );
+
+ final ServiceReference<EntityFinder> serviceReference;
+ try
+ {
+ serviceReference = finder.findService( EntityFinder.class );
+ return new QueryBuilderImpl<T>( serviceReference.get(), resultType, null );
+ }
+ catch( NoSuchServiceException e )
+ {
+ return new QueryBuilderImpl<T>( null, resultType, null );
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/query/QueryBuilderImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/query/QueryBuilderImpl.java b/core/runtime/src/main/java/org/apache/zest/runtime/query/QueryBuilderImpl.java
new file mode 100644
index 0000000..67ab342
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/query/QueryBuilderImpl.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2007-2009 Niclas Hedhman.
+ * Copyright 2008 Alin Dreghiciu.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zest.runtime.query;
+
+import org.apache.zest.api.composite.Composite;
+import org.apache.zest.api.query.Query;
+import org.apache.zest.api.query.QueryBuilder;
+import org.apache.zest.api.query.QueryExpressions;
+import org.apache.zest.functional.Specification;
+import org.apache.zest.spi.query.EntityFinder;
+import org.apache.zest.spi.query.QueryBuilderSPI;
+import org.apache.zest.spi.query.QuerySource;
+
+/**
+ * Default implementation of {@link QueryBuilder}
+ */
+final class QueryBuilderImpl<T>
+ implements QueryBuilder<T>, QueryBuilderSPI<T>
+{
+
+ /**
+ * Entity finder to be used to locate entities.
+ */
+ private final EntityFinder entityFinder;
+
+ /**
+ * Type of queried entities.
+ */
+ private final Class<T> resultType;
+ /**
+ * Where clause.
+ */
+ private final Specification<Composite> whereClause;
+
+ /**
+ * Constructor.
+ *
+ * @param entityFinder entity finder to be used to locate entities; canot be null
+ * @param resultType type of queried entities; cannot be null
+ * @param whereClause current where-clause
+ */
+ QueryBuilderImpl( final EntityFinder entityFinder,
+ final Class<T> resultType,
+ final Specification<Composite> whereClause
+ )
+ {
+ this.entityFinder = entityFinder;
+ this.resultType = resultType;
+ this.whereClause = whereClause;
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public QueryBuilder<T> where( Specification<Composite> specification )
+ {
+ if( specification == null )
+ {
+ throw new IllegalArgumentException( "Where clause cannot be null" );
+ }
+ if( this.whereClause != null )
+ {
+ specification = QueryExpressions.and( this.whereClause, specification );
+ }
+ return new QueryBuilderImpl<>( entityFinder, resultType, specification );
+ }
+
+ @Override
+ public Query<T> newQuery( Iterable<T> iterable )
+ {
+ return new QueryImpl<>( resultType, whereClause, new IterableQuerySource( iterable ) );
+ }
+
+ // SPI
+ @Override
+ public Query<T> newQuery( QuerySource querySource )
+ {
+ return new QueryImpl<>( resultType, whereClause, querySource );
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/query/QueryImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/query/QueryImpl.java b/core/runtime/src/main/java/org/apache/zest/runtime/query/QueryImpl.java
new file mode 100644
index 0000000..59ebb5d
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/query/QueryImpl.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2007 Niclas Hedhman.
+ * Copyright 2008 Alin Dreghiciu.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zest.runtime.query;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.apache.zest.api.composite.Composite;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.api.query.Query;
+import org.apache.zest.api.query.QueryExecutionException;
+import org.apache.zest.api.query.QueryExpressions;
+import org.apache.zest.api.query.grammar.OrderBy;
+import org.apache.zest.functional.Iterables;
+import org.apache.zest.functional.Specification;
+import org.apache.zest.spi.query.QuerySource;
+
+/**
+ * Default implementation of {@link org.apache.zest.api.query.Query}.
+ */
+/* package */ class QueryImpl<T>
+ implements Query<T>
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Type of queried entities.
+ */
+ private final Class<T> resultType;
+ /**
+ * Where clause.
+ */
+ private final Specification<Composite> whereClause;
+ private QuerySource querySource;
+ /**
+ * Order by clause segments.
+ */
+ private Iterable<OrderBy> orderBySegments;
+ /**
+ * First result to be returned.
+ */
+ private Integer firstResult;
+ /**
+ * Maximum number of results to be returned.
+ */
+ private Integer maxResults;
+ /**
+ * Mapping between variable name and variable values.
+ */
+ private Map<String, Object> variables;
+
+ /**
+ * Constructor.
+ *
+ * @param resultType type of queried entities; cannot be null
+ * @param whereClause where clause
+ */
+ /* package */ QueryImpl( final Class<T> resultType,
+ final Specification<Composite> whereClause,
+ final QuerySource querySource
+ )
+ {
+ this.resultType = resultType;
+ this.whereClause = whereClause;
+ this.querySource = querySource;
+ }
+
+ /**
+ * @see org.apache.zest.api.query.Query#orderBy(org.apache.zest.api.query.grammar.OrderBy[])
+ */
+ @Override
+ public Query<T> orderBy( final OrderBy... segments )
+ {
+ orderBySegments = Iterables.iterable( segments );
+ return this;
+ }
+
+ /**
+ * @see org.apache.zest.api.query.Query#orderBy(org.apache.zest.api.property.Property, org.apache.zest.api.query.grammar.OrderBy.Order)
+ */
+ @Override
+ public Query<T> orderBy( Property<?> property, OrderBy.Order order )
+ {
+ if( orderBySegments == null )
+ {
+ orderBySegments = Iterables.iterable( new OrderBy( QueryExpressions.property( property ), order ) );
+ }
+ else
+ {
+ orderBySegments = Iterables.append( new OrderBy( QueryExpressions.property( property ), order ), orderBySegments );
+ }
+ return this;
+ }
+
+ /**
+ * @see org.apache.zest.api.query.Query#orderBy(org.apache.zest.api.property.Property)
+ */
+ @Override
+ public Query<T> orderBy( Property<?> property )
+ {
+ orderBy( property, OrderBy.Order.ASCENDING );
+ return this;
+ }
+
+ /**
+ * @see org.apache.zest.api.query.Query#firstResult(int)
+ */
+ @Override
+ public Query<T> firstResult( int firstResult )
+ {
+ this.firstResult = firstResult;
+ return this;
+ }
+
+ /**
+ * @see org.apache.zest.api.query.Query#maxResults(int)
+ */
+ @Override
+ public Query<T> maxResults( int maxResults )
+ {
+ this.maxResults = maxResults;
+ return this;
+ }
+
+ /**
+ * @see org.apache.zest.api.query.Query#setVariable(String, Object)
+ */
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public Query<T> setVariable( final String name, final Object value )
+ {
+ if( variables == null )
+ {
+ variables = new HashMap<String, Object>();
+ }
+ variables.put( name, value );
+
+ return this;
+ }
+
+ /**
+ * @see org.apache.zest.api.query.Query#getVariable(String)
+ */
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public <V> V getVariable( final String name )
+ {
+ if( variables == null )
+ {
+ return null;
+ }
+ else
+ {
+ return (V) variables.get( name );
+ }
+ }
+
+ @Override
+ public Class<T> resultType()
+ {
+ return resultType;
+ }
+
+ @Override
+ public T find()
+ throws QueryExecutionException
+ {
+ return querySource.find( resultType, whereClause, orderBySegments, firstResult, maxResults, variables );
+ }
+
+ @Override
+ public long count()
+ throws QueryExecutionException
+ {
+ return querySource.count( resultType, whereClause, orderBySegments, firstResult, maxResults, variables );
+ }
+
+ @Override
+ public Iterator<T> iterator()
+ {
+ return querySource.iterator( resultType, whereClause, orderBySegments, firstResult, maxResults, variables );
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Query{" +
+ " FROM " + querySource +
+ " WHERE " + whereClause +
+ ( orderBySegments != null ? " ORDER BY " + orderBySegments : "" ) +
+ ( firstResult != null ? " FIRST " + firstResult : "" ) +
+ ( maxResults != null ? " MAX " + maxResults : "" ) +
+ " EXPECT " + resultType +
+ ( variables != null ? " WITH VARIABLES " + variables : "" ) +
+ '}';
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServiceInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServiceInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServiceInstance.java
new file mode 100644
index 0000000..b63bf11
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServiceInstance.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2012, Paul Merlin.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.zest.runtime.service;
+
+import org.apache.zest.api.activation.Activation;
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.api.activation.PassivationException;
+import org.apache.zest.api.service.ServiceImporter;
+
+/**
+ * JAVADOC
+ */
+public final class ImportedServiceInstance<T>
+ implements Activation
+{
+ private final T instance;
+ private final ServiceImporter<T> importer;
+
+ public ImportedServiceInstance( T instance, ServiceImporter<T> importer )
+ {
+ this.importer = importer;
+ this.instance = instance;
+ }
+
+ public T instance()
+ {
+ return instance;
+ }
+
+ public ServiceImporter importer()
+ {
+ return importer;
+ }
+
+ public boolean isAvailable()
+ {
+ return importer.isAvailable( instance );
+ }
+
+ @Override
+ public void activate()
+ throws ActivationException
+ {
+ // NOOP
+ }
+
+ @Override
+ public void passivate()
+ throws PassivationException
+ {
+ // NOOP
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServiceModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServiceModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServiceModel.java
new file mode 100644
index 0000000..669010d
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServiceModel.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
+ * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zest.runtime.service;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import org.apache.zest.api.common.MetaInfo;
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.api.service.ImportedServiceDescriptor;
+import org.apache.zest.api.service.ServiceImporter;
+import org.apache.zest.api.service.ServiceImporterException;
+import org.apache.zest.api.structure.Module;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.VisitableHierarchy;
+import org.apache.zest.runtime.activation.ActivatorsInstance;
+import org.apache.zest.runtime.activation.ActivatorsModel;
+
+import static org.apache.zest.functional.Iterables.iterable;
+
+/**
+ * JAVADOC
+ */
+public final class ImportedServiceModel
+ implements ImportedServiceDescriptor, VisitableHierarchy<Object, Object>
+{
+ private final Class<?> type;
+ private final Visibility visibility;
+ @SuppressWarnings( "raw" )
+ private final Class<? extends ServiceImporter> serviceImporter;
+ private final String identity;
+ private final boolean importOnStartup;
+ private final MetaInfo metaInfo;
+ private final ActivatorsModel<?> activatorsModel;
+ private final String moduleName;
+
+ @SuppressWarnings( "raw" )
+ public ImportedServiceModel( Class serviceType,
+ Visibility visibility,
+ Class<? extends ServiceImporter> serviceImporter,
+ String identity,
+ boolean importOnStartup,
+ MetaInfo metaInfo,
+ ActivatorsModel<?> activatorsModel,
+ String moduleName
+ )
+ {
+ type = serviceType;
+ this.visibility = visibility;
+ this.serviceImporter = serviceImporter;
+ this.identity = identity;
+ this.importOnStartup = importOnStartup;
+ this.metaInfo = metaInfo;
+ this.activatorsModel = activatorsModel;
+ this.moduleName = moduleName;
+ }
+
+ public boolean isImportOnStartup()
+ {
+ return importOnStartup;
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public Iterable<Class<?>> types()
+ {
+ Iterable<? extends Class<?>> iterable = iterable( type );
+ return (Iterable<Class<?>>) iterable;
+ }
+
+ @Override
+ public Visibility visibility()
+ {
+ return visibility;
+ }
+
+ @Override
+ public <T> T metaInfo( Class<T> infoType )
+ {
+ return metaInfo.get( infoType );
+ }
+
+ @Override
+ @SuppressWarnings( "raw" )
+ public Class<? extends ServiceImporter> serviceImporter()
+ {
+ return serviceImporter;
+ }
+
+ @Override
+ public Class<?> type()
+ {
+ return type;
+ }
+
+ @Override
+ public String identity()
+ {
+ return identity;
+ }
+
+ public String moduleName()
+ {
+ return moduleName;
+ }
+
+ @SuppressWarnings( {"raw", "unchecked"} )
+ public ActivatorsInstance<?> newActivatorsInstance( Module module )
+ throws Exception
+ {
+ return new ActivatorsInstance( activatorsModel.newInstances( module ) );
+ }
+
+ @Override
+ public boolean isAssignableTo( Class<?> type )
+ {
+ return this.type.isAssignableFrom( type );
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ if( visitor.visitEnter( this ) )
+ {
+ activatorsModel.accept( visitor );
+ }
+ return visitor.visitLeave( this );
+ }
+
+ @SuppressWarnings( {"raw", "unchecked"} )
+ public <T> ImportedServiceInstance<T> importInstance( Module module )
+ {
+ ServiceImporter importer = module.newObject( serviceImporter );
+ try
+ {
+ T instance = (T) importer.importService( this );
+ return new ImportedServiceInstance<>( instance, importer );
+ }
+ catch( ServiceImporterException e )
+ {
+ throw e;
+ }
+ catch( Exception e )
+ {
+ throw new ServiceImporterException( "Could not import service " + identity, e );
+ }
+ }
+
+ @SuppressWarnings( "raw" )
+ public Object newProxy( InvocationHandler serviceInvocationHandler )
+ {
+ if( type.isInterface() )
+ {
+ return Proxy.newProxyInstance( type.getClassLoader(),
+ new Class[]{ type },
+ serviceInvocationHandler );
+ }
+ else
+ {
+ Class[] interfaces = type.getInterfaces();
+ return Proxy.newProxyInstance( type.getClassLoader(),
+ interfaces,
+ serviceInvocationHandler );
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return type.getName() + ":" + identity;
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServiceReferenceInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServiceReferenceInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServiceReferenceInstance.java
new file mode 100644
index 0000000..750985f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServiceReferenceInstance.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
+ * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zest.runtime.service;
+
+import org.apache.zest.api.activation.Activation;
+import org.apache.zest.api.activation.ActivationEventListener;
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.api.activation.PassivationException;
+import org.apache.zest.api.service.ServiceImporterException;
+import org.apache.zest.api.service.ServiceReference;
+import org.apache.zest.api.service.ServiceUnavailableException;
+import org.apache.zest.api.structure.Module;
+import org.apache.zest.runtime.activation.ActivationDelegate;
+
+/**
+ * Implementation of ServiceReference. This manages the reference to the imported service.
+ * <p>
+ * Whenever the service is requested it is returned directly to the client. That means that
+ * to handle service passivation and unavailability correctly, any proxying must be done in the
+ * service importer.
+ * </p>
+ * @param <T> Service Type
+ */
+public final class ImportedServiceReferenceInstance<T>
+ implements ServiceReference<T>, Activation
+{
+ private volatile ImportedServiceInstance<T> serviceInstance;
+ private T instance;
+ private final Module module;
+ private final ImportedServiceModel serviceModel;
+ private final ActivationDelegate activation = new ActivationDelegate( this );
+ private boolean active = false;
+
+ public ImportedServiceReferenceInstance( ImportedServiceModel serviceModel, Module module )
+ {
+ this.module = module;
+ this.serviceModel = serviceModel;
+ }
+
+ @Override
+ public String identity()
+ {
+ return serviceModel.identity();
+ }
+
+ @Override
+ public Iterable<Class<?>> types()
+ {
+ return serviceModel.types();
+ }
+
+ @Override
+ public <T> T metaInfo( Class<T> infoType )
+ {
+ return serviceModel.metaInfo( infoType );
+ }
+
+ @Override
+ public synchronized T get()
+ {
+ return getInstance();
+ }
+
+ public ImportedServiceModel serviceDescriptor()
+ {
+ return serviceModel;
+ }
+
+ @Override
+ public void activate()
+ throws ActivationException
+ {
+ if( serviceModel.isImportOnStartup() )
+ {
+ getInstance();
+ }
+ }
+
+ @Override
+ public void passivate()
+ throws PassivationException
+ {
+ if( serviceInstance != null )
+ {
+ try
+ {
+ activation.passivate( new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ active = false;
+ }
+ } );
+ }
+ finally
+ {
+ serviceInstance = null;
+ active = false;
+ }
+ }
+ }
+
+ @Override
+ public boolean isActive()
+ {
+ return active;
+ }
+
+ @Override
+ public boolean isAvailable()
+ {
+ try
+ {
+ getInstance();
+ return serviceInstance.isAvailable();
+ }
+ catch( ServiceImporterException ex )
+ {
+ return false;
+ }
+ }
+
+ public Module module()
+ {
+ return module;
+ }
+
+ private T getInstance()
+ throws ServiceImporterException
+ {
+ // DCL that works with Java 1.5 volatile semantics
+ if( serviceInstance == null )
+ {
+ synchronized( this )
+ {
+ if( serviceInstance == null )
+ {
+ serviceInstance = serviceModel.<T>importInstance( module );
+ instance = serviceInstance.instance();
+
+ try
+ {
+ activation.activate( serviceModel.newActivatorsInstance( module ), serviceInstance, new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ active = true;
+ }
+ } );
+ }
+ catch( Exception e )
+ {
+ serviceInstance = null;
+ throw new ServiceUnavailableException( "Could not activate service " + serviceModel.identity(), e );
+ }
+ }
+ }
+ }
+
+ return instance;
+ }
+
+ @Override
+ public String toString()
+ {
+ return serviceModel.identity() + ", active=" + isActive() + ", module='" + serviceModel.moduleName() + "'";
+ }
+
+ @Override
+ public void registerActivationEventListener( ActivationEventListener listener )
+ {
+ activation.registerActivationEventListener( listener );
+ }
+
+ @Override
+ public void deregisterActivationEventListener( ActivationEventListener listener )
+ {
+ activation.deregisterActivationEventListener( listener );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return identity().hashCode();
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ if( obj == null )
+ {
+ return false;
+ }
+ if( getClass() != obj.getClass() )
+ {
+ return false;
+ }
+ final ServiceReference other = (ServiceReference) obj;
+ return identity().equals( other.identity() );
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServicesInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServicesInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServicesInstance.java
new file mode 100644
index 0000000..f957f11
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServicesInstance.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2012, Paul Merlin.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.zest.runtime.service;
+
+import java.util.List;
+import org.apache.zest.api.activation.Activation;
+import org.apache.zest.api.activation.ActivationEventListener;
+import org.apache.zest.api.activation.ActivationEventListenerRegistration;
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.api.activation.PassivationException;
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.api.service.ServiceReference;
+import org.apache.zest.functional.Iterables;
+import org.apache.zest.functional.Specification;
+import org.apache.zest.runtime.activation.ActivationDelegate;
+import org.apache.zest.runtime.activation.ActivatorsInstance;
+
+import static org.apache.zest.api.util.Classes.instanceOf;
+import static org.apache.zest.functional.Iterables.filter;
+
+/**
+ * JAVADOC
+ */
+public class ImportedServicesInstance
+ implements Activation, ActivationEventListenerRegistration
+{
+ private final ImportedServicesModel servicesModel;
+ private final List<ServiceReference> serviceReferences;
+ private final ActivationDelegate activation = new ActivationDelegate( this, false );
+
+ public ImportedServicesInstance( ImportedServicesModel servicesModel,
+ List<ServiceReference> serviceReferences
+ )
+ {
+ this.servicesModel = servicesModel;
+ this.serviceReferences = serviceReferences;
+ for( ServiceReference serviceReference : serviceReferences )
+ {
+ serviceReference.registerActivationEventListener( activation );
+ }
+ }
+
+ @Override
+ public void activate()
+ throws ActivationException
+ {
+ Iterable<Activation> activatees = Iterables.<Activation>cast( filter( instanceOf( Activation.class ), serviceReferences ) );
+ activation.activate( ActivatorsInstance.EMPTY, activatees );
+ }
+
+ @Override
+ public void passivate()
+ throws PassivationException
+ {
+ activation.passivate();
+ }
+
+ public Iterable<ServiceReference> visibleServices( final Visibility visibility )
+ {
+ return Iterables.filter( new Specification<ServiceReference>()
+ {
+ @Override
+ public boolean satisfiedBy( ServiceReference item )
+ {
+ return ( (ImportedServiceReferenceInstance) item ).serviceDescriptor()
+ .visibility()
+ .ordinal() >= visibility.ordinal();
+ }
+ }, serviceReferences );
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder( "Services{" );
+ String sep = " ";
+ for( ServiceReference serviceReference : serviceReferences )
+ {
+ sb.append( sep ).
+ append( serviceReference.identity() ).
+ append( "(active=" ).append( serviceReference.isActive() ).append( ")" );
+ sep = ", ";
+ }
+ return sb.append( " }" ).toString();
+ }
+
+ @Override
+ public void registerActivationEventListener( ActivationEventListener listener )
+ {
+ activation.registerActivationEventListener( listener );
+ }
+
+ @Override
+ public void deregisterActivationEventListener( ActivationEventListener listener )
+ {
+ activation.deregisterActivationEventListener( listener );
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServicesModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServicesModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServicesModel.java
new file mode 100644
index 0000000..5d19cc9
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/service/ImportedServicesModel.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.zest.runtime.service;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.zest.api.service.ServiceReference;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.VisitableHierarchy;
+import org.apache.zest.runtime.structure.ModuleInstance;
+
+/**
+ * JAVADOC
+ */
+public class ImportedServicesModel
+ implements VisitableHierarchy<Object, Object>
+{
+ private List<ImportedServiceModel> importedServiceModels;
+
+ public ImportedServicesModel( List<ImportedServiceModel> importedServiceModels )
+ {
+ this.importedServiceModels = importedServiceModels;
+ }
+
+ public ImportedServicesInstance newInstance( ModuleInstance module )
+ {
+ List<ServiceReference> serviceReferences = new ArrayList<ServiceReference>();
+ for( ImportedServiceModel serviceModel : importedServiceModels )
+ {
+ ImportedServiceReferenceInstance serviceReferenceInstance = new ImportedServiceReferenceInstance( serviceModel, module );
+ serviceReferences.add( serviceReferenceInstance );
+ }
+
+ return new ImportedServicesInstance( this, serviceReferences );
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ if( visitor.visitEnter( this ) )
+ {
+ for( ImportedServiceModel importedServiceModel : importedServiceModels )
+ {
+ if( !importedServiceModel.accept( visitor ) )
+ {
+ break;
+ }
+ }
+ }
+ return visitor.visitLeave( this );
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/service/ServiceInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/service/ServiceInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/service/ServiceInstance.java
new file mode 100644
index 0000000..727b6fd
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/service/ServiceInstance.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.zest.runtime.service;
+
+import java.lang.reflect.Proxy;
+import org.apache.zest.api.activation.Activation;
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.api.activation.PassivationException;
+import org.apache.zest.api.configuration.Configuration;
+import org.apache.zest.api.configuration.Enabled;
+import org.apache.zest.api.service.Availability;
+import org.apache.zest.api.service.ServiceComposite;
+import org.apache.zest.api.util.Classes;
+import org.apache.zest.runtime.composite.TransientInstance;
+import org.apache.zest.runtime.composite.TransientStateInstance;
+import org.apache.zest.runtime.structure.ModuleInstance;
+
+/**
+ * JAVADOC
+ */
+public class ServiceInstance
+ extends TransientInstance
+ implements Activation
+{
+ public static TransientInstance serviceInstanceOf( ServiceComposite composite )
+ {
+ return (TransientInstance) Proxy.getInvocationHandler( composite );
+ }
+
+ private final boolean implementsServiceAvailable;
+ private final boolean hasEnabledConfiguration;
+
+ public ServiceInstance( ServiceModel compositeModel,
+ ModuleInstance moduleInstance,
+ Object[] mixins,
+ TransientStateInstance state
+ )
+ {
+ super( compositeModel, moduleInstance, mixins, state );
+
+ implementsServiceAvailable =
+ Classes.assignableTypeSpecification( Availability.class ).satisfiedBy( descriptor() );
+ hasEnabledConfiguration = compositeModel.configurationType() != null
+ && Enabled.class.isAssignableFrom( compositeModel.configurationType() );
+ }
+
+ @Override
+ public void activate()
+ throws ActivationException
+ {
+ // NOOP
+ }
+
+ @Override
+ public void passivate()
+ throws PassivationException
+ {
+ // NOOP
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public boolean isAvailable()
+ {
+ // Check Enabled in configuration first
+ if( hasEnabledConfiguration && !( (Configuration<Enabled>) proxy() ).get().enabled().get() )
+ {
+ return false;
+ }
+
+ // Ask service if it's available
+ return !implementsServiceAvailable || ( (Availability) proxy() ).isAvailable();
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/service/ServiceModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/service/ServiceModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/service/ServiceModel.java
new file mode 100644
index 0000000..86eaa3f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/service/ServiceModel.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
+ * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zest.runtime.service;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.zest.api.common.MetaInfo;
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.api.configuration.Configuration;
+import org.apache.zest.api.entity.Identity;
+import org.apache.zest.api.injection.scope.This;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.api.service.ServiceDescriptor;
+import org.apache.zest.api.structure.Module;
+import org.apache.zest.api.util.Classes;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.Specifications;
+import org.apache.zest.runtime.activation.ActivatorsInstance;
+import org.apache.zest.runtime.activation.ActivatorsModel;
+import org.apache.zest.runtime.composite.CompositeMethodsModel;
+import org.apache.zest.runtime.composite.CompositeModel;
+import org.apache.zest.runtime.composite.MixinModel;
+import org.apache.zest.runtime.composite.MixinsModel;
+import org.apache.zest.runtime.composite.StateModel;
+import org.apache.zest.runtime.composite.TransientStateInstance;
+import org.apache.zest.runtime.composite.UsesInstance;
+import org.apache.zest.runtime.injection.DependencyModel;
+import org.apache.zest.runtime.injection.InjectionContext;
+import org.apache.zest.runtime.property.PropertyInstance;
+import org.apache.zest.runtime.property.PropertyModel;
+import org.apache.zest.runtime.structure.ModuleInstance;
+
+import static org.apache.zest.functional.Iterables.filter;
+import static org.apache.zest.functional.Specifications.and;
+import static org.apache.zest.functional.Specifications.translate;
+
+/**
+ * JAVADOC
+ */
+public final class ServiceModel extends CompositeModel
+ implements ServiceDescriptor
+{
+ private static Method identityMethod;
+
+ static
+ {
+ try
+ {
+ identityMethod = Identity.class.getMethod( "identity" );
+ }
+ catch( NoSuchMethodException e )
+ {
+ e.printStackTrace();
+ }
+ }
+
+ private final String identity;
+ private final boolean instantiateOnStartup;
+ private final ActivatorsModel<?> activatorsModel;
+ @SuppressWarnings( "raw" )
+ private final Class configurationType;
+
+ public ServiceModel( Iterable<Class<?>> types,
+ Visibility visibility,
+ MetaInfo metaInfo,
+ ActivatorsModel<?> activatorsModel,
+ MixinsModel mixinsModel,
+ StateModel stateModel,
+ CompositeMethodsModel compositeMethodsModel,
+ String identity,
+ boolean instantiateOnStartup
+ )
+ {
+ super( types, visibility, metaInfo, mixinsModel, stateModel, compositeMethodsModel );
+
+ this.identity = identity;
+ this.instantiateOnStartup = instantiateOnStartup;
+ this.activatorsModel = activatorsModel;
+
+ // Calculate configuration type
+ this.configurationType = calculateConfigurationType();
+ }
+
+ @Override
+ public boolean isInstantiateOnStartup()
+ {
+ return instantiateOnStartup;
+ }
+
+ @Override
+ public String identity()
+ {
+ return identity;
+ }
+
+ @SuppressWarnings( {"raw", "unchecked"} )
+ public ActivatorsInstance<?> newActivatorsInstance( Module module ) throws Exception
+ {
+ return new ActivatorsInstance( activatorsModel.newInstances( module ) );
+ }
+
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> Class<T> configurationType()
+ {
+ return configurationType;
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ if( visitor.visitEnter( this ) )
+ {
+ if( activatorsModel.accept( visitor ) )
+ {
+ if( compositeMethodsModel.accept( visitor ) )
+ {
+ if( stateModel.accept( visitor ) )
+ {
+ mixinsModel.accept( visitor );
+ }
+ }
+ }
+ }
+ return visitor.visitLeave( this );
+ }
+
+ public ServiceInstance newInstance( final ModuleInstance module )
+ {
+ Object[] mixins = mixinsModel.newMixinHolder();
+
+ Map<AccessibleObject, Property<?>> properties = new HashMap<>();
+ for( PropertyModel propertyModel : stateModel.properties() )
+ {
+ Object initialValue = propertyModel.initialValue( module );
+ if( propertyModel.accessor().equals( identityMethod ) )
+ {
+ initialValue = identity;
+ }
+
+ Property<?> property = new PropertyInstance<>( propertyModel, initialValue );
+ properties.put( propertyModel.accessor(), property );
+ }
+
+ TransientStateInstance state = new TransientStateInstance( properties );
+ ServiceInstance compositeInstance = new ServiceInstance( this, module, mixins, state );
+
+ // Instantiate all mixins
+ int i = 0;
+ UsesInstance uses = UsesInstance.EMPTY_USES.use( this );
+ InjectionContext injectionContext = new InjectionContext( compositeInstance, uses, state );
+ for( MixinModel mixinModel : mixinsModel.mixinModels() )
+ {
+ mixins[ i++ ] = mixinModel.newInstance( injectionContext );
+ }
+
+ return compositeInstance;
+ }
+
+ @Override
+ public String toString()
+ {
+ return super.toString() + ":" + identity;
+ }
+
+ @SuppressWarnings( { "raw", "unchecked" } )
+ public Class calculateConfigurationType()
+ {
+ Class injectionClass = null;
+ Iterable<DependencyModel> configurationThisDependencies = filter( and( translate( new DependencyModel.InjectionTypeFunction(), Specifications
+ .<Class<?>>in( Configuration.class ) ), new DependencyModel.ScopeSpecification( This.class ) ), dependencies() );
+ for( DependencyModel dependencyModel : configurationThisDependencies )
+ {
+ if( dependencyModel.rawInjectionType()
+ .equals( Configuration.class ) && dependencyModel.injectionType() instanceof ParameterizedType )
+ {
+ Class<?> type = Classes.RAW_CLASS
+ .map( ( (ParameterizedType) dependencyModel.injectionType() ).getActualTypeArguments()[ 0 ] );
+ if( injectionClass == null )
+ {
+ injectionClass = type;
+ }
+ else
+ {
+ if( injectionClass.isAssignableFrom( type ) )
+ {
+ injectionClass = type;
+ }
+ }
+ }
+ }
+ return injectionClass;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/service/ServiceReferenceInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/service/ServiceReferenceInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/service/ServiceReferenceInstance.java
new file mode 100644
index 0000000..6543917
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/service/ServiceReferenceInstance.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
+ * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zest.runtime.service;
+
+import java.lang.reflect.Method;
+import org.apache.zest.api.activation.Activation;
+import org.apache.zest.api.activation.ActivationEventListener;
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.api.activation.PassivationException;
+import org.apache.zest.api.composite.CompositeDescriptor;
+import org.apache.zest.api.composite.CompositeInstance;
+import org.apache.zest.api.property.StateHolder;
+import org.apache.zest.api.service.ServiceDescriptor;
+import org.apache.zest.api.service.ServiceImporterException;
+import org.apache.zest.api.service.ServiceReference;
+import org.apache.zest.api.service.ServiceUnavailableException;
+import org.apache.zest.api.structure.Module;
+import org.apache.zest.runtime.activation.ActivationDelegate;
+import org.apache.zest.runtime.structure.ModuleInstance;
+
+/**
+ * Implementation of ServiceReference.
+ * <p>
+ * This manages the actual instance of the service and implements the service Activation.
+ * </p>
+ * <p>
+ * Whenever the service is requested a proxy is returned which points to this class. This means
+ * that the instance can be passivated even though a client is holding on to a service proxy.
+ * </p>
+ * @param <T> Service Type
+ */
+public final class ServiceReferenceInstance<T>
+ implements ServiceReference<T>, Activation
+{
+ private volatile ServiceInstance instance;
+ private final T serviceProxy;
+ private final ModuleInstance module;
+ private final ServiceModel serviceModel;
+ private final ActivationDelegate activation = new ActivationDelegate( this );
+ private boolean active = false;
+
+ public ServiceReferenceInstance( ServiceModel serviceModel, ModuleInstance module )
+ {
+ this.module = module;
+ this.serviceModel = serviceModel;
+
+ serviceProxy = newProxy();
+ }
+
+ @Override
+ public String identity()
+ {
+ return serviceModel.identity();
+ }
+
+ @Override
+ public Iterable<Class<?>> types()
+ {
+ return serviceModel.types();
+ }
+
+ @Override
+ public <T> T metaInfo( Class<T> infoType )
+ {
+ return serviceModel.metaInfo( infoType );
+ }
+
+ @Override
+ public synchronized T get()
+ {
+ return serviceProxy;
+ }
+
+ @Override
+ public boolean isActive()
+ {
+ return active;
+ }
+
+ @Override
+ public boolean isAvailable()
+ {
+ return getInstance().isAvailable();
+ }
+
+ public Module module()
+ {
+ return module;
+ }
+
+ @Override
+ public void activate()
+ throws ActivationException
+ {
+ if( serviceModel.isInstantiateOnStartup() )
+ {
+ getInstance();
+ }
+ }
+
+ @Override
+ public void passivate()
+ throws PassivationException
+ {
+ if( instance != null )
+ {
+ try {
+ activation.passivate( new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ active = false;
+ }
+ } );
+ } finally {
+ instance = null;
+ active = false;
+ }
+ }
+ }
+
+ private ServiceInstance getInstance()
+ throws ServiceImporterException
+ {
+ // DCL that works with Java 1.5 volatile semantics
+ if( instance == null )
+ {
+ synchronized( this )
+ {
+ if( instance == null )
+ {
+ instance = serviceModel.newInstance( module );
+
+ try
+ {
+ activation.activate( serviceModel.newActivatorsInstance( module ), instance, new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ active = true;
+ }
+ } );
+ }
+ catch( Exception e )
+ {
+ instance = null;
+ throw new ServiceUnavailableException( "Could not activate service " + serviceModel.identity(), e );
+ }
+ }
+ }
+ }
+
+ return instance;
+ }
+
+ @Override
+ public String toString()
+ {
+ return serviceModel.identity() + "(active=" + isActive() + ",module='" + module.name() + "')";
+ }
+
+ @SuppressWarnings( "unchecked" )
+ public T newProxy()
+ {
+ return (T) serviceModel.newProxy( new ServiceReferenceInstance.ServiceInvocationHandler() );
+ }
+
+ public ServiceDescriptor serviceDescriptor()
+ {
+ return serviceModel;
+ }
+
+ public final class ServiceInvocationHandler
+ implements CompositeInstance
+ {
+ @Override
+ @SuppressWarnings( "unchecked" )
+ public <T> T proxy()
+ {
+ return (T) ServiceReferenceInstance.this.get();
+ }
+
+ @Override
+ public <T> T newProxy( Class<T> mixinType )
+ throws IllegalArgumentException
+ {
+ return getInstance().newProxy( mixinType );
+ }
+
+ @Override
+ public <T> T metaInfo( Class<T> infoType )
+ {
+ return ServiceReferenceInstance.this.metaInfo( infoType );
+ }
+
+ @Override
+ public Iterable<Class<?>> types()
+ {
+ return ServiceReferenceInstance.this.types();
+ }
+
+ @Override
+ public CompositeDescriptor descriptor()
+ {
+ return ServiceReferenceInstance.this.serviceDescriptor();
+ }
+
+ @Override
+ public Object invokeComposite( Method method, Object[] args )
+ throws Throwable
+ {
+ return getInstance().invokeComposite( method, args );
+ }
+
+ @Override
+ public StateHolder state()
+ {
+ return getInstance().state();
+ }
+
+ @Override
+ public Object invoke( Object object, Method method, Object[] objects )
+ throws Throwable
+ {
+ if( method.getDeclaringClass().equals( Object.class ) )
+ {
+ switch( method.getName() )
+ {
+ case "toString":
+ return serviceModel.toString();
+ case "equals":
+ return objects[0] == object;
+ case "hashCode":
+ return serviceModel.toString().hashCode();
+ }
+ }
+
+ ServiceInstance instance = getInstance();
+
+/*
+ if (!instance.isAvailable())
+ {
+ throw new ServiceUnavailableException("Service is currently not available");
+ }
+
+*/
+ return instance.invoke( object, method, objects );
+ }
+
+ @Override
+ public String toString()
+ {
+ return serviceModel.toString();
+ }
+
+ @Override
+ public Module module()
+ {
+ return module;
+ }
+ }
+
+ @Override
+ public void registerActivationEventListener( ActivationEventListener listener )
+ {
+ activation.registerActivationEventListener( listener );
+ }
+
+ @Override
+ public void deregisterActivationEventListener( ActivationEventListener listener )
+ {
+ activation.deregisterActivationEventListener( listener );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return identity().hashCode();
+ }
+
+ @Override
+ @SuppressWarnings( "raw" )
+ public boolean equals( Object obj )
+ {
+ if ( obj == null ) {
+ return false;
+ }
+ if ( getClass() != obj.getClass() ) {
+ return false;
+ }
+ final ServiceReference other = ( ServiceReference ) obj;
+ return identity().equals( other.identity() );
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/service/ServicesInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/service/ServicesInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/service/ServicesInstance.java
new file mode 100644
index 0000000..bb03428
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/service/ServicesInstance.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2012, Paul Merlin.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.zest.runtime.service;
+
+import java.util.List;
+import org.apache.zest.api.activation.Activation;
+import org.apache.zest.api.activation.ActivationEventListener;
+import org.apache.zest.api.activation.ActivationEventListenerRegistration;
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.api.activation.PassivationException;
+import org.apache.zest.api.common.Visibility;
+import org.apache.zest.api.service.ServiceReference;
+import org.apache.zest.functional.Iterables;
+import org.apache.zest.functional.Specification;
+import org.apache.zest.runtime.activation.ActivationDelegate;
+import org.apache.zest.runtime.activation.ActivatorsInstance;
+
+import static org.apache.zest.api.util.Classes.instanceOf;
+import static org.apache.zest.functional.Iterables.filter;
+
+/**
+ * JAVADOC
+ */
+public class ServicesInstance
+ implements Activation, ActivationEventListenerRegistration
+{
+ private final ServicesModel servicesModel;
+ private final List<ServiceReference> serviceReferences;
+ private final ActivationDelegate activation = new ActivationDelegate( this, false );
+
+ public ServicesInstance( ServicesModel servicesModel, List<ServiceReference> serviceReferences )
+ {
+ this.servicesModel = servicesModel;
+ this.serviceReferences = serviceReferences;
+ for( ServiceReference serviceReference : serviceReferences )
+ {
+ serviceReference.registerActivationEventListener( activation );
+ }
+ }
+
+ @Override
+ public void activate()
+ throws ActivationException
+ {
+ Iterable<Activation> activatees = Iterables.<Activation>cast( filter( instanceOf( Activation.class ), serviceReferences ) );
+ activation.activate( ActivatorsInstance.EMPTY, activatees );
+ }
+
+ @Override
+ public void passivate()
+ throws PassivationException
+ {
+ activation.passivate();
+ }
+
+ public Iterable<ServiceReference> visibleServices( final Visibility visibility )
+ {
+ return Iterables.filter( new Specification<ServiceReference>()
+ {
+ @Override
+ public boolean satisfiedBy( ServiceReference item )
+ {
+ return ( (ServiceReferenceInstance) item ).serviceDescriptor()
+ .visibility()
+ .ordinal() >= visibility.ordinal();
+ }
+ }, serviceReferences );
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder( "Services{" );
+ String sep = " ";
+ for( ServiceReference serviceReference : serviceReferences )
+ {
+ sb.append( sep ).
+ append( serviceReference.identity() ).
+ append( "(active=" ).append( serviceReference.isActive() ).append( ")" );
+ sep = ", ";
+ }
+ return sb.append( " }" ).toString();
+ }
+
+ @Override
+ public void registerActivationEventListener( ActivationEventListener listener )
+ {
+ activation.registerActivationEventListener( listener );
+ }
+
+ @Override
+ public void deregisterActivationEventListener( ActivationEventListener listener )
+ {
+ activation.deregisterActivationEventListener( listener );
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/service/ServicesModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/service/ServicesModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/service/ServicesModel.java
new file mode 100644
index 0000000..ee8b46e
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/service/ServicesModel.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.zest.runtime.service;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.zest.api.service.ServiceReference;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.functional.VisitableHierarchy;
+import org.apache.zest.runtime.structure.ModuleInstance;
+
+/**
+ * JAVADOC
+ */
+public class ServicesModel
+ implements VisitableHierarchy<Object, Object>
+{
+ private final Iterable<ServiceModel> serviceModels;
+
+ public ServicesModel( Iterable<ServiceModel> serviceModels )
+ {
+ this.serviceModels = serviceModels;
+ }
+
+ public ServicesInstance newInstance( ModuleInstance module )
+ {
+ List<ServiceReference> serviceReferences = new ArrayList<ServiceReference>();
+ for( ServiceModel serviceModel : serviceModels )
+ {
+ ServiceReferenceInstance serviceReferenceInstance = new ServiceReferenceInstance( serviceModel, module );
+ serviceReferences.add( serviceReferenceInstance );
+ }
+
+ return new ServicesInstance( this, serviceReferences );
+ }
+
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ if( visitor.visitEnter( this ) )
+ {
+ for( ServiceModel serviceModel : serviceModels )
+ {
+ if( !serviceModel.accept( visitor ) )
+ {
+ break;
+ }
+ }
+ }
+ return visitor.visitLeave( this );
+ }
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/structure/ApplicationInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/structure/ApplicationInstance.java b/core/runtime/src/main/java/org/apache/zest/runtime/structure/ApplicationInstance.java
new file mode 100644
index 0000000..cd739e0
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/structure/ApplicationInstance.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2008, Niclas Hedhman.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.zest.runtime.structure;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.zest.api.activation.ActivationEventListener;
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.api.activation.PassivationException;
+import org.apache.zest.api.common.MetaInfo;
+import org.apache.zest.api.structure.Application;
+import org.apache.zest.api.structure.ApplicationDescriptor;
+import org.apache.zest.api.structure.Layer;
+import org.apache.zest.api.structure.Module;
+import org.apache.zest.bootstrap.Qi4jRuntime;
+import org.apache.zest.runtime.activation.ActivationDelegate;
+
+/**
+ * Instance of a Zest application. Contains a list of layers which are managed by this application
+ */
+public class ApplicationInstance
+ implements Application
+{
+
+ // Constructor parameters
+ private final ApplicationModel applicationModel;
+ private final Qi4jRuntime runtime;
+ private final MetaInfo instanceMetaInfo;
+ // Eager instance objects
+ private final ActivationDelegate activation;
+ private final List<LayerInstance> layerInstances;
+
+ public ApplicationInstance( ApplicationModel model, Qi4jRuntime runtime, MetaInfo instanceMetaInfo )
+ {
+ // Constructor parameters
+ this.applicationModel = model;
+ this.runtime = runtime;
+ this.instanceMetaInfo = instanceMetaInfo;
+
+ // Eager instance objects
+ activation = new ActivationDelegate( this );
+ layerInstances = new ArrayList<>();
+ }
+
+ @Override
+ public String toString()
+ {
+ return name();
+ }
+
+ // Implementation of Application
+ @Override
+ public String name()
+ {
+ return applicationModel.name();
+ }
+
+ @Override
+ public String version()
+ {
+ return applicationModel.version();
+ }
+
+ @Override
+ public Mode mode()
+ {
+ return applicationModel.mode();
+ }
+
+ @Override
+ public Layer findLayer( String layerName )
+ {
+ for( LayerInstance layerInstance : layerInstances )
+ {
+ if( layerInstance.model().name().equals( layerName ) )
+ {
+ return layerInstance;
+ }
+ }
+
+ throw new IllegalArgumentException( "No such layer:" + layerName );
+ }
+
+ @Override
+ public Module findModule( String layerName, String moduleName )
+ {
+ for( LayerInstance layerInstance : layerInstances )
+ {
+ if( layerInstance.model().name().equals( layerName ) )
+ {
+ return layerInstance.findModule( moduleName );
+ }
+ }
+
+ throw new IllegalArgumentException( "No such layer:" + layerName );
+ }
+
+ @Override
+ public ApplicationDescriptor descriptor()
+ {
+ return applicationModel;
+ }
+
+ // Implementation of MetaInfoHolder
+ @Override
+ public <T> T metaInfo( Class<T> infoType )
+ {
+ return instanceMetaInfo.get( infoType );
+ }
+
+ // Implementation of Activation
+ @Override
+ public void activate()
+ throws ActivationException
+ {
+ activation.activate( applicationModel.newActivatorsInstance(), layerInstances );
+ }
+
+ @Override
+ public void passivate()
+ throws PassivationException
+ {
+ activation.passivate();
+ }
+
+ @Override
+ public void registerActivationEventListener( ActivationEventListener listener )
+ {
+ activation.registerActivationEventListener( listener );
+ }
+
+ @Override
+ public void deregisterActivationEventListener( ActivationEventListener listener )
+ {
+ activation.deregisterActivationEventListener( listener );
+ }
+
+ // Other methods
+ /* package */ void addLayer( LayerInstance layer )
+ {
+ layer.registerActivationEventListener( activation );
+ layerInstances.add( layer );
+ }
+
+ public Qi4jRuntime runtime()
+ {
+ return runtime;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zest-java/blob/8744a67f/core/runtime/src/main/java/org/apache/zest/runtime/structure/ApplicationModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/structure/ApplicationModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/structure/ApplicationModel.java
new file mode 100644
index 0000000..a5e9d5b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/structure/ApplicationModel.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2008-2011, Rickard Öberg. All Rights Reserved.
+ * Copyright (c) 2008-2013, Niclas Hedhman. All Rights Reserved.
+ * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.zest.runtime.structure;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.zest.api.Qi4j;
+import org.apache.zest.api.activation.ActivationException;
+import org.apache.zest.api.common.InvalidApplicationException;
+import org.apache.zest.api.common.MetaInfo;
+import org.apache.zest.api.structure.Application;
+import org.apache.zest.api.structure.ApplicationDescriptor;
+import org.apache.zest.bootstrap.Qi4jRuntime;
+import org.apache.zest.functional.HierarchicalVisitor;
+import org.apache.zest.runtime.activation.ActivatorsInstance;
+import org.apache.zest.runtime.activation.ActivatorsModel;
+import org.apache.zest.runtime.injection.InjectionProviderFactory;
+import org.apache.zest.runtime.injection.provider.InjectionProviderFactoryStrategy;
+
+/**
+ * JAVADOC
+ */
+public final class ApplicationModel
+ implements ApplicationDescriptor
+{
+ private final String name;
+ private final String version;
+ private final Application.Mode mode;
+ private final MetaInfo metaInfo;
+ private final ActivatorsModel<Application> activatorsModel;
+ private final List<LayerModel> layers;
+ private final InjectionProviderFactory ipf;
+
+ public ApplicationModel( String name,
+ String version,
+ Application.Mode mode,
+ MetaInfo metaInfo,
+ ActivatorsModel<Application> activatorsModel,
+ List<LayerModel> layers
+ )
+ {
+ this.name = name;
+ this.version = version;
+ this.mode = mode;
+ this.metaInfo = metaInfo;
+ this.activatorsModel = activatorsModel;
+ this.layers = layers;
+ ipf = new InjectionProviderFactoryStrategy( metaInfo );
+ }
+
+ @Override
+ public String name()
+ {
+ return name;
+ }
+
+ public String version()
+ {
+ return version;
+ }
+
+ public Application.Mode mode()
+ {
+ return mode;
+ }
+
+ public MetaInfo metaInfo()
+ {
+ return metaInfo;
+ }
+
+ public ActivatorsInstance<Application> newActivatorsInstance()
+ throws ActivationException
+ {
+ return new ActivatorsInstance<>( activatorsModel.newInstances() );
+ }
+
+ // SPI
+ @Override
+ public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> visitor )
+ throws ThrowableType
+ {
+ if( visitor.visitEnter( this ) )
+ {
+ if( activatorsModel.accept( visitor ) )
+ {
+ for( LayerModel layer : layers )
+ {
+ if( !layer.accept( visitor ) )
+ {
+ break;
+ }
+ }
+ }
+ }
+ return visitor.visitLeave( this );
+ }
+
+ @Override
+ public ApplicationInstance newInstance( Qi4j runtime, Object... importedServiceInstances )
+ throws InvalidApplicationException
+ {
+ MetaInfo instanceMetaInfo = new MetaInfo( metaInfo );
+ for( Object importedServiceInstance : importedServiceInstances )
+ {
+ instanceMetaInfo.set( importedServiceInstance );
+ }
+
+ ApplicationInstance applicationInstance = new ApplicationInstance( this, (Qi4jRuntime) runtime, instanceMetaInfo );
+
+ // Create layer instances
+ Map<LayerModel, LayerInstance> layerInstanceMap = new HashMap<>();
+ Map<LayerModel, List<LayerInstance>> usedLayers = new HashMap<>();
+ for( LayerModel layer : layers )
+ {
+ List<LayerInstance> usedLayerInstances = new ArrayList<>();
+ usedLayers.put( layer, usedLayerInstances );
+ UsedLayersInstance usedLayersInstance = layer.usedLayers().newInstance( usedLayerInstances );
+ LayerInstance layerInstance = layer.newInstance( applicationInstance, usedLayersInstance );
+ applicationInstance.addLayer( layerInstance );
+ layerInstanceMap.put( layer, layerInstance );
+ }
+
+ // Resolve used layer instances
+ for( LayerModel layer : layers )
+ {
+ List<LayerInstance> usedLayerInstances = usedLayers.get( layer );
+ for( LayerModel usedLayer : layer.usedLayers().layers() )
+ {
+ LayerInstance layerInstance = layerInstanceMap.get( usedLayer );
+ if( layerInstance == null )
+ {
+ throw new InvalidApplicationException( "Could not find used layer:" + usedLayer.name() );
+ }
+ usedLayerInstances.add( layerInstance );
+ }
+ }
+
+ return applicationInstance;
+ }
+
+ public InjectionProviderFactory injectionProviderFactory()
+ {
+ return ipf;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder();
+ sb.append( "ApplicationModel" );
+ sb.append( "{name='" ).append( name ).append( '\'' );
+ sb.append( ", version='" ).append( version ).append( '\'' );
+ sb.append( ", mode=" ).append( mode );
+ sb.append( '}' );
+ return sb.toString();
+ }
+}