polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nic...@apache.org
Subject [32/51] [abbrv] [partial] zest-java git commit: Revert "First round of changes to move to org.apache.zest namespace."
Date Fri, 31 Jul 2015 02:47:51 GMT
http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/util/Base64Encoder.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/util/Base64Encoder.java b/core/api/src/main/java/org/qi4j/api/util/Base64Encoder.java
new file mode 100644
index 0000000..9246b13
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/util/Base64Encoder.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2009 Alin Dreghiciu.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.qi4j.api.util;
+
+/**
+ * Base64Encoder.
+ */
+public final class Base64Encoder
+{
+
+    /**
+     * Utility class. ment to be used via static methods.
+     */
+    private Base64Encoder()
+    {
+        // utility class
+    }
+
+    /**
+     * Encodes a String into a base 64 String. The resulting encoding is chunked at 76 bytes.
+     *
+     * @param s String to encode.
+     *
+     * @return encoded string.
+     */
+    public static String encode( String s, boolean includePadding )
+    {
+        byte[] sBytes = s.getBytes();
+        sBytes = encode( sBytes, includePadding );
+        s = new String( sBytes );
+        return s;
+    }
+
+    /**
+     * Decodes a base 64 String into a String.
+     *
+     * @param s String to decode.
+     *
+     * @return encoded string.
+     *
+     * @throws java.lang.IllegalArgumentException
+     *          _ If the given byte array was not valid base64 encoding.
+     */
+    public static String decode( String s )
+        throws IllegalArgumentException
+    {
+        s = s.replaceAll( "\n", "" );
+        s = s.replaceAll( "\r", "" );
+        byte[] sBytes = s.getBytes();
+        sBytes = decode( sBytes );
+        s = new String( sBytes );
+        return s;
+    }
+
+    private static final byte[] ALPHASET =
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".getBytes();
+
+    private static final int I6O2 = 255 - 3;
+    private static final int O6I2 = 3;
+    private static final int I4O4 = 255 - 15;
+    private static final int O4I4 = 15;
+    private static final int I2O6 = 255 - 63;
+    private static final int O2I6 = 63;
+
+    /**
+     * Encodes a byte array into a base 64 byte array.
+     *
+     * @param dData byte array to encode.
+     *
+     * @return encoded byte array.
+     */
+    public static byte[] encode( byte[] dData, boolean includePadding )
+    {
+        if( dData == null )
+        {
+            throw new IllegalArgumentException( "Cannot encode null" );
+        }
+        byte[] eData = new byte[ ( ( dData.length + 2 ) / 3 ) * 4 ];
+
+        int eIndex = 0;
+        for( int i = 0; i < dData.length; i += 3 )
+        {
+            int d1;
+            int d2 = 0;
+            int d3 = 0;
+            int e1;
+            int e2;
+            int e3;
+            int e4;
+            int pad = 0;
+
+            d1 = dData[ i ];
+            if( ( i + 1 ) < dData.length )
+            {
+                d2 = dData[ i + 1 ];
+                if( ( i + 2 ) < dData.length )
+                {
+                    d3 = dData[ i + 2 ];
+                }
+                else
+                {
+                    pad = 1;
+                }
+            }
+            else
+            {
+                pad = 2;
+            }
+
+            e1 = ALPHASET[ ( d1 & I6O2 ) >> 2 ];
+            e2 = ALPHASET[ ( d1 & O6I2 ) << 4 | ( d2 & I4O4 ) >> 4 ];
+            e3 = ALPHASET[ ( d2 & O4I4 ) << 2 | ( d3 & I2O6 ) >> 6 ];
+            e4 = ALPHASET[ ( d3 & O2I6 ) ];
+
+            eData[ eIndex++ ] = (byte) e1;
+            eData[ eIndex++ ] = (byte) e2;
+            eData[ eIndex++ ] = ( pad < 2 ) ? (byte) e3 : (byte) '=';
+            eData[ eIndex++ ] = ( pad < 1 ) ? (byte) e4 : (byte) '=';
+
+            if( pad > 0 && !includePadding )
+            {
+                byte[] neweData = new byte[ eData.length - pad ];
+                System.arraycopy( eData, 0, neweData, 0, eIndex - pad );
+                eData = neweData;
+            }
+        }
+
+        return eData;
+    }
+
+    private final static int[] CODES = new int[ 256 ];
+
+    static
+    {
+        for( int i = 0; i < CODES.length; i++ )
+        {
+            CODES[ i ] = 64;
+        }
+        for( int i = 0; i < ALPHASET.length; i++ )
+        {
+            CODES[ ALPHASET[ i ] ] = i;
+        }
+    }
+
+    /**
+     * Decodes a base64 byte array into a byte array.
+     * <p>
+     *
+     * @param eData byte array to decode.
+     *
+     * @return decoded byte array.
+     *
+     * @throws java.lang.IllegalArgumentException
+     *          thrown if the given byte array was not valid com.sun.syndication.io.impl.Base64 encoding.
+     */
+    public static byte[] decode( byte[] eData )
+    {
+        if( eData == null )
+        {
+            throw new IllegalArgumentException( "Cannot decode null" );
+        }
+        byte[] cleanEData = eData.clone();
+        int cleanELength = 0;
+        for( byte anEData : eData )
+        {
+            if( anEData < 256 && CODES[ anEData ] < 64 )
+            {
+                cleanEData[ cleanELength++ ] = anEData;
+            }
+        }
+
+        int dLength = ( cleanELength / 4 ) * 3;
+        switch( cleanELength % 4 )
+        {
+        case 3:
+            dLength += 2;
+            break;
+        case 2:
+            dLength++;
+            break;
+        }
+
+        byte[] dData = new byte[ dLength ];
+        int dIndex = 0;
+        for( int i = 0; i < eData.length; i += 4 )
+        {
+            if( ( i + 3 ) > eData.length )
+            {
+                throw new IllegalArgumentException(
+                    "byte array is not a valid base64 encoding"
+                );
+            }
+            int e1 = CODES[ cleanEData[ i ] ];
+            int e2 = CODES[ cleanEData[ i + 1 ] ];
+            int e3 = CODES[ cleanEData[ i + 2 ] ];
+            int e4 = CODES[ cleanEData[ i + 3 ] ];
+            dData[ dIndex++ ] = (byte) ( ( e1 << 2 ) | ( e2 >> 4 ) );
+            if( dIndex < dData.length )
+            {
+                dData[ dIndex++ ] = (byte) ( ( e2 << 4 ) | ( e3 >> 2 ) );
+            }
+            if( dIndex < dData.length )
+            {
+                dData[ dIndex++ ] = (byte) ( ( e3 << 6 ) | ( e4 ) );
+            }
+        }
+        return dData;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/util/Classes.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/util/Classes.java b/core/api/src/main/java/org/qi4j/api/util/Classes.java
new file mode 100644
index 0000000..34f4b05
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/util/Classes.java
@@ -0,0 +1,699 @@
+/*
+ * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.qi4j.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.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.qi4j.api.composite.ModelDescriptor;
+import org.qi4j.functional.Function;
+import org.qi4j.functional.Iterables;
+import org.qi4j.functional.Specification;
+
+import static org.qi4j.functional.Iterables.cast;
+import static org.qi4j.functional.Iterables.empty;
+import static org.qi4j.functional.Iterables.flatten;
+import static org.qi4j.functional.Iterables.flattenIterables;
+import static org.qi4j.functional.Iterables.iterable;
+import static org.qi4j.functional.Iterables.map;
+import static org.qi4j.functional.Iterables.matchesAny;
+import static org.qi4j.functional.Iterables.prepend;
+
+/**
+ * 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 = new Function<Type, Type>()
+    {
+        @Override
+        public Type map( Type aClass )
+        {
+            Type wrapperClass = wrapperClasses.get( aClass );
+            return wrapperClass == null ? aClass : 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 = new Function<Type, Type>()
+    {
+        @Override
+        public Type map( Type 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 = new Function<Type, Class<?>>()
+    {
+        @Override
+        public Class<?> map( Type 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 = new Function<AccessibleObject, Type>()
+    {
+        @Override
+        public Type map( AccessibleObject accessor )
+        {
+            return accessor instanceof Method ? ( (Method) accessor ).getGenericReturnType() : ( (Field) accessor ).getGenericType();
+        }
+    };
+
+    private static final Function<Type, Iterable<Class<?>>> CLASS_HIERARCHY = new Function<Type, Iterable<Class<?>>>()
+    {
+        @Override
+        @SuppressWarnings( {"raw", "unchecked"} )
+        public Iterable<Class<?>> map( Type type )
+        {
+            if( type == null )
+            {
+                return empty();
+            }
+            if( type.equals( Object.class ) )
+            {
+                Class<?> aClass = (Class<?>) type;
+                return cast( iterable( aClass ) );
+            }
+            else
+            {
+                type = RAW_CLASS.map( type );
+                Class superclass = ( (Class) type ).getSuperclass();
+                return prepend( (Class<?>) type, map( superclass ) );
+            }
+        }
+    };
+
+    @SuppressWarnings( "raw" )
+    private static final Function<Type, Iterable<Type>> INTERFACES_OF = new Function<Type, Iterable<Type>>()
+    {
+        @Override
+        public Iterable<Type> map( Type type )
+        {
+            Class clazz = RAW_CLASS.map( type );
+
+            if( clazz.isInterface() )
+            {
+                Iterable<Type> genericInterfaces = iterable( clazz.getGenericInterfaces() );
+                Iterable<Type> flattenIterables = flattenIterables( Iterables.map( INTERFACES_OF, genericInterfaces ) );
+                return prepend( type, flattenIterables );
+            }
+            else
+            {
+                if( type.equals( Object.class ) )
+                {
+                    return iterable( clazz.getGenericInterfaces() );
+                }
+                else
+                {
+                    return flatten( flattenIterables( Iterables.map( INTERFACES_OF,
+                                                                     iterable( clazz.getGenericInterfaces() ) ) ),
+                                    INTERFACES_OF.map( RAW_CLASS.map( type ).getSuperclass() ) );
+                }
+            }
+        }
+    };
+
+    @SuppressWarnings( "raw" )
+    private static final Function<Type, Iterable<Type>> TYPES_OF = new Function<Type, Iterable<Type>>()
+    {
+        @Override
+        public Iterable<Type> map( Type type )
+        {
+            Class clazz = RAW_CLASS.map( type );
+
+            if( clazz.isInterface() )
+            {
+                Iterable<Type> genericInterfaces = iterable( clazz.getGenericInterfaces() );
+                Iterable<Type> flattenIterables = flattenIterables( Iterables.map( INTERFACES_OF, genericInterfaces ) );
+                return prepend( clazz, flattenIterables );
+            }
+            else
+            {
+                return flatten( CLASS_HIERARCHY.map( type ),
+                                flattenIterables( Iterables.map( INTERFACES_OF, CLASS_HIERARCHY.map( type ) ) ) );
+            }
+        }
+    };
+
+    public static Type typeOf( AccessibleObject from )
+    {
+        return TYPE_OF.map( from );
+    }
+
+    public static Iterable<Type> typesOf( Iterable<Type> types )
+    {
+        Iterable<Type> result = empty();
+        for( Type type : types )
+        {
+            result = flatten( result, typesOf( type ) );
+        }
+        return result;
+    }
+
+    public static Iterable<Type> typesOf( Type type )
+    {
+        return TYPES_OF.map( type );
+    }
+
+    public static Iterable<? extends Type> interfacesOf( Iterable<? extends Type> types )
+    {
+        Iterable<Type> result = empty();
+        for( Type type : types )
+        {
+            result = flatten( result, interfacesOf( type ) );
+        }
+        return result;
+    }
+
+    public static Iterable<Type> interfacesOf( Type type )
+    {
+        return INTERFACES_OF.map( type );
+    }
+
+    public static Iterable<Class<?>> classHierarchy( Class<?> type )
+    {
+        return CLASS_HIERARCHY.map( type );
+    }
+
+    public static Type wrapperClass( Type type )
+    {
+        return WRAPPER_CLASS.map( type );
+    }
+
+    public static Specification<Class<?>> isAssignableFrom( final Class clazz )
+    {
+        return new Specification<Class<?>>()
+        {
+            @Override
+            @SuppressWarnings( "unchecked" )
+            public boolean satisfiedBy( Class<?> item )
+            {
+                return clazz.isAssignableFrom( item );
+            }
+        };
+    }
+
+    @SuppressWarnings( "raw" )
+    public static Specification<Object> instanceOf( final Class clazz )
+    {
+        return new Specification<Object>()
+        {
+            @Override
+            public boolean satisfiedBy( Object item )
+            {
+                return clazz.isInstance( item );
+            }
+        };
+    }
+
+    public static Specification<Class<?>> hasModifier( final int classModifier )
+    {
+        return new Specification<Class<?>>()
+        {
+            @Override
+            public boolean satisfiedBy( Class<?> item )
+            {
+                return ( item.getModifiers() & classModifier ) != 0;
+            }
+        };
+    }
+
+    public static <T> Function<Type, Iterable<T>> forClassHierarchy( final Function<Class<?>, Iterable<T>> function )
+    {
+        return new Function<Type, Iterable<T>>()
+        {
+            @Override
+            public Iterable<T> map( Type type )
+            {
+                return flattenIterables( Iterables.map( function, CLASS_HIERARCHY.map( type ) ) );
+            }
+        };
+    }
+
+    public static <T> Function<Type, Iterable<T>> forTypes( final Function<Type, Iterable<T>> function )
+    {
+        return new Function<Type, Iterable<T>>()
+        {
+            @Override
+            public Iterable<T> map( Type type )
+            {
+                return flattenIterables( Iterables.map( function, TYPES_OF.map( type ) ) );
+            }
+        };
+    }
+
+    @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 )
+    {
+        AnnotationType result = null;
+        for( Type clazz : Classes.TYPES_OF.map( type ) )
+        {
+            result = Classes.RAW_CLASS.map( clazz ).getAnnotation( annotationClass );
+            if( result != null )
+            {
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    public static Specification<Member> memberNamed( final String name )
+    {
+        return new Specification<Member>()
+        {
+            @Override
+            public boolean satisfiedBy( Member item )
+            {
+                return 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<TypeVariable, Type>(), topClass );
+        if( type == null )
+        {
+            type = Object.class;
+        }
+        return type;
+    }
+
+    @SuppressWarnings( "raw" )
+    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;
+        }
+
+        List<Type> types = new ArrayList<>();
+        for( Type type : current.getGenericInterfaces() )
+        {
+            Iterable<Type> interfaces = Classes.INTERFACES_OF.map( type );
+            for( Type anInterface : interfaces )
+            {
+                if( !types.contains( anInterface ) )
+                {
+                    types.add( anInterface );
+                }
+            }
+            types.add( type );
+        }
+
+        if( current.getGenericSuperclass() != null )
+        {
+            types.add( current.getGenericSuperclass() );
+        }
+
+        for( Type type : types )
+        {
+            Class subClass;
+            if( type instanceof ParameterizedType )
+            {
+                ParameterizedType pt = (ParameterizedType) type;
+                Type[] args = pt.getActualTypeArguments();
+                Class clazz = (Class) pt.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) pt.getRawType();
+            }
+            else
+            {
+                subClass = (Class) type;
+            }
+
+            Type resolvedType = resolveTypeVariable( name, declaringClass, mappings, subClass );
+            if( resolvedType != null )
+            {
+                return resolvedType;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * 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:qi4j: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:qi4j: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:qi4j: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 Specification<ModelDescriptor> modelTypeSpecification( final String className )
+    {
+        return new Specification<ModelDescriptor>()
+        {
+            @Override
+            public boolean satisfiedBy( ModelDescriptor item )
+            {
+                return matchesAny( new Specification<String>()
+                {
+                    @Override
+                    public boolean satisfiedBy( String item )
+                    {
+                        return item.equals( className );
+                    }
+                }, map( new Function<Class<?>, String>()
+                {
+                    @Override
+                    public String map( Class<?> item )
+                    {
+                        return item.getName();
+                    }
+                }, item.types() ) );
+            }
+        };
+    }
+
+    @SuppressWarnings( "raw" )
+    public static Specification<ModelDescriptor> exactTypeSpecification( final Class type )
+    {
+        return new Specification<ModelDescriptor>()
+        {
+            @Override
+            public boolean satisfiedBy( ModelDescriptor item )
+            {
+                return matchesAny( new Specification<Class<?>>()
+                {
+                    @Override
+                    public boolean satisfiedBy( Class<?> item )
+                    {
+                        return item.equals( type );
+                    }
+                }, item.types() );
+            }
+        };
+    }
+
+    @SuppressWarnings( "raw" )
+    public static Specification<ModelDescriptor> assignableTypeSpecification( final Class type )
+    {
+        return new Specification<ModelDescriptor>()
+        {
+            @Override
+            public boolean satisfiedBy( ModelDescriptor item )
+            {
+                return matchesAny( new Specification<Class<?>>()
+                {
+                    @Override
+                    @SuppressWarnings( "unchecked" )
+                    public boolean satisfiedBy( Class<?> itemType )
+                    {
+                        return !type.equals( itemType ) && type.isAssignableFrom( itemType );
+                    }
+                }, item.types() );
+            }
+        };
+    }
+
+    @SuppressWarnings( "raw" )
+    public static String toString( Iterable<? extends Class> type )
+    {
+        StringBuilder builder = new StringBuilder();
+        builder.append( "[" );
+        boolean first = true;
+        for( Class c : type )
+        {
+            if( !first )
+            {
+                builder.append( "," );
+            }
+            first = false;
+            builder.append( c.getSimpleName() );
+        }
+        builder.append( "]" );
+        return builder.toString();
+    }
+
+    public static Function<Type, String> toClassName()
+    {
+        return new Function<Type, String>()
+        {
+            @Override
+            public String map( Type type )
+            {
+                return RAW_CLASS.map( type ).getName();
+            }
+        };
+    }
+
+    private Classes()
+    {
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/util/Constructors.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/util/Constructors.java b/core/api/src/main/java/org/qi4j/api/util/Constructors.java
new file mode 100644
index 0000000..17062ca
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/util/Constructors.java
@@ -0,0 +1,40 @@
+/*
+ * 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.qi4j.api.util;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Type;
+import org.qi4j.functional.Function;
+
+import static org.qi4j.functional.Iterables.iterable;
+
+/**
+ * Useful methods for handling Constructors.
+ */
+public final class Constructors
+{
+    public static final Function<Type, Iterable<Constructor<?>>> CONSTRUCTORS_OF = Classes.forClassHierarchy( new Function<Class<?>, Iterable<Constructor<?>>>()
+    {
+        @Override
+        public Iterable<Constructor<?>> map( Class<?> type )
+        {
+            return iterable( type.getDeclaredConstructors() );
+        }
+    } );
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/util/Dates.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/util/Dates.java b/core/api/src/main/java/org/qi4j/api/util/Dates.java
new file mode 100644
index 0000000..3324df2
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/util/Dates.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2009 Niclas Hedhman.
+ *
+ * Licensed  under the  Apache License,  Version 2.0  (the "License");
+ * you may not use  this file  except in  compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed  under the  License is distributed on an "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
+ * implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.qi4j.api.util;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * Useful methods for handling Dates.
+ */
+public final class Dates
+{
+    // Formatters are not thread-safe. Create one per thread
+    private static final ThreadLocal<DateFormat> ISO8601 = new ThreadLocal<DateFormat>()
+    {
+        @Override
+        protected DateFormat initialValue()
+        {
+            return new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSSZ" );
+        }
+    };
+
+    private static final ThreadLocal<DateFormat> ISO8601_UTC = new ThreadLocal<DateFormat>()
+    {
+        @Override
+        protected DateFormat initialValue()
+        {
+            SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" );
+            dateFormat.setTimeZone( TimeZone.getTimeZone( "UTC" ) );
+            return dateFormat;
+        }
+    };
+
+    /**
+     * @param stringDate a string representing a date as either ISO8601, @millis@ or /Date() formats
+     * @return a Date
+     */
+    public static Date fromString( String stringDate )
+    {
+        try
+        {
+            Date date = ISO8601_UTC.get().parse( stringDate );
+            return date;
+        }
+        catch( ParseException e )
+        {
+            try
+            {
+                Date date = ISO8601.get().parse( stringDate );
+                return date;
+            }
+            catch( ParseException e1 )
+            {
+                // @millis@ format
+                if( stringDate.startsWith( "@" ) && stringDate.endsWith( "@" ) )
+                {
+                    long time = Long.parseLong( stringDate.substring( 1, stringDate.length() - 1 ) );
+                    Date date = new Date( time );
+                    return date;
+                }
+                else if( stringDate.startsWith( "/Date(" ) && stringDate.endsWith( ")/" ) ) // Microsoft format
+                {
+                    long time = Long.parseLong( stringDate.substring( 6, stringDate.length() - 2 ) );
+                    Date date = new Date( time );
+                    return date;
+                }
+                throw new IllegalStateException( "Illegal date:" + stringDate );
+            }
+        }
+    }
+
+    /**
+     * @param date a Date
+     * @return String representation in ISO8601 UTC
+     */
+    public static String toUtcString( Date date )
+    {
+        return ISO8601_UTC.get().format( date );
+    }
+
+    private Dates()
+    {
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/util/Fields.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/util/Fields.java b/core/api/src/main/java/org/qi4j/api/util/Fields.java
new file mode 100644
index 0000000..c68d131
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/util/Fields.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.qi4j.api.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import org.qi4j.functional.Function;
+import org.qi4j.functional.Function2;
+import org.qi4j.functional.Iterables;
+
+import static org.qi4j.functional.Iterables.iterable;
+
+/**
+ * Useful methods for handling Fields.
+ */
+public final class Fields
+{
+    public static final Function2<Class<?>, String, Field> FIELD_NAMED = new Function2<Class<?>, String, Field>()
+    {
+        @Override
+        public Field map( Class<?> aClass, String name )
+        {
+            return Iterables.first( Iterables.filter( Classes.memberNamed( name ), FIELDS_OF.map( aClass ) ) );
+        }
+    };
+
+    public static final Function<Type, Iterable<Field>> FIELDS_OF = Classes.forClassHierarchy( new Function<Class<?>, Iterable<Field>>()
+    {
+        @Override
+        public Iterable<Field> map( Class<?> type )
+        {
+            return iterable( type.getDeclaredFields() );
+        }
+    } );
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/util/ListMap.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/util/ListMap.java b/core/api/src/main/java/org/qi4j/api/util/ListMap.java
new file mode 100644
index 0000000..56778b8
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/util/ListMap.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.qi4j.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/a789141d/core/api/src/main/java/org/qi4j/api/util/Methods.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/util/Methods.java b/core/api/src/main/java/org/qi4j/api/util/Methods.java
new file mode 100644
index 0000000..93b78cf
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/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.qi4j.api.util;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import org.qi4j.functional.Function;
+import org.qi4j.functional.Specification;
+
+import static org.qi4j.functional.Iterables.iterable;
+
+/**
+ * Useful methods for handling Methods.
+ */
+public class Methods
+{
+    public static final Specification<Type> HAS_METHODS = new Specification<Type>()
+    {
+        @Override
+        public boolean satisfiedBy( Type item )
+        {
+            return Classes.RAW_CLASS.map( item ).getDeclaredMethods().length > 0;
+        }
+    };
+
+    public static final Function<Type, Iterable<Method>> METHODS_OF = Classes.forTypes( new Function<Type, Iterable<Method>>()
+    {
+        @Override
+        public Iterable<Method> map( Type type )
+        {
+            return iterable( Classes.RAW_CLASS.map( type ).getDeclaredMethods() );
+        }
+    } );
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/util/NullArgumentException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/util/NullArgumentException.java b/core/api/src/main/java/org/qi4j/api/util/NullArgumentException.java
new file mode 100644
index 0000000..58e514f
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/util/NullArgumentException.java
@@ -0,0 +1,56 @@
+/*  Copyright 2007 Niclas Hedhman.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *  
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * 
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.qi4j.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/a789141d/core/api/src/main/java/org/qi4j/api/util/package.html
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/util/package.html b/core/api/src/main/java/org/qi4j/api/util/package.html
new file mode 100644
index 0000000..ea75db3
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/util/package.html
@@ -0,0 +1,21 @@
+<!--
+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/a789141d/core/api/src/main/java/org/qi4j/api/value/NoSuchValueException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/value/NoSuchValueException.java b/core/api/src/main/java/org/qi4j/api/value/NoSuchValueException.java
new file mode 100644
index 0000000..256e9fc
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/value/NoSuchValueException.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.qi4j.api.value;
+
+import org.qi4j.api.composite.NoSuchCompositeException;
+
+/**
+ * Thrown when no visible value of the requested type is found.
+ */
+public class NoSuchValueException
+    extends NoSuchCompositeException
+{
+    public NoSuchValueException( String valueType, String moduleName )
+    {
+        super( "ValueComposite", valueType, moduleName );
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/value/ValueBuilder.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueBuilder.java b/core/api/src/main/java/org/qi4j/api/value/ValueBuilder.java
new file mode 100644
index 0000000..1073a0d
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/value/ValueBuilder.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.qi4j.api.value;
+
+import org.qi4j.api.association.AssociationStateHolder;
+import org.qi4j.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.qi4j.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/a789141d/core/api/src/main/java/org/qi4j/api/value/ValueBuilderFactory.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueBuilderFactory.java b/core/api/src/main/java/org/qi4j/api/value/ValueBuilderFactory.java
new file mode 100644
index 0000000..57c4e29
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/value/ValueBuilderFactory.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.qi4j.api.value;
+
+import java.util.Map;
+import org.qi4j.api.association.AssociationDescriptor;
+import org.qi4j.api.common.ConstructionException;
+import org.qi4j.api.entity.EntityReference;
+import org.qi4j.api.property.PropertyDescriptor;
+import org.qi4j.functional.Function;
+
+/**
+ * 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, Iterable<EntityReference>> manyAssociationFunction,
+                                                  Function<AssociationDescriptor, Map<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/a789141d/core/api/src/main/java/org/qi4j/api/value/ValueBuilderTemplate.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueBuilderTemplate.java b/core/api/src/main/java/org/qi4j/api/value/ValueBuilderTemplate.java
new file mode 100644
index 0000000..11cbddb
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/value/ValueBuilderTemplate.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.qi4j.api.value;
+
+import org.qi4j.api.structure.Module;
+
+/**
+ * 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( Module module )
+    {
+        ValueBuilder<T> builder = module.newValueBuilder( type );
+        build( builder.prototype() );
+        return builder.newInstance();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/value/ValueComposite.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueComposite.java b/core/api/src/main/java/org/qi4j/api/value/ValueComposite.java
new file mode 100644
index 0000000..7d5f48f
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/value/ValueComposite.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2008, Rickard Öberg. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.qi4j.api.value;
+
+import org.qi4j.api.association.AssociationMixin;
+import org.qi4j.api.association.ManyAssociationMixin;
+import org.qi4j.api.association.NamedAssociationMixin;
+import org.qi4j.api.composite.Composite;
+import org.qi4j.api.mixin.Mixins;
+import org.qi4j.api.property.Immutable;
+
+/**
+ * ValueComposites are Composites that has state, and equality is defined from its values and not any identity 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/a789141d/core/api/src/main/java/org/qi4j/api/value/ValueDescriptor.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueDescriptor.java b/core/api/src/main/java/org/qi4j/api/value/ValueDescriptor.java
new file mode 100644
index 0000000..710de89
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/value/ValueDescriptor.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2009, Rickard Öberg. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.qi4j.api.value;
+
+import org.qi4j.api.association.AssociationStateDescriptor;
+import org.qi4j.api.composite.CompositeDescriptor;
+import org.qi4j.api.composite.StatefulCompositeDescriptor;
+import org.qi4j.api.type.ValueCompositeType;
+
+/**
+ * Descriptor for ValueComposites.
+ */
+public interface ValueDescriptor
+    extends CompositeDescriptor, StatefulCompositeDescriptor
+{
+    ValueCompositeType valueType();
+
+    @Override
+    AssociationStateDescriptor state();
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/value/ValueDeserializer.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueDeserializer.java b/core/api/src/main/java/org/qi4j/api/value/ValueDeserializer.java
new file mode 100644
index 0000000..175b176
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/value/ValueDeserializer.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ *
+ *     You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.qi4j.api.value;
+
+import java.io.InputStream;
+import org.qi4j.api.type.ValueType;
+import org.qi4j.functional.Function;
+import org.qi4j.functional.Function2;
+
+/**
+ * Use a ValueDeserializer to create new values instances from serialized state.
+ *
+ * <p>
+ *     Serialized state must be one of:
+ * </p>
+ * <ul>
+ *     <li>a ValueComposite,</li>
+ *     <li>an EntityReference,</li>
+ *     <li>a Collection,</li>
+ *     <li>a Map,</li>
+ *     <li>a Plain Value.</li>
+ * </ul>
+ * <p>
+ *     Nested plain values, EntityReferences, Collections, Maps, ValueComposites are supported.
+ *     EntityReferences are deserialized as their identity string.
+ * </p>
+ * <p>
+ *     Plain values can be one of:
+ * </p>
+ * <ul>
+ *     <li>String,</li>
+ *     <li>Character or char,</li>
+ *     <li>Boolean or boolean,</li>
+ *     <li>Integer or int,</li>
+ *     <li>Long or long,</li>
+ *     <li>Short or short,</li>
+ *     <li>Byte or byte,</li>
+ *     <li>Float or float,</li>
+ *     <li>Double or double,</li>
+ *     <li>BigInteger,</li>
+ *     <li>BigDecimal,</li>
+ *     <li>Date,</li>
+ *     <li>DateTime (JodaTime),</li>
+ *     <li>LocalDateTime (JodaTime),</li>
+ *     <li>LocalDate (JodaTime).</li>
+ * </ul>
+ * <p>
+ *     Values of unknown types and all arrays are considered as {@link java.io.Serializable} and by so are deserialized
+ *     from base64 encoded bytes using pure Java serialization. If it happens that the input is invalid, a
+ *     ValueSerializationException is thrown.
+ * </p>
+ * <p>
+ *     Having type information in the serialized payload allows to keep actual ValueComposite types and by so
+ *     circumvent {@link org.qi4j.api.composite.AmbiguousTypeException} when deserializing.
+ * </p>
+ */
+public interface ValueDeserializer
+{
+
+    /**
+     * Factory method for a typed deserialize function.
+     *
+     * <p>The returned Function may throw {@link ValueSerializationException}.</p>
+     *
+     * @param type the value type
+     * @param <T> the parametrized function return type
+     * @return a deserialization function
+     */
+    <T> Function<String, T> deserialize( Class<T> type );
+
+    /**
+     * Factory method for a typed deserialize function.
+     *
+     * <p>The returned Function may throw {@link ValueSerializationException}.</p>
+     *
+     * @param valueType the value type
+     * @param <T> the parametrized function return type
+     * @return a deserialization function
+     */
+    <T> Function<String, T> deserialize( ValueType valueType );
+
+    /**
+     * Factory method for an untyped deserialize function.
+     *
+     * <p>The returned Function may throw {@link ValueSerializationException}.</p>
+     *
+     * @param <T> the parametrized function return type
+     * @return a deserialization function
+     */
+    <T> Function2<ValueType, String, T> deserialize();
+
+    /**
+     * Deserialize a value from a state.
+     *
+     * @param <T> the parametrized returned type
+     * @param type the value type
+     * @param input the state
+     * @return the value
+     * @throws ValueSerializationException if the deserialization failed
+     */
+    <T> T deserialize( Class<?> type, String input )
+        throws ValueSerializationException;
+
+    /**
+     * Deserialize a value from a state.
+     *
+     * @param <T> the parametrized returned type
+     * @param valueType the value type
+     * @param input the state
+     * @return the value
+     * @throws ValueSerializationException if the deserialization failed
+     */
+    <T> T deserialize( ValueType valueType, String input )
+        throws ValueSerializationException;
+
+    /**
+     * Deserialize a value from a state.
+     *
+     * @param <T> the parametrized returned type
+     * @param type the value type
+     * @param input the state stream
+     * @return the value
+     * @throws ValueSerializationException if the deserialization failed
+     */
+    <T> T deserialize( Class<?> type, InputStream input )
+        throws ValueSerializationException;
+
+    /**
+     * Deserialize a value from a state.
+     *
+     * @param <T> the parametrized returned type
+     * @param valueType the value type
+     * @param input the state stream
+     * @return the value
+     * @throws ValueSerializationException if the deserialization failed
+     */
+    <T> T deserialize( ValueType valueType, InputStream input )
+        throws ValueSerializationException;
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/value/ValueSerialization.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueSerialization.java b/core/api/src/main/java/org/qi4j/api/value/ValueSerialization.java
new file mode 100644
index 0000000..31a4af0
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/value/ValueSerialization.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ *
+ *     You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.qi4j.api.value;
+
+/**
+ * ValueSerialization API.
+ *
+ * See {@link ValueSerializer} and {@link ValueDeserializer}.
+ */
+public interface ValueSerialization
+    extends ValueSerializer, ValueDeserializer
+{
+
+    /**
+     * Serialization format @Service tags.
+     *
+     * <p>
+     *     ValueSerialization implementations should be tagged with theses at assembly time so that consumers can
+     *     specify which format they need.
+     * </p>
+     */
+    interface Formats
+    {
+
+        /**
+         * Tag a ValueSerialization service that support the JSON format.
+         */
+        String JSON = "json";
+        /**
+         * Tag a ValueSerialization service that support the XML format.
+         */
+        String XML = "xml";
+        /**
+         * Tag a ValueSerialization service that support the YAML format.
+         */
+        String YAML = "yaml";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/value/ValueSerializationException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueSerializationException.java b/core/api/src/main/java/org/qi4j/api/value/ValueSerializationException.java
new file mode 100644
index 0000000..e1f3d44
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/value/ValueSerializationException.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ *
+ *     You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.qi4j.api.value;
+
+/**
+ * Thrown when an error occur during value state (de)serialization.
+ */
+public class ValueSerializationException
+    extends RuntimeException
+{
+
+    private static final long serialVersionUID = 1L;
+
+    public ValueSerializationException()
+    {
+        super();
+    }
+
+    public ValueSerializationException( String message )
+    {
+        super( message );
+    }
+
+    public ValueSerializationException( String message, Throwable cause )
+    {
+        super( message, cause );
+    }
+
+    public ValueSerializationException( Throwable cause )
+    {
+        super( cause.getClass().getName() + ": " + cause.getMessage(), cause );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/value/ValueSerializer.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/value/ValueSerializer.java b/core/api/src/main/java/org/qi4j/api/value/ValueSerializer.java
new file mode 100644
index 0000000..337c37e
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/value/ValueSerializer.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2012-2014, Paul Merlin. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ *
+ *     You may obtain a copy of the License at
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.qi4j.api.value;
+
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+import org.qi4j.api.composite.AmbiguousTypeException;
+import org.qi4j.functional.Function;
+
+/**
+ * Use a ValueSerializer to serialize values state.
+ *
+ * <p>
+ *     Serialized object must be one of:
+ * </p>
+ * <ul>
+ *     <li>a ValueComposite,</li>
+ *     <li>an EntityComposite or EntityReference,</li>
+ *     <li>an Iterable,</li>
+ *     <li>a Map,</li>
+ *     <li>a Plain Value.</li>
+ * </ul>
+ * <p>
+ *     Nested plain values, EntityReferences, Iterables, Maps, ValueComposites and EntityComposites are supported.
+ *     EntityComposites and EntityReferences are serialized as their identity string.
+ * </p>
+ * <p>
+ *     Plain values can be one of:
+ * </p>
+ * <ul>
+ *     <li>String,</li>
+ *     <li>Character or char,</li>
+ *     <li>Boolean or boolean,</li>
+ *     <li>Integer or int,</li>
+ *     <li>Long or long,</li>
+ *     <li>Short or short,</li>
+ *     <li>Byte or byte,</li>
+ *     <li>Float or float,</li>
+ *     <li>Double or double,</li>
+ *     <li>BigInteger,</li>
+ *     <li>BigDecimal,</li>
+ *     <li>Date,</li>
+ *     <li>DateTime (JodaTime),</li>
+ *     <li>LocalDateTime (JodaTime),</li>
+ *     <li>LocalDate (JodaTime).</li>
+ * </ul>
+ * <p>
+ *     Values of unknown types and all arrays are considered as {@link java.io.Serializable} and by so are serialized to
+ *     base64 encoded bytes using pure Java serialization. If it happens that the value is not Serializable, a
+ *     ValueSerializationException is thrown.
+ * </p>
+ * <p>
+ *     Having type information in the serialized payload allows to keep actual ValueComposite types and by so
+ *     circumvent {@link AmbiguousTypeException} when deserializing.
+ * </p>
+ */
+public interface ValueSerializer
+{
+
+    /**
+     * Factory method for a serialize function.
+     *
+     * @param <T> the parametrized function input type
+     * @return a serialization function.
+     */
+    <T> Function<T, String> serialize();
+
+    /**
+     * Factory method for a serialize function.
+     *
+     * @param <T> the parametrized function input type
+     * @param options ValueSerializer Options
+     * @return a serialization function.
+     */
+    <T> Function<T, String> serialize( Options options );
+
+    /**
+     * Factory method for a serialize function.
+     *
+     * @param <T> the parametrized function input type
+     * @param includeTypeInfo if type information should be included in the output
+     * @return a serialization function.
+     */
+    @Deprecated
+    <T> Function<T, String> serialize( boolean includeTypeInfo );
+
+    /**
+     * Serialize the state of a value with type information.
+     *
+     * @param object an Object to serialize
+     * @return the state
+     * @throws ValueSerializationException if the Value serialization failed
+     */
+    String serialize( Object object )
+        throws ValueSerializationException;
+
+    /**
+     * Serialize the state of a value.
+     *
+     * @param options ValueSerializer Options
+     * @param object an Object to serialize
+     * @return the state
+     * @throws ValueSerializationException if the Value serialization failed
+     */
+    String serialize( Options options, Object object )
+        throws ValueSerializationException;
+
+    /**
+     * Serialize the state of a value.
+     *
+     * @param object an Object to serialize
+     * @param includeTypeInfo if type information should be included in the output
+     * @return the state
+     * @throws ValueSerializationException if the Value serialization failed
+     */
+    @Deprecated
+    String serialize( Object object, boolean includeTypeInfo )
+        throws ValueSerializationException;
+
+    /**
+     * Serialize the state of a value with type information.
+     *
+     * @param object an Object to serialize
+     * @param output that will be used as output
+     * @throws ValueSerializationException if the Value serialization failed
+     */
+    void serialize( Object object, OutputStream output )
+        throws ValueSerializationException;
+
+    /**
+     * Serialize the state of a value.
+     *
+     * @param options ValueSerializer Options
+     * @param object an Object to serialize
+     * @param output that will be used as output
+     * @throws ValueSerializationException if the Value serialization failed
+     */
+    void serialize( Options options, Object object, OutputStream output )
+        throws ValueSerializationException;
+
+    /**
+     * Serialize the state of a value.
+     *
+     * @param object an Object to serialize
+     * @param output that will be used as output
+     * @param includeTypeInfo if type information should be included in the output
+     * @throws ValueSerializationException if the Value serialization failed
+     */
+    @Deprecated
+    void serialize( Object object, OutputStream output, boolean includeTypeInfo )
+        throws ValueSerializationException;
+
+    /**
+     * Serialization options.
+     */
+    final class Options
+    {
+        /**
+         * Boolean flag to include type information.
+         * Default to TRUE.
+         */
+        public static final String INCLUDE_TYPE_INFO = "includeTypeInfo";
+        public static final String MAP_ENTRIES_AS_OBJECTS = "mapentriesasobjects";
+        private final Map<String, String> options = new HashMap<>();
+
+        /**
+         * Create new default ValueSerializer Options.
+         */
+        public Options()
+        {
+            this.options.put( INCLUDE_TYPE_INFO, "true" );
+            this.options.put( MAP_ENTRIES_AS_OBJECTS, "false" );
+        }
+
+        /**
+         * Set {@link #INCLUDE_TYPE_INFO} option to TRUE.
+         * @return This
+         */
+        public Options withTypeInfo()
+        {
+            return put( INCLUDE_TYPE_INFO, true );
+        }
+
+        /**
+         * Set {@link #INCLUDE_TYPE_INFO} option to FALSE.
+         * @return This
+         */
+        public Options withoutTypeInfo()
+        {
+            return put( INCLUDE_TYPE_INFO, false );
+        }
+
+        public Options withMapEntriesAsObjects()
+        {
+            return put( MAP_ENTRIES_AS_OBJECTS, true );
+        }
+
+        public Options withMapEntriesAsKeyValuePairs()
+        {
+            return put( MAP_ENTRIES_AS_OBJECTS, false );
+        }
+
+        /**
+         * Get Boolean option value.
+         * @param option The option
+         * @return The boolean value of the option, or null if absent
+         */
+        public Boolean getBoolean( String option )
+        {
+            if( !options.containsKey( option ) )
+            {
+                return null;
+            }
+            return Boolean.valueOf( options.get( option ) );
+        }
+
+        /**
+         * Get Integer option value.
+         * @param option The option
+         * @return The integer value of the option, or null if absent
+         */
+        public Integer getInteger( String option )
+        {
+            if( !options.containsKey( option ) )
+            {
+                return null;
+            }
+            return Integer.valueOf( options.get( option ) );
+        }
+
+        /**
+         * Get String option value.
+         * @param option The option
+         * @return The string value of the option, or null if absent
+         */
+        public String getString( String option )
+        {
+            return options.get( option );
+        }
+
+        /**
+         * Put an option String value.
+         * @param option The option
+         * @param value The value
+         * @return This Options instance
+         */
+        public Options put( String option, String value )
+        {
+            if( value == null )
+            {
+                return remove( option );
+            }
+            options.put( option, value );
+            return this;
+        }
+
+        /**
+         * Put an option boolean value.
+         * @param option The option
+         * @param value The value
+         * @return This Options instance
+         */
+        public Options put( String option, Boolean value )
+        {
+            if( value == null )
+            {
+                return remove( option );
+            }
+            options.put( option, Boolean.toString( value ) );
+            return this;
+        }
+
+        /**
+         * Put an option Integer value.
+         * @param option The option
+         * @param value The value
+         * @return This Options instance
+         */
+        public Options put( String option, Integer value )
+        {
+            if( value == null )
+            {
+                return remove( option );
+            }
+            options.put( option, value.toString() );
+            return this;
+        }
+
+        /**
+         * Remove an option value.
+         * @param option The option
+         * @return This Options instance
+         */
+        public Options remove( String option )
+        {
+            options.remove( option );
+            return this;
+        }
+
+        /**
+         * Get all defined options as a Map.
+         * @return All defined options in a new Map
+         */
+        public Map<String, String> toMap()
+        {
+            return new HashMap<>( options );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/main/java/org/qi4j/api/value/package.html
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/qi4j/api/value/package.html b/core/api/src/main/java/org/qi4j/api/value/package.html
new file mode 100644
index 0000000..540b3f6
--- /dev/null
+++ b/core/api/src/main/java/org/qi4j/api/value/package.html
@@ -0,0 +1,21 @@
+<!--
+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>Value API.</h2>
+    </body>
+</html>

http://git-wip-us.apache.org/repos/asf/zest-java/blob/a789141d/core/api/src/test/java/org/apache/zest/api/OperatorsTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/zest/api/OperatorsTest.java b/core/api/src/test/java/org/apache/zest/api/OperatorsTest.java
deleted file mode 100644
index 2f4301a..0000000
--- a/core/api/src/test/java/org/apache/zest/api/OperatorsTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.zest.api;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.apache.zest.api.activation.ActivationException;
-import org.apache.zest.api.composite.Composite;
-import org.apache.zest.api.entity.EntityBuilder;
-import org.apache.zest.api.entity.EntityComposite;
-import org.apache.zest.api.property.Property;
-import org.apache.zest.api.query.QueryBuilder;
-import org.apache.zest.api.query.QueryExpressions;
-import org.apache.zest.api.unitofwork.UnitOfWork;
-import org.apache.zest.api.unitofwork.UnitOfWorkCompletionException;
-import org.apache.zest.api.value.ValueComposite;
-import org.apache.zest.bootstrap.AssemblyException;
-import org.apache.zest.bootstrap.ModuleAssembly;
-import org.apache.zest.bootstrap.SingletonAssembler;
-import org.apache.zest.functional.Iterables;
-import org.apache.zest.functional.Specification;
-import org.apache.zest.test.EntityTestAssembler;
-
-/**
- * TODO
- */
-public class OperatorsTest
-{
-    @Test
-    public void testOperators()
-        throws UnitOfWorkCompletionException, ActivationException, AssemblyException
-    {
-        SingletonAssembler assembler = new SingletonAssembler()
-        {
-            @Override
-            public void assemble( ModuleAssembly module )
-                throws AssemblyException
-            {
-                new EntityTestAssembler().assemble( module );
-
-                module.entities( TestEntity.class );
-                module.values( TestValue.class );
-                module.forMixin( TestEntity.class ).declareDefaults().foo().set( "Bar" );
-                module.forMixin( TestValue.class ).declareDefaults().bar().set( "Xyz" );
-            }
-        };
-
-        UnitOfWork uow = assembler.module().newUnitOfWork();
-
-        try
-        {
-            EntityBuilder<TestEntity> entityBuilder = uow.newEntityBuilder( TestEntity.class, "123" );
-            entityBuilder.instance().value().set( assembler.module().newValue( TestValue.class ) );
-            TestEntity testEntity = entityBuilder.newInstance();
-
-            uow.complete();
-            uow = assembler.module().newUnitOfWork();
-
-            Iterable<TestEntity> entities = Iterables.iterable( testEntity = uow.get( testEntity ) );
-
-            QueryBuilder<TestEntity> builder = assembler.module().newQueryBuilder( TestEntity.class );
-
-            {
-                Specification<Composite> where = QueryExpressions.eq( QueryExpressions.templateFor( TestEntity.class )
-                                                                          .foo(), "Bar" );
-                Assert.assertTrue( where.satisfiedBy( testEntity ) );
-                System.out.println( where );
-            }
-            {
-                Specification<Composite> where = QueryExpressions.eq( QueryExpressions.templateFor( TestEntity.class )
-                                                                          .value()
-                                                                          .get()
-                                                                          .bar(), "Xyz" );
-                Assert.assertTrue( where.satisfiedBy( testEntity ) );
-                System.out.println( where );
-
-                Assert.assertTrue( builder.where( where ).newQuery( entities ).find().equals( testEntity ) );
-            }
-        }
-        finally
-        {
-            uow.discard();
-        }
-    }
-
-    public interface TestEntity
-        extends EntityComposite
-    {
-        Property<String> foo();
-
-        Property<TestValue> value();
-    }
-
-    public interface TestValue
-        extends ValueComposite
-    {
-        Property<String> bar();
-    }
-}


Mime
View raw message