polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject [39/81] [abbrv] [partial] zest-java git commit: ZEST-195 ; Replace all "zest" with "polygene"
Date Sat, 17 Dec 2016 10:28:15 GMT
http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/structure/UsedLayersDescriptor.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/structure/UsedLayersDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/structure/UsedLayersDescriptor.java
new file mode 100644
index 0000000..37ad6b2
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/structure/UsedLayersDescriptor.java
@@ -0,0 +1,31 @@
+/*
+ *  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.structure;
+
+import java.util.stream.Stream;
+
+/**
+ * Used Layers Descriptor.
+ */
+public interface UsedLayersDescriptor
+{
+    Stream<? extends LayerDescriptor> layers();
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/structure/package.html
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/structure/package.html b/core/api/src/main/java/org/apache/polygene/api/structure/package.html
new file mode 100644
index 0000000..c44c4ad
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/structure/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>Application Structure 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/time/SystemTime.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/time/SystemTime.java b/core/api/src/main/java/org/apache/polygene/api/time/SystemTime.java
new file mode 100644
index 0000000..a469001
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/time/SystemTime.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.time;
+
+import java.time.Clock;
+import java.time.Instant;
+
+public class SystemTime
+{
+    private static Clock defaultClock = Clock.systemUTC();
+
+    public static Clock getDefaultClock()
+    {
+        return defaultClock;
+    }
+
+    public static void setDefaultClock(Clock defaultClock)
+    {
+        SystemTime.defaultClock = defaultClock;
+    }
+
+    public static Instant now()
+    {
+        return Instant.now(defaultClock);
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/type/CollectionType.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/CollectionType.java b/core/api/src/main/java/org/apache/polygene/api/type/CollectionType.java
new file mode 100644
index 0000000..faf19c5
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/CollectionType.java
@@ -0,0 +1,78 @@
+/*
+ *  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.type;
+
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import org.apache.polygene.api.util.Classes;
+
+/**
+ * Collection ValueType.
+ * <p>This handles Collection, List and Set types.</p>
+ */
+public final class CollectionType
+    extends ValueType
+{
+
+    public static boolean isCollection( Type type )
+    {
+        Class<?> cl = Classes.RAW_CLASS.apply( type );
+        return cl.equals( Collection.class ) || cl.equals( List.class ) || cl.equals( Set.class );
+    }
+
+    public static CollectionType collectionOf( Class<?> collectedType )
+    {
+        return new CollectionType( Collection.class, ValueType.of( collectedType ) );
+    }
+
+    public static CollectionType listOf( Class<?> collectedType )
+    {
+        return new CollectionType( List.class, ValueType.of( collectedType ) );
+    }
+
+    public static CollectionType setOf( Class<?> collectedType )
+    {
+        return new CollectionType( Set.class, ValueType.of( collectedType ) );
+    }
+    private ValueType collectedType;
+
+    public CollectionType( Class<?> type, ValueType collectedType )
+    {
+        super( type );
+        this.collectedType = collectedType;
+        if( !isCollection( type ) )
+        {
+            throw new IllegalArgumentException( type + " is not a Collection, List or Set." );
+        }
+    }
+
+    public ValueType collectedType()
+    {
+        return collectedType;
+    }
+
+    @Override
+    public String toString()
+    {
+        return super.toString() + "<" + collectedType + ">";
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/type/EnumType.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/EnumType.java b/core/api/src/main/java/org/apache/polygene/api/type/EnumType.java
new file mode 100644
index 0000000..ba7dc5a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/EnumType.java
@@ -0,0 +1,54 @@
+/*
+ *  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.type;
+
+import java.lang.reflect.Type;
+
+/**
+ * Enum ValueType.
+ */
+public final class EnumType
+    extends ValueType
+{
+
+    public static boolean isEnum( Type type )
+    {
+        if( type instanceof Class )
+        {
+            Class<?> typeClass = (Class) type;
+            return ( typeClass.isEnum() );
+        }
+        return false;
+    }
+
+    public static EnumType of( Class<?> type )
+    {
+        return new EnumType( type );
+    }
+
+    public EnumType( Class<?> type )
+    {
+        super( type );
+        if( !isEnum( type ) )
+        {
+            throw new IllegalArgumentException( type + " is not an Enum." );
+        }
+    }
+}
\ 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/type/HasTypes.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasTypes.java b/core/api/src/main/java/org/apache/polygene/api/type/HasTypes.java
new file mode 100644
index 0000000..ae1f3c9
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/HasTypes.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.type;
+
+import java.lang.reflect.Type;
+import java.util.stream.Stream;
+import org.apache.polygene.api.util.Classes;
+
+/**
+ * Has types.
+ */
+public interface HasTypes
+{
+    Stream<Class<?>> types();
+
+    default boolean hasType( Type type )
+    {
+        Class<?> rawType = Classes.RAW_CLASS.apply( type );
+        return types().map( Classes.RAW_CLASS ).anyMatch( rawType::isAssignableFrom );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/type/MapType.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/MapType.java b/core/api/src/main/java/org/apache/polygene/api/type/MapType.java
new file mode 100644
index 0000000..4046628
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/MapType.java
@@ -0,0 +1,91 @@
+/*
+ *  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.type;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+import org.apache.polygene.api.util.Classes;
+
+/**
+ * Map ValueType.
+ * <p>This handles instances of Map.</p>
+ */
+public final class MapType
+    extends ValueType
+{
+
+    private ValueType keyType;
+    private ValueType valueType;
+    private final Serialization.Variant variant;
+
+    public static boolean isMap( Type type )
+    {
+        Class<?> cl = Classes.RAW_CLASS.apply( type );
+        return Map.class.isAssignableFrom( cl );
+    }
+
+    public static MapType of( Class<?> keyType, Class<?> valueType )
+    {
+        return new MapType( Map.class, ValueType.of( keyType ), ValueType.of( valueType ) );
+    }
+
+    public static MapType of( Class<?> keyType, Class<?> valueType, Serialization.Variant variant )
+    {
+        return new MapType( Map.class, ValueType.of( keyType ), ValueType.of( valueType ), variant );
+    }
+
+    public MapType( Class<?> type, ValueType keyType, ValueType valueType )
+    {
+        this( type, keyType, valueType, Serialization.Variant.entry );
+    }
+
+    public MapType( Class<?> type, ValueType keyType, ValueType valueType, Serialization.Variant variant )
+    {
+        super( type );
+        this.keyType = keyType;
+        this.valueType = valueType;
+        this.variant = variant;
+        if( !isMap( type ) )
+        {
+            throw new IllegalArgumentException( type + " is not a Map." );
+        }
+    }
+
+    public ValueType keyType()
+    {
+        return keyType;
+    }
+
+    public ValueType valueType()
+    {
+        return valueType;
+    }
+
+    public Serialization.Variant variant()
+    {
+        return variant;
+    }
+
+    @Override
+    public String toString()
+    {
+        return super.toString() + "<" + keyType + "," + valueType + ">";
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/type/MatchTypeSpecification.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/MatchTypeSpecification.java b/core/api/src/main/java/org/apache/polygene/api/type/MatchTypeSpecification.java
new file mode 100644
index 0000000..8d8ff92
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/MatchTypeSpecification.java
@@ -0,0 +1,51 @@
+/*
+ *  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.type;
+
+import java.util.function.Predicate;
+
+/**
+ * Match Type Specification for HasTypes.
+ */
+public class MatchTypeSpecification
+    implements Predicate<HasTypes>
+{
+    private final Class<?> matchType;
+
+    public MatchTypeSpecification( Class<?> matchType )
+    {
+        this.matchType = matchType;
+    }
+
+    @Override
+    public boolean test( HasTypes item )
+    {
+        return item.types().anyMatch( matchType::isAssignableFrom );
+//        for( Class<?> type : item.types() )
+//        {
+//            if( matchType.isAssignableFrom( type ) )
+//            {
+//                return true;
+//            }
+//        }
+//        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/type/Serialization.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/Serialization.java b/core/api/src/main/java/org/apache/polygene/api/type/Serialization.java
new file mode 100644
index 0000000..981ab00
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/Serialization.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.type;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Serialization options for Property intstances.
+ * <p>
+ * The {@code entry} type represents the explicit key=keyValue, value=valueValue. For JSON serialization;
+ * </p>
+ * <pre>
+ *     [
+ *         { "key1" : "value1" },
+ *         { "key2" : "value2" }
+ *     ]
+ * </pre>
+ * <p>
+ * For XML serialization;
+ * </p>
+ * <pre>
+ *     &lt;object&gt;
+ *         &lt;
+ *     &lt;/object&gt;
+ * </pre>
+ * <p>
+ * The {@code object} type represents the explicit keyValue=valueValue.
+ * </p>
+ */
+@Retention( RetentionPolicy.RUNTIME )
+@Target( { ElementType.TYPE, ElementType.METHOD } )
+@Documented
+public @interface Serialization
+{
+    Variant value();
+
+    enum Variant
+    {
+        entry, object
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/type/ValueCompositeType.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/ValueCompositeType.java b/core/api/src/main/java/org/apache/polygene/api/type/ValueCompositeType.java
new file mode 100644
index 0000000..4cf86a6
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/ValueCompositeType.java
@@ -0,0 +1,69 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.util.Classes;
+import org.apache.polygene.api.value.ValueComposite;
+import org.apache.polygene.api.value.ValueDescriptor;
+
+/**
+ * ValueComposite ValueType.
+ */
+public final class ValueCompositeType
+    extends ValueType
+{
+    private final ValueDescriptor model;
+
+    public static boolean isValueComposite( Type type )
+    {
+        return ValueComposite.class.isAssignableFrom( Classes.RAW_CLASS.apply( type ) );
+    }
+
+    public ValueCompositeType( ValueDescriptor model )
+    {
+        super( model.types().collect( Collectors.toList() ) );
+        this.model = model;
+    }
+
+    public Stream<? extends PropertyDescriptor> properties()
+    {
+        return model.state().properties();
+    }
+
+    public Stream<? extends AssociationDescriptor> associations()
+    {
+        return model.state().associations();
+    }
+
+    public Stream<? extends AssociationDescriptor> manyAssociations()
+    {
+        return model.state().manyAssociations();
+    }
+
+    public Stream<? extends AssociationDescriptor> namedAssociations()
+    {
+        return model.state().namedAssociations();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/type/ValueType.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/ValueType.java b/core/api/src/main/java/org/apache/polygene/api/type/ValueType.java
new file mode 100644
index 0000000..13277d7
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/ValueType.java
@@ -0,0 +1,154 @@
+/*
+ *  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.type;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.util.NullArgumentException;
+
+import static java.util.stream.Collectors.joining;
+
+/**
+ * Base class for types of values in ValueComposites and Properties.
+ */
+public class ValueType
+    implements HasTypes
+{
+
+    public static ValueType of( Class<?> type )
+    {
+        return new ValueType( type );
+    }
+
+    /**
+     * Check if a non-null object is of any of the Primitive Value Types or an array of them.
+     * <p>
+     *     String, Boolean, Integer, Double, Float, Long, Byte, Short and Character and their Java primitive types
+     *     counterparts are considered as Primitive Value Types.
+     * </p>
+     * <p>
+     *     Date, BigInteger, BigDecimal and JodaTime types are not considered as Primitive Value Types.
+     * </p>
+     *
+     * @return true if object is a primitive value or an array of primitive values
+     * @throws IllegalArgumentException if object is null
+     */
+    public static boolean isPrimitiveValue( Object object )
+    {
+        NullArgumentException.validateNotNull( "object", object );
+        if( object instanceof String
+            || object instanceof Character
+            || object instanceof Boolean
+            || object instanceof Integer
+            || object instanceof Double
+            || object instanceof Float
+            || object instanceof Long
+            || object instanceof Byte
+            || object instanceof Short )
+        {
+            return true;
+        }
+        if( object.getClass().isArray() )
+        {
+            return isArrayOfPrimitiveValues( object );
+        }
+        return false;
+    }
+
+    public static boolean isIdentity( Object object )
+    {
+        return object instanceof Identity;
+    }
+
+    private static boolean isArrayOfPrimitiveValues( Object array )
+    {
+        if( array instanceof String[]
+            || array instanceof char[] || array instanceof Character[]
+            || array instanceof boolean[] || array instanceof Boolean[]
+            || array instanceof int[] || array instanceof Integer[]
+            || array instanceof double[] || array instanceof Double[]
+            || array instanceof float[] || array instanceof Float[]
+            || array instanceof long[] || array instanceof Long[]
+            || array instanceof byte[] || array instanceof Byte[]
+            || array instanceof short[] || array instanceof Short[] )
+        {
+            return true;
+        }
+        return false;
+    }
+
+    public static boolean isPrimitiveValueType( ValueType valueType )
+    {
+        return isPrimitiveValueType( valueType.mainType() );
+    }
+
+    /**
+     * @see ValueType#isPrimitiveValue(java.lang.Object) 
+     */
+    public static boolean isPrimitiveValueType( Class<?> type )
+    {
+        NullArgumentException.validateNotNull( "type", type );
+        if( String.class.isAssignableFrom( type ) )
+        {
+            return true;
+        }
+        if( type.isArray() )
+        {
+            return isPrimitiveValueType( type.getComponentType() );
+        }
+        return false;
+    }
+    protected final List<Class<?>> types;
+
+    public ValueType( Class<?> type )
+    {
+        this( Collections.singletonList( type ) );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    public ValueType( List<Class<?>> types )
+    {
+        this.types = types;
+    }
+
+    public Class<?> mainType()
+    {
+        return types.stream().findFirst().orElse( null );
+    }
+
+    @Override
+    public Stream<Class<?>> types()
+    {
+        return types.stream();
+    }
+
+    @Override
+    public String toString()
+    {
+        String name = types.stream().map( Class::getName ).collect( joining( "," ) );
+        if( name.contains( "," ) )
+        {
+            name = "{" + name + "}";
+        }
+        return name;
+    }
+}
\ 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/type/package.html
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/package.html b/core/api/src/main/java/org/apache/polygene/api/type/package.html
new file mode 100644
index 0000000..c0c3eca
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/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>Type 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/unitofwork/ConcurrentEntityModificationException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/ConcurrentEntityModificationException.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/ConcurrentEntityModificationException.java
new file mode 100644
index 0000000..7d439b0
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/ConcurrentEntityModificationException.java
@@ -0,0 +1,64 @@
+/*
+ *  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;
+
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.type.HasTypes;
+import org.apache.polygene.api.usecase.Usecase;
+
+/**
+ * This exception is thrown by UnitOfWork.complete() if any entities that are being committed
+ * had been changed while the UnitOfWork was being executed.
+ */
+public class ConcurrentEntityModificationException
+    extends UnitOfWorkCompletionException
+{
+    private static final long serialVersionUID = 3872723845064767689L;
+
+    private final Map<EntityComposite, HasTypes> concurrentlyModifiedEntities;
+
+    public ConcurrentEntityModificationException( Map<EntityComposite, HasTypes> concurrentlyModifiedEntities,
+                                                  Usecase usecase
+    )
+    {
+        super( "Entities changed concurrently, and detected in usecase '" + usecase + "'\nModified entities : " + format( concurrentlyModifiedEntities ) );
+        this.concurrentlyModifiedEntities = concurrentlyModifiedEntities;
+    }
+
+    private static String format( Map<EntityComposite, HasTypes> concurrentlyModifiedEntities )
+    {
+        return concurrentlyModifiedEntities.entrySet().stream()
+            .map( entry ->
+                      entry.getKey()
+                      + " : "
+                      + entry.getValue().types().map( Class::getSimpleName )
+                          .collect( Collectors.joining( "," ) )
+            )
+            .collect( Collectors.joining( "\n" ) );
+    }
+
+    public Map<EntityComposite, HasTypes> concurrentlyModifiedEntities()
+    {
+        return concurrentlyModifiedEntities;
+    }
+}
\ 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/unitofwork/EntityCompositeAlreadyExistsException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/EntityCompositeAlreadyExistsException.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/EntityCompositeAlreadyExistsException.java
new file mode 100644
index 0000000..dec6965
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/EntityCompositeAlreadyExistsException.java
@@ -0,0 +1,45 @@
+/*
+ *  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;
+
+import org.apache.polygene.api.entity.EntityReference;
+
+/**
+ * If you try to create an EntityComposite whose reference already exists,
+ * then this exception will be thrown.
+ */
+public class EntityCompositeAlreadyExistsException
+    extends UnitOfWorkException
+{
+    private static final long serialVersionUID = -7297710939536508481L;
+
+    private final EntityReference reference;
+
+    public EntityCompositeAlreadyExistsException( EntityReference reference)
+    {
+        super( "EntityComposite (" + reference + ") already exists." );
+        this.reference = reference;
+    }
+
+    public EntityReference reference()
+    {
+        return reference;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/unitofwork/NoSuchEntityException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/NoSuchEntityException.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/NoSuchEntityException.java
new file mode 100644
index 0000000..7b31427
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/NoSuchEntityException.java
@@ -0,0 +1,80 @@
+/*
+ *  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;
+
+import java.util.stream.Stream;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.usecase.Usecase;
+
+import static java.util.Arrays.stream;
+
+/**
+ * This exception indicates that the requested Entity with the given
+ * reference does not exist.
+ */
+public class NoSuchEntityException
+    extends UnitOfWorkException
+{
+    private final EntityReference reference;
+    private final Usecase usecase;
+    private final Class<?>[] mixinTypes;
+
+    public NoSuchEntityException(EntityReference reference, Class<?> mixinType, Usecase usecase )
+    {
+        super( "Could not find entity (" + reference + ") of type " + mixinType.getName() + " in usecase '" + usecase.name() + "'" );
+        this.reference = reference;
+        this.usecase = usecase;
+        this.mixinTypes = new Class<?>[]{ mixinType };
+    }
+
+    public NoSuchEntityException(EntityReference reference, Class<?>[] mixinTypes, Usecase usecase )
+    {
+        super( "Could not find entity (" + reference + ") of type " + toString( mixinTypes ) + " in usecase '" + usecase.name() + "'" );
+        this.reference = reference;
+        this.mixinTypes = mixinTypes;
+        this.usecase = usecase;
+    }
+
+    public NoSuchEntityException(EntityReference reference, Stream<Class<?>> types, Usecase usecase )
+    {
+        this(reference, types.toArray( Class[]::new ), usecase );
+    }
+
+    public EntityReference reference()
+    {
+        return reference;
+    }
+
+    public Class<?>[] mixinTypes()
+    {
+        return mixinTypes;
+    }
+
+    public Usecase usecase()
+    {
+        return usecase;
+    }
+
+    private static String toString( Class<?>[] mixinTypes )
+    {
+        String reduced = stream( mixinTypes ).map( Class::getName ).reduce( "", ( ret, name ) -> ret + "," + name );
+        return "[" + reduced.substring( 1 ) + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/unitofwork/NoSuchEntityTypeException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/NoSuchEntityTypeException.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/NoSuchEntityTypeException.java
new file mode 100644
index 0000000..bd038f2
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/NoSuchEntityTypeException.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.unitofwork;
+
+import java.util.stream.Collectors;
+import org.apache.polygene.api.composite.NoSuchCompositeException;
+import org.apache.polygene.api.structure.TypeLookup;
+
+/**
+ * Polygene exception to be thrown in case that an entity composite
+ * was not found during a lookup call.
+ */
+public class NoSuchEntityTypeException
+    extends NoSuchCompositeException
+{
+    public NoSuchEntityTypeException( String typeName, String moduleName, TypeLookup typeLookup )
+    {
+        super( "EntityComposite", typeName, moduleName, formatVisibleTypes( typeLookup ) );
+    }
+
+    private static String formatVisibleTypes( TypeLookup typeLookup )
+    {
+        return typeLookup.allEntities()
+            .map( descriptor -> descriptor.primaryType().getName() )
+            .collect( Collectors.joining( "\n", "Visible entity types are:\n", "" ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWork.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWork.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWork.java
new file mode 100644
index 0000000..10e4216
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWork.java
@@ -0,0 +1,528 @@
+/*
+ *  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;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.association.ManyAssociation;
+import org.apache.polygene.api.association.NamedAssociation;
+import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.AmbiguousTypeException;
+import org.apache.polygene.api.entity.EntityBuilder;
+import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.identity.HasIdentity;
+import org.apache.polygene.api.entity.LifecycleException;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.property.PropertyDescriptor;
+import org.apache.polygene.api.query.Query;
+import org.apache.polygene.api.query.QueryBuilder;
+import org.apache.polygene.api.structure.MetaInfoHolder;
+import org.apache.polygene.api.structure.ModuleDescriptor;
+import org.apache.polygene.api.usecase.Usecase;
+
+/**
+ * All operations on entities goes through an UnitOfWork.
+ * <p>
+ * A UnitOfWork allows you to access
+ * Entities and work with them. All modifications to Entities are recorded by the UnitOfWork,
+ * and at the end they may be sent to the underlying EntityStore by calling complete(). If the
+ * UoW was read-only you may instead simply discard() it.
+ * </p>
+ * <p>
+ * A UoW differs from a traditional Transaction in the sense that it is not tied at all to the underlying
+ * storage resource. Because of this there is no timeout on a UoW. It can be very short or very long.
+ * Another difference is that if a call to complete() fails, and the cause is validation errors in the
+ * Entities of the UoW, then these can be corrected and the UoW retried. By contrast, when a Transaction
+ * commit fails, then the whole transaction has to be done from the beginning again.
+ * </p>
+ * <p>
+ * A UoW can be associated with a Usecase. A Usecase describes the metainformation about the process
+ * to be performed by the UoW.
+ * </p>
+ * <p>
+ * If a code block that uses a UoW throws an exception you need to ensure that this is handled properly,
+ * and that the UoW is closed before returning. Because discard() is a no-op if the UoW is closed, we therefore
+ * recommend the following template to be used:
+ * </p>
+ * <pre>
+ *     UnitOfWork uow = module.newUnitOfWork();
+ *     try
+ *     {
+ *         ...
+ *         uow.complete();
+ *     }
+ *     finally
+ *     {
+ *         uow.discard();
+ *     }
+ * </pre>
+ * <p>
+ * This ensures that in the happy case the UoW is completed, and if any exception is thrown the UoW is discarded. After
+ * the UoW has completed the discard() method doesn't do anything, and so has no effect. You can choose to either add
+ * catch blocks for any exceptions, including exceptions from complete(), or skip them.
+ * </p>
+ * <p>
+ * Since 2.1 you can leverage Java 7 Automatic Resource Management (ie. Try With Resources) and use the following
+ * template instead:
+ * </p>
+ * <pre>
+ *     try( UnitOfWork uow = module.newUnitOfWork() )
+ *     {
+ *         ...
+ *         uow.complete();
+ *     }
+ * </pre>
+ * <p>
+ * It has the very same effect than the template above but is shorter.</p>
+ */
+public interface UnitOfWork extends MetaInfoHolder, AutoCloseable
+{
+
+    /**
+     * Get the UnitOfWorkFactory that this UnitOfWork was created from.
+     *
+     * @return The UnitOfWorkFactory instance that was used to create this UnitOfWork.
+     */
+    UnitOfWorkFactory unitOfWorkFactory();
+
+    Instant currentTime();
+
+    /**
+     * Get the Usecase for this UnitOfWork
+     *
+     * @return the Usecase
+     */
+    Usecase usecase();
+
+    void setMetaInfo( Object metaInfo );
+
+    <T> Query<T> newQuery( QueryBuilder<T> queryBuilder );
+
+//    DataSet newDataSetBuilder(Specification<?>... constraints);
+
+    /**
+     * Create a new Entity which implements the given mixin type.
+     * <p>
+     * An EntityComposite
+     * will be chosen according to what has been registered and the visibility rules
+     * for Modules and Layers will be considered. If several
+     * EntityComposites implement the type then an AmbiguousTypeException will be thrown.
+     * </p>
+     * <p>
+     * The reference of the Entity will be generated by the IdentityGenerator of the Module of the EntityComposite.
+     * </p>
+     *
+     * @param type the mixin type that the EntityComposite must implement
+     *
+     * @return a new Entity
+     *
+     * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered
+     * @throws AmbiguousTypeException    If several mixins implement the given type
+     * @throws LifecycleException        if the entity cannot be created
+     */
+    <T> T newEntity( Class<T> type )
+        throws NoSuchEntityTypeException, AmbiguousTypeException, LifecycleException;
+
+    /**
+     * Create a new Entity which implements the given mixin type. An EntityComposite
+     * will be chosen according to what has been registered and the visibility rules
+     * for Modules and Layers will be considered. If several
+     * EntityComposites implement the type then an AmbiguousTypeException will be thrown.
+     *
+     * @param type     the mixin type that the EntityComposite must implement
+     * @param identity the reference of the new Entity
+     *
+     * @return a new Entity
+     *
+     * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered
+     * @throws AmbiguousTypeException    If several mixins implement the given type
+     * @throws LifecycleException        if the entity cannot be created
+     */
+    <T> T newEntity( Class<T> type, @Optional Identity identity )
+        throws NoSuchEntityTypeException, AmbiguousTypeException, LifecycleException;
+
+    /**
+     * Create a new EntityBuilder for an EntityComposite which implements the given mixin type. An EntityComposite
+     * will be chosen according to what has been registered and the visibility rules
+     * for Modules and Layers will be considered. If several
+     * EntityComposites implement the type then an AmbiguousTypeException will be thrown.
+     *
+     * @param type the mixin type that the EntityComposite must implement
+     *
+     * @return a new EntityBuilder
+     *
+     * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered
+     * @throws AmbiguousTypeException    If several mixins implement the given type
+     */
+    <T> EntityBuilder<T> newEntityBuilder( Class<T> type )
+        throws NoSuchEntityTypeException, AmbiguousTypeException;
+
+    /**
+     * Create a new EntityBuilder for an EntityComposite which implements the given mixin type. An EntityComposite
+     * will be chosen according to what has been registered and the visibility rules
+     * for Modules and Layers will be considered. If several
+     * mixins implement the type then an AmbiguousTypeException will be thrown.
+     *
+     * @param type     the mixin type that the EntityComposite must implement
+     * @param identity the reference of the new Entity
+     *
+     * @return a new EntityBuilder
+     *
+     * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered
+     * @throws AmbiguousTypeException    If several mixins implement the given type
+     */
+    <T> EntityBuilder<T> newEntityBuilder( Class<T> type, @Optional Identity identity )
+        throws NoSuchEntityTypeException, AmbiguousTypeException;
+
+    /**
+     * Create a new EntityBuilder for an EntityComposite wich implements the given mixin type starting with the given
+     * state.
+     * <p>
+     * An EntityComposite will be chosen according to what has been registered and the visibility rules for Modules and
+     * Layers will be considered.
+     *
+     * @param <T>                      Entity type
+     * @param type                     Entity type
+     * @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 new EntityBuilder starting with the given state
+     *
+     * @throws NoSuchEntityTypeException if no EntityComposite type of the given mixin type has been registered
+     * @throws AmbiguousTypeException    If several mixins implement the given type
+     */
+    <T> EntityBuilder<T> newEntityBuilderWithState( Class<T> type,
+                                                    Function<PropertyDescriptor, Object> propertyFunction,
+                                                    Function<AssociationDescriptor, EntityReference> associationFunction,
+                                                    Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction,
+                                                    Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction
+    )
+        throws NoSuchEntityTypeException, AmbiguousTypeException;
+
+    /**
+     * Create a new EntityBuilder for an EntityComposite wich implements the given mixin type starting with the given
+     * state.
+     * <p>
+     * An EntityComposite will be chosen according to what has been registered and the visibility rules for Modules and
+     * Layers will be considered.
+     *
+     * @param <T>                      Entity type
+     * @param type                     Entity type
+     * @param identity                 the reference of the new Entity
+     * @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 new EntityBuilder starting with the given state
+     *
+     * @throws NoSuchEntityTypeException If no mixins implements the given type
+     * @throws AmbiguousTypeException    If several mixins implement the given type
+     */
+    <T> EntityBuilder<T> newEntityBuilderWithState( Class<T> type, @Optional Identity identity,
+                                                    Function<PropertyDescriptor, Object> propertyFunction,
+                                                    Function<AssociationDescriptor, EntityReference> associationFunction,
+                                                    Function<AssociationDescriptor, Stream<EntityReference>> manyAssociationFunction,
+                                                    Function<AssociationDescriptor, Stream<Map.Entry<String, EntityReference>>> namedAssociationFunction
+    )
+        throws NoSuchEntityTypeException, AmbiguousTypeException;
+
+    /**
+     * Find an Entity of the given mixin type with the give reference. This
+     * method verifies that it exists by asking the underlying EntityStore.
+     *
+     * @param type     of the entity
+     * @param identity of the entity
+     *
+     * @return the entity
+     *
+     * @throws NoSuchEntityTypeException if no entity type could be found
+     * @throws NoSuchEntityException     if the entity could not be found
+     */
+    <T> T get( Class<T> type, Identity identity )
+        throws NoSuchEntityTypeException, NoSuchEntityException;
+
+    /**
+     * If you have a reference to an Entity from another
+     * UnitOfWork and want to create a reference to it in this
+     * UnitOfWork, then call this method.
+     *
+     * @param entity the Entity to be dereferenced
+     *
+     * @return an Entity from this UnitOfWork
+     *
+     * @throws NoSuchEntityTypeException if no entity type could be found
+     */
+    <T> T get( T entity )
+        throws NoSuchEntityTypeException;
+
+    /**
+     * Remove the given Entity.
+     *
+     * @param entity the Entity to be removed.
+     *
+     * @throws LifecycleException if the entity could not be removed
+     */
+    void remove( Object entity )
+        throws LifecycleException;
+
+    /**
+     * Complete this UnitOfWork. This will send all the changes down to the underlying
+     * EntityStore's.
+     *
+     * @throws UnitOfWorkCompletionException         if the UnitOfWork could not be completed
+     * @throws ConcurrentEntityModificationException if entities have been modified by others
+     */
+    void complete()
+        throws UnitOfWorkCompletionException, ConcurrentEntityModificationException;
+
+    /**
+     * Discard this UnitOfWork. Use this if a failure occurs that you cannot handle,
+     * or if the usecase was of a read-only character. This is a no-op of the UnitOfWork
+     * is already closed.
+     */
+    void discard();
+
+    /**
+     * Discard this UnitOfWork. Use this if a failure occurs that you cannot handle,
+     * or if the usecase was of a read-only character. This is a no-op of the UnitOfWork
+     * is already closed. This simply call the {@link #discard()} method and is an
+     * implementation of the {@link AutoCloseable} interface providing Try With Resources
+     * support for UnitOfWork.
+     */
+    @Override
+    public void close();
+
+    /**
+     * Check if the UnitOfWork is open. It is closed after either complete() or discard()
+     * methods have been called successfully.
+     *
+     * @return true if the UnitOfWork is open.
+     */
+    boolean isOpen();
+
+    /**
+     * Check if the UnitOfWork is paused. It is not paused after it has been create through the
+     * UnitOfWorkFactory, and it can be paused by calling {@link #pause()} and then resumed by calling
+     * {@link #resume()}.
+     *
+     * @return true if this UnitOfWork has been paused.
+     */
+    boolean isPaused();
+
+    /**
+     * Pauses this UnitOfWork.
+     * <p>
+     * Calling this method will cause the underlying UnitOfWork to become the current UnitOfWork until the
+     * the resume() method is called. It is the client's responsibility not to drop the reference to this
+     * UnitOfWork while being paused.
+     * </p>
+     */
+    void pause();
+
+    /**
+     * Resumes this UnitOfWork to again become the current UnitOfWork.
+     */
+    void resume();
+
+    /**
+     * Register a callback. Callbacks are invoked when the UnitOfWork
+     * is completed or discarded.
+     *
+     * @param callback a callback to be registered with this UnitOfWork
+     */
+    void addUnitOfWorkCallback( UnitOfWorkCallback callback );
+
+    /**
+     * Unregister a callback. Callbacks are invoked when the UnitOfWork
+     * is completed or discarded.
+     *
+     * @param callback a callback to be unregistered with this UnitOfWork
+     */
+    void removeUnitOfWorkCallback( UnitOfWorkCallback callback );
+
+    /**
+     * Converts the provided Entity to a Value of the same type.
+     * This is a convenience method to convert an EntityComposite to a ValueComposite.
+     * <p>
+     * All Property values are transferred across as-is, and the Association, ManyAssociation
+     * and NamedAssociatino values are kept in the ValueComposite as EntityReferences
+     * until they are dereferenced (get() and other methods), and IF a UnitOfWork is
+     * present at dereferencing the corresponding EntityCompoiste is retrieved from the
+     * EntityStore. If there is not an UnitOfWork present, an exception is thrown.
+     * </p>
+     * <p>
+     * For this to work, the Composites (both Entity and Value) must not declare the
+     * EntityComposite and ValueComposite super types, but rely on the declaration in
+     * the assembly, and also extend the Identity supertype.
+     * </p>
+     * Example;
+     * <pre><code>
+     *     public interface Person extends Identity { ... };
+     *     public class MyAssembler
+     *     {
+     *         public void assemble( ModuleAssembly module )
+     *         {
+     *             module.values( Person.class );
+     *             module.entities( Person.class );
+     *         }
+     *     }
+     * </code></pre>
+     *
+     * @param <T>             The generic shared type
+     * @param primaryType     The shared type for which the properties and associations will
+     *                        be converted. Properties outside this type will be ignored.
+     * @param entityComposite The entity to be convered.
+     *
+     * @return The Value
+     */
+    <T extends HasIdentity> T toValue(Class<T> primaryType, T entityComposite );
+
+    /**
+     * Converts all the entities referenced in the ManyAssociation into a List of values of the same type.
+     *
+     * <p>
+     * All the referenced entities inside the association will be fetched from the underlying entity store,
+     * which is potentially very expensive operation. Each of the fetched entities will be passed to
+     * {@link #toValue(Class, HasIdentity)}, and its associations will NOT be converted into values, but remain
+     * {@link EntityReference} values. Hence there is no problem with circular references.
+     * </p>
+     *
+     * <p>
+     * For this to work, the type &lt;T&gt; must be registered at bootstrap as both an Entity and a Value, and
+     * as seen in the method signature, also be sub-type of {@link HasIdentity}.
+     * </p>
+     *
+     * @param association The association of entities to be converted into values.
+     * @param <T>         The primary type of the association.
+     *
+     * @return A List of ValueComposites that has been converted from EntityComposites referenced by the Associations.
+     *
+     * @see #toValue(Class, HasIdentity)
+     */
+    <T extends HasIdentity> List<T> toValueList(ManyAssociation<T> association );
+
+    /**
+     * Converts all the entities referenced in the ManyAssociation into a Set of values of the same type.
+     *
+     * <p>
+     * All the referenced entities inside the association will be fetched from the underlying entity store,
+     * which is potentially very expensive operation. However, any duplicate EntityReferences in the association
+     * will be dropped before the fetch occurs. Each of the fetched entities will be passed to
+     * {@link #toValue(Class, HasIdentity)}, and its associations will NOT be converted into values, but remain
+     * {@link EntityReference} values. Hence there is no problem with circular references.
+     * </p>
+     *
+     * <p>
+     * For this to work, the type &lt;T&gt; must be registered at bootstrap as both an Entity and a Value, and
+     * as seen in the method signature, also be sub-type of {@link HasIdentity}.
+     * </p>
+     *
+     * @param association The association of entities to be converted into values.
+     * @param <T>         The primary type of the association.
+     *
+     * @return A List of ValueComposites that has been converted from EntityComposites referenced by the Associations.
+     *
+     * @see #toValue(Class, HasIdentity)
+     */
+    <T extends HasIdentity> Set<T> toValueSet(ManyAssociation<T> association );
+
+    /**
+     * Converts the {@link NamedAssociation} into a Map with a String key and a ValueComposite as the value.
+     *
+     * <p>
+     * A {@link NamedAssociation} is effectively a Map with a String key and an EntityReference as the value. The
+     * EntityReference is fetched from the entity store and converted into a value of the same type.Each of the fetched
+     * entities will be passed to {@link #toValue(Class, HasIdentity)}, and its associations will NOT be converted into
+     * values, but remain {@link EntityReference} values. Hence there is no problem with circular references.
+     * </p>
+     * <p>
+     * For this to work, the type &lt;T&gt; must be registered at bootstrap as both an Entity and a Value, and
+     * as seen in the method signature, also be sub-type of {@link HasIdentity}.
+     * </p>
+     *
+     * @param association The association of entities to be converted into values.
+     * @param <T>         The primary type of the association.
+     *
+     * @return A List of ValueComposites that has been converted from EntityComposites referenced by the Associations.
+     *
+     * @see #toValue(Class, HasIdentity)
+     */
+    <T extends HasIdentity> Map<String, T> toValueMap(NamedAssociation<T> association );
+
+    /**
+     * Converts the provided Value to an Entity of the same type.
+     * This is a convenience method to convert a ValueComposite to an EntityComposite.
+     * <p>
+     * All Property values are transferred across as-is (no deep copy in case mutable
+     * types (DISCOURAGED!) are used), and the Association, ManyAssociation
+     * and NamedAssociatino that were in the ValueComposite as EntityReferences are
+     * transferred into the EntityComposite correctly, and can be dereferenced.
+     * </p>
+     * <p>
+     * This method MUST be called within a UnitOfWork.
+     * </p>
+     * <p>
+     * If an Entity with the Identity in the ValueComposite already exists, then that
+     * Entity is updated with the values from the ValueComposite. If an Entity of
+     * that Identity doesn't exist a new one is created.
+     * </p>
+     * <p>
+     * For this to work, the Composites (both Entity and Value) must not declare the
+     * EntityComposite and ValueComposite super types, but rely on the declaration in
+     * the assembly, and also extend the Identity supertype.
+     * </p>
+     * Example;
+     * <pre><code>
+     *     public interface Person extends Identity { ... };
+     *     public class MyAssembler
+     *     {
+     *         public void assemble( ModuleAssembly module )
+     *         {
+     *             module.values( Person.class );
+     *             module.entities( Person.class );
+     *         }
+     *     }
+     * </code></pre>
+     *
+     * @param <T>            The generic shared type
+     * @param primaryType    The shared type for which the properties and associations will
+     *                       be converted. Properties outside this type will be ignored.
+     * @param valueComposite The Value to be convered into an Entity.
+     *
+     * @return The new or updated Entity
+     */
+    <T extends HasIdentity> T toEntity(Class<T> primaryType, T valueComposite );
+
+    /**
+     * The Module of the UnitOfWork is defined as the Module the UnitOfWorkFactory belonged to from where the
+     * UnitOfWork was created.
+     *
+     * @return the Module where this UnitOfWork was initialized.
+     */
+    ModuleDescriptor module();
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkCallback.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkCallback.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkCallback.java
new file mode 100644
index 0000000..f8e467b
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkCallback.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.unitofwork;
+
+/**
+ * Callback interface for UnitOfWork completion or discard. Implementations
+ * of this interface can be registered through {@link UnitOfWork#addUnitOfWorkCallback(UnitOfWorkCallback)}.
+ *
+ * If Entities implement this interface they will also receive invocations of this callback interface.
+ */
+public interface UnitOfWorkCallback
+{
+    /**
+     * This is called before the completion of the UnitOfWork.
+     * The callback may do any validation checks and throw
+     * UnitOfWorkCompletionException if there is any reason
+     * why the UnitOfWork is not in a valid state to be completed.
+     *
+     * @throws UnitOfWorkCompletionException
+     */
+    void beforeCompletion()
+        throws UnitOfWorkCompletionException;
+
+    /**
+     * This is called after the completion or discarding
+     * of the UnitOfWork. The callback may do any cleanup
+     * necessary related to the UnitOfWork. Note that the
+     * UnitOfWork is no longer active when this method is
+     * called, so no methods on it may be invoked.
+     *
+     * @param status
+     */
+    void afterCompletion( UnitOfWorkStatus status );
+
+    enum UnitOfWorkStatus
+    {
+        COMPLETED, DISCARDED
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkCompletionException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkCompletionException.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkCompletionException.java
new file mode 100644
index 0000000..0fd8335
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkCompletionException.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.unitofwork;
+
+/**
+ * When an attempt to {@link UnitOfWork#complete()} an UnitOfWork
+ * fails, this exception will be thrown.
+ */
+public class UnitOfWorkCompletionException
+    extends RuntimeException
+{
+    private static final long serialVersionUID = 6531642131384516904L;
+
+    public UnitOfWorkCompletionException()
+    {
+    }
+
+    public UnitOfWorkCompletionException( String string )
+    {
+        super( string );
+    }
+
+    public UnitOfWorkCompletionException( String string, Throwable throwable )
+    {
+        super( string, throwable );
+    }
+
+    public UnitOfWorkCompletionException( Throwable throwable )
+    {
+        super( throwable );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkException.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkException.java
new file mode 100644
index 0000000..fdf6903
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkException.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.unitofwork;
+
+/**
+ * Base Exception for UnitOfWork related concerns.
+ */
+public class UnitOfWorkException
+    extends RuntimeException
+{
+    private static final long serialVersionUID = -8544178439804058558L;
+
+    public UnitOfWorkException()
+    {
+    }
+
+    public UnitOfWorkException( String message )
+    {
+        super( message );
+    }
+
+    public UnitOfWorkException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+    public UnitOfWorkException( 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/unitofwork/UnitOfWorkFactory.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkFactory.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkFactory.java
new file mode 100644
index 0000000..98d23ba
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkFactory.java
@@ -0,0 +1,97 @@
+/*
+ *  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;
+
+import java.time.Instant;
+import org.apache.polygene.api.entity.EntityComposite;
+import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.api.usecase.Usecase;
+
+/**
+ * Factory for UnitOfWork.
+ */
+public interface UnitOfWorkFactory
+{
+    /**
+     * Create a new UnitOfWork and associate it with the current thread.
+     * <p>
+     * The UnitOfWork will use the default Usecase settings.
+     * </p>
+     * <p>
+     * Current time will be set to {@link SystemTime#now()}
+     * </p>
+     * @return a new UnitOfWork
+     */
+    UnitOfWork newUnitOfWork();
+
+    /**
+     * Create a new UnitOfWork and associate it with the current thread.
+     * <p>
+     * The UnitOfWork will use the default Usecase settings.
+     * </p>
+     * @return a new UnitOfWork
+     */
+    UnitOfWork newUnitOfWork( Instant currentTime );
+
+    /**
+     * Create a new UnitOfWork for the given Usecase and associate it with the current thread.
+     * <p>
+     * Current time will be set to {@link SystemTime#now()}
+     * </p>
+     * @param usecase the Usecase for this UnitOfWork
+     *
+     * @return a new UnitOfWork
+     */
+    UnitOfWork newUnitOfWork( Usecase usecase );
+
+    /**
+     * Create a new UnitOfWork for the given Usecase and associate it with the current thread.
+     *
+     * @param usecase the Usecase for this UnitOfWork
+     *
+     * @return a new UnitOfWork
+     */
+    UnitOfWork newUnitOfWork( Usecase usecase, Instant currentTime );
+
+    /**
+     * @return true if there is an active UnitOfWork associated with the executing thread
+     */
+    boolean isUnitOfWorkActive();
+
+    /**
+     * Returns the UnitOfWork that is currently associated with the executing thread.
+     *
+     * @return The current UnitOfWork associated with the executing thread
+     *
+     * @throws IllegalStateException if no current UnitOfWork is active
+     */
+    UnitOfWork currentUnitOfWork()
+        throws IllegalStateException;
+
+    /**
+     * Returns the UnitOfWork that the EntityComposite is bound to.
+     *
+     * @param entity the entity to be checked.
+     *
+     * @return The UnitOfWork instance that the Entity is bound to, or null if the entity is not associated with
+     *         any UnitOfWork.
+     */
+    UnitOfWork getUnitOfWork( EntityComposite entity );
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkOptions.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkOptions.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkOptions.java
new file mode 100644
index 0000000..02c6d5a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkOptions.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.unitofwork;
+
+/**
+ * Set instances of this in MetaInfo on UnitOfWork or the associated Usecase.
+ *  <p>
+ * Options:
+ *  </p>
+ * <p>
+ * "pruneOnPause": if true, then clear out all instances that have been loaded in the UoW but not modified
+ * </p>
+ */
+public class UnitOfWorkOptions
+{
+    private boolean pruneOnPause = false;
+
+    public UnitOfWorkOptions( boolean pruneOnPause )
+    {
+        this.pruneOnPause = pruneOnPause;
+    }
+
+    public boolean isPruneOnPause()
+    {
+        return pruneOnPause;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkTemplate.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkTemplate.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkTemplate.java
new file mode 100644
index 0000000..1c821c3
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/UnitOfWorkTemplate.java
@@ -0,0 +1,94 @@
+/*
+ *  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;
+
+import org.apache.polygene.api.structure.Module;
+import org.apache.polygene.api.usecase.Usecase;
+
+/**
+ * UnitOfWork Template.
+ */
+public abstract class UnitOfWorkTemplate<RESULT, ThrowableType extends Throwable>
+{
+    private Usecase usecase = Usecase.DEFAULT;
+    private int retries = 10;
+    private boolean complete = true;
+
+    protected UnitOfWorkTemplate()
+    {
+    }
+
+    protected UnitOfWorkTemplate( int retries, boolean complete )
+    {
+        this.retries = retries;
+        this.complete = complete;
+    }
+
+    protected UnitOfWorkTemplate( Usecase usecase, int retries, boolean complete )
+    {
+        this.usecase = usecase;
+        this.retries = retries;
+        this.complete = complete;
+    }
+
+    protected abstract RESULT withUnitOfWork( UnitOfWork uow )
+        throws ThrowableType;
+
+    @SuppressWarnings( "unchecked" )
+    public RESULT withModule( Module module )
+        throws ThrowableType, UnitOfWorkCompletionException
+    {
+        int loop = 0;
+        ThrowableType ex = null;
+        do
+        {
+            UnitOfWork uow = module.unitOfWorkFactory().newUnitOfWork( usecase );
+
+            try
+            {
+                RESULT result = withUnitOfWork( uow );
+                if( complete )
+                {
+                    try
+                    {
+                        uow.complete();
+                        return result;
+                    }
+                    catch( ConcurrentEntityModificationException e )
+                    {
+                        // Retry?
+                        ex = (ThrowableType) e;
+                    }
+                }
+            }
+            catch( Throwable e )
+            {
+                ex = (ThrowableType) e;
+            }
+            finally
+            {
+                uow.discard();
+            }
+        }
+        while( loop++ < retries );
+
+        throw ex;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/1c722f44/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkConcern.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkConcern.java b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkConcern.java
new file mode 100644
index 0000000..f982c45
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/unitofwork/concern/UnitOfWorkConcern.java
@@ -0,0 +1,212 @@
+/*
+ *  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.reflect.Method;
+import java.lang.reflect.UndeclaredThrowableException;
+import org.apache.polygene.api.common.AppliesTo;
+import org.apache.polygene.api.concern.GenericConcern;
+import org.apache.polygene.api.injection.scope.Invocation;
+import org.apache.polygene.api.injection.scope.Structure;
+import org.apache.polygene.api.unitofwork.ConcurrentEntityModificationException;
+import org.apache.polygene.api.unitofwork.UnitOfWork;
+import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
+import org.apache.polygene.api.usecase.Usecase;
+import org.apache.polygene.api.usecase.UsecaseBuilder;
+
+/**
+ * {@code UnitOfWorkConcern} manages the unit of work complete, discard and retry policy.
+ *
+ * @see UnitOfWorkPropagation
+ * @see UnitOfWorkDiscardOn
+ */
+@AppliesTo( UnitOfWorkPropagation.class )
+public class UnitOfWorkConcern
+    extends GenericConcern
+{
+    private static final Class<?>[] DEFAULT_DISCARD_CLASSES = new Class[]{ Throwable.class };
+
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    @Invocation
+    private UnitOfWorkPropagation propagation;
+
+    /**
+     * Handles method with {@code UnitOfWorkPropagation} annotation.
+     *
+     * @param proxy  The object.
+     * @param method The invoked method.
+     * @param args   The method arguments.
+     *
+     * @return The returned value of method invocation.
+     *
+     * @throws Throwable Thrown if the method invocation throw exception.
+     */
+    @Override
+    public Object invoke( Object proxy, Method method, Object[] args )
+        throws Throwable
+    {
+        UnitOfWorkPropagation.Propagation propagationPolicy = propagation.value();
+        if( propagationPolicy == UnitOfWorkPropagation.Propagation.REQUIRED )
+        {
+            if( uowf.isUnitOfWorkActive() )
+            {
+                //noinspection ConstantConditions
+                return next.invoke( proxy, method, args );
+            }
+            else
+            {
+                Usecase usecase = usecase();
+                return invokeWithCommit( proxy, method, args, uowf.newUnitOfWork( usecase ) );
+            }
+        }
+        else if( propagationPolicy == UnitOfWorkPropagation.Propagation.MANDATORY )
+        {
+            if( !uowf.isUnitOfWorkActive() )
+            {
+                throw new IllegalStateException( "UnitOfWork was required but there is no available unit of work." );
+            }
+        }
+        else if( propagationPolicy == UnitOfWorkPropagation.Propagation.REQUIRES_NEW )
+        {
+            Usecase usecase = usecase();
+            return invokeWithCommit( proxy, method, args, uowf.newUnitOfWork( usecase ) );
+        }
+        //noinspection ConstantConditions
+        return next.invoke( proxy, method, args );
+    }
+
+    private Usecase usecase()
+    {
+        String usecaseName = propagation.usecase();
+        Usecase usecase;
+        if( usecaseName == null )
+        {
+            usecase = Usecase.DEFAULT;
+        }
+        else
+        {
+            usecase = UsecaseBuilder.newUsecase( usecaseName );
+        }
+        return usecase;
+    }
+
+    protected Object invokeWithCommit( Object proxy, Method method, Object[] args, UnitOfWork currentUnitOfWork )
+        throws Throwable
+    {
+        try
+        {
+            UnitOfWorkRetry retryAnnot = method.getAnnotation( UnitOfWorkRetry.class );
+            int maxTries = 0;
+            long delayFactor = 0;
+            long initialDelay = 0;
+            if( retryAnnot != null )
+            {
+                maxTries = retryAnnot.retries();
+                initialDelay = retryAnnot.initialDelay();
+                delayFactor = retryAnnot.delayFactor();
+            }
+            int retry = 0;
+            while( true )
+            {
+                //noinspection ConstantConditions
+                Object result = next.invoke( proxy, method, args );
+                try
+                {
+                    currentUnitOfWork.complete();
+                    return result;
+                }
+                catch( UndeclaredThrowableException e )
+                {
+                    Throwable undeclared = e.getUndeclaredThrowable();
+                    if( undeclared instanceof ConcurrentEntityModificationException )
+                    {
+                        ConcurrentEntityModificationException ceme = (ConcurrentEntityModificationException) undeclared;
+                        currentUnitOfWork = checkRetry( maxTries, delayFactor, initialDelay, retry, ceme );
+                        retry++;
+                    }
+                    else
+                    {
+                        throw e;
+                    }
+                }
+                catch( ConcurrentEntityModificationException e )
+                {
+                    currentUnitOfWork = checkRetry( maxTries, delayFactor, initialDelay, retry, e );
+                    retry++;
+                }
+            }
+        }
+        catch( Throwable throwable )
+        {
+            // Discard only if this concern create a unit of work
+            discardIfRequired( method, currentUnitOfWork, throwable );
+            throw throwable;
+        }
+    }
+
+    private UnitOfWork checkRetry( int maxTries,
+                                   long delayFactor,
+                                   long initialDelay,
+                                   int retry,
+                                   ConcurrentEntityModificationException e
+    )
+        throws ConcurrentEntityModificationException, InterruptedException
+    {
+        if( retry >= maxTries )
+        {
+            throw e;
+        }
+        uowf.currentUnitOfWork().discard();
+        Thread.sleep( initialDelay + retry * delayFactor );
+        return uowf.newUnitOfWork( usecase() );
+    }
+
+    /**
+     * Discard unit of work if the discard policy match.
+     *
+     * @param aMethod     The invoked method. This argument must not be {@code null}.
+     * @param aUnitOfWork The current unit of work. This argument must not be {@code null}.
+     * @param aThrowable  The exception thrown. This argument must not be {@code null}.
+     */
+    protected void discardIfRequired( Method aMethod, UnitOfWork aUnitOfWork, Throwable aThrowable )
+    {
+        UnitOfWorkDiscardOn discardPolicy = aMethod.getAnnotation( UnitOfWorkDiscardOn.class );
+        Class<?>[] discardClasses;
+        if( discardPolicy != null )
+        {
+            discardClasses = discardPolicy.value();
+        }
+        else
+        {
+            discardClasses = DEFAULT_DISCARD_CLASSES;
+        }
+
+        Class<? extends Throwable> aThrowableClass = aThrowable.getClass();
+        for( Class<?> discardClass : discardClasses )
+        {
+            if( discardClass.isAssignableFrom( aThrowableClass ) )
+            {
+                aUnitOfWork.discard();
+            }
+        }
+    }
+}
\ No newline at end of file


Mime
View raw message