polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject [38/81] [abbrv] [partial] zest-java git commit: ZEST-195 ; Replace all "zest" with "polygene"
Date Sat, 17 Dec 2016 10:28:14 GMT
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkDiscardOn.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkDiscardOn.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkDiscardOn.java
new file mode 100644
index 0000000..aec32d4
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkDiscardOn.java
@@ -0,0 +1,73 @@
+/*
+ *  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.api.unitofwork.concern;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Annotation to denote the unit of work discard policy.
+ * <p>
+ * By default, discard is applied on any method that has {@link UnitOfWorkPropagation} and any exception is thrown.
+ * </p>
+ * <p>
+ * Apply {@code UnitOfWorkDiscardOn} to override the default settings.
+ * </p>
+ * <p>
+ * Usage example:
+ * </p>
+ * <pre>
+ * <code>
+ *
+ * &#64;Concerns( UnitOfWorkConcern.class )
+ * public class MyBusinessServiceMixin implements BusinessService
+ * {
+ *   &#64;Structure UnitOfWorkFactory uowf;
+ *
+ *   &#64;UnitOfWorkDiscardOn( MyBusinessException.class )
+ *   public void myBusinessMethod()
+ *   {
+ *     // Must invoke current unit of work.
+ *     UnitOfWork uow = uowf.currentUnitOfWork();
+ *
+ *     // Perform business logic
+ *   }
+ * }
+ * </code>
+ * </pre>
+ *
+ * <p>
+ * The unit of work will be discarded iff {@code MyBusinessException} exceptions or its subclass is thrown from within
+ * {@code myBusinessMethod} method.
+ * </p>
+ */
+@Retention( RUNTIME )
+@Target( METHOD )
+@Inherited
+@Documented
+public @interface UnitOfWorkDiscardOn
+{
+    Class<? extends Throwable>[] value() default { Throwable.class };
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkPropagation.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkPropagation.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkPropagation.java
new file mode 100644
index 0000000..b29a355
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkPropagation.java
@@ -0,0 +1,92 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.api.unitofwork.concern;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Annotation to denote the unit of work propagation.
+ * <p>
+ * Usage example:
+ * </p>
+ * <pre>
+ * <code>
+ *
+ * &#64;Concerns( UnitOfWorkConcern.class )
+ * public class MyBusinessServiceMixin implements BusinessService
+ * {
+ *   &#64;Structure UnitOfWorkFactory uowf;
+ *
+ *   &#64;UnitOfWorkPropagation
+ *   public void myBusinessMethod()
+ *   {
+ *     // Must invoke current unit of work.
+ *     UnitOfWork uow = uowf.currentUnitOfWork();
+ *
+ *     // Perform business logic
+ *   }
+ * }
+ * </code>
+ * </pre>
+ */
+@Retention( RUNTIME )
+@Target( METHOD )
+@Inherited
+@Documented
+public @interface UnitOfWorkPropagation
+{
+    Propagation value() default Propagation.REQUIRED;
+
+    String usecase() default "";
+
+    /**
+     * Propagation behaviors.
+     */
+    enum Propagation
+    {
+        /**
+         * Default propagation behavior.
+         * Behavior: <br>
+         * If no current transaction: creates a new UnitOfWork <br>
+         * If there is a current UnitOfWork: use the current UnitOfWork.
+         */
+        REQUIRED,
+
+        /**
+         * Behavior: <br>
+         * If no current UnitOfWork: throw an exception <br>
+         * If there is a current UnitOfWork: use the current UnitOfWork.
+         */
+        MANDATORY,
+
+        /**
+         * Behavior: <br>
+         * If no current UnitOfWork: creates a new UnitOfWork <br>
+         * If there is a current UnitOfWork: suspend the current UnitOfWork and create a new UnitOfWork.
+         */
+        REQUIRES_NEW
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkRetry.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkRetry.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkRetry.java
new file mode 100644
index 0000000..9f2d481
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkRetry.java
@@ -0,0 +1,81 @@
+/*
+ *  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.api.unitofwork.concern;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * This annotation describes the retries that should occur in case of
+ * {@link org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException}
+ * occurs.
+ */
+@Retention( RUNTIME )
+@Target( METHOD )
+@Inherited
+@Documented
+public @interface UnitOfWorkRetry
+{
+    /**
+     * Number of times that the UnitOfWork should be tried in total.
+     * The default value is 1, which means that the UnitOfWork will execute only one time. It is also the minimum
+     * value allowed.
+     *
+     * @return Number of times that the UnitOfWork will be executed. Must be 1 or higher. If a value of 0 or lower is
+     * given, the UnitOfWork is still executed one time.
+     */
+    int retries() default 1;
+
+    /**
+     * Number of milliseconds to wait before executing the second UnitOfOfWork.
+     * The default value is 0, which means that there is no delay and it is tried immediately.
+     *
+     * @return Number of milliseconds to wait before executing the second UnitOfOfWork.
+     */
+    long initialDelay() default 0;
+
+    /**
+     * Number of milliseconds to be added for each additional retry, beyond the second one.
+     * The default value is 10.
+     *
+     * The delay is defined as;
+     *
+     * <pre><code>
+     *
+     * Thread.sleep( initialDelay + retry * delayFactor );
+     * </code></pre>
+     * where retry will be 0 after first UnitOfWork had a {@link ConcurrentEntityModificationException} and is 1 after
+     * the first retry and so forth.
+     * <p>
+     * So, with the {@code retries=4, initialDelay=5, delayFactor=20} the 3 delays between the UnitOfWorks will be
+     * {@code 5ms, 25ms, 45ms}
+     * </p>
+     *
+     * @return The number of milliseconds per retry, except the first one, that should be added to the delay between
+     * tries.
+     */
+    long delayFactor() default 10;
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/package.html
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/package.html b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/package.html
new file mode 100644
index 0000000..20aa625
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/package.html
@@ -0,0 +1,27 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you under the Apache License, Version 2.0 (the
+  ~  "License"); you may not use this file except in compliance
+  ~  with the License.  You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing, software
+  ~  distributed under the License is distributed on an "AS IS" BASIS,
+  ~  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>UnitOfWork Concerns.</h2>
+        <p>
+            UnitOfWork Concerns allow declarative UnitOfWork propagation, discard wrt. exceptions and automatic retry.
+        </p>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/unitofwork/package.html
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/package.html b/core/api/src/main/java/org/apache/polygene/api/unitofwork/package.html
new file mode 100644
index 0000000..70ff9e9
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you under the Apache License, Version 2.0 (the
+  ~  "License"); you may not use this file except in compliance
+  ~  with the License.  You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing, software
+  ~  distributed under the License is distributed on an "AS IS" BASIS,
+  ~  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>UnitOfWork API.</h2>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/usecase/Usecase.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/usecase/Usecase.java b/core/api/src/main/java/org/apache/polygene/api/usecase/Usecase.java
new file mode 100644
index 0000000..c47ce27
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/usecase/Usecase.java
@@ -0,0 +1,75 @@
+/*
+ *  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.api.usecase;
+
+import java.io.Serializable;
+import org.apache.polygene.api.common.MetaInfo;
+import org.apache.polygene.api.structure.MetaInfoHolder;
+
+/**
+ * A Usecase. A Usecase is used as a model for UnitOfWork, and helps
+ * implementations decide what to do in certain circumstances.
+ */
+public final class Usecase
+    implements Serializable, MetaInfoHolder
+{
+    public static final Usecase DEFAULT = new Usecase( "Default", new MetaInfo() );
+
+    private static final long serialVersionUID = 1L;
+    private final String name;
+    private final MetaInfo metaInfo;
+
+    Usecase( String name, MetaInfo metaInfo )
+    {
+        this.name = name;
+        this.metaInfo = metaInfo;
+    }
+
+    /**
+     * Name of the usecase.
+     *
+     * @return the name
+     */
+    public String name()
+    {
+        return name;
+    }
+
+    /**
+     * Meta-info for the usecase. This can be of any type, and is typically set when creating the usecase
+     * and read during the execution of the usecase.
+     *
+     * @param infoType the MetaInfo type to retrieve.
+     *
+     * @return the previously stored metaInfo of the given type for the usecase.
+     */
+    @Override
+    public <T> T metaInfo( Class<T> infoType )
+    {
+        return metaInfo.get( infoType );
+    }
+
+    @Override
+    public String toString()
+    {
+        return name + ", meta info:" + metaInfo;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/usecase/UsecaseBuilder.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/usecase/UsecaseBuilder.java b/core/api/src/main/java/org/apache/polygene/api/usecase/UsecaseBuilder.java
new file mode 100644
index 0000000..ae89aad
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/usecase/UsecaseBuilder.java
@@ -0,0 +1,59 @@
+/*
+ *  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.api.usecase;
+
+import org.apache.polygene.api.common.MetaInfo;
+
+/**
+ * Builder for Usecases.
+ */
+public final class UsecaseBuilder
+{
+    public static UsecaseBuilder buildUsecase( String aName )
+    {
+        return new UsecaseBuilder( aName );
+    }
+
+    public static Usecase newUsecase( String aName )
+    {
+        return new UsecaseBuilder( aName ).newUsecase();
+    }
+
+    private MetaInfo metaInfo = new MetaInfo();
+
+    private String name;
+
+    private UsecaseBuilder( String name )
+    {
+        this.name = name;
+    }
+
+    public UsecaseBuilder withMetaInfo( Object metaInfo )
+    {
+        this.metaInfo.set( metaInfo );
+        return this;
+    }
+
+    public Usecase newUsecase()
+    {
+        return new Usecase( name, metaInfo );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/usecase/package.html
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/usecase/package.html b/core/api/src/main/java/org/apache/polygene/api/usecase/package.html
new file mode 100644
index 0000000..1d55001
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/usecase/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you under the Apache License, Version 2.0 (the
+  ~  "License"); you may not use this file except in compliance
+  ~  with the License.  You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing, software
+  ~  distributed under the License is distributed on an "AS IS" BASIS,
+  ~  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>Usecase API.</h2>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/util/Annotations.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Annotations.java b/core/api/src/main/java/org/apache/polygene/api/util/Annotations.java
new file mode 100644
index 0000000..b172945
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Annotations.java
@@ -0,0 +1,79 @@
+/*
+ *  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.api.util;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+import static org.apache.polygene.api.util.Classes.typeOf;
+
+/**
+ * Useful methods for handling Annotations.
+ */
+public final class Annotations
+{
+    public static final Function<Type, Stream<Annotation>> ANNOTATIONS_OF =
+        Classes.forTypes( type -> Arrays.stream( Classes.RAW_CLASS.apply( type ).getAnnotations() ) );
+
+    public static Predicate<Annotation> typeHasAnnotation( Class<? extends Annotation> annotationType )
+    {
+        return element -> hasAnnotation( annotationType ).test( type().apply( element ) );
+    }
+
+    public static Predicate<AnnotatedElement> hasAnnotation( final Class<? extends Annotation> annotationType )
+    {
+        return element -> element.getAnnotation( annotationType ) != null;
+    }
+
+    public static Function<Annotation, Class<? extends Annotation>> type()
+    {
+        return Annotation::annotationType;
+    }
+
+    public static Predicate<Annotation> isType( final Class<? extends Annotation> annotationType )
+    {
+        return annotation -> annotation.annotationType().equals( annotationType );
+    }
+
+    public static <T extends Annotation> T annotationOn( Type type, Class<T> annotationType )
+    {
+        return annotationType.cast( Classes.RAW_CLASS.apply( type ).getAnnotation( annotationType ) );
+    }
+
+    public static List<Annotation> findAccessorAndTypeAnnotationsIn(AccessibleObject accessor) {
+        Stream<Annotation> stream = Stream.concat(
+                Arrays.stream(accessor.getAnnotations()),
+                interfacesOf(typeOf(accessor)).flatMap(ANNOTATIONS_OF)
+        );
+        Collector<Annotation, ?, List<Annotation>> collector = Collectors.toList();
+        return stream.collect(collector);
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/util/Classes.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Classes.java b/core/api/src/main/java/org/apache/polygene/api/util/Classes.java
new file mode 100644
index 0000000..175be95
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Classes.java
@@ -0,0 +1,541 @@
+/*
+ *  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.api.util;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.composite.ModelDescriptor;
+
+import static java.util.stream.Stream.concat;
+import static java.util.stream.StreamSupport.stream;
+
+/**
+ * Useful methods for handling Classes.
+ */
+public final class Classes
+{
+    private final static Map<Type, Type> wrapperClasses = new HashMap<>();
+
+    static
+    {
+        wrapperClasses.put( boolean.class, Boolean.class );
+        wrapperClasses.put( byte.class, Byte.class );
+        wrapperClasses.put( short.class, Short.class );
+        wrapperClasses.put( char.class, Character.class );
+        wrapperClasses.put( int.class, Integer.class );
+        wrapperClasses.put( long.class, Long.class );
+        wrapperClasses.put( float.class, Float.class );
+        wrapperClasses.put( double.class, Double.class );
+    }
+
+    private final static Map<Type, Type> primitiveClasses = new HashMap<>();
+
+    static
+    {
+        primitiveClasses.put( boolean.class, Boolean.class );
+        primitiveClasses.put( byte.class, Byte.class );
+        primitiveClasses.put( short.class, Short.class );
+        primitiveClasses.put( char.class, Character.class );
+        primitiveClasses.put( int.class, Integer.class );
+        primitiveClasses.put( long.class, Long.class );
+        primitiveClasses.put( float.class, Float.class );
+        primitiveClasses.put( double.class, Double.class );
+    }
+
+    /**
+     * Convert from primitive class (int, short, double, etc.) to wrapper class (Integer, Short, Double, etc.).
+     * Return the same class if it's not a primitive class. This can therefore safely be used on all types
+     * to ensure that they are not primitives.
+     */
+    private static final Function<Type, Type> WRAPPER_CLASS = clazz -> {
+        Type wrapperClass = wrapperClasses.get( clazz );
+        return wrapperClass == null ? clazz : wrapperClass;
+    };
+
+    /**
+     * Convert from wrapper class (Integer, Short, Double, etc.) to primitive class (int, short, double, etc.).
+     * Return the same class if it's not a wrapper class. This can therefore safely be used on all types
+     * to ensure that they are primitives if possible.
+     */
+    @SuppressWarnings( "UnusedDeclaration" )
+    private static final Function<Type, Type> PRIMITIVE_CLASS = aClass -> {
+        Type primitiveClass = primitiveClasses.get( aClass );
+        return primitiveClass == null ? aClass : primitiveClass;
+    };
+
+    /**
+     * Function that extract the raw class of a type.
+     */
+    public static final Function<Type, Class<?>> RAW_CLASS = genericType -> {
+        // Calculate raw type
+        if( genericType instanceof Class )
+        {
+            return (Class<?>) genericType;
+        }
+        else if( genericType instanceof ParameterizedType )
+        {
+            return (Class<?>) ( (ParameterizedType) genericType ).getRawType();
+        }
+        else if( genericType instanceof TypeVariable )
+        {
+            return (Class<?>) ( (TypeVariable) genericType ).getGenericDeclaration();
+        }
+        else if( genericType instanceof WildcardType )
+        {
+            return (Class<?>) ( (WildcardType) genericType ).getUpperBounds()[ 0 ];
+        }
+        else if( genericType instanceof GenericArrayType )
+        {
+            Object temp = Array.newInstance( (Class<?>) ( (GenericArrayType) genericType ).getGenericComponentType(), 0 );
+            return temp.getClass();
+        }
+        throw new IllegalArgumentException( "Could not extract the raw class of " + genericType );
+    };
+
+    private static final Function<AccessibleObject, Type> TYPE_OF = accessor -> {
+        if( accessor instanceof Method )
+        {
+            return ( (Method) accessor ).getGenericReturnType();
+        }
+        return ( (Field) accessor ).getGenericType();
+    };
+
+    private static final Function<Type, Stream<Class<?>>> CLASS_HIERARCHY = new Function<Type, Stream<Class<?>>>()
+    {
+        @Override
+        public Stream<Class<?>> apply( Type type )
+        {
+            if( type == null )
+            {
+                return Stream.empty();
+            }
+            if( type.equals( Object.class ) )
+            {
+                return Stream.of( (Class<?>) type );
+            }
+            else
+            {
+                type = RAW_CLASS.apply( type );
+                Class superclass = ( (Class) type ).getSuperclass();
+                return concat( Stream.of( (Class<?>) type ), apply( superclass ) );
+            }
+        }
+    };
+
+    @SuppressWarnings( "raw" )
+    private static final Function<Type, Stream<? extends Type>> INTERFACES_OF = new Function<Type, Stream<? extends Type>>()
+    {
+        @Override
+        public Stream<? extends Type> apply( Type type )
+        {
+            Class clazz = RAW_CLASS.apply( type );
+
+            if( clazz.isInterface() )
+            {
+                Stream<? extends Type> genericInterfaces = Arrays.stream( clazz.getGenericInterfaces() );
+                Stream<? extends Type> intfaces = genericInterfaces.flatMap( INTERFACES_OF );
+                return concat( Stream.of( type ), intfaces );
+            }
+            else
+            {
+                if( type.equals( Object.class ) )
+                {
+                    return Arrays.stream( clazz.getGenericInterfaces() );
+                }
+                else
+                {
+                    return concat( Stream.of( clazz.getGenericInterfaces() ).flatMap( INTERFACES_OF ),
+                                   Stream.of( clazz.getSuperclass() ).flatMap( INTERFACES_OF ) );
+
+                }
+            }
+        }
+    };
+
+    private static final Function<Type, Stream<? extends Type>> TYPES_OF = type -> {
+        Class clazz = RAW_CLASS.apply( type );
+
+        if( clazz.isInterface() )
+        {
+            Stream<Type> intfaces = Arrays.stream( clazz.getGenericInterfaces() ).flatMap( INTERFACES_OF );
+            return concat( Stream.of( clazz ), intfaces );
+        }
+        else
+        {
+            return concat( Stream.of( clazz ),
+                           Stream.of( type ).flatMap( CLASS_HIERARCHY ).flatMap( INTERFACES_OF ) );
+        }
+    };
+
+    public static Type typeOf( AccessibleObject from )
+    {
+        return TYPE_OF.apply( from );
+    }
+
+    public static Stream<Type> typesOf( Stream<? extends Type> types )
+    {
+        return types.flatMap( TYPES_OF );
+    }
+
+    public static Stream<? extends Type> typesOf( Type type )
+    {
+        return TYPES_OF.apply( type );
+    }
+
+    public static Stream<? extends Type> interfacesOf( Stream<? extends Type> types )
+    {
+        return types.flatMap( INTERFACES_OF );
+    }
+
+    public static Stream<? extends Type> interfacesOf( Type type )
+    {
+        return Stream.of( type ).flatMap( INTERFACES_OF );
+    }
+
+    public static Stream<Class<?>> classHierarchy( Class<?> type )
+    {
+        return Stream.of( type ).flatMap( CLASS_HIERARCHY );
+    }
+
+    public static Type wrapperClass( Type type )
+    {
+        return WRAPPER_CLASS.apply( type );
+    }
+
+    public static Predicate<Class<?>> isAssignableFrom( final Class<?> clazz )
+    {
+        return clazz::isAssignableFrom;
+    }
+
+    public static Predicate<Object> instanceOf( final Class<?> clazz )
+    {
+        return clazz::isInstance;
+    }
+
+    public static Predicate<Class<?>> hasModifier( final int classModifier )
+    {
+        return item -> ( item.getModifiers() & classModifier ) != 0;
+    }
+
+    public static <T> Function<Type, Stream<T>> forClassHierarchy( final Function<Class<?>, Stream<T>> function )
+    {
+        return type -> Stream.of( type ).flatMap( CLASS_HIERARCHY ).flatMap( function );
+    }
+
+    public static <T> Function<Type, Stream<T>> forTypes( final Function<Type, Stream<T>> function )
+    {
+        return type -> Stream.of( type ).flatMap( TYPES_OF ).flatMap( function );
+    }
+
+    @SuppressWarnings( "raw" )
+    public static Set<Class<?>> interfacesWithMethods( Set<Class<?>> interfaces )
+    {
+        Set<Class<?>> newSet = new LinkedHashSet<>();
+        for( Class type : interfaces )
+        {
+            if( type.isInterface() && type.getDeclaredMethods().length > 0 )
+            {
+                newSet.add( type );
+            }
+        }
+
+        return newSet;
+    }
+
+    public static String simpleGenericNameOf( Type type )
+    {
+        StringBuilder sb = new StringBuilder();
+        simpleGenericNameOf( sb, type );
+        return sb.toString();
+    }
+
+    @SuppressWarnings( "raw" )
+    private static void simpleGenericNameOf( StringBuilder sb, Type type )
+    {
+        if( type instanceof Class )
+        {
+            sb.append( ( (Class) type ).getSimpleName() );
+        }
+        else if( type instanceof ParameterizedType )
+        {
+            ParameterizedType pt = (ParameterizedType) type;
+            simpleGenericNameOf( sb, pt.getRawType() );
+            sb.append( "<" );
+            boolean atLeastOne = false;
+            for( Type typeArgument : pt.getActualTypeArguments() )
+            {
+                if( atLeastOne )
+                {
+                    sb.append( ", " );
+                }
+                simpleGenericNameOf( sb, typeArgument );
+                atLeastOne = true;
+            }
+            sb.append( ">" );
+        }
+        else if( type instanceof GenericArrayType )
+        {
+            GenericArrayType gat = (GenericArrayType) type;
+            simpleGenericNameOf( sb, gat.getGenericComponentType() );
+            sb.append( "[]" );
+        }
+        else if( type instanceof TypeVariable )
+        {
+            TypeVariable tv = (TypeVariable) type;
+            sb.append( tv.getName() );
+        }
+        else if( type instanceof WildcardType )
+        {
+            WildcardType wt = (WildcardType) type;
+            sb.append( "? extends " );
+            boolean atLeastOne = false;
+            for( Type typeArgument : wt.getUpperBounds() )
+            {
+                if( atLeastOne )
+                {
+                    sb.append( ", " );
+                }
+                simpleGenericNameOf( sb, typeArgument );
+                atLeastOne = true;
+            }
+        }
+        else
+        {
+            throw new IllegalArgumentException( "Don't know how to deal with type:" + type );
+        }
+    }
+
+    @SuppressWarnings( "UnusedDeclaration" )
+    public static <AnnotationType extends Annotation>
+    AnnotationType findAnnotationOfTypeOrAnyOfSuperTypes( Class<?> type, Class<AnnotationType> annotationClass )
+    {
+        return Stream.of( type )
+            .flatMap( TYPES_OF )
+            .map( RAW_CLASS )
+            .map( clazz -> clazz.getAnnotation( annotationClass ) )
+            .filter( Objects::nonNull )
+            .findAny().orElse( null );
+    }
+
+    public static Predicate<Member> memberNamed( final String name )
+    {
+        return item -> item.getName().equals( name );
+    }
+
+    /**
+     * Given a type variable, find what it resolves to given the declaring class where type
+     * variable was found and a top class that extends the declaring class.
+     *
+     * @param name           The TypeVariable name.
+     * @param declaringClass The class where the TypeVariable is declared.
+     * @param topClass       The top class that extends the declaringClass
+     *
+     * @return The Type instance of the given TypeVariable
+     */
+    @SuppressWarnings( "raw" )
+    public static Type resolveTypeVariable( TypeVariable name, Class declaringClass, Class topClass )
+    {
+        Type type = resolveTypeVariable( name, declaringClass, new HashMap<>(), topClass );
+        if( type == null )
+        {
+            type = Object.class;
+        }
+        return type;
+    }
+
+    private static Type resolveTypeVariable( TypeVariable name,
+                                             Class declaringClass,
+                                             Map<TypeVariable, Type> mappings,
+                                             Class current
+    )
+    {
+        if( current.equals( declaringClass ) )
+        {
+            Type resolvedType = name;
+            while( resolvedType instanceof TypeVariable )
+            {
+                resolvedType = mappings.get( resolvedType );
+            }
+            return resolvedType;
+        }
+
+        Stream<? extends Type> stream = Arrays.stream( current.getGenericInterfaces() )
+            .flatMap( INTERFACES_OF )
+            .distinct();
+
+        Type genericSuperclass = current.getGenericSuperclass();
+        if( genericSuperclass != null )
+        {
+            stream = concat( stream, Stream.of( genericSuperclass ) );
+        }
+        return stream.map( type -> {
+            Class subClass;
+            if( type instanceof ParameterizedType )
+            {
+                subClass = extractTypeVariables( mappings, (ParameterizedType) type );
+            }
+            else
+            {
+                subClass = (Class) type;
+            }
+            return subClass;
+        } )
+            .map( subClass -> resolveTypeVariable( name, declaringClass, mappings, subClass ) )
+            .filter( type -> type != null )
+            .findAny().orElse( null );
+    }
+
+    private static Class extractTypeVariables( Map<TypeVariable, Type> mappings, ParameterizedType type )
+    {
+        Class subClass;
+        Type[] args = type.getActualTypeArguments();
+        Class clazz = (Class) type.getRawType();
+        TypeVariable[] vars = clazz.getTypeParameters();
+        for( int i = 0; i < vars.length; i++ )
+        {
+            TypeVariable var = vars[ i ];
+            Type mappedType = args[ i ];
+            mappings.put( var, mappedType );
+        }
+        subClass = (Class) type.getRawType();
+        return subClass;
+    }
+
+    /**
+     * Get URI for a class.
+     *
+     * @param clazz class
+     *
+     * @return URI
+     *
+     * @throws NullPointerException if clazz is null
+     */
+    @SuppressWarnings( "raw" )
+    public static String toURI( final Class clazz )
+        throws NullPointerException
+    {
+        return toURI( clazz.getName() );
+    }
+
+    /**
+     * Get URI for a class name.
+     * <p>
+     * Example:
+     * </p>
+     * <p>
+     * Class name com.example.Foo$Bar is converted to URI urn:polygene:com.example.Foo-Bar
+     * </p>
+     *
+     * @param className class name
+     *
+     * @return URI
+     *
+     * @throws NullPointerException if className is null
+     */
+    public static String toURI( String className )
+        throws NullPointerException
+    {
+        className = normalizeClassToURI( className );
+        return "urn:polygene:type:" + className;
+    }
+
+    /**
+     * Get class name from a URI
+     *
+     * @param uri URI
+     *
+     * @return class name
+     *
+     * @throws NullPointerException if uri is null
+     */
+    public static String toClassName( String uri )
+        throws NullPointerException
+    {
+        uri = uri.substring( "urn:polygene:type:".length() );
+        uri = denormalizeURIToClass( uri );
+        return uri;
+    }
+
+    public static String normalizeClassToURI( String className )
+    {
+        return className.replace( '$', '-' );
+    }
+
+    public static String denormalizeURIToClass( String uriPart )
+    {
+        return uriPart.replace( '-', '$' );
+    }
+
+    public static Predicate<ModelDescriptor> modelTypeSpecification( final String className )
+    {
+        return item ->
+            stream( item.types().spliterator(), false )
+                .map( Class::getName ).anyMatch( typeName -> typeName.equals( className ) );
+    }
+
+    @SuppressWarnings( "raw" )
+    public static Predicate<ModelDescriptor> exactTypeSpecification( final Class type )
+    {
+        return item -> item.types().anyMatch( clazz -> clazz.equals( type ) );
+    }
+
+    @SuppressWarnings( "raw" )
+    public static Predicate<ModelDescriptor> assignableTypeSpecification( final Class<?> type )
+    {
+        return item ->
+            item.types().anyMatch(
+                itemType -> !type.equals( itemType ) && type.isAssignableFrom( itemType )
+            );
+    }
+
+    @SuppressWarnings( "raw" )
+    public static String toString( Stream<? extends Class> types )
+    {
+        return "[" + types.map( Class::getSimpleName ).collect( Collectors.joining( "," ) ) + "]";
+    }
+
+    public static Function<Type, String> toClassName()
+    {
+        return type -> RAW_CLASS.apply( type ).getName();
+    }
+
+    private Classes()
+    {
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/util/Collectors.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Collectors.java b/core/api/src/main/java/org/apache/polygene/api/util/Collectors.java
new file mode 100644
index 0000000..e419b21
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Collectors.java
@@ -0,0 +1,105 @@
+/*
+ *  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.api.util;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+
+public class Collectors
+{
+    /**
+     * Collect a single element.
+     * @param <T> Element type
+     * @return The single element
+     * @throws IllegalArgumentException if no or more than one element
+     */
+    public static <T>
+    Collector<T, ?, T> single()
+        throws IllegalArgumentException
+    {
+        Supplier<T> thrower = () ->
+        {
+            throw new IllegalArgumentException( "No or more than one element in stream" );
+        };
+        return java.util.stream.Collectors.collectingAndThen( java.util.stream.Collectors.reducing( ( a, b ) -> null ),
+                                                              optional -> optional.orElseGet( thrower ) );
+    }
+
+    /**
+     * Eventually collect a single element.
+     * @param <T> Element type
+     * @return The single element, optional
+     * @throws IllegalArgumentException if more than one element
+     */
+    public static <T>
+    Collector<T, ?, Optional<T>> singleOrEmpty()
+        throws IllegalArgumentException
+    {
+        return java.util.stream.Collectors.reducing(
+            ( left, right ) ->
+            {
+                if( left != null && right != null )
+                {
+                    throw new IllegalArgumentException( "More than one element in stream" );
+                }
+                if( left != null )
+                {
+                    return left;
+                }
+                return right;
+            } );
+    }
+
+    public static <T, K, U, M extends Map<K, U>>
+    Collector<T, ?, M> toMap( Function<? super T, ? extends K> keyMapper,
+                              Function<? super T, ? extends U> valueMapper,
+                              Supplier<M> mapSupplier )
+    {
+        return java.util.stream.Collectors.toMap( keyMapper,
+                                                  valueMapper,
+                                                  throwingMerger(),
+                                                  mapSupplier );
+    }
+
+
+    public static <T extends Map.Entry<K, U>, K, U>
+    Collector<T, ?, Map<K, U>> toMap()
+    {
+        return java.util.stream.Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue );
+    }
+
+    public static <T extends Map.Entry<K, U>, K, U, M extends Map<K, U>>
+    Collector<T, ?, M> toMap( Supplier<M> mapSupplier )
+    {
+        return toMap( Map.Entry::getKey, Map.Entry::getValue, mapSupplier );
+    }
+
+    private static <T> BinaryOperator<T> throwingMerger()
+    {
+        return ( left, right ) ->
+        {
+            throw new IllegalStateException( String.format( "Duplicate key %s", left ) );
+        };
+    }
+
+    private Collectors() {}
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/util/Constructors.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Constructors.java b/core/api/src/main/java/org/apache/polygene/api/util/Constructors.java
new file mode 100644
index 0000000..12f2e01
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Constructors.java
@@ -0,0 +1,35 @@
+/*
+ *  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.api.util;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+/**
+ * Useful methods for handling Constructors.
+ */
+public final class Constructors
+{
+    public static final Function<Type, Stream<Constructor<?>>> CONSTRUCTORS_OF =
+        Classes.forClassHierarchy( type -> Arrays.stream( type.getDeclaredConstructors() ) );
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/util/Fields.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Fields.java b/core/api/src/main/java/org/apache/polygene/api/util/Fields.java
new file mode 100644
index 0000000..c29c3bf
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Fields.java
@@ -0,0 +1,44 @@
+/*
+ *  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.api.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+/**
+ * Useful methods for handling Fields.
+ */
+public final class Fields
+{
+    public static final Function<Type, Stream<Field>> FIELDS_OF =
+        Classes.forClassHierarchy( type -> Arrays.stream( type.getDeclaredFields() ) );
+
+    public static final BiFunction<Class<?>, String, Field> FIELD_NAMED = ( clazz, name ) ->
+        FIELDS_OF.apply( clazz ).filter( Classes.memberNamed( name ) ).findFirst().orElse( null );
+
+    public static Stream<Field> fieldsOf( Type type )
+    {
+        return Stream.of( type ).flatMap( FIELDS_OF );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/util/HierarchicalVisitor.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/HierarchicalVisitor.java b/core/api/src/main/java/org/apache/polygene/api/util/HierarchicalVisitor.java
new file mode 100644
index 0000000..33fcb40
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/HierarchicalVisitor.java
@@ -0,0 +1,57 @@
+/*
+ *  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.api.util;
+
+/**
+ * Visitor to visit hierarchies.
+ */
+public interface HierarchicalVisitor<NODE, LEAF, ThrowableType extends Throwable> extends Visitor<LEAF, ThrowableType>
+{
+    /**
+     * Enter an instance of T
+     *
+     * @param visited the visited instance which is now entered
+     *
+     * @return true if the visitor pattern should continue, false if it should be aborted for this level
+     *
+     * @throws ThrowableType if an exception occurred during processing. Any client call that initiated the visiting should
+     *                       get the exception in order to handle it properly.
+     */
+    boolean visitEnter( NODE visited )
+        throws ThrowableType;
+
+    /**
+     * Leave an instance of T
+     *
+     * @param visited the visited instance which is now left
+     *
+     * @return true if the visitor pattern should continue, false if it should be aborted for the level of this node
+     *
+     * @throws ThrowableType if an exception occurred during processing. Any client call that initiated the visiting should
+     *                       get the exception in order to handle it properly.
+     */
+    boolean visitLeave( NODE visited )
+        throws ThrowableType;
+
+    @Override
+    boolean visit( LEAF visited )
+        throws ThrowableType;
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/util/HierarchicalVisitorAdapter.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/HierarchicalVisitorAdapter.java b/core/api/src/main/java/org/apache/polygene/api/util/HierarchicalVisitorAdapter.java
new file mode 100644
index 0000000..4756b3c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/HierarchicalVisitorAdapter.java
@@ -0,0 +1,48 @@
+/*
+ *  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.api.util;
+
+/**
+ * Generic Hierarchical Visitor interface.
+ */
+public class HierarchicalVisitorAdapter<NODE, LEAF, ThrowableType extends Throwable>
+    implements HierarchicalVisitor<NODE, LEAF, ThrowableType>
+{
+    @Override
+    public boolean visitEnter( NODE visited )
+        throws ThrowableType
+    {
+        return true;
+    }
+
+    @Override
+    public boolean visitLeave( NODE visited )
+        throws ThrowableType
+    {
+        return true;
+    }
+
+    @Override
+    public boolean visit( LEAF visited )
+        throws ThrowableType
+    {
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/util/ListMap.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/ListMap.java b/core/api/src/main/java/org/apache/polygene/api/util/ListMap.java
new file mode 100644
index 0000000..4cba48e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/ListMap.java
@@ -0,0 +1,48 @@
+/*
+ *  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.api.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Map whose values are Lists of things. Create
+ * one ArrayList for each key that is added. The list does not allow
+ * duplicates.
+ */
+public final class ListMap<K, V>
+    extends HashMap<K, List<V>>
+{
+    public void add( K key, V value )
+    {
+        List<V> list = get( key );
+        if( list == null )
+        {
+            list = new ArrayList<V>();
+            put( key, list );
+        }
+        if( !list.contains( value ) )
+        {
+            list.add( value );
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/util/Methods.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Methods.java b/core/api/src/main/java/org/apache/polygene/api/util/Methods.java
new file mode 100644
index 0000000..bf0d4dd
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Methods.java
@@ -0,0 +1,50 @@
+/*
+ *  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.api.util;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+/**
+ * Useful methods for handling Methods.
+ */
+public class Methods
+{
+    public static final Predicate<Type> HAS_METHODS =
+        item -> Classes.RAW_CLASS.apply( item ).getDeclaredMethods().length > 0;
+
+    public static final Function<Type, Stream<Method>> METHODS_OF = Classes.forTypes( type ->
+        Stream.of( type ).map( Classes.RAW_CLASS ).flatMap( clazz -> Arrays.stream( clazz.getDeclaredMethods() ) )
+    );
+
+    public static final BiFunction<Class<?>, String, Method> METHOD_NAMED = ( clazz, name ) ->
+        METHODS_OF.apply( clazz ).filter( Classes.memberNamed( name ) ).findFirst().orElse( null );
+
+
+    public static Stream<Method> methodsOf( Type type )
+    {
+        return Stream.of(type).flatMap( METHODS_OF );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/util/NullArgumentException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/NullArgumentException.java b/core/api/src/main/java/org/apache/polygene/api/util/NullArgumentException.java
new file mode 100644
index 0000000..927a438
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/NullArgumentException.java
@@ -0,0 +1,59 @@
+/*
+ *  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.api.util;
+
+/**
+ * Thrown if an argument to a method was null, and the method required
+ * it to be non-null.
+ */
+public class NullArgumentException
+    extends IllegalArgumentException
+{
+    private static final long serialVersionUID = 4815431779868729780L;
+
+    private NullArgumentException( String message )
+    {
+        super( message );
+    }
+
+    public static void validateNotNull( String parameterName, Object value )
+    {
+        if( value != null )
+        {
+            return;
+        }
+        String message = parameterName + " was null.";
+        throw new NullArgumentException( message );
+    }
+
+    public static void validateNotEmpty( String parameterName, String value )
+    {
+        if( value == null )
+        {
+            String message = parameterName + " was null.";
+            throw new NullArgumentException( message );
+        }
+        if( value.length() == 0 )
+        {
+            String message = parameterName + " was empty.";
+            throw new NullArgumentException( message );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/util/Visitable.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Visitable.java b/core/api/src/main/java/org/apache/polygene/api/util/Visitable.java
new file mode 100644
index 0000000..8d163a3
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Visitable.java
@@ -0,0 +1,29 @@
+/*
+ *  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.api.util;
+
+/**
+ * Interface that visitable objects should implement.
+ */
+public interface Visitable<T>
+{
+    <ThrowableType extends Throwable> boolean accept( Visitor<? super T, ThrowableType> visitor )
+        throws ThrowableType;
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/util/VisitableHierarchy.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/VisitableHierarchy.java b/core/api/src/main/java/org/apache/polygene/api/util/VisitableHierarchy.java
new file mode 100644
index 0000000..33015db
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/VisitableHierarchy.java
@@ -0,0 +1,29 @@
+/*
+ *  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.api.util;
+
+/**
+ * Interface that visitable hierarchies of objects should implement.
+ */
+public interface VisitableHierarchy<NODE, LEAF>
+{
+    <ThrowableType extends Throwable> boolean accept( HierarchicalVisitor<? super NODE, ? super LEAF, ThrowableType> visitor )
+        throws ThrowableType;
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/util/Visitor.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Visitor.java b/core/api/src/main/java/org/apache/polygene/api/util/Visitor.java
new file mode 100644
index 0000000..80f45a0
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Visitor.java
@@ -0,0 +1,39 @@
+/*
+ *  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.api.util;
+
+/**
+ * Generic Visitor interface.
+ */
+public interface Visitor<T, ThrowableType extends Throwable>
+{
+    /**
+     * Visit an instance of T
+     *
+     * @param visited the visited instance
+     *
+     * @return true if the visitor pattern should continue, false if it should be aborted
+     *
+     * @throws ThrowableType if an exception occurred during processing. Any client call that initiated the visiting should
+     *                       get the exception in order to handle it properly.
+     */
+    boolean visit( T visited )
+        throws ThrowableType;
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/util/package.html
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/package.html b/core/api/src/main/java/org/apache/polygene/api/util/package.html
new file mode 100644
index 0000000..cc0b40b
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/util/package.html
@@ -0,0 +1,24 @@
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you under the Apache License, Version 2.0 (the
+  ~  "License"); you may not use this file except in compliance
+  ~  with the License.  You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing, software
+  ~  distributed under the License is distributed on an "AS IS" BASIS,
+  ~  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  ~
+  ~
+  -->
+<html>
+    <body>
+        <h2>API Utilities.</h2>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/value/MissingValueSerializationException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/MissingValueSerializationException.java b/core/api/src/main/java/org/apache/polygene/api/value/MissingValueSerializationException.java
new file mode 100644
index 0000000..00b1af7
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/value/MissingValueSerializationException.java
@@ -0,0 +1,43 @@
+/*
+ *  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.api.value;
+
+public class MissingValueSerializationException extends ValueSerializationException
+{
+    public MissingValueSerializationException()
+    {
+    }
+
+    public MissingValueSerializationException( String message )
+    {
+        super( message );
+    }
+
+    public MissingValueSerializationException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+    public MissingValueSerializationException( Throwable cause )
+    {
+        super( cause );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/value/NoSuchValueException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/NoSuchValueException.java b/core/api/src/main/java/org/apache/polygene/api/value/NoSuchValueException.java
new file mode 100644
index 0000000..4e5cb30
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/value/NoSuchValueException.java
@@ -0,0 +1,43 @@
+/*
+ *  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.api.value;
+
+import java.util.stream.Collectors;
+import org.apache.polygene.api.composite.NoSuchCompositeException;
+import org.apache.polygene.api.structure.TypeLookup;
+
+/**
+ * Thrown when no visible value of the requested type is found.
+ */
+public class NoSuchValueException
+    extends NoSuchCompositeException
+{
+    public NoSuchValueException( String valueType, String moduleName, TypeLookup typeLookup )
+    {
+        super( "ValueComposite", valueType, moduleName, formatVisibleTypes(typeLookup) );
+    }
+
+    private static String formatVisibleTypes( TypeLookup typeLookup )
+    {
+        return typeLookup.allValues()
+            .map(descriptor -> descriptor.primaryType().getName())
+            .collect( Collectors.joining( "\n", "Visible value types are:\n", "" ) );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilder.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilder.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilder.java
new file mode 100644
index 0000000..fe7a8e1
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilder.java
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.polygene.api.value;
+
+import org.apache.polygene.api.association.AssociationStateHolder;
+import org.apache.polygene.api.common.ConstructionException;
+
+/**
+ * Builder for Values.
+ */
+public interface ValueBuilder<T>
+{
+    AssociationStateHolder state();
+
+    /**
+     * Get a representation of the state for the new Value.
+     * It is possible to access and update properties and associations,
+     * even immutable ones since the builder represents the initial state.
+     *
+     * @return a mutable instance of the Value type
+     */
+    T prototype();
+
+    /**
+     * Get a representation of the state of the given type for the new ValueComposite.
+     * This is primarily used if you want to provide state for a private mixin type.
+     *
+     * @param mixinType the mixin which you want to provide state for
+     *
+     * @return a proxy implementing the given mixin type
+     */
+    <K> K prototypeFor( Class<K> mixinType );
+
+    /**
+     * Create a new Composite instance.
+     *
+     * @return a new Composite instance
+     *
+     * @throws org.apache.polygene.api.common.ConstructionException
+     *          thrown if it was not possible to instantiate the Composite
+     */
+    T newInstance()
+        throws ConstructionException;
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilderFactory.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilderFactory.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilderFactory.java
new file mode 100644
index 0000000..b23889c
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilderFactory.java
@@ -0,0 +1,107 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.api.value;
+
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.common.ConstructionException;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.property.PropertyDescriptor;
+
+/**
+ * Factory for Values and ValueBuilders.
+ */
+public interface ValueBuilderFactory
+{
+
+    /**
+     * Instantiate a Value of the given type.
+     *
+     * @param valueType the Value type to instantiate
+     *
+     * @return a new Value instance
+     *
+     * @throws NoSuchValueException if no value extending the mixinType has been registered
+     * @throws ConstructionException if the value could not be instantiated
+     */
+    <T> T newValue( Class<T> valueType )
+        throws NoSuchValueException, ConstructionException;
+
+    /**
+     * Create a builder for creating new Values that implements the given Value type.
+     * <p>The returned ValueBuilder can be reused to create several Values instances.</p>
+     *
+     * @param valueType an interface that describes the Composite to be instantiated
+     *
+     * @return a ValueBuilder for creation of ValueComposites implementing the interface
+     *
+     * @throws NoSuchValueException if no value extending the mixinType has been registered
+     */
+    <T> ValueBuilder<T> newValueBuilder( Class<T> valueType )
+        throws NoSuchValueException;
+
+    /**
+     * Create a builder for creating a new Value starting with the given prototype.
+     * <p>The returned ValueBuilder can only be used ONCE.</p>
+     *
+     * @param prototype a prototype the builder will use
+     *
+     * @return a ValueBuilder for creation of ValueComposites implementing the interface of the prototype
+     *
+     * @throws NoSuchValueException if no value extending the mixinType has been registered
+     */
+    <T> ValueBuilder<T> newValueBuilderWithPrototype( T prototype );
+
+    /**
+     * Create a builder for creating a new Value starting with the given state.
+     * <p>The returned ValueBuilder can only be used ONCE.</p>
+     *
+     * @param mixinType an interface that describes the Composite to be instantiated
+     * @param propertyFunction a function providing the state of properties
+     * @param associationFunction a function providing the state of associations
+     * @param manyAssociationFunction a function providing the state of many associations
+     * @param namedAssociationFunction a function providing the state of named associations
+     *
+     * @return a ValueBuilder for creation of ValueComposites implementing the interface
+     *
+     * @throws NoSuchValueException if no value extending the mixinType has been registered
+     */
+    <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 );
+
+    /**
+     * Instantiate a Value of the given type using the serialized state given as String.
+     *
+     * @param valueType the Value type to instantiate
+     * @param serializedState  the state of the Value
+     *
+     * @return a new Value instance
+     *
+     * @throws NoSuchValueException if no value extending the mixinType has been registered
+     * @throws ConstructionException if the value could not be instantiated
+     */
+    <T> T newValueFromSerializedState( Class<T> valueType, String serializedState );
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilderTemplate.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilderTemplate.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilderTemplate.java
new file mode 100644
index 0000000..59fd667
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/value/ValueBuilderTemplate.java
@@ -0,0 +1,44 @@
+/*
+ *  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.api.value;
+
+import org.apache.polygene.api.structure.ModuleDescriptor;
+
+/**
+ * Builder template for Values.
+ */
+public abstract class ValueBuilderTemplate<T>
+{
+    Class<T> type;
+
+    protected ValueBuilderTemplate( Class<T> type )
+    {
+        this.type = type;
+    }
+
+    protected abstract void build( T prototype );
+
+    public T newInstance( ModuleDescriptor module )
+    {
+        ValueBuilder<T> builder = module.instance().newValueBuilder( type );
+        build( builder.prototype() );
+        return builder.newInstance();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/value/ValueComposite.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueComposite.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueComposite.java
new file mode 100644
index 0000000..be0b54a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/value/ValueComposite.java
@@ -0,0 +1,49 @@
+/*
+ *  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.api.value;
+
+import org.apache.polygene.api.association.AssociationMixin;
+import org.apache.polygene.api.association.ManyAssociationMixin;
+import org.apache.polygene.api.association.NamedAssociationMixin;
+import org.apache.polygene.api.composite.Composite;
+import org.apache.polygene.api.mixin.Mixins;
+import org.apache.polygene.api.property.Immutable;
+
+/**
+ * ValueComposites are Composites that has state, and equality is defined from its values and not any reference nor
+ * instance references.
+ *
+ * <ul>
+ * <li>No Identity</li>
+ * <li>No Lifecycle</li>
+ * <li>Immutable</li>
+ * <li>equals()/hashCode() operates on the Properties</li>
+ * <li>Can have property and associations methods.</li>
+ * <li>Can not reference Services</li>
+ * <li>Can not have @Uses</li>
+ * </ul>
+ */
+@Immutable
+@Mixins( { AssociationMixin.class, ManyAssociationMixin.class, NamedAssociationMixin.class } )
+public interface ValueComposite
+    extends Composite
+{
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/value/ValueDescriptor.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueDescriptor.java
new file mode 100644
index 0000000..b9b3f54
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/value/ValueDescriptor.java
@@ -0,0 +1,38 @@
+/*
+ *  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.api.value;
+
+import org.apache.polygene.api.association.AssociationStateDescriptor;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.StatefulCompositeDescriptor;
+import org.apache.polygene.api.type.ValueCompositeType;
+
+/**
+ * Descriptor for ValueComposites.
+ */
+public interface ValueDescriptor
+    extends CompositeDescriptor, StatefulCompositeDescriptor
+{
+    ValueCompositeType valueType();
+
+    @Override
+    AssociationStateDescriptor state();
+}


Mime
View raw message