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

[07/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/structure/ApplicationInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ApplicationInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ApplicationInstance.java
new file mode 100644
index 0000000..e27a0af
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ApplicationInstance.java
@@ -0,0 +1,174 @@
+/*
+ *  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.structure;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+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.MetaInfo;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.bootstrap.PolygeneRuntime;
+import org.apache.polygene.runtime.activation.ActivationDelegate;
+
+/**
+ * Instance of a Polygene 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 PolygeneRuntime runtime;
+    private final MetaInfo instanceMetaInfo;
+    // Eager instance objects
+    private final ActivationDelegate activation;
+    private final List<LayerInstance> layerInstances;
+
+    public ApplicationInstance( ApplicationModel model, PolygeneRuntime 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 Stream<? extends Layer> layers()
+    {
+        return layerInstances.stream();
+    }
+
+    @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
+    void addLayer( LayerInstance layer )
+    {
+        layer.registerActivationEventListener( activation );
+        layerInstances.add( layer );
+    }
+
+    public PolygeneRuntime runtime()
+    {
+        return runtime;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ApplicationModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ApplicationModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ApplicationModel.java
new file mode 100644
index 0000000..a163bed
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ApplicationModel.java
@@ -0,0 +1,178 @@
+/*
+ *  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.structure;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.polygene.api.PolygeneAPI;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.InvalidApplicationException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.structure.Application;
+import org.apache.polygene.api.structure.ApplicationDescriptor;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.bootstrap.PolygeneRuntime;
+import org.apache.polygene.runtime.activation.ActivatorsInstance;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+import org.apache.polygene.runtime.injection.InjectionProviderFactory;
+import org.apache.polygene.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( PolygeneAPI runtime, Object... importedServiceInstances )
+        throws InvalidApplicationException
+    {
+        MetaInfo instanceMetaInfo = new MetaInfo( metaInfo );
+        for( Object importedServiceInstance : importedServiceInstances )
+        {
+            instanceMetaInfo.set( importedServiceInstance );
+        }
+
+        ApplicationInstance applicationInstance = new ApplicationInstance( this, (PolygeneRuntime) runtime, instanceMetaInfo );
+
+        // Create layer instances
+        Map<LayerDescriptor, LayerDescriptor> layerInstanceMap = new HashMap<>();
+        Map<LayerDescriptor, List<LayerDescriptor>> usedLayers = new HashMap<>();
+        for( LayerModel layer : layers )
+        {
+            List<LayerDescriptor> usedLayerInstances = new ArrayList<>();
+            usedLayers.put( layer, usedLayerInstances );
+            UsedLayersInstance usedLayersInstance = layer.usedLayers().newInstance( usedLayerInstances );
+            LayerInstance layerInstance = layer.newInstance( applicationInstance );
+            applicationInstance.addLayer( layerInstance );
+            layerInstanceMap.put( layer, layerInstance.descriptor() );
+        }
+
+        // Resolve used layer instances
+        for( LayerModel layer : layers )
+        {
+            List<LayerDescriptor> usedLayerInstances = usedLayers.get( layer );
+            layer.usedLayers().layers().forEach(
+                usedLayer ->
+                {
+                    LayerDescriptor layerDescriptor = layerInstanceMap.get( usedLayer );
+                    if( layerDescriptor == null )
+                    {
+                        throw new InvalidApplicationException( "Could not find used layer:" + usedLayer
+                            .name() );
+                    }
+                    usedLayerInstances.add( layerDescriptor );
+                } );
+        }
+
+        return applicationInstance;
+    }
+
+    public InjectionProviderFactory injectionProviderFactory()
+    {
+        return ipf;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "ApplicationModel" +
+               "{name='" + name + '\'' +
+               ", version='" + version + '\'' +
+               ", mode=" + mode +
+               '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/structure/LayerInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/LayerInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/LayerInstance.java
new file mode 100644
index 0000000..09201fb
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/LayerInstance.java
@@ -0,0 +1,150 @@
+/*
+ *  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.structure;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+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.structure.Application;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.runtime.activation.ActivationDelegate;
+
+/**
+ * Instance of a Polygene application layer. Contains a list of modules which are managed by this layer.
+ */
+public class LayerInstance
+    implements Layer
+{
+
+    // Constructor parameters
+    private final LayerModel layerModel;
+    private final ApplicationInstance applicationInstance;
+
+    // Eager instance objects
+    private final ActivationDelegate activation;
+    private final List<ModuleInstance> moduleInstances;
+
+    public LayerInstance( LayerModel model,
+                          ApplicationInstance applicationInstance
+    )
+    {
+        // Constructor parameters
+        this.layerModel = model;
+        this.applicationInstance = applicationInstance;
+
+        // Eager instance objects
+        activation = new ActivationDelegate( this );
+        moduleInstances = new ArrayList<>();
+    }
+
+    @Override
+    public String toString()
+    {
+        return layerModel.toString();
+    }
+
+    // Implementation of Layer
+    @Override
+    public String name()
+    {
+        return layerModel.name();
+    }
+
+    @Override
+    public Application application()
+    {
+        return applicationInstance;
+    }
+
+    // Implementation of MetaInfoHolder
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return layerModel.metaInfo( infoType );
+    }
+
+    // Implementation of Activation
+    @Override
+    public void activate()
+        throws ActivationException
+    {
+        activation.activate( layerModel.newActivatorsInstance(), moduleInstances );
+    }
+
+    @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 );
+    }
+
+    @Override
+    public Stream<? extends Module> modules()
+    {
+        return moduleInstances.stream();
+    }
+
+    @Override
+    public LayerDescriptor descriptor()
+    {
+        return layerModel;
+    }
+
+    void addModule( ModuleInstance module )
+    {
+        module.registerActivationEventListener( activation );
+        moduleInstances.add( module );
+    }
+
+    public LayerModel model()
+    {
+        return layerModel;
+    }
+
+    /* package */ ModuleInstance findModule( String moduleName )
+    {
+        for( ModuleInstance moduleInstance : moduleInstances )
+        {
+            if( moduleInstance.model().name().equals( moduleName ) )
+            {
+                return moduleInstance;
+            }
+        }
+
+        throw new IllegalArgumentException( "No such module:" + moduleName );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/structure/LayerModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/LayerModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/LayerModel.java
new file mode 100644
index 0000000..04ca846
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/LayerModel.java
@@ -0,0 +1,170 @@
+/*
+ *  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.structure;
+
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.structure.Layer;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.activation.ActivatorsInstance;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+
+/**
+ * JAVADOC
+ */
+public final class LayerModel
+    implements LayerDescriptor, VisitableHierarchy<Object, Object>
+{
+    // Model
+    private final String name;
+    private final MetaInfo metaInfo;
+    private final UsedLayersModel usedLayersModel;
+    private final ActivatorsModel<Layer> activatorsModel;
+    private final List<ModuleModel> modules;
+    private LayerInstance layerInstance;
+
+    public LayerModel( String name,
+                       MetaInfo metaInfo,
+                       UsedLayersModel usedLayersModel,
+                       ActivatorsModel<Layer> activatorsModel,
+                       List<ModuleModel> modules
+    )
+    {
+        this.name = name;
+        this.metaInfo = metaInfo;
+        this.usedLayersModel = usedLayersModel;
+        this.activatorsModel = activatorsModel;
+        this.modules = modules;
+    }
+
+    @Override
+    public String name()
+    {
+        return name;
+    }
+
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    public Iterable<ModuleModel> modules()
+    {
+        return modules;
+    }
+
+    @Override
+    public UsedLayersModel usedLayers()
+    {
+        return usedLayersModel;
+    }
+
+    public ActivatorsInstance<Layer> newActivatorsInstance()
+        throws ActivationException
+    {
+        return new ActivatorsInstance<>( activatorsModel.newInstances() );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            if( activatorsModel.accept( modelVisitor ) )
+            {
+                for( ModuleModel module : modules )
+                {
+                    if( !module.accept( modelVisitor ) )
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+
+    @Override
+    public Layer instance()
+    {
+        return layerInstance;
+    }
+
+    public LayerInstance newInstance( ApplicationInstance applicationInstance )
+    {
+        layerInstance = new LayerInstance( this, applicationInstance );
+        for( ModuleModel module : modules )
+        {
+            ModuleInstance moduleInstance = module.newInstance( this );
+            layerInstance.addModule( moduleInstance );
+        }
+        return layerInstance;
+    }
+
+    @Override
+    public Stream<? extends ObjectDescriptor> visibleObjects( final Visibility visibility )
+    {
+        return modules.stream().flatMap( module -> module.visibleObjects( visibility ) );
+    }
+
+    @Override
+    public Stream<? extends TransientDescriptor> visibleTransients( final Visibility visibility )
+    {
+        return modules.stream().flatMap( module -> module.visibleTransients( visibility ) );
+    }
+
+    @Override
+    public Stream<? extends EntityDescriptor> visibleEntities( final Visibility visibility )
+    {
+        return modules.stream().flatMap( module -> module.visibleEntities( visibility ) );
+    }
+
+    /* package */
+    @Override
+    public Stream<? extends ValueDescriptor> visibleValues( final Visibility visibility )
+    {
+        return modules.stream().flatMap( module -> module.visibleValues( visibility ) );
+    }
+
+    /* package */
+    @Override
+    public Stream<? extends ModelDescriptor> visibleServices( final Visibility visibility )
+    {
+        return modules.stream().flatMap( module -> module.visibleServices( visibility ) );
+    }
+
+
+    @Override
+    public String toString()
+    {
+        return name;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleClassLoader.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleClassLoader.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleClassLoader.java
new file mode 100644
index 0000000..65873f1
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleClassLoader.java
@@ -0,0 +1,182 @@
+/*
+ *  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.structure;
+
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.AmbiguousTypeException;
+import org.apache.polygene.api.composite.ModelDescriptor;
+
+import static java.util.stream.Stream.concat;
+import static org.apache.polygene.api.common.Visibility.application;
+import static org.apache.polygene.api.common.Visibility.module;
+import static org.apache.polygene.api.util.Classes.modelTypeSpecification;
+
+// Module ClassLoader
+class ModuleClassLoader
+    extends ClassLoader
+{
+
+    private final ModuleModel moduleModel;
+    private final ConcurrentHashMap<String, Class<?>> classes = new ConcurrentHashMap<>();
+
+    ModuleClassLoader( ModuleModel moduleModel, ClassLoader classLoader )
+    {
+        super( classLoader );
+        this.moduleModel = moduleModel;
+    }
+
+    @Override
+    protected Class<?> findClass( String className )
+        throws ClassNotFoundException
+    {
+        try
+        {
+            Class<?> resultingClass = classes.computeIfAbsent( className, name ->
+            {
+                Predicate<ModelDescriptor> modelTypeSpecification = modelTypeSpecification( name );
+                Stream<? extends ModelDescriptor> moduleModels = concat(
+                    moduleModel.visibleObjects( Visibility.module ),
+                    concat(
+                        moduleModel.visibleEntities( Visibility.module ),
+                        concat(
+                            moduleModel.visibleTransients( Visibility.module ),
+                            moduleModel.visibleValues( Visibility.module )
+                        )
+                    )
+                ).filter( modelTypeSpecification );
+
+                Class<?> clazz = null;
+                Iterator<? extends ModelDescriptor> iterator = moduleModels.iterator();
+                if( iterator.hasNext() )
+                {
+                    clazz = iterator.next().types().findFirst().orElse( null );
+
+                    if( iterator.hasNext() )
+                    {
+                        // Ambiguous exception
+                        new AmbiguousTypeException(
+                            "More than one model matches the classname " + name + ":" + iterator.next()
+                        );
+                    }
+                }
+
+                // Check layer
+                if( clazz == null )
+                {
+                    Stream<? extends ModelDescriptor> modelsInLayer1 = concat(
+                        moduleModel.layer().visibleObjects( Visibility.layer ),
+                        concat(
+                            moduleModel.layer().visibleEntities( Visibility.layer ),
+                            concat(
+                                moduleModel.layer().visibleTransients( Visibility.layer ),
+                                moduleModel.layer().visibleValues( Visibility.layer )
+                            )
+                        )
+                    );
+                    // TODO: What does this actually represents?? Shouldn't 'application' visible models already be handed back from lasyerInstance().visibleXyz() ??
+                    Stream<? extends ModelDescriptor> modelsInLayer2 = concat(
+                        moduleModel.layer().visibleObjects( Visibility.application ),
+                        concat(
+                            moduleModel.layer().visibleEntities( Visibility.application ),
+                            concat(
+                                moduleModel.layer().visibleTransients( Visibility.application ),
+                                moduleModel.layer().visibleValues( Visibility.application )
+                            )
+                        )
+                    );
+                    Stream<? extends ModelDescriptor> layerModels = concat(
+                        modelsInLayer1,
+                        modelsInLayer2
+                    ).filter( modelTypeSpecification );
+
+                    Iterator<? extends ModelDescriptor> layerModelsIter = layerModels.iterator();
+                    if( layerModelsIter.hasNext() )
+                    {
+                        clazz = layerModelsIter.next().types().findFirst().orElse( null );
+
+                        if( layerModelsIter.hasNext() )
+                        {
+                            // Ambiguous exception
+                            new AmbiguousTypeException(
+                                "More than one model matches the classname " + name + ":" + layerModelsIter.next()
+                            );
+                        }
+                    }
+                }
+
+                // Check used layers
+                if( clazz == null )
+                {
+                    Stream<? extends ModelDescriptor> usedLayersModels = concat(
+                        moduleModel.layer()
+                            .usedLayers()
+                            .layers()
+                            .flatMap( layer -> layer.visibleObjects( module ) ),
+                        concat(
+                            moduleModel.layer()
+                                .usedLayers()
+                                .layers()
+                                .flatMap( layer -> layer.visibleEntities( Visibility.layer ) ),
+                            concat(
+                                moduleModel.layer()
+                                    .usedLayers()
+                                    .layers()
+                                    .flatMap( layer -> layer.visibleTransients( application ) ),
+                                moduleModel.layer()
+                                    .usedLayers()
+                                    .layers()
+                                    .flatMap( layer -> layer.visibleValues( application ) )
+                            )
+                        )
+                    ).filter( modelTypeSpecification );
+
+                    Iterator<? extends ModelDescriptor> usedLayersModelsIter = usedLayersModels.iterator();
+                    if( usedLayersModelsIter.hasNext() )
+                    {
+                        clazz = usedLayersModelsIter.next().types().findFirst().orElse( null );
+
+                        if( usedLayersModelsIter.hasNext() )
+                        {
+                            // Ambiguous exception
+                            new AmbiguousTypeException(
+                                "More than one model matches the classname " + name + ":" + usedLayersModelsIter.next()
+                            );
+                        }
+                    }
+                }
+                return clazz;
+            } );
+            if( resultingClass == null )
+            {
+                throw new ClassNotFoundException();
+            }
+            return resultingClass;
+        }
+        catch( AmbiguousTypeException e )
+        {
+            throw new ClassNotFoundException( className, e );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleInstance.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleInstance.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleInstance.java
new file mode 100644
index 0000000..4eb9ac1
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleInstance.java
@@ -0,0 +1,606 @@
+/*
+ *  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.structure;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Function;
+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.association.AssociationDescriptor;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.composite.NoSuchTransientException;
+import org.apache.polygene.api.composite.TransientBuilder;
+import org.apache.polygene.api.composite.TransientBuilderFactory;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.IdentityGenerator;
+import org.apache.polygene.api.metrics.MetricsProvider;
+import org.apache.polygene.api.object.NoSuchObjectException;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.object.ObjectFactory;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.property.PropertyDescriptor;
+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.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.structure.TypeLookup;
+import org.apache.polygene.api.type.HasTypes;
+import org.apache.polygene.api.unitofwork.UnitOfWorkException;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.util.NullArgumentException;
+import org.apache.polygene.api.value.NoSuchValueException;
+import org.apache.polygene.api.value.ValueBuilder;
+import org.apache.polygene.api.value.ValueBuilderFactory;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.api.value.ValueSerialization;
+import org.apache.polygene.api.value.ValueSerializationException;
+import org.apache.polygene.runtime.activation.ActivationDelegate;
+import org.apache.polygene.runtime.composite.FunctionStateResolver;
+import org.apache.polygene.runtime.composite.StateResolver;
+import org.apache.polygene.runtime.composite.TransientBuilderInstance;
+import org.apache.polygene.runtime.composite.TransientStateInstance;
+import org.apache.polygene.runtime.composite.UsesInstance;
+import org.apache.polygene.runtime.injection.InjectionContext;
+import org.apache.polygene.runtime.object.ObjectModel;
+import org.apache.polygene.runtime.property.PropertyInstance;
+import org.apache.polygene.runtime.property.PropertyModel;
+import org.apache.polygene.runtime.query.QueryBuilderFactoryImpl;
+import org.apache.polygene.runtime.service.ImportedServicesInstance;
+import org.apache.polygene.runtime.service.ImportedServicesModel;
+import org.apache.polygene.runtime.service.ServicesInstance;
+import org.apache.polygene.runtime.service.ServicesModel;
+import org.apache.polygene.runtime.value.ValueBuilderInstance;
+import org.apache.polygene.runtime.value.ValueBuilderWithPrototype;
+import org.apache.polygene.runtime.value.ValueBuilderWithState;
+import org.apache.polygene.runtime.value.ValueInstance;
+import org.apache.polygene.spi.entitystore.EntityStore;
+import org.apache.polygene.spi.metrics.MetricsProviderAdapter;
+import org.apache.polygene.spi.module.ModuleSpi;
+
+import static java.util.Arrays.asList;
+import static java.util.stream.Stream.concat;
+
+/**
+ * Instance of a Polygene Module. Contains the various composites for this Module.
+ */
+public class ModuleInstance
+    implements Module, ModuleSpi, Activation
+{
+    // Constructor parameters
+    private final ModuleModel model;
+    private final LayerDescriptor layer;
+    private final TypeLookup typeLookup;
+    private final ServicesInstance services;
+    private final ImportedServicesInstance importedServices;
+    // Eager instance objects
+    private final ActivationDelegate activation;
+    private final QueryBuilderFactory queryBuilderFactory;
+    // Lazy assigned on accessors
+    private EntityStore store;
+    private IdentityGenerator generator;
+    private ValueSerialization valueSerialization;
+    private MetricsProvider metrics;
+    private UnitOfWorkFactory uowf;
+
+    @SuppressWarnings( "LeakingThisInConstructor" )
+    public ModuleInstance( ModuleModel moduleModel, LayerDescriptor layer, TypeLookup typeLookup,
+                           ServicesModel servicesModel, ImportedServicesModel importedServicesModel
+    )
+    {
+        // Constructor parameters
+        model = moduleModel;
+        this.layer = layer;
+        this.typeLookup = typeLookup;
+        services = servicesModel.newInstance( moduleModel );
+        importedServices = importedServicesModel.newInstance( moduleModel );
+
+        // Eager instance objects
+        activation = new ActivationDelegate( this );
+        queryBuilderFactory = new QueryBuilderFactoryImpl( this );
+
+        // Activation
+        services.registerActivationEventListener( activation );
+        importedServices.registerActivationEventListener( activation );
+    }
+
+    @Override
+    public String toString()
+    {
+        return model.toString();
+    }
+
+    @Override
+    public ModuleDescriptor descriptor()
+    {
+        return model;
+    }
+
+    // Implementation of Module
+    @Override
+    public String name()
+    {
+        return model.name();
+    }
+
+    // Implementation of MetaInfoHolder
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return model.metaInfo( infoType );
+    }
+
+    // Implementation of ObjectFactory
+    @Override
+    public <T> T newObject( Class<T> mixinType, Object... uses )
+        throws NoSuchObjectException
+    {
+        NullArgumentException.validateNotNull( "mixinType", mixinType );
+        ObjectDescriptor model = typeLookup.lookupObjectModel( mixinType );
+
+        if( model == null )
+        {
+            throw new NoSuchObjectException( mixinType.getName(), name(),
+                                             typeLookup.allObjects().flatMap( HasTypes::types ) );
+        }
+
+        InjectionContext injectionContext = new InjectionContext( model.module(), UsesInstance.EMPTY_USES.use( uses ) );
+        return mixinType.cast( ( (ObjectModel) model ).newInstance( injectionContext ) );
+    }
+
+    @Override
+    public void injectTo( Object instance, Object... uses )
+        throws ConstructionException
+    {
+        NullArgumentException.validateNotNull( "instance", instance );
+        ObjectDescriptor model = typeLookup.lookupObjectModel( instance.getClass() );
+
+        if( model == null )
+        {
+            throw new NoSuchObjectException( instance.getClass().getName(), name(),
+                                             typeLookup.allObjects().flatMap( HasTypes::types ) );
+        }
+
+        InjectionContext injectionContext = new InjectionContext( model.module(), UsesInstance.EMPTY_USES.use( uses ) );
+        ( (ObjectModel) model ).inject( injectionContext, instance );
+    }
+
+    // Implementation of TransientBuilderFactory
+    @Override
+    public <T> TransientBuilder<T> newTransientBuilder( Class<T> mixinType )
+        throws NoSuchTransientException
+    {
+        NullArgumentException.validateNotNull( "mixinType", mixinType );
+        TransientDescriptor model = typeLookup.lookupTransientModel( mixinType );
+
+        if( model == null )
+        {
+            throw new NoSuchTransientException( mixinType.getName(), name(), typeLookup );
+        }
+
+        Map<AccessibleObject, Property<?>> properties = new HashMap<>();
+        model.state().properties().forEach(
+            propertyModel ->
+            {
+                Property<?> property = new PropertyInstance<>( ( (PropertyModel) propertyModel ).getBuilderInfo(),
+                                                               propertyModel.initialValue( model.module() ) );
+                properties.put( propertyModel.accessor(), property );
+            } );
+
+        TransientStateInstance state = new TransientStateInstance( properties );
+
+        return new TransientBuilderInstance<>( model, state, UsesInstance.EMPTY_USES );
+    }
+
+    @Override
+    public <T> T newTransient( final Class<T> mixinType, Object... uses )
+        throws NoSuchTransientException, ConstructionException
+    {
+        return newTransientBuilder( mixinType ).use( uses ).newInstance();
+    }
+
+    // Implementation of ValueBuilderFactory
+    @Override
+    public <T> T newValue( Class<T> mixinType )
+        throws NoSuchValueException, ConstructionException
+    {
+        return newValueBuilder( mixinType ).newInstance();
+    }
+
+    @Override
+    public <T> ValueBuilder<T> newValueBuilder( Class<T> mixinType )
+        throws NoSuchValueException
+    {
+        NullArgumentException.validateNotNull( "mixinType", mixinType );
+        ValueDescriptor compositeModelModule = typeLookup.lookupValueModel( mixinType );
+
+        if( compositeModelModule == null )
+        {
+            throw new NoSuchValueException( mixinType.getName(), name(), typeLookup );
+        }
+
+        StateResolver stateResolver = new InitialStateResolver( compositeModelModule.module() );
+        return new ValueBuilderInstance<>( compositeModelModule, this, stateResolver );
+    }
+
+    @Override
+    public <T> ValueBuilder<T> newValueBuilderWithState( Class<T> mixinType,
+                                                         Function<PropertyDescriptor, Object> propertyFunction,
+                                                         Function<AssociationDescriptor, EntityReference> associationFunction,
+                                                         Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction,
+                                                         Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction
+    )
+    {
+        NullArgumentException.validateNotNull( "propertyFunction", propertyFunction );
+        NullArgumentException.validateNotNull( "associationFunction", associationFunction );
+        NullArgumentException.validateNotNull( "manyAssociationFunction", manyAssociationFunction );
+        NullArgumentException.validateNotNull( "namedAssociationFunction", namedAssociationFunction );
+
+        ValueDescriptor compositeModelModule = typeLookup.lookupValueModel( mixinType );
+
+        if( compositeModelModule == null )
+        {
+            throw new NoSuchValueException( mixinType.getName(), name(), typeLookup );
+        }
+
+        StateResolver stateResolver = new FunctionStateResolver(
+            propertyFunction, associationFunction, manyAssociationFunction, namedAssociationFunction
+        );
+        return new ValueBuilderWithState<>( compositeModelModule, this, stateResolver );
+    }
+
+    private static class InitialStateResolver
+        implements StateResolver
+    {
+        private final ModuleDescriptor module;
+
+        private InitialStateResolver( ModuleDescriptor module )
+        {
+            this.module = module;
+        }
+
+        @Override
+        public Object getPropertyState( PropertyDescriptor propertyDescriptor )
+        {
+            return propertyDescriptor.initialValue( module );
+        }
+
+        @Override
+        public EntityReference getAssociationState( AssociationDescriptor associationDescriptor )
+        {
+            return null;
+        }
+
+        @Override
+        public Stream<EntityReference> getManyAssociationState( AssociationDescriptor associationDescriptor )
+        {
+            return new ArrayList<EntityReference>().stream();
+        }
+
+        @Override
+        public Stream<Map.Entry<String, EntityReference>> getNamedAssociationState( AssociationDescriptor associationDescriptor )
+        {
+            return new HashMap<String, EntityReference>().entrySet().stream();
+        }
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T> ValueBuilder<T> newValueBuilderWithPrototype( T prototype )
+    {
+        NullArgumentException.validateNotNull( "prototype", prototype );
+
+        ValueInstance valueInstance = ValueInstance.valueInstanceOf( (ValueComposite) prototype );
+        Class<Composite> valueType = (Class<Composite>) valueInstance.types().findFirst().orElse( null );
+
+        ValueDescriptor model = typeLookup.lookupValueModel( valueType );
+
+        if( model == null )
+        {
+            throw new NoSuchValueException( valueType.getName(), name(), typeLookup );
+        }
+
+        return new ValueBuilderWithPrototype<>( model, this, prototype );
+    }
+
+    @Override
+    public <T> T newValueFromSerializedState( Class<T> mixinType, String serializedState )
+        throws NoSuchValueException, ConstructionException
+    {
+        NullArgumentException.validateNotNull( "mixinType", mixinType );
+        ValueDescriptor model = typeLookup.lookupValueModel( mixinType );
+
+        if( model == null )
+        {
+            throw new NoSuchValueException( mixinType.getName(), name(), typeLookup );
+        }
+
+        try
+        {
+            return valueSerialization().deserialize( model.module(), model.valueType(), serializedState );
+        }
+        catch( ValueSerializationException ex )
+        {
+            throw new ConstructionException( "Could not create value from serialized state", ex );
+        }
+    }
+
+    // Implementation of QueryBuilderFactory
+    @Override
+    public <T> QueryBuilder<T> newQueryBuilder( final Class<T> resultType )
+    {
+        return queryBuilderFactory.newQueryBuilder( resultType );
+    }
+
+    @Override
+    public <T> ServiceReference<T> findService( Class<T> serviceType )
+        throws NoSuchServiceException
+    {
+        return findService( (Type) serviceType );
+    }
+
+    @Override
+    public <T> ServiceReference<T> findService( Type serviceType )
+    {
+        ModelDescriptor serviceModel = typeLookup.lookupServiceModel( serviceType );
+        if( serviceModel == null )
+        {
+            throw new NoSuchServiceException( serviceType.getTypeName(), name(),typeLookup );
+        }
+        return findServiceReferenceInstance( serviceModel );
+    }
+
+    @Override
+    public <T> Stream<ServiceReference<T>> findServices( final Class<T> serviceType )
+    {
+        return findServices( (Type) serviceType );
+    }
+
+    @Override
+    public <T> Stream<ServiceReference<T>> findServices( final Type serviceType )
+    {
+        List<? extends ModelDescriptor> serviceModels = typeLookup.lookupServiceModels( serviceType );
+        if( serviceModels == null )
+        {
+            return Stream.empty();
+        }
+        //noinspection unchecked
+        return serviceModels.stream()
+                            .map( this::findServiceReferenceInstance )
+                            .filter( Objects::nonNull )
+                            .filter( ref -> ref.hasType( serviceType ) )
+                            .map( ref -> (ServiceReference<T>) ref );
+    }
+
+    private <T> ServiceReference<T> findServiceReferenceInstance( ModelDescriptor model )
+    {
+        ModuleInstance moduleInstanceOfModel = (ModuleInstance) model.module().instance();
+        Optional<ServiceReference<?>> candidate =
+            concat( moduleInstanceOfModel.services.references(), moduleInstanceOfModel.importedServices.references() )
+                .filter( ref -> ref.model().equals( model ) )
+                .findAny();
+        if( candidate.isPresent() )
+        {
+            ServiceReference<?> serviceReference = candidate.get();
+            return (ServiceReference<T>) serviceReference;
+        }
+        return null;
+    }
+
+    // Implementation of Activation
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public void activate()
+        throws ActivationException
+    {
+        activation.activate( model.newActivatorsInstance(), asList( services, importedServices ) );
+    }
+
+    @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
+    ModuleModel model()
+    {
+        return model;
+    }
+
+    public LayerDescriptor layer()
+    {
+        return layer;
+    }
+
+    @Override
+    public TypeLookup typeLookup()
+    {
+        return typeLookup;
+    }
+
+    public EntityStore entityStore()
+    {
+        synchronized( this )
+        {
+            if( store == null )
+            {
+                try
+                {
+                    ServiceReference<EntityStore> service = findService( EntityStore.class );
+                    store = service.get();
+                }
+                catch( NoSuchServiceException e )
+                {
+                    throw new UnitOfWorkException( "No EntityStore service available in module " + name() );
+                }
+            }
+        }
+        return store;
+    }
+
+    public UnitOfWorkFactory unitOfWorkFactory()
+    {
+        synchronized( this )
+        {
+            if( uowf == null )
+            {
+                try
+                {
+                    ServiceReference<UnitOfWorkFactory> service = findService( UnitOfWorkFactory.class );
+                    uowf = service.get();
+                }
+                catch( NoSuchServiceException e )
+                {
+                    throw new UnitOfWorkException( "No UnitOfWorkFactory service available in module " + name() );
+                }
+            }
+        }
+        return uowf;
+    }
+
+    @Override
+    public ServiceFinder serviceFinder()
+    {
+        return this;
+    }
+
+    @Override
+    public ValueBuilderFactory valueBuilderFactory()
+    {
+        return this;
+    }
+
+    @Override
+    public TransientBuilderFactory transientBuilderFactory()
+    {
+        return this;
+    }
+
+    @Override
+    public ObjectFactory objectFactory()
+    {
+        return this;
+    }
+
+    public IdentityGenerator identityGenerator()
+    {
+        synchronized( this )
+        {
+            if( generator == null )
+            {
+                ServiceReference<IdentityGenerator> service = findService( IdentityGenerator.class );
+                generator = service.get();
+            }
+            return generator;
+        }
+    }
+
+    public ValueSerialization valueSerialization()
+    {
+        synchronized( this )
+        {
+            if( valueSerialization == null )
+            {
+                try
+                {
+                    ServiceReference<ValueSerialization> service = findService( ValueSerialization.class );
+                    valueSerialization = service.get();
+                }
+                catch( NoSuchServiceException e )
+                {
+                    throw new ValueSerializationException( "No ValueSeriaservice available in module " + name() );
+                }
+            }
+        }
+        return valueSerialization;
+    }
+
+    public MetricsProvider metricsProvider()
+    {
+        synchronized( this )
+        {
+            if( metrics == null )
+            {
+                try
+                {
+                    ServiceReference<MetricsProvider> service = findService( MetricsProvider.class );
+                    metrics = service.get();
+                }
+                catch( NoSuchServiceException e )
+                {
+                    metrics = new MetricsProviderAdapter();
+                }
+            }
+        }
+        return metrics;
+    }
+
+//    public Stream<ServiceReference<?>> visibleServices( Visibility visibility )
+//    {
+//        return concat( services.visibleServices( visibility ),
+//                       importedServices.visibleServices( visibility ) );
+//    }
+//
+//
+//
+//    public Stream<ServiceReference<?>> findVisibleServiceTypes()
+//    {
+//        return concat( visibleServices( Visibility.module ),
+//                       concat(
+//                           layer().visibleServices( Visibility.layer ),
+//                           concat(
+//                               layer().visibleServices( Visibility.application ),
+//                               layer().usedLayers().layers().flatMap( layer -> layer.visibleServices(Visibility.application) )
+//                           )
+//                       )
+//        );
+//    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleModel.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleModel.java
new file mode 100644
index 0000000..f83a2cd
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/ModuleModel.java
@@ -0,0 +1,394 @@
+/*
+ *  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.structure;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.activation.ActivationException;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.service.ImportedServiceDescriptor;
+import org.apache.polygene.api.service.ServiceDescriptor;
+import org.apache.polygene.api.structure.LayerDescriptor;
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.structure.TypeLookup;
+import org.apache.polygene.api.util.HierarchicalVisitor;
+import org.apache.polygene.api.util.VisitableHierarchy;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.runtime.activation.ActivatorsInstance;
+import org.apache.polygene.runtime.activation.ActivatorsModel;
+import org.apache.polygene.runtime.composite.TransientsModel;
+import org.apache.polygene.runtime.entity.EntitiesModel;
+import org.apache.polygene.runtime.object.ObjectsModel;
+import org.apache.polygene.runtime.service.ImportedServicesModel;
+import org.apache.polygene.runtime.service.ServicesModel;
+import org.apache.polygene.runtime.value.ValuesModel;
+
+import static java.util.stream.Stream.concat;
+import static org.apache.polygene.api.common.Visibility.application;
+import static org.apache.polygene.api.common.Visibility.layer;
+import static org.apache.polygene.api.common.Visibility.module;
+
+/**
+ * JAVADOC
+ */
+public class ModuleModel
+    implements ModuleDescriptor, VisitableHierarchy<Object, Object>
+{
+    private final LayerDescriptor layerModel;
+    private final ActivatorsModel<Module> activatorsModel;
+    private final TransientsModel transientsModel;
+    private final EntitiesModel entitiesModel;
+    private final ObjectsModel objectsModel;
+    private final ValuesModel valuesModel;
+    private final ServicesModel servicesModel;
+    private final ImportedServicesModel importedServicesModel;
+    private final TypeLookupImpl typeLookup;
+    private final ClassLoader classLoader;
+
+    private final String name;
+    private final MetaInfo metaInfo;
+    private ModuleInstance moduleInstance;
+
+    public ModuleModel( String name,
+                        MetaInfo metaInfo,
+                        LayerDescriptor layerModel,
+                        ActivatorsModel<Module> activatorsModel,
+                        TransientsModel transientsModel,
+                        EntitiesModel entitiesModel,
+                        ObjectsModel objectsModel,
+                        ValuesModel valuesModel,
+                        ServicesModel servicesModel,
+                        ImportedServicesModel importedServicesModel
+    )
+    {
+        this.name = name;
+        this.metaInfo = metaInfo;
+        this.layerModel = layerModel;
+        this.activatorsModel = activatorsModel;
+        this.transientsModel = transientsModel;
+        this.entitiesModel = entitiesModel;
+        this.objectsModel = objectsModel;
+        this.valuesModel = valuesModel;
+        this.servicesModel = servicesModel;
+        this.importedServicesModel = importedServicesModel;
+        typeLookup = new TypeLookupImpl( this );
+        classLoader = new ModuleClassLoader( this, Thread.currentThread().getContextClassLoader() );
+    }
+
+    @Override
+    public String name()
+    {
+        return name;
+    }
+
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    @Override
+    public LayerDescriptor layer()
+    {
+        return layerModel;
+    }
+
+    @Override
+    public ClassLoader classLoader()
+    {
+        return classLoader;
+    }
+
+    public ActivatorsInstance<Module> newActivatorsInstance()
+        throws ActivationException
+    {
+        return new ActivatorsInstance<>( activatorsModel.newInstances() );
+    }
+
+    @Override
+    public EntityDescriptor entityDescriptor( String name )
+    {
+        try
+        {
+            Class<?> type = classLoader().loadClass( name );
+            EntityDescriptor entityModel = typeLookup.lookupEntityModel( type );
+            if( entityModel == null )
+            {
+                return null;
+            }
+            return entityModel;
+        }
+        catch( ClassNotFoundException e )
+        {
+            return null;
+        }
+    }
+
+    @Override
+    public ObjectDescriptor objectDescriptor( String typeName )
+    {
+        try
+        {
+            Class<?> type = classLoader().loadClass( typeName );
+            ObjectDescriptor objectModel = typeLookup.lookupObjectModel( type );
+            if( objectModel == null )
+            {
+                return null;
+            }
+            return objectModel;
+        }
+        catch( ClassNotFoundException e )
+        {
+            return null;
+        }
+    }
+
+    @Override
+    public TransientDescriptor transientDescriptor( String name )
+    {
+        try
+        {
+            Class<?> type = classLoader().loadClass( name );
+            TransientDescriptor transientModel = typeLookup.lookupTransientModel( type );
+            if( transientModel == null )
+            {
+                return null;
+            }
+            return transientModel;
+        }
+        catch( ClassNotFoundException e )
+        {
+            return null;
+        }
+    }
+
+    @Override
+    public ValueDescriptor valueDescriptor( String name )
+    {
+        try
+        {
+            Class<?> type = classLoader().loadClass( name );
+            ValueDescriptor valueModel = typeLookup.lookupValueModel( type );
+            if( valueModel == null )
+            {
+                return null;
+            }
+            return valueModel;
+        }
+        catch( ClassNotFoundException e )
+        {
+            return null;
+        }
+    }
+
+    @Override
+    public Module instance()
+    {
+        return moduleInstance;
+    }
+
+    @Override
+    public TypeLookup typeLookup()
+    {
+        return typeLookup;
+    }
+
+    public ModuleInstance newInstance( LayerDescriptor layerInstance )
+    {
+        moduleInstance = new ModuleInstance( this, layerInstance, typeLookup, servicesModel, importedServicesModel );
+        return moduleInstance;
+    }
+
+    @Override
+    public Stream<? extends TransientDescriptor> transientComposites()
+    {
+        return transientsModel.stream();
+    }
+
+    @Override
+    public Stream<? extends ValueDescriptor> valueComposites()
+    {
+        return valuesModel.stream();
+    }
+
+    @Override
+    public Stream<? extends ServiceDescriptor> serviceComposites()
+    {
+        return servicesModel.models();
+    }
+
+    @Override
+    public Stream<? extends EntityDescriptor> entityComposites()
+    {
+        return entitiesModel.stream();
+    }
+
+    @Override
+    public Stream<? extends ImportedServiceDescriptor> importedServices()
+    {
+        return importedServicesModel.models();
+    }
+
+    @Override
+    public Stream<? extends ObjectDescriptor> objects()
+    {
+        return objectsModel.models();
+    }
+
+    public Stream<? extends ValueDescriptor> findVisibleValueTypes()
+    {
+        return concat( visibleValues( module ),
+                       concat(
+                           layer().visibleValues( layer ),
+                           concat(
+                               layer().visibleValues( application ),
+                               layer().usedLayers().layers().flatMap( layer1 -> layer1.visibleValues( application ) )
+                           )
+                       )
+        );
+    }
+
+    public Stream<? extends EntityDescriptor> findVisibleEntityTypes()
+    {
+        return concat( visibleEntities( module ),
+                       concat(
+                           layer().visibleEntities( layer ),
+                           concat(
+                               layer().visibleEntities( application ),
+                               layer().usedLayers().layers().flatMap( layer1 -> layer1.visibleEntities( application ) )
+                           )
+                       )
+        );
+    }
+
+    public Stream<? extends TransientDescriptor> findVisibleTransientTypes()
+    {
+        return concat( visibleTransients( module ),
+                       concat(
+                           layer().visibleTransients( layer ),
+                           concat(
+                               layer().visibleTransients( application ),
+                               layer().usedLayers()
+                                   .layers()
+                                   .flatMap( layer1 -> layer1.visibleTransients( application ) )
+                           )
+                       )
+        );
+    }
+
+    public Stream<? extends ModelDescriptor> findVisibleServiceTypes()
+    {
+        return concat( visibleServices( module ),
+                       concat(
+                           layer().visibleServices( layer ),
+                           concat(
+                               layer().visibleServices( application ),
+                               layer().usedLayers().layers().flatMap( layer1 -> layer1.visibleServices( application ) )
+                           )
+                       )
+        );
+    }
+
+    public Stream<? extends ObjectDescriptor> findVisibleObjectTypes()
+    {
+        return concat( visibleObjects( module ),
+                       concat(
+                           layer().visibleObjects( layer ),
+                           concat(
+                               layer().visibleObjects( application ),
+                               layer().usedLayers().layers().flatMap( layer -> layer.visibleObjects( application ) )
+                           )
+                       )
+        );
+    }
+
+    public Stream<? extends ObjectDescriptor> visibleObjects( Visibility visibility )
+    {
+        return objectsModel.models()
+            .filter( new Visibilitypredicate( visibility ) );
+    }
+
+    public Stream<? extends TransientDescriptor> visibleTransients( Visibility visibility )
+    {
+        return transientsModel.models()
+            .filter( new Visibilitypredicate( visibility ) );
+    }
+
+    public Stream<? extends EntityDescriptor> visibleEntities( Visibility visibility )
+    {
+        return entitiesModel.models()
+            .filter( new Visibilitypredicate( visibility ) );
+    }
+
+    public Stream<? extends ValueDescriptor> visibleValues( Visibility visibility )
+    {
+        return valuesModel.models()
+            .filter( new Visibilitypredicate( visibility ) );
+    }
+
+    public Stream<? extends ModelDescriptor> visibleServices( Visibility visibility )
+    {
+        return concat(
+            servicesModel.models()
+                .filter( new Visibilitypredicate( visibility ) ),
+            importedServicesModel.models()
+                .filter( new Visibilitypredicate( visibility ) )
+        );
+    }
+
+    @Override
+    public <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super Object, ? super Object, ThrowableType> modelVisitor )
+        throws ThrowableType
+    {
+        if( modelVisitor.visitEnter( this ) )
+        {
+            if( activatorsModel.accept( modelVisitor ) )
+            {
+                if( transientsModel.accept( modelVisitor ) )
+                {
+                    if( entitiesModel.accept( modelVisitor ) )
+                    {
+                        if( servicesModel.accept( modelVisitor ) )
+                        {
+                            if( importedServicesModel.accept( modelVisitor ) )
+                            {
+                                if( objectsModel.accept( modelVisitor ) )
+                                {
+                                    valuesModel.accept( modelVisitor );
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return modelVisitor.visitLeave( this );
+    }
+
+    @Override
+    public String toString()
+    {
+        return name;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/runtime/src/main/java/org/apache/polygene/runtime/structure/TypeLookupImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/polygene/runtime/structure/TypeLookupImpl.java b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/TypeLookupImpl.java
new file mode 100644
index 0000000..9df92c9
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/polygene/runtime/structure/TypeLookupImpl.java
@@ -0,0 +1,543 @@
+/*
+ *  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.structure;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+import org.apache.polygene.api.common.Visibility;
+import org.apache.polygene.api.composite.AmbiguousTypeException;
+import org.apache.polygene.api.composite.ModelDescriptor;
+import org.apache.polygene.api.composite.TransientDescriptor;
+import org.apache.polygene.api.entity.EntityDescriptor;
+import org.apache.polygene.api.object.ObjectDescriptor;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.structure.TypeLookup;
+import org.apache.polygene.api.type.HasTypes;
+import org.apache.polygene.api.value.ValueDescriptor;
+
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Stream.concat;
+import static org.apache.polygene.api.common.Visibility.application;
+import static org.apache.polygene.api.common.Visibility.layer;
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+
+/**
+ * Central place for Composite Type lookups.
+ */
+class TypeLookupImpl
+    implements TypeLookup
+{
+    private final LazyValue<List<ObjectDescriptor>> allObjects;
+    private final LazyValue<List<TransientDescriptor>> allTransients;
+    private final LazyValue<List<ValueDescriptor>> allValues;
+    private final LazyValue<List<EntityDescriptor>> allEntities;
+    private final LazyValue<List<? extends ModelDescriptor>> allServices;
+    private final ConcurrentHashMap<Class<?>, ObjectDescriptor> objectModels;
+    private final ConcurrentHashMap<Class<?>, TransientDescriptor> transientModels;
+    private final ConcurrentHashMap<Class<?>, ValueDescriptor> valueModels;
+    private final ConcurrentHashMap<Class<?>, List<EntityDescriptor>> entityModels;
+    private final ConcurrentHashMap<Class<?>, EntityDescriptor> unambiguousEntityModels;
+    private final ConcurrentHashMap<Type, ModelDescriptor> serviceModels;
+    private final ConcurrentHashMap<Type, List<? extends ModelDescriptor>> servicesReferences;
+
+    private final ModuleDescriptor moduleModel;
+
+    /**
+     * Create a new TypeLookup bound to the given ModuleModel.
+     *
+     * @param module ModuleModel bound to this TypeLookup
+     */
+    TypeLookupImpl( ModuleModel module )
+    {
+        moduleModel = module;
+
+        // Instance caches
+        allObjects = new LazyValue<>();
+        allTransients = new LazyValue<>();
+        allValues = new LazyValue<>();
+        allEntities = new LazyValue<>();
+        allServices = new LazyValue<>();
+        objectModels = new ConcurrentHashMap<>();
+        transientModels = new ConcurrentHashMap<>();
+        valueModels = new ConcurrentHashMap<>();
+        entityModels = new ConcurrentHashMap<>();
+        unambiguousEntityModels = new ConcurrentHashMap<>();
+        serviceModels = new ConcurrentHashMap<>();
+        servicesReferences = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public ObjectDescriptor lookupObjectModel( final Class<?> type )
+    {
+        return objectModels.computeIfAbsent( type, key ->
+        {
+            List<? extends ObjectDescriptor> allModels = getAllObjects();
+            ObjectDescriptor model = ambiguityMatching( key, allModels, new ExactTypeMatching<>( key ) );
+            if( model == null )
+            {
+                model = ambiguityMatching( key, allModels, new AssignableFromTypeMatching<>( key ) );
+            }
+            return model;
+        } );
+    }
+
+    @Override
+    public TransientDescriptor lookupTransientModel( final Class<?> type )
+    {
+        return transientModels.computeIfAbsent( type, key ->
+        {
+            List<? extends TransientDescriptor> allModels = getAllTransients();
+            TransientDescriptor model = ambiguityMatching( key, allModels, new ExactTypeMatching<>( key ) );
+            if( model == null )
+            {
+                model = ambiguityMatching( key, allModels, new AssignableFromTypeMatching<>( key ) );
+            }
+            return model;
+        } );
+    }
+
+    @Override
+    public ValueDescriptor lookupValueModel( final Class<?> type )
+    {
+        return valueModels.computeIfAbsent( type, key ->
+        {
+            List<? extends ValueDescriptor> allModels = getAllValues();
+            ValueDescriptor model = ambiguityMatching( key, allModels, new ExactTypeMatching<>( key ) );
+            if( model == null )
+            {
+                model = ambiguityMatching( key, allModels, new AssignableFromTypeMatching<>( key ) );
+            }
+            return model;
+        } );
+    }
+
+    @Override
+    public EntityDescriptor lookupEntityModel( final Class<?> type )
+    {
+        return unambiguousEntityModels.computeIfAbsent( type, key ->
+        {
+            List<? extends EntityDescriptor> allModels = getAllEntities();
+            EntityDescriptor model = ambiguityMatching( key, allModels, new ExactTypeMatching<>( key ) );
+            if( model == null )
+            {
+                model = ambiguityMatching( key, allModels, new AssignableFromTypeMatching<>( key ) );
+            }
+            return model;
+        } );
+    }
+
+    @Override
+    public List<EntityDescriptor> lookupEntityModels( final Class type )
+    {
+        return entityModels.computeIfAbsent(
+            type,
+            key -> new TypeMatchesSelector<EntityDescriptor>( key ).selectFrom( allEntities() ) );
+    }
+
+    @Override
+    public ModelDescriptor lookupServiceModel( Type serviceType )
+    {
+        return serviceModels.computeIfAbsent(
+            serviceType,
+            key -> new BestTypeMatchSelector<ModelDescriptor>( key ).selectFrom( allServices() )
+                                                                    .bestMatchOrElse( null ) );
+    }
+
+    @Override
+    public List<? extends ModelDescriptor> lookupServiceModels( final Type type )
+    {
+        return servicesReferences.computeIfAbsent(
+            type,
+            key -> new TypeMatchesSelector<ModelDescriptor>( key ).selectFrom( allServices() ) );
+    }
+
+    @Override
+    public Stream<ObjectDescriptor> allObjects()
+    {
+        return getAllObjects().stream();
+    }
+
+    private List<ObjectDescriptor> getAllObjects()
+    {
+        return allObjects.computeIfAbsent(
+            () -> concat( moduleModel.objects(),
+                          concat(
+                              concat(
+                                  moduleModel.layer().visibleObjects( layer ),
+                                  moduleModel.layer()
+                                             .visibleObjects( application )
+                              ),
+                              moduleModel.layer()
+                                         .usedLayers()
+                                         .layers()
+                                         .flatMap( layer -> layer.visibleObjects( application ) )
+                          )
+            ).collect( toList() )
+        );
+    }
+
+    @Override
+    public Stream<TransientDescriptor> allTransients()
+    {
+        return getAllTransients().stream();
+    }
+
+    private List<TransientDescriptor> getAllTransients()
+    {
+        return allTransients.computeIfAbsent(
+            () -> concat( moduleModel.transientComposites(),
+                          concat(
+                              concat(
+                                  moduleModel.layer().visibleTransients( layer ),
+                                  moduleModel.layer().visibleTransients( application )
+                              ),
+                              moduleModel.layer()
+                                         .usedLayers()
+                                         .layers()
+                                         .flatMap( layer -> layer.visibleTransients( application ) )
+                          )
+            ).collect( toList() )
+        );
+    }
+
+    @Override
+    public Stream<ValueDescriptor> allValues()
+    {
+        return getAllValues().stream();
+    }
+
+    private List<ValueDescriptor> getAllValues()
+    {
+        return allValues.computeIfAbsent(
+            () -> concat( moduleModel.valueComposites(),
+                          concat(
+                              concat( moduleModel.layer().visibleValues( layer ),
+                                      moduleModel.layer().visibleValues( application )
+                              ),
+                              moduleModel.layer()
+                                         .usedLayers()
+                                         .layers()
+                                         .flatMap( layer1 -> layer1.visibleValues( application ) )
+                          )
+            ).collect( toList() )
+        );
+    }
+
+    @Override
+    public Stream<EntityDescriptor> allEntities()
+    {
+        return getAllEntities().stream();
+    }
+
+    private List<EntityDescriptor> getAllEntities()
+    {
+        return allEntities.computeIfAbsent(
+            () -> concat( moduleModel.entityComposites(),
+                          concat(
+                              concat(
+                                  moduleModel.layer().visibleEntities( layer ),
+                                  moduleModel.layer().visibleEntities( application )
+                              ),
+                              moduleModel.layer()
+                                         .usedLayers()
+                                         .layers()
+                                         .flatMap( layer -> layer.visibleEntities( application ) )
+                          )
+            ).collect( toList() )
+        );
+    }
+
+    @Override
+    public Stream<? extends ModelDescriptor> allServices()
+    {
+        return getAllServices().stream();
+    }
+
+    private List<? extends ModelDescriptor> getAllServices()
+    {
+        return allServices.computeIfAbsent(
+            () -> concat(
+                concat( moduleModel.serviceComposites(),
+                        concat(
+                            concat(
+                                moduleModel.layer().visibleServices( layer ),
+                                moduleModel.layer().visibleServices( application )
+                            ),
+                            moduleModel.layer()
+                                       .usedLayers()
+                                       .layers()
+                                       .flatMap( layer -> layer.visibleServices( application ) )
+                        )
+                ),
+                concat( moduleModel.importedServices(),
+                        concat(
+                            concat(
+                                moduleModel.layer().visibleServices( layer ),
+                                moduleModel.layer().visibleServices( application )
+                            ),
+                            moduleModel.layer()
+                                       .usedLayers()
+                                       .layers()
+                                       .flatMap( layer -> layer.visibleServices( application ) )
+                        )
+                )
+            ).collect( toList() )
+        );
+    }
+
+    private static <T extends ModelDescriptor> T ambiguityMatching(
+        Class type,
+        List<T> modelModules,
+        TypeMatching<T> matching
+    )
+    {
+        List<T> models = modelModules.stream()
+                                     .filter( matching.and( new SameVisibility<>() ) )
+                                     .distinct()
+                                     .collect( toList() );
+        if( models.size() > 1 )
+        {
+            throw new AmbiguousTypeException( "More than one type matches " + type.getName() + ": " + models + "]" );
+        }
+        if( models.isEmpty() )
+        {
+            return null;
+        }
+        return models.get( 0 );
+    }
+
+    private static abstract class TypeMatching<T extends HasTypes>
+        implements Predicate<T>
+    {
+        protected final Type lookedUpType;
+
+        protected TypeMatching( Type lookedUpType )
+        {
+            this.lookedUpType = lookedUpType;
+        }
+
+        @Override
+        public final boolean test( T model )
+        {
+            if( lookedUpType instanceof Class )
+            {
+                return model.types().anyMatch( checkMatch( lookedUpType ) );
+            }
+            else
+            {
+                if( lookedUpType instanceof ParameterizedType )
+                {
+                    // Foo<Bar> check
+                    // First check Foo
+                    ParameterizedType parameterizedType = (ParameterizedType) lookedUpType;
+                    Type rawType = parameterizedType.getRawType();
+                    if( model.types().noneMatch( checkMatch( rawType ) ) )
+                    {
+                        return false;
+                    }
+                    // Then check Bar
+                    return interfacesOf( model.types() ).anyMatch( intf -> intf.equals( lookedUpType ) );
+                }
+                else if( lookedUpType instanceof WildcardType )
+                {
+                    return true;
+                }
+                return false;
+            }
+        }
+
+        protected abstract Predicate<Type> checkMatch( Type matchTo );
+    }
+
+    private static class ExactTypeMatching<T extends HasTypes> extends TypeMatching<T>
+    {
+        private ExactTypeMatching( Type lookedUpType )
+        {
+            super( lookedUpType );
+        }
+
+        protected Predicate<Type> checkMatch( Type matchTo )
+        {
+            return matchTo::equals;
+        }
+    }
+
+    private static class AssignableFromTypeMatching<T extends HasTypes> extends TypeMatching<T>
+    {
+        private AssignableFromTypeMatching( Type lookedUpType )
+        {
+            super( lookedUpType );
+        }
+
+        protected Predicate<Type> checkMatch( Type matchTo )
+        {
+            // TODO; what to do if there is ParameterizedType here?? Now set to ClassCastException and see if anything surfaces
+//            if( matchTo instanceof Class )
+            {
+                Class<?> clazz = (Class<?>) matchTo;
+                return candidate -> !candidate.equals( matchTo ) && clazz.isAssignableFrom( (Class<?>) candidate );
+            }
+//            return candidate -> candidate.equals( matchTo );
+        }
+    }
+
+    /**
+     * Selects descriptors by combining {@link ExactTypeMatching} and {@link AssignableFromTypeMatching}.
+     *
+     * Selected descriptors are sorted, exact matches first, assignable ones second.
+     * Other than that, original order is preserved.
+     *
+     * <code>
+     *     [ assignable1, matching1, assignable2, assignable3, matching2, non-matching-nor-assignable ]
+     * </code>
+     * results in
+     * <code>
+     *     [ matching1, matching2, assignable1, assignable2, assignable3 ]
+     * </code>
+     *
+     * @param <T> Descriptor type
+     */
+    private static class TypeMatchesSelector<T extends HasTypes> extends ArrayList<T>
+    {
+        private final ExactTypeMatching<T> exactMatchPredicate;
+        private final AssignableFromTypeMatching<T> assignablePredicate;
+        private Integer lastMatchIndex;
+
+        private TypeMatchesSelector( Type type )
+        {
+            this.exactMatchPredicate = new ExactTypeMatching<>( type );
+            this.assignablePredicate = new AssignableFromTypeMatching<>( type );
+        }
+
+        List<T> selectFrom( Stream<? extends T> candidates )
+        {
+            candidates.forEach( this::addDescriptor );
+            return this;
+        }
+
+        private void addDescriptor( T descriptor )
+        {
+            if( contains( descriptor ) )
+            {
+                return;
+            }
+            if( exactMatchPredicate.test( descriptor ) )
+            {
+                Integer nextMatchIndex = lastMatchIndex == null ? 0 : lastMatchIndex + 1;
+                add( nextMatchIndex, descriptor );
+                lastMatchIndex = nextMatchIndex;
+            }
+            else if( assignablePredicate.test( descriptor ) )
+            {
+                add( descriptor );
+            }
+        }
+
+        boolean containsExactMatches()
+        {
+            return lastMatchIndex != null;
+        }
+    }
+
+    /**
+     * Selects the best matching descriptor by combining {@link ExactTypeMatching} and {@link AssignableFromTypeMatching}.
+     *
+     * Selected descriptor is the first exact match if it exists, the first assignable otherwise.
+     *
+     * @param <T> Descriptor type
+     */
+    private static class BestTypeMatchSelector<T extends HasTypes>
+    {
+        private TypeMatchesSelector<T> descriptors;
+
+        BestTypeMatchSelector( Type type )
+        {
+            this.descriptors = new TypeMatchesSelector<>( type );
+        }
+
+        BestTypeMatchSelector<T> selectFrom( Stream<? extends T> candidates )
+        {
+            candidates.forEach( this::addDescriptor );
+            return this;
+        }
+
+        T bestMatchOrElse( T or )
+        {
+            return !descriptors.isEmpty() ? descriptors.get( 0 ) : or;
+        }
+
+        private void addDescriptor( T descriptor )
+        {
+            // Until an exact match is found, even if we already found assignable ones,
+            // keep selecting in case the last element is an exact match.
+            if( !descriptors.containsExactMatches() )
+            {
+                descriptors.addDescriptor( descriptor );
+            }
+        }
+    }
+
+    /**
+     * This Predicate will filter out all Models that doesn't have the same visibility as the first one.
+     */
+    private static class SameVisibility<T extends ModelDescriptor>
+        implements Predicate<T>
+    {
+        private Visibility current = null;
+
+        @Override
+        public boolean test( T model )
+        {
+            if( current == null )
+            {
+                current = model.visibility();
+                return true;
+            }
+            return current == model.visibility();
+        }
+    }
+
+    private static class LazyValue<T>
+    {
+        private volatile T value;
+
+        public T computeIfAbsent( Supplier<T> supplier )
+        {
+            if( value == null )
+            {
+                synchronized( this )
+                {
+                    if( value == null )
+                    {
+                        value = supplier.get();
+                    }
+                }
+            }
+            return value;
+        }
+    }
+}