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:44 UTC

[08/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/property/PropertyModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyModel.java
new file mode 100644
index 0000000..6aa5041
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/property/PropertyModel.java
@@ -0,0 +1,338 @@
+/*
+ *  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.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.QualifiedName;
+import org.apache.polygene.api.constraint.ConstraintViolation;
+import org.apache.polygene.api.constraint.ConstraintViolationException;
+import org.apache.polygene.api.entity.Queryable;
+import org.apache.polygene.api.property.DefaultValues;
+import org.apache.polygene.api.property.GenericPropertyInfo;
+import org.apache.polygene.api.property.InvalidPropertyTypeException;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.service.NoSuchServiceException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.type.Serialization;
+import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.type.ValueType;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.value.MissingValueSerializationException;
+import org.apache.polygene.api.value.ValueDeserializer;
+import org.apache.polygene.api.util.Visitable;
+import org.apache.polygene.api.util.Visitor;
+import org.apache.polygene.bootstrap.BindingException;
+import org.apache.polygene.runtime.composite.ValueConstraintsInstance;
+import org.apache.polygene.runtime.model.Binder;
+import org.apache.polygene.runtime.model.Resolution;
+import org.apache.polygene.runtime.types.ValueTypeFactory;
+
+/**
+ * Model for a Property.
+ *
+ * <p>Equality is based on the Property accessor object (property type and name), not on the QualifiedName.</p>
+ */
+public class PropertyModel
+    implements PropertyDescriptor, PropertyInfo, Binder, Visitable<PropertyModel>
+{
+    private Type type;
+
+    private transient AccessibleObject accessor; // Interface accessor
+
+    private final QualifiedName qualifiedName;
+
+    private final ValueConstraintsInstance constraints; // May be null
+
+    protected final MetaInfo metaInfo;
+
+    private final Object initialValue;
+
+    private final boolean useDefaults;
+
+    private final boolean immutable;
+
+    private ValueType valueType;
+
+    protected PropertyInfo builderInfo;
+
+    private final boolean queryable;
+
+    public PropertyModel( AccessibleObject accessor,
+                          boolean immutable,
+                          boolean useDefaults,
+                          ValueConstraintsInstance constraints,
+                          MetaInfo metaInfo,
+                          Object initialValue
+    )
+    {
+        if( accessor instanceof Method )
+        {
+            Method m = (Method) accessor;
+            if( !m.getReturnType().equals( Property.class ) )
+            {
+                throw new InvalidPropertyTypeException( accessor );
+            }
+        }
+        this.immutable = immutable;
+        this.metaInfo = metaInfo;
+        type = GenericPropertyInfo.propertyTypeOf( accessor );
+        this.accessor = accessor;
+        qualifiedName = QualifiedName.fromAccessor( accessor );
+
+        this.useDefaults = useDefaults;
+
+        this.initialValue = initialValue;
+
+        this.constraints = constraints;
+
+        final Queryable queryable = accessor.getAnnotation( Queryable.class );
+        this.queryable = queryable == null || queryable.value();
+    }
+
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    public String name()
+    {
+        return qualifiedName.name();
+    }
+
+    @Override
+    public QualifiedName qualifiedName()
+    {
+        return qualifiedName;
+    }
+
+    @Override
+    public Type type()
+    {
+        return type;
+    }
+
+    @Override
+    public AccessibleObject accessor()
+    {
+        return accessor;
+    }
+
+    @Override
+    public ValueType valueType()
+    {
+        return valueType;
+    }
+
+    @Override
+    public boolean isImmutable()
+    {
+        return immutable;
+    }
+
+    public PropertyInfo getBuilderInfo()
+    {
+        return builderInfo;
+    }
+
+    @Override
+    public boolean queryable()
+    {
+        return queryable;
+    }
+
+    @Override
+    public Object initialValue( ModuleDescriptor module )
+    {
+        // Use supplied value from assembly
+        Object value = initialValue;
+
+        // Check for @UseDefaults annotation
+        if( useDefaults )
+        {
+            if( value == null || ( ( value instanceof String ) && ( (String) value ).length() == 0 ) )
+            {
+                if( valueType instanceof ValueCompositeType )
+                {
+                    Class<?> propertyType = valueType().types().findFirst().orElse( null );
+                    value = module.instance().newValue( propertyType );
+                }
+                else
+                {
+                    value = DefaultValues.getDefaultValueOf( type );
+                }
+            }
+            else
+            {
+                Class<?> propertyType = valueType().types().findFirst().orElse( null );
+                if( value instanceof String && !propertyType.equals( String.class ) )
+                {
+                    try
+                    {
+                        // here we could possibly deserialize json to other types...
+                        ValueDeserializer deserializer = module.instance()
+                            .serviceFinder()
+                            .findService( ValueDeserializer.class )
+                            .get();
+                        if( deserializer != null )
+                        {
+                            value = deserializer.deserialize( module, propertyType ).apply( (String) value );
+                        }
+                    }
+                    catch( NoSuchServiceException e )
+                    {
+                        throw new MissingValueSerializationException( "@UseDefaults with initialization value requires that there is a visible ValueDeserializer service available.", e);
+                    }
+                }
+            }
+        }
+        return value;
+    }
+
+    @Override
+    public void bind( Resolution resolution )
+        throws BindingException
+    {
+        ValueTypeFactory factory = ValueTypeFactory.instance();
+        Class<?> declaringClass = ( (Member) accessor() ).getDeclaringClass();
+        Class<?> mainType = resolution.model().types().findFirst().orElse( null );
+        Serialization.Variant variant = findVariant();
+        valueType = factory.newValueType( type(), declaringClass, mainType, resolution.layer(), resolution.module(), variant );
+        builderInfo = new BuilderPropertyInfo();
+        if( type instanceof TypeVariable )
+        {
+            type = Classes.resolveTypeVariable( (TypeVariable) type, declaringClass, mainType );
+        }
+    }
+
+    private Serialization.Variant findVariant()
+    {
+        Serialization serialization = metaInfo.get( Serialization.class );
+        Serialization.Variant variant = null;
+        if( serialization != null )
+        {
+            variant = serialization.value();
+        }
+        if( variant == null )
+        {
+            variant = Serialization.Variant.entry;
+        }
+        return variant;
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( Visitor<? super PropertyModel, ThrowableType> visitor )
+        throws ThrowableType
+    {
+        return visitor.visit( this );
+    }
+
+    @Override
+    public void checkConstraints( Object value )
+        throws ConstraintViolationException
+    {
+        if( constraints == null )
+        {
+            return;
+        }
+        constraints.checkConstraints( value, accessor );
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if( this == o )
+        {
+            return true;
+        }
+        if( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        PropertyModel that = (PropertyModel) o;
+        return accessor.equals( that.accessor );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return accessor.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+        if( accessor instanceof Field )
+        {
+            return ( (Field) accessor ).toGenericString();
+        }
+        else
+        {
+            return ( (Method) accessor ).toGenericString();
+        }
+    }
+
+    private class BuilderPropertyInfo implements PropertyInfo
+    {
+        @Override
+        public boolean isImmutable()
+        {
+            return false;
+        }
+
+        @Override
+        public QualifiedName qualifiedName()
+        {
+            return qualifiedName;
+        }
+
+        @Override
+        public Type type()
+        {
+            return type;
+        }
+
+        @Override
+        public void checkConstraints( Object value )
+            throws ConstraintViolationException
+        {
+            if( constraints != null )
+            {
+                List<ConstraintViolation> violations = constraints.checkConstraints( value );
+                if( !violations.isEmpty() )
+                {
+                    Stream<Class<?>> empty = Stream.empty();
+                    throw new ConstraintViolationException( "", empty, (Member) accessor, violations );
+                }
+            }
+        }
+    }
+}
\ 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/query/IterableQuerySource.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/query/IterableQuerySource.java b/core/runtime/src/main/java/org/apache/polygene/runtime/query/IterableQuerySource.java
new file mode 100644
index 0000000..b12ba18
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/query/IterableQuerySource.java
@@ -0,0 +1,245 @@
+/*
+ *  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.query;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.spi.query.QuerySource;
+
+import static java.util.stream.Collectors.toList;
+import static org.apache.polygene.api.util.Classes.instanceOf;
+
+/**
+ * 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,
+                       Predicate<Composite> whereClause,
+                       List<OrderBy> orderBySegments,
+                       Integer firstResult,
+                       Integer maxResults,
+                       Map<String, Object> variables
+    )
+    {
+        return stream( resultType, whereClause, orderBySegments, firstResult, maxResults, variables )
+            .findFirst().orElse( null );
+    }
+
+    @Override
+    public <T> long count( Class<T> resultType,
+                           Predicate<Composite> whereClause,
+                           List<OrderBy> orderBySegments,
+                           Integer firstResult,
+                           Integer maxResults,
+                           Map<String, Object> variables
+    )
+    {
+        return list( resultType, whereClause, orderBySegments, firstResult, maxResults, variables ).size();
+    }
+
+    @Override
+    public <T> Stream<T> stream( Class<T> resultType,
+                                     Predicate<Composite> whereClause,
+                                     List<OrderBy> orderBySegments,
+                                     Integer firstResult,
+                                     Integer maxResults,
+                                     Map<String, Object> variables
+    )
+    {
+        return list( resultType, whereClause, orderBySegments, firstResult, maxResults, variables ).stream();
+    }
+
+    @SuppressWarnings( {"raw", "unchecked"} )
+    private <T> List<T> list( Class<T> resultType,
+                              Predicate<Composite> whereClause,
+                              List<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
+            list.sort( 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, Predicate whereClause )
+    {
+        Stream stream = StreamSupport.stream( iterable.spliterator(), false );
+        if( whereClause == null )
+        {
+            return List.class.cast( stream.filter( resultType::isInstance )
+                                          .collect( toList() ) );
+        }
+        else
+        {
+            return List.class.cast( stream.filter( instanceOf( resultType ).and( whereClause ) )
+                                          .collect( toList() ) );
+        }
+    }
+
+    @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().apply( o1 );
+                    final Property prop2 = orderBySegment.property().apply( 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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryBuilderFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryBuilderFactoryImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryBuilderFactoryImpl.java
new file mode 100644
index 0000000..2cf716b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryBuilderFactoryImpl.java
@@ -0,0 +1,69 @@
+/*
+ *  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.query;
+
+import org.apache.polygene.api.query.NotQueryableException;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryBuilderFactory;
+import org.apache.polygene.api.service.NoSuchServiceException;
+import org.apache.polygene.api.service.ServiceFinder;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.util.NullArgumentException;
+import org.apache.polygene.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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryBuilderImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryBuilderImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryBuilderImpl.java
new file mode 100644
index 0000000..7d5cb4b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryBuilderImpl.java
@@ -0,0 +1,96 @@
+/*
+ *  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.query;
+
+import java.util.function.Predicate;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.query.QueryExpressions;
+import org.apache.polygene.spi.query.EntityFinder;
+import org.apache.polygene.spi.query.QueryBuilderSPI;
+import org.apache.polygene.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 Predicate<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 Predicate<Composite> whereClause
+    )
+    {
+        this.entityFinder = entityFinder;
+        this.resultType = resultType;
+        this.whereClause = whereClause;
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public QueryBuilder<T> where( Predicate<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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryImpl.java
new file mode 100644
index 0000000..d4d768c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/query/QueryImpl.java
@@ -0,0 +1,220 @@
+/*
+ *  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.query;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryExecutionException;
+import org.apache.polygene.api.query.QueryExpressions;
+import org.apache.polygene.api.query.grammar.OrderBy;
+import org.apache.polygene.spi.query.QuerySource;
+
+/**
+ * Default implementation of {@link org.apache.polygene.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 Predicate<Composite> whereClause;
+    private QuerySource querySource;
+    /**
+     * Order by clause segments.
+     */
+    private List<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 Predicate<Composite> whereClause,
+               final QuerySource querySource
+    )
+    {
+        this.resultType = resultType;
+        this.whereClause = whereClause;
+        this.querySource = querySource;
+    }
+
+    /**
+     * @see org.apache.polygene.api.query.Query#orderBy(org.apache.polygene.api.query.grammar.OrderBy[])
+     */
+    @Override
+    public Query<T> orderBy( final OrderBy... segments )
+    {
+        orderBySegments = Arrays.asList( segments );
+        return this;
+    }
+
+    /**
+     * @see org.apache.polygene.api.query.Query#orderBy(org.apache.polygene.api.property.Property, org.apache.polygene.api.query.grammar.OrderBy.Order)
+     */
+    @Override
+    public Query<T> orderBy( Property<?> property, OrderBy.Order order )
+    {
+        if( orderBySegments == null )
+        {
+            orderBySegments = new ArrayList<>();
+        }
+        orderBySegments.add( new OrderBy( QueryExpressions.property( property ), order ) );
+        return this;
+    }
+
+    /**
+     * @see org.apache.polygene.api.query.Query#orderBy(org.apache.polygene.api.property.Property)
+     */
+    @Override
+    public Query<T> orderBy( Property<?> property )
+    {
+        orderBy( property, OrderBy.Order.ASCENDING );
+        return this;
+    }
+
+    /**
+     * @see org.apache.polygene.api.query.Query#firstResult(int)
+     */
+    @Override
+    public Query<T> firstResult( int firstResult )
+    {
+        this.firstResult = firstResult;
+        return this;
+    }
+
+    /**
+     * @see org.apache.polygene.api.query.Query#maxResults(int)
+     */
+    @Override
+    public Query<T> maxResults( int maxResults )
+    {
+        this.maxResults = maxResults;
+        return this;
+    }
+
+    /**
+     * @see org.apache.polygene.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.polygene.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 stream().iterator();
+    }
+
+    @Override
+    public Stream<T> stream()
+    {
+        return querySource.stream( 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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceInstance.java
new file mode 100644
index 0000000..104938f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceInstance.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.service;
+
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceModel.java
new file mode 100644
index 0000000..174735f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceModel.java
@@ -0,0 +1,197 @@
+/*
+ *  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.service;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceImporter;
+import org.apache.polygene.api.service.ServiceImporterException;
+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.activation.ActivatorsInstance;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+
+/**
+ * JAVADOC
+ */
+public final class ImportedServiceModel
+    implements ImportedServiceDescriptor, VisitableHierarchy<Object, Object>
+{
+    private final ModuleDescriptor module;
+    private final Class<?> type;
+    private final Visibility visibility;
+    @SuppressWarnings( "raw" )
+    private final Class<? extends ServiceImporter> serviceImporter;
+    private final Identity identity;
+    private final boolean importOnStartup;
+    private final MetaInfo metaInfo;
+    private final ActivatorsModel<?> activatorsModel;
+    private final String moduleName;
+
+    @SuppressWarnings( "raw" )
+    public ImportedServiceModel( ModuleDescriptor module,
+                                 Class serviceType,
+                                 Visibility visibility,
+                                 Class<? extends ServiceImporter> serviceImporter,
+                                 Identity identity,
+                                 boolean importOnStartup,
+                                 MetaInfo metaInfo,
+                                 ActivatorsModel<?> activatorsModel,
+                                 String moduleName
+    )
+    {
+        this.module = module;
+        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 Stream<Class<?>> types()
+    {
+        return Stream.of( type );
+    }
+
+    @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
+    @SuppressWarnings( "raw" )
+    public Class<? extends ServiceImporter> serviceImporter()
+    {
+        return serviceImporter;
+    }
+
+    @Override
+    public Class<?> type()
+    {
+        return type;
+    }
+
+    @Override
+    public Identity identity()
+    {
+        return identity;
+    }
+
+    public String moduleName()
+    {
+        return moduleName;
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    public ActivatorsInstance<?> newActivatorsInstance( ModuleDescriptor 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( ModuleDescriptor module )
+    {
+        try
+        {
+            ServiceImporter importer = module.instance().newObject( serviceImporter );
+            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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceReferenceInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceReferenceInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceReferenceInstance.java
new file mode 100644
index 0000000..328e26b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServiceReferenceInstance.java
@@ -0,0 +1,221 @@
+/*
+ *  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.service;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationEventListener;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.service.ServiceUnavailableException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.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 ModuleDescriptor module;
+    private final ImportedServiceModel serviceModel;
+    private final ActivationDelegate activation = new ActivationDelegate( this );
+    private boolean active = false;
+
+    public ImportedServiceReferenceInstance( ImportedServiceModel serviceModel, ModuleDescriptor module )
+    {
+        this.module = module;
+        this.serviceModel = serviceModel;
+    }
+
+    @Override
+    public Identity identity()
+    {
+        return serviceModel.identity();
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return serviceModel.types();
+    }
+
+    @Override
+    public <M> M metaInfo( Class<M> 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( () -> 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;
+        }
+    }
+
+    @Override
+    public ModelDescriptor model()
+    {
+        return serviceModel;
+    }
+
+    public ModuleDescriptor 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, () -> {
+                                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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServicesInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServicesInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServicesInstance.java
new file mode 100644
index 0000000..61a15c9
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServicesInstance.java
@@ -0,0 +1,128 @@
+/*
+ *  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.service;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationEventListener;
+import org.apache.polygene.api.activation.ActivationEventListenerRegistration;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.runtime.activation.ActivationDelegate;
+import org.apache.polygene.runtime.activation.ActivatorsInstance;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * 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 );
+        }
+    }
+
+    public Stream<ImportedServiceModel> models()
+    {
+        return servicesModel.models();
+    }
+
+    @Override
+    public void activate()
+        throws ActivationException
+    {
+        Iterable<Activation> activatees = serviceReferences.stream().filter( Activation.class::isInstance )
+                                                           .map( Activation.class::cast )
+                                                           .collect( toList() );
+        activation.activate( ActivatorsInstance.EMPTY, activatees );
+    }
+
+    @Override
+    public void passivate()
+        throws PassivationException
+    {
+        activation.passivate();
+    }
+
+    public Stream<ServiceReference<?>> visibleServices( final Visibility visibility )
+    {
+        return serviceReferences.stream()
+            .filter( item ->
+                         ( (ImportedServiceReferenceInstance) item ).serviceDescriptor()
+                             .visibility()
+                             .ordinal() >= visibility.ordinal()
+            );
+    }
+
+    @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 );
+    }
+
+    public Stream<? extends ImportedServiceDescriptor> stream()
+    {
+        return servicesModel.models();
+    }
+
+    public Stream<ServiceReference<?>> references()
+    {
+        return serviceReferences.stream();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServicesModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServicesModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServicesModel.java
new file mode 100644
index 0000000..af34755
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ImportedServicesModel.java
@@ -0,0 +1,77 @@
+/*
+ *  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.service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public class ImportedServicesModel
+    implements VisitableHierarchy<Object, Object>
+{
+    private List<ImportedServiceModel> importedServiceModels;
+
+    public ImportedServicesModel( List<ImportedServiceModel> importedServiceModels )
+    {
+        this.importedServiceModels = importedServiceModels;
+    }
+
+    public ImportedServicesInstance newInstance( ModuleDescriptor module )
+    {
+        List<ServiceReference<?>> serviceReferences = new ArrayList<>();
+        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 );
+    }
+
+    public Stream<ImportedServiceModel> models()
+    {
+        return importedServiceModels.stream();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceInstance.java
new file mode 100644
index 0000000..da40e1f
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceInstance.java
@@ -0,0 +1,89 @@
+/*
+ *  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.service;
+
+import java.lang.reflect.Proxy;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.configuration.Enabled;
+import org.apache.polygene.api.service.Availability;
+import org.apache.polygene.api.service.ServiceComposite;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.runtime.composite.TransientInstance;
+import org.apache.polygene.runtime.composite.TransientStateInstance;
+
+/**
+ * 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,
+                            Object[] mixins,
+                            TransientStateInstance state
+    )
+    {
+        super( compositeModel, mixins, state );
+
+        implementsServiceAvailable =
+            Classes.assignableTypeSpecification( Availability.class ).test( 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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceModel.java
new file mode 100644
index 0000000..abbe40b
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceModel.java
@@ -0,0 +1,192 @@
+/*
+ *  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.service;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.ParameterizedType;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.configuration.Configuration;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.injection.scope.This;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.runtime.activation.ActivatorsInstance;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+import org.apache.polygene.runtime.composite.CompositeMethodsModel;
+import org.apache.polygene.runtime.composite.CompositeModel;
+import org.apache.polygene.runtime.composite.MixinModel;
+import org.apache.polygene.runtime.composite.MixinsModel;
+import org.apache.polygene.runtime.composite.StateModel;
+import org.apache.polygene.runtime.composite.TransientStateInstance;
+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.property.PropertyInstance;
+
+/**
+ * JAVADOC
+ */
+public final class ServiceModel extends CompositeModel
+    implements ServiceDescriptor
+{
+    private final Identity identity;
+    private final boolean instantiateOnStartup;
+    private final ActivatorsModel<?> activatorsModel;
+    private final Class configurationType;
+
+    public ServiceModel( ModuleDescriptor module,
+                         List<Class<?>> types,
+                         Visibility visibility,
+                         MetaInfo metaInfo,
+                         ActivatorsModel<?> activatorsModel,
+                         MixinsModel mixinsModel,
+                         StateModel stateModel,
+                         CompositeMethodsModel compositeMethodsModel,
+                         Identity identity,
+                         boolean instantiateOnStartup
+    )
+    {
+        super( module, 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 Identity identity()
+    {
+        return identity;
+    }
+
+    @SuppressWarnings( { "raw", "unchecked" } )
+    public ActivatorsInstance<?> newActivatorsInstance( ModuleDescriptor 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 ModuleDescriptor module )
+    {
+        Object[] mixins = mixinsModel.newMixinHolder();
+
+        Map<AccessibleObject, Property<?>> properties = new HashMap<>();
+        stateModel.properties().forEach( propertyModel -> {
+            Object initialValue = propertyModel.initialValue( module );
+            if( propertyModel.accessor().equals( HasIdentity.IDENTITY_METHOD ) )
+            {
+                initialValue = identity;
+            }
+
+            Property<?> property = new PropertyInstance<>( propertyModel, initialValue );
+            properties.put( propertyModel.accessor(), property );
+        } );
+
+        TransientStateInstance state = new TransientStateInstance( properties );
+        ServiceInstance compositeInstance = new ServiceInstance( this, 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()
+    {
+        DependencyModel.ScopeSpecification thisSpec = new DependencyModel.ScopeSpecification( This.class );
+        Predicate<DependencyModel> configurationCheck = item -> item.rawInjectionType().equals( Configuration.class );
+        return dependencies().filter( thisSpec.and( configurationCheck ) )
+            .filter( dependencyModel -> dependencyModel.rawInjectionType().equals( Configuration.class ) )
+            .filter( dependencyModel -> dependencyModel.injectionType() instanceof ParameterizedType )
+            .map( dependencyModel -> Classes.RAW_CLASS.apply( ( (ParameterizedType) dependencyModel.injectionType() ).getActualTypeArguments()[ 0 ] ) )
+            .reduce( null, ( injectionClass, type ) -> {
+                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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceReferenceInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceReferenceInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceReferenceInstance.java
new file mode 100644
index 0000000..e6e53bd
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServiceReferenceInstance.java
@@ -0,0 +1,323 @@
+/*
+ *  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.service;
+
+import java.lang.reflect.Method;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationEventListener;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.property.StateHolder;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceImporterException;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.service.ServiceUnavailableException;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.runtime.activation.ActivationDelegate;
+
+/**
+ * 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, ModelDescriptor
+{
+    private volatile ServiceInstance instance;
+    private final T serviceProxy;
+    private final ModuleDescriptor module;
+    private final ServiceModel serviceModel;
+    private final ActivationDelegate activation = new ActivationDelegate( this );
+    private boolean active = false;
+
+    ServiceReferenceInstance( ServiceModel serviceModel, ModuleDescriptor module )
+    {
+        this.module = module;
+        this.serviceModel = serviceModel;
+
+        serviceProxy = newProxy();
+    }
+
+    @Override
+    public Identity identity()
+    {
+        return serviceModel.identity();
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return serviceModel.types();
+    }
+
+    @Override
+    public <M> M metaInfo( Class<M> 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();
+    }
+
+    @Override
+    public ModelDescriptor model()
+    {
+        return serviceModel;
+    }
+
+    public ModuleDescriptor 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( () -> 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,
+                                             () -> 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;
+    }
+
+    @Override
+    public Visibility visibility()
+    {
+        return serviceModel.visibility();
+    }
+
+    @Override
+    public boolean isAssignableTo( Class<?> type )
+    {
+        return serviceModel.isAssignableTo( type );
+    }
+
+    public final class ServiceInvocationHandler
+        implements CompositeInstance
+    {
+        @Override
+        @SuppressWarnings( "unchecked" )
+        public <P> P proxy()
+        {
+            return (P) ServiceReferenceInstance.this.get();
+        }
+
+        @Override
+        public <P> P newProxy( Class<P> mixinType )
+            throws IllegalArgumentException
+        {
+            return getInstance().newProxy( mixinType );
+        }
+
+        @Override
+        public <M> M metaInfo( Class<M> infoType )
+        {
+            return ServiceReferenceInstance.this.metaInfo( infoType );
+        }
+
+        @Override
+        public Stream<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 ModuleDescriptor 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/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServicesInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServicesInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServicesInstance.java
new file mode 100644
index 0000000..c40a74a
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServicesInstance.java
@@ -0,0 +1,122 @@
+/*
+ *  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.service;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.Activation;
+import org.apache.polygene.api.activation.ActivationEventListener;
+import org.apache.polygene.api.activation.ActivationEventListenerRegistration;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.activation.PassivationException;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.runtime.activation.ActivationDelegate;
+import org.apache.polygene.runtime.activation.ActivatorsInstance;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * 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 );
+        }
+    }
+
+    public Stream<? extends ServiceDescriptor> models()
+    {
+        return servicesModel.models();
+    }
+
+    @Override
+    public void activate()
+        throws ActivationException
+    {
+        Iterable<Activation> activatees = serviceReferences.stream().filter( Activation.class::isInstance )
+                                                           .map( Activation.class::cast )
+                                                           .collect( toList() );
+        activation.activate( ActivatorsInstance.EMPTY, activatees );
+    }
+
+    @Override
+    public void passivate()
+        throws PassivationException
+    {
+        activation.passivate();
+    }
+
+    public Stream<ServiceReference<?>> visibleServices( final Visibility visibility )
+    {
+        return serviceReferences.stream()
+            .filter( item -> ( (ServiceReferenceInstance) item ).serviceDescriptor()
+                                 .visibility().ordinal() >= visibility.ordinal() );
+    }
+
+    @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 );
+    }
+
+    public Stream<? extends ServiceDescriptor> descriptors()
+    {
+        return servicesModel.models();
+    }
+
+    public Stream<ServiceReference<?>> references()
+    {
+        return serviceReferences.stream();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServicesModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServicesModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServicesModel.java
new file mode 100644
index 0000000..ebdf64c
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/service/ServicesModel.java
@@ -0,0 +1,90 @@
+/*
+ *  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.service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.service.ServiceReference;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+
+/**
+ * JAVADOC
+ */
+public class ServicesModel
+    implements VisitableHierarchy<Object, Object>
+{
+    private final List<ServiceModel> serviceModels;
+
+    public ServicesModel( List<ServiceModel> serviceModels )
+    {
+        this.serviceModels = serviceModels;
+    }
+
+    public ServicesInstance newInstance( ModuleDescriptor module )
+    {
+        List<ServiceReference<?>> serviceReferences = new ArrayList<>();
+        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 );
+    }
+
+    public Stream<? extends ServiceDescriptor> models()
+    {
+        return serviceModels.stream();
+    }
+
+    public boolean contains( Class<?> type )
+    {
+        for( ServiceModel model : serviceModels )
+        {
+            if( model.hasType( type ) )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+}