You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by pa...@apache.org on 2017/03/13 10:35:26 UTC
[34/50] [abbrv] polygene-java git commit: New (de)serialization API
and SPI & new implementations
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/core/api/src/main/java/org/apache/polygene/api/type/HasTypesCollectors.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasTypesCollectors.java b/core/api/src/main/java/org/apache/polygene/api/type/HasTypesCollectors.java
new file mode 100644
index 0000000..ef6274e
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/HasTypesCollectors.java
@@ -0,0 +1,408 @@
+package org.apache.polygene.api.type;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+
+/**
+ * Collectors for HasTypes.
+ */
+public class HasTypesCollectors
+{
+ private static final String EQUAL_KEY = "equal";
+ private static final String EQUAL_TYPE_KEY = "equalType";
+ private static final String ASSIGNABLE_TYPE_KEY = "assignableType";
+
+ public static <T extends HasTypes> Collector<T, ?, Optional<T>> matchingType( T hasTypes )
+ {
+ return hasTypesFindFirstCollector( hasTypes, new HasAssignableFromType<>( hasTypes ) );
+ }
+
+ public static <T extends HasTypes> Collector<T, ?, Optional<T>> closestType( T hasTypes )
+ {
+ return hasTypesFindFirstCollector( hasTypes, new HasAssignableToType<>( hasTypes ) );
+ }
+
+ private static <T extends HasTypes> Collector<T, ?, Optional<T>>
+ hasTypesFindFirstCollector( T hasTypes, Predicate<T> assignableTypePredicate )
+ {
+ Predicate<T> equalPredicate = o -> Objects.equals( o, hasTypes );
+ Predicate<T> equalTypePredicate = new HasEqualType<>( hasTypes );
+ return new Collector<T, Map<String, Set<T>>, Optional<T>>()
+ {
+ @Override
+ public Supplier<Map<String, Set<T>>> supplier()
+ {
+ return () -> new HashMap<String, Set<T>>( 3 )
+ {{
+ put( EQUAL_KEY, new LinkedHashSet<>( 1 ) );
+ put( EQUAL_TYPE_KEY, new LinkedHashSet<>( 1 ) );
+ put( ASSIGNABLE_TYPE_KEY, new LinkedHashSet<>() );
+ }};
+ }
+
+ @Override
+ public BiConsumer<Map<String, Set<T>>, T> accumulator()
+ {
+ return ( map, candidate ) ->
+ {
+ Set<T> equalObjects = map.get( EQUAL_KEY );
+ if( equalObjects.isEmpty() )
+ {
+ if( equalPredicate.test( candidate ) )
+ {
+ equalObjects.add( candidate );
+ }
+ else
+ {
+ Set<T> equalTypes = map.get( EQUAL_TYPE_KEY );
+ if( equalTypes.isEmpty() )
+ {
+ if( equalTypePredicate.test( candidate ) )
+ {
+ equalTypes.add( candidate );
+ }
+ else if( assignableTypePredicate.test( candidate ) )
+ {
+ map.get( ASSIGNABLE_TYPE_KEY ).add( candidate );
+ }
+ }
+ }
+ }
+ };
+ }
+
+ @Override
+ public BinaryOperator<Map<String, Set<T>>> combiner()
+ {
+ return ( left, right ) ->
+ {
+ left.get( EQUAL_KEY ).addAll( right.get( EQUAL_KEY ) );
+ left.get( EQUAL_TYPE_KEY ).addAll( right.get( EQUAL_TYPE_KEY ) );
+ left.get( ASSIGNABLE_TYPE_KEY ).addAll( right.get( ASSIGNABLE_TYPE_KEY ) );
+ return left;
+ };
+ }
+
+ @Override
+ public Function<Map<String, Set<T>>, Optional<T>> finisher()
+ {
+ return map ->
+ {
+ Set<T> equalObjects = map.get( EQUAL_KEY );
+ if( !equalObjects.isEmpty() )
+ {
+ return Optional.of( equalObjects.iterator().next() );
+ }
+ Set<T> equalTypes = map.get( EQUAL_TYPE_KEY );
+ if( !equalTypes.isEmpty() )
+ {
+ return Optional.of( equalTypes.iterator().next() );
+ }
+ Set<T> assignableTypes = map.get( ASSIGNABLE_TYPE_KEY );
+ if( !assignableTypes.isEmpty() )
+ {
+ return Optional.of( assignableTypes.iterator().next() );
+ }
+ return Optional.empty();
+ };
+ }
+
+ @Override
+ public Set<Characteristics> characteristics()
+ {
+ return Collections.emptySet();
+ }
+ };
+ }
+
+
+ public static <T extends HasTypes> Collector<T, ?, List<T>> matchingTypes( T hasTypes )
+ {
+ return hasTypesToListCollector( hasTypes, new HasAssignableFromType<>( hasTypes ) );
+ }
+
+ public static <T extends HasTypes> Collector<T, ?, List<T>> closestTypes( T hasTypes )
+ {
+ return hasTypesToListCollector( hasTypes, new HasAssignableToType<>( hasTypes ) );
+ }
+
+ private static <T extends HasTypes> Collector<T, ?, List<T>>
+ hasTypesToListCollector( T hasTypes, Predicate<T> assignableTypePredicate )
+ {
+ Predicate<T> equalPredicate = o -> Objects.equals( o, hasTypes );
+ Predicate<T> equalTypePredicate = new HasEqualType<>( hasTypes );
+ return new Collector<T, Map<String, Set<T>>, List<T>>()
+ {
+ @Override
+ public Supplier<Map<String, Set<T>>> supplier()
+ {
+ return () -> new HashMap<String, Set<T>>( 3 )
+ {{
+ put( EQUAL_KEY, new LinkedHashSet<>() );
+ put( EQUAL_TYPE_KEY, new LinkedHashSet<>() );
+ put( ASSIGNABLE_TYPE_KEY, new LinkedHashSet<>() );
+ }};
+ }
+
+ @Override
+ public BiConsumer<Map<String, Set<T>>, T> accumulator()
+ {
+ return ( map, candidate ) ->
+ {
+ Set<T> equalObjects = map.get( EQUAL_KEY );
+ if( equalObjects.isEmpty() )
+ {
+ if( equalPredicate.test( candidate ) )
+ {
+ equalObjects.add( candidate );
+ }
+ else
+ {
+ Set<T> equalTypes = map.get( EQUAL_TYPE_KEY );
+ if( equalTypes.isEmpty() )
+ {
+ if( equalTypePredicate.test( candidate ) )
+ {
+ equalTypes.add( candidate );
+ }
+ else if( assignableTypePredicate.test( candidate ) )
+ {
+ map.get( ASSIGNABLE_TYPE_KEY ).add( candidate );
+ }
+ }
+ }
+ }
+ };
+ }
+
+ @Override
+ public BinaryOperator<Map<String, Set<T>>> combiner()
+ {
+ return ( left, right ) ->
+ {
+ left.get( EQUAL_KEY ).addAll( right.get( EQUAL_KEY ) );
+ left.get( EQUAL_TYPE_KEY ).addAll( right.get( EQUAL_TYPE_KEY ) );
+ left.get( ASSIGNABLE_TYPE_KEY ).addAll( right.get( ASSIGNABLE_TYPE_KEY ) );
+ return left;
+ };
+ }
+
+ @Override
+ public Function<Map<String, Set<T>>, List<T>> finisher()
+ {
+ return map ->
+ {
+ Set<T> equalObjects = map.get( EQUAL_KEY );
+ Set<T> equalSet = map.get( EQUAL_TYPE_KEY );
+ Set<T> assignableSet = map.get( ASSIGNABLE_TYPE_KEY );
+ List<T> list = new ArrayList<>( equalObjects.size() + equalSet.size() + assignableSet.size() );
+ list.addAll( equalObjects );
+ list.addAll( equalSet );
+ list.addAll( assignableSet );
+ return list;
+ };
+ }
+
+ @Override
+ public Set<Characteristics> characteristics()
+ {
+ return Collections.emptySet();
+ }
+ };
+ }
+
+
+ /**
+ * Collect a single matching HasTypes.
+ *
+ * TODO Detail
+ *
+ * @param type type to match
+ * @param <T> type of HasTypes
+ * @return an optional best matching HasTypes
+ */
+ public static <T extends HasTypes> Collector<T, ?, Optional<T>> matchingType( Type type )
+ {
+ return typeFindFirstCollector( type, new HasAssignableFromType<>( type ) );
+ }
+
+ public static <T extends HasTypes> Collector<T, ?, Optional<T>> closestType( Type type )
+ {
+ return typeFindFirstCollector( type, new HasAssignableToType<T>( type ) );
+ }
+
+ private static <T extends HasTypes> Collector<T, ?, Optional<T>>
+ typeFindFirstCollector( Type type, Predicate<T> assignableTypePredicate )
+ {
+ Predicate<T> equalTypePredicate = new HasEqualType<>( type );
+ return new Collector<T, Map<String, Set<T>>, Optional<T>>()
+ {
+ @Override
+ public Supplier<Map<String, Set<T>>> supplier()
+ {
+ return () -> new HashMap<String, Set<T>>( 2 )
+ {{
+ put( EQUAL_TYPE_KEY, new LinkedHashSet<>( 1 ) );
+ put( ASSIGNABLE_TYPE_KEY, new LinkedHashSet<>() );
+ }};
+ }
+
+ @Override
+ public BiConsumer<Map<String, Set<T>>, T> accumulator()
+ {
+ return ( map, candidate ) ->
+ {
+ Set<T> equalSet = map.get( EQUAL_TYPE_KEY );
+ if( equalSet.isEmpty() )
+ {
+ if( equalTypePredicate.test( candidate ) )
+ {
+ equalSet.add( candidate );
+ }
+ else if( assignableTypePredicate.test( candidate ) )
+ {
+ map.get( ASSIGNABLE_TYPE_KEY ).add( candidate );
+ }
+ }
+ };
+ }
+
+ @Override
+ public BinaryOperator<Map<String, Set<T>>> combiner()
+ {
+ return ( left, right ) ->
+ {
+ left.get( EQUAL_TYPE_KEY ).addAll( right.get( EQUAL_TYPE_KEY ) );
+ left.get( ASSIGNABLE_TYPE_KEY ).addAll( right.get( ASSIGNABLE_TYPE_KEY ) );
+ return left;
+ };
+ }
+
+ @Override
+ public Function<Map<String, Set<T>>, Optional<T>> finisher()
+ {
+ return map ->
+ {
+ Set<T> equalSet = map.get( EQUAL_TYPE_KEY );
+ if( !equalSet.isEmpty() )
+ {
+ return Optional.of( equalSet.iterator().next() );
+ }
+ Set<T> assignableSet = map.get( ASSIGNABLE_TYPE_KEY );
+ if( !assignableSet.isEmpty() )
+ {
+ return Optional.of( assignableSet.iterator().next() );
+ }
+ return Optional.empty();
+ };
+ }
+
+ @Override
+ public final Set<Characteristics> characteristics()
+ {
+ return Collections.emptySet();
+ }
+ };
+ }
+
+ /**
+ * Collect all matching HasTypes.
+ *
+ * First the ones with at least on equal type.
+ * Then the ones with at least one type assignable from {@literal type}.
+ *
+ * @param type type to match
+ * @param <T> type of HasTypes
+ * @return an optional best matching HasTypes
+ */
+ public static <T extends HasTypes> Collector<T, ?, List<T>> matchingTypes( Type type )
+ {
+ return typeToListCollector( type, new HasAssignableFromType<>( type ) );
+ }
+
+ public static <T extends HasTypes> Collector<T, ?, List<T>> closestTypes( Type type )
+ {
+ return typeToListCollector( type, new HasAssignableToType<>( type ) );
+ }
+
+ private static <T extends HasTypes> Collector<T, ?, List<T>>
+ typeToListCollector( Type type, Predicate<T> assignableTypePredicate )
+ {
+ Predicate<T> equalTypePredicate = new HasEqualType<>( type );
+ return new Collector<T, Map<String, Set<T>>, List<T>>()
+ {
+ @Override
+ public Supplier<Map<String, Set<T>>> supplier()
+ {
+ return () -> new HashMap<String, Set<T>>( 2 )
+ {{
+ put( EQUAL_TYPE_KEY, new LinkedHashSet<>() );
+ put( ASSIGNABLE_TYPE_KEY, new LinkedHashSet<>() );
+ }};
+ }
+
+ @Override
+ public BiConsumer<Map<String, Set<T>>, T> accumulator()
+ {
+ return ( map, candidate ) ->
+ {
+ if( equalTypePredicate.test( candidate ) )
+ {
+ map.get( EQUAL_TYPE_KEY ).add( candidate );
+ }
+ else if( assignableTypePredicate.test( candidate ) )
+ {
+ map.get( ASSIGNABLE_TYPE_KEY ).add( candidate );
+ }
+ };
+ }
+
+ @Override
+ public BinaryOperator<Map<String, Set<T>>> combiner()
+ {
+ return ( left, right ) ->
+ {
+ left.get( EQUAL_TYPE_KEY ).addAll( right.get( EQUAL_TYPE_KEY ) );
+ left.get( ASSIGNABLE_TYPE_KEY ).addAll( right.get( ASSIGNABLE_TYPE_KEY ) );
+ return left;
+ };
+ }
+
+ @Override
+ public Function<Map<String, Set<T>>, List<T>> finisher()
+ {
+ return map ->
+ {
+ Set<T> equalSet = map.get( EQUAL_TYPE_KEY );
+ Set<T> assignableSet = map.get( ASSIGNABLE_TYPE_KEY );
+ List<T> list = new ArrayList<>( equalSet.size() + assignableSet.size() );
+ list.addAll( equalSet );
+ list.addAll( assignableSet );
+ return list;
+ };
+ }
+
+ @Override
+ public final Set<Characteristics> characteristics()
+ {
+ return Collections.emptySet();
+ }
+ };
+ }
+
+ private HasTypesCollectors() {}
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/core/api/src/main/java/org/apache/polygene/api/type/HasTypesPredicate.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/type/HasTypesPredicate.java b/core/api/src/main/java/org/apache/polygene/api/type/HasTypesPredicate.java
new file mode 100644
index 0000000..fd91a3a
--- /dev/null
+++ b/core/api/src/main/java/org/apache/polygene/api/type/HasTypesPredicate.java
@@ -0,0 +1,60 @@
+package org.apache.polygene.api.type;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.WildcardType;
+import java.util.List;
+import java.util.function.Predicate;
+
+import static org.apache.polygene.api.util.Classes.interfacesOf;
+
+public abstract class HasTypesPredicate<T extends HasTypes> implements Predicate<T>
+{
+ protected final List<Type> matchTypes;
+
+ protected HasTypesPredicate( List<Type> types )
+ {
+ matchTypes = types;
+ }
+
+ @Override
+ public final boolean test( T hasTypes )
+ {
+ for( Type matchType : matchTypes )
+ {
+ if( matchType instanceof Class )
+ {
+ if( hasTypes.types().anyMatch( matchPredicate( matchType ) ) )
+ {
+ return true;
+ }
+ }
+ else
+ {
+ if( matchType instanceof ParameterizedType )
+ {
+ // Foo<Bar> check
+ // First check Foo
+ ParameterizedType parameterizedType = (ParameterizedType) matchType;
+ Type rawType = parameterizedType.getRawType();
+
+ if( hasTypes.types().anyMatch( matchPredicate( rawType ) ) )
+ {
+ // Then check Bar
+ if( interfacesOf( hasTypes.types() ).anyMatch( intf -> intf.equals( matchType ) ) )
+ {
+ return true;
+ }
+ }
+ }
+ else if( matchType instanceof WildcardType )
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ protected abstract Predicate<Type> matchPredicate( Type candidate );
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/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
index 4046628..23124eb 100644
--- 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
@@ -21,6 +21,7 @@ package org.apache.polygene.api.type;
import java.lang.reflect.Type;
import java.util.Map;
+import java.util.Objects;
import org.apache.polygene.api.util.Classes;
/**
@@ -30,38 +31,40 @@ import org.apache.polygene.api.util.Classes;
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 )
+ public static MapType of( Class<?> mapType, ValueType keyType, ValueType valueType )
{
- return new MapType( Map.class, ValueType.of( keyType ), ValueType.of( valueType ) );
+ return new MapType( mapType, keyType, valueType );
}
- public static MapType of( Class<?> keyType, Class<?> valueType, Serialization.Variant variant )
+ public static MapType of( Class<?> mapType, Class<?> keyType, Class<?> valueType )
{
- return new MapType( Map.class, ValueType.of( keyType ), ValueType.of( valueType ), variant );
+ return of( mapType, ValueType.of( keyType ), ValueType.of( valueType ) );
}
- public MapType( Class<?> type, ValueType keyType, ValueType valueType )
+ public static MapType of( ValueType keyType, ValueType valueType )
{
- this( type, keyType, valueType, Serialization.Variant.entry );
+ return new MapType( Map.class, keyType, valueType );
}
- public MapType( Class<?> type, ValueType keyType, ValueType valueType, Serialization.Variant variant )
+ public static MapType of( Class<?> keyType, Class<?> valueType )
+ {
+ return of( ValueType.of( keyType ), ValueType.of( valueType ) );
+ }
+
+ private ValueType keyType;
+ private ValueType valueType;
+
+ public MapType( Class<?> type, ValueType keyType, ValueType valueType )
{
super( type );
this.keyType = keyType;
this.valueType = valueType;
- this.variant = variant;
if( !isMap( type ) )
{
throw new IllegalArgumentException( type + " is not a Map." );
@@ -78,9 +81,21 @@ public final class MapType
return valueType;
}
- public Serialization.Variant variant()
+ @Override
+ public boolean equals( final Object o )
+ {
+ if( this == o ) { return true; }
+ if( o == null || getClass() != o.getClass() ) { return false; }
+ if( !super.equals( o ) ) { return false; }
+ MapType mapType = (MapType) o;
+ return Objects.equals( keyType, mapType.keyType ) &&
+ Objects.equals( valueType, mapType.valueType );
+ }
+
+ @Override
+ public int hashCode()
{
- return variant;
+ return Objects.hash( super.hashCode(), keyType, valueType );
}
@Override
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/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
deleted file mode 100644
index 8d8ff92..0000000
--- a/core/api/src/main/java/org/apache/polygene/api/type/MatchTypeSpecification.java
+++ /dev/null
@@ -1,51 +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.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/polygene-java/blob/c9dd7229/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
deleted file mode 100644
index 981ab00..0000000
--- a/core/api/src/main/java/org/apache/polygene/api/type/Serialization.java
+++ /dev/null
@@ -1,62 +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.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>
- * <object>
- * <
- * </object>
- * </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/polygene-java/blob/c9dd7229/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
index 4cf86a6..9190e68 100644
--- 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
@@ -20,7 +20,7 @@
package org.apache.polygene.api.type;
import java.lang.reflect.Type;
-import java.util.stream.Collectors;
+import java.util.Objects;
import java.util.stream.Stream;
import org.apache.polygene.api.association.AssociationDescriptor;
import org.apache.polygene.api.property.PropertyDescriptor;
@@ -28,22 +28,28 @@ import org.apache.polygene.api.util.Classes;
import org.apache.polygene.api.value.ValueComposite;
import org.apache.polygene.api.value.ValueDescriptor;
+import static java.util.stream.Collectors.toList;
+
/**
* ValueComposite ValueType.
*/
-public final class ValueCompositeType
- extends ValueType
+public final class ValueCompositeType extends ValueType
{
- private final ValueDescriptor model;
+ public static ValueCompositeType of( ValueDescriptor model )
+ {
+ return new ValueCompositeType( model );
+ }
public static boolean isValueComposite( Type type )
{
return ValueComposite.class.isAssignableFrom( Classes.RAW_CLASS.apply( type ) );
}
+ private final ValueDescriptor model;
+
public ValueCompositeType( ValueDescriptor model )
{
- super( model.types().collect( Collectors.toList() ) );
+ super( model.types().collect( toList() ) );
this.model = model;
}
@@ -66,4 +72,20 @@ public final class ValueCompositeType
{
return model.state().namedAssociations();
}
+
+ @Override
+ public boolean equals( final Object o )
+ {
+ if( this == o ) { return true; }
+ if( o == null || getClass() != o.getClass() ) { return false; }
+ if( !super.equals( o ) ) { return false; }
+ ValueCompositeType that = (ValueCompositeType) o;
+ return Objects.equals( model, that.model );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash( super.hashCode(), model );
+ }
}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/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
index fee41cb..d457d81 100644
--- 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
@@ -19,10 +19,21 @@
*/
package org.apache.polygene.api.type;
-import java.util.Collections;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.Period;
+import java.time.ZonedDateTime;
+import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
+import org.apache.polygene.api.entity.EntityReference;
import org.apache.polygene.api.identity.Identity;
import static java.util.stream.Collectors.joining;
@@ -30,105 +41,44 @@ import static java.util.stream.Collectors.joining;
/**
* Base class for types of values in ValueComposites and Properties.
*/
-public class ValueType
- implements HasTypes
+public class ValueType implements HasTypes
{
+ public static final ValueType OBJECT = ValueType.of( Object.class );
+ public static final ValueType STRING = ValueType.of( String.class );
+ public static final ValueType CHARACTER = ValueType.of( Character.class, char.class );
+ public static final ValueType BOOLEAN = ValueType.of( Boolean.class, boolean.class );
+ public static final ValueType INTEGER = ValueType.of( Integer.class, int.class );
+ public static final ValueType LONG = ValueType.of( Long.class, long.class );
+ public static final ValueType SHORT = ValueType.of( Short.class, short.class );
+ public static final ValueType BYTE = ValueType.of( Byte.class, byte.class );
+ public static final ValueType FLOAT = ValueType.of( Float.class, float.class );
+ public static final ValueType DOUBLE = ValueType.of( Double.class, double.class );
+ public static final ValueType BIG_DECIMAL = ValueType.of( BigDecimal.class );
+ public static final ValueType BIG_INTEGER = ValueType.of( BigInteger.class );
+ public static final ValueType INSTANT = ValueType.of( Instant.class );
+ public static final ValueType ZONED_DATE_TIME = ValueType.of( ZonedDateTime.class );
+ public static final ValueType OFFSET_DATE_TIME = ValueType.of( OffsetDateTime.class );
+ public static final ValueType LOCAL_DATE_TIME = ValueType.of( LocalDateTime.class );
+ public static final ValueType LOCAL_DATE = ValueType.of( LocalDate.class );
+ public static final ValueType LOCAL_TIME = ValueType.of( LocalTime.class );
+ public static final ValueType DURATION = ValueType.of( Duration.class );
+ public static final ValueType PERIOD = ValueType.of( Period.class );
+ public static final ValueType IDENTITY = ValueType.of( Identity.class );
+ public static final ValueType ENTITY_REFERENCE = ValueType.of( EntityReference.class );
- public static ValueType of( Class<?> type )
+ public static ValueType of( Class<?>... types )
{
- return new ValueType( type );
+ return new ValueType( types );
}
- /**
- * 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>
- *
- * @param object Object
- * @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 )
- {
- Objects.requireNonNull( 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.primaryType() );
- }
-
- /**
- * @see ValueType#isPrimitiveValue(java.lang.Object)
- * @param type Type
- * @return true if object is a primitive value or an array of primitive values
- */
- public static boolean isPrimitiveValueType( Class<?> type )
- {
- Objects.requireNonNull( 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 )
+ protected ValueType( Class<?>... types )
{
- this( Collections.singletonList( type ) );
+ this( Arrays.asList( types ) );
}
- @SuppressWarnings( "unchecked" )
- public ValueType( List<Class<?>> types )
+ protected ValueType( List<Class<?>> types )
{
this.types = types;
}
@@ -145,6 +95,21 @@ public class ValueType
}
@Override
+ public boolean equals( Object o )
+ {
+ if( this == o ) { return true; }
+ if( o == null || getClass() != o.getClass() ) { return false; }
+ ValueType valueType = (ValueType) o;
+ return Objects.equals( types, valueType.types );
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash( types );
+ }
+
+ @Override
public String toString()
{
String name = types.stream().map( Class::getName ).collect( joining( "," ) );
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/core/api/src/main/java/org/apache/polygene/api/util/Collectors.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/util/Collectors.java b/core/api/src/main/java/org/apache/polygene/api/util/Collectors.java
index e419b21..906b062 100644
--- a/core/api/src/main/java/org/apache/polygene/api/util/Collectors.java
+++ b/core/api/src/main/java/org/apache/polygene/api/util/Collectors.java
@@ -17,6 +17,7 @@
*/
package org.apache.polygene.api.util;
+import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.BinaryOperator;
@@ -24,13 +25,18 @@ import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
+/**
+ * Implementations of {@link Collector} missing from the JDK.
+ */
public class Collectors
{
/**
* Collect a single element.
+ *
+ * The Collector throws {@link IllegalArgumentException} if no or more than one element.
+ *
* @param <T> Element type
- * @return The single element
- * @throws IllegalArgumentException if no or more than one element
+ * @return The single element collector
*/
public static <T>
Collector<T, ?, T> single()
@@ -46,13 +52,14 @@ public class Collectors
/**
* Eventually collect a single element.
+ *
+ * The Collector throws {@link IllegalArgumentException} if more than one element.
+ *
* @param <T> Element type
- * @return The single element, optional
- * @throws IllegalArgumentException if more than one element
+ * @return The optional single element collector
*/
public static <T>
Collector<T, ?, Optional<T>> singleOrEmpty()
- throws IllegalArgumentException
{
return java.util.stream.Collectors.reducing(
( left, right ) ->
@@ -69,6 +76,59 @@ public class Collectors
} );
}
+ /**
+ * Collect map entries into a {@link HashMap}.
+ *
+ * The Collector throws {@link NullPointerException} if one entry has a {@literal null} value.
+ * The Collector throws {@link IllegalStateException} if duplicate keys are found.
+ *
+ * @param <T> the Map entry type
+ * @param <K> the collected map key type
+ * @param <U> the collected map value type
+ * @return a {@code Collector} which collects elements into a {@code Map}
+ */
+ public static <T extends Map.Entry<K, U>, K, U>
+ Collector<T, ?, Map<K, U>> toMap()
+ {
+ return toMap( Map.Entry::getKey, Map.Entry::getValue, HashMap::new );
+ }
+
+ /**
+ * Collect map entries into a map.
+ *
+ * The Collector throws {@link NullPointerException} if one entry has a {@literal null} value.
+ * The Collector throws {@link IllegalStateException} if duplicate keys are found.
+ *
+ * @param <M> the type of the resulting {@code Map}
+ * @param <T> the Map entry type
+ * @param <K> the collected map key type
+ * @param <U> the collected map value type
+ * @param mapSupplier a function which returns a new, empty {@code Map} into
+ * which the results will be inserted
+ * @return The map collector
+ */
+ public static <T extends Map.Entry<K, U>, K, U, M extends Map<K, U>>
+ Collector<T, ?, M> toMap( Supplier<M> mapSupplier )
+ {
+ return toMap( Map.Entry::getKey, Map.Entry::getValue, mapSupplier );
+ }
+
+ /**
+ * Collect map entries into a map.
+ *
+ * The Collector throws {@link NullPointerException} if one entry has a {@literal null} value.
+ * The Collector throws {@link IllegalStateException} if duplicate keys are found.
+ *
+ * @param <M> the type of the resulting {@code Map}
+ * @param <T> the Map entry type
+ * @param <K> the collected map key type
+ * @param <U> the collected map value type
+ * @param keyMapper a mapping function to produce keys
+ * @param valueMapper a mapping function to produce values
+ * @param mapSupplier a function which returns a new, empty {@code Map} into
+ * which the results will be inserted
+ * @return The map collector
+ */
public static <T, K, U, M extends Map<K, U>>
Collector<T, ?, M> toMap( Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
@@ -80,17 +140,86 @@ public class Collectors
mapSupplier );
}
-
+ /**
+ * Collect map entries into a {@link HashMap}, allowing null values.
+ *
+ * The Collector throws {@link IllegalStateException} if duplicate keys are found.
+ *
+ * See https://bugs.openjdk.java.net/browse/JDK-8148463
+ *
+ * @param <T> the Map entry type
+ * @param <K> the collected map key type
+ * @param <U> the collected map value type
+ * @return The map collector
+ */
public static <T extends Map.Entry<K, U>, K, U>
- Collector<T, ?, Map<K, U>> toMap()
+ Collector<T, ?, Map<K, U>> toMapWithNullValues()
{
- return java.util.stream.Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue );
+ return toMapWithNullValues( Map.Entry::getKey, Map.Entry::getValue, HashMap::new );
}
+ /**
+ * Collect map entries into a map, allowing null values.
+ *
+ * The Collector throws {@link IllegalStateException} if duplicate keys are found.
+ *
+ * See https://bugs.openjdk.java.net/browse/JDK-8148463
+ *
+ * @param <M> the type of the resulting {@code Map}
+ * @param <T> the Map entry type
+ * @param <K> the collected map key type
+ * @param <U> the collected map value type
+ * @param mapSupplier a function which returns a new, empty {@code Map} into
+ * which the results will be inserted
+ * @return The map collector
+ */
public static <T extends Map.Entry<K, U>, K, U, M extends Map<K, U>>
- Collector<T, ?, M> toMap( Supplier<M> mapSupplier )
+ Collector<T, ?, M> toMapWithNullValues( Supplier<M> mapSupplier )
{
- return toMap( Map.Entry::getKey, Map.Entry::getValue, mapSupplier );
+ return toMapWithNullValues( Map.Entry::getKey, Map.Entry::getValue, mapSupplier );
+ }
+
+ /**
+ * Collect map entries into a map, allowing null values.
+ *
+ * The Collector throws {@link IllegalStateException} if duplicate keys are found.
+ *
+ * See https://bugs.openjdk.java.net/browse/JDK-8148463
+ *
+ * @param <M> the type of the resulting {@code Map}
+ * @param <T> the Map entry type
+ * @param <K> the collected map key type
+ * @param <U> the collected map value type
+ * @param keyMapper a mapping function to produce keys
+ * @param valueMapper a mapping function to produce values
+ * @param mapSupplier a function which returns a new, empty {@code Map} into
+ * which the results will be inserted
+ * @return The map collector
+ */
+ public static <T, K, U, M extends Map<K, U>>
+ Collector<T, ?, M> toMapWithNullValues( Function<? super T, ? extends K> keyMapper,
+ Function<? super T, ? extends U> valueMapper,
+ Supplier<M> mapSupplier )
+ {
+ return java.util.stream.Collector
+ .of( mapSupplier,
+ ( map, entry ) -> map.put( keyMapper.apply( entry ),
+ valueMapper.apply( entry ) ),
+ ( left, right ) ->
+ {
+ M result = mapSupplier.get();
+ result.putAll( left );
+ for( Map.Entry<K, U> entry : right.entrySet() )
+ {
+ K key = entry.getKey();
+ if( result.containsKey( key ) )
+ {
+ throw new IllegalStateException( String.format( "Duplicate key %s", key ) );
+ }
+ result.put( key, entry.getValue() );
+ }
+ return result;
+ } );
}
private static <T> BinaryOperator<T> throwingMerger()
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/core/api/src/main/java/org/apache/polygene/api/value/MissingValueSerializationException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/MissingValueSerializationException.java b/core/api/src/main/java/org/apache/polygene/api/value/MissingValueSerializationException.java
deleted file mode 100644
index 00b1af7..0000000
--- a/core/api/src/main/java/org/apache/polygene/api/value/MissingValueSerializationException.java
+++ /dev/null
@@ -1,43 +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.polygene.api.value;
-
-public class MissingValueSerializationException extends ValueSerializationException
-{
- public MissingValueSerializationException()
- {
- }
-
- public MissingValueSerializationException( String message )
- {
- super( message );
- }
-
- public MissingValueSerializationException( String message, Throwable cause )
- {
- super( message, cause );
- }
-
- public MissingValueSerializationException( Throwable cause )
- {
- super( cause );
- }
-}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/core/api/src/main/java/org/apache/polygene/api/value/ValueDescriptor.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueDescriptor.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueDescriptor.java
index b9b3f54..8407fa9 100644
--- a/core/api/src/main/java/org/apache/polygene/api/value/ValueDescriptor.java
+++ b/core/api/src/main/java/org/apache/polygene/api/value/ValueDescriptor.java
@@ -20,19 +20,15 @@
package org.apache.polygene.api.value;
-import org.apache.polygene.api.association.AssociationStateDescriptor;
import org.apache.polygene.api.composite.CompositeDescriptor;
-import org.apache.polygene.api.composite.StatefulCompositeDescriptor;
+import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor;
import org.apache.polygene.api.type.ValueCompositeType;
/**
* Descriptor for ValueComposites.
*/
public interface ValueDescriptor
- extends CompositeDescriptor, StatefulCompositeDescriptor
+ extends CompositeDescriptor, StatefulAssociationCompositeDescriptor
{
ValueCompositeType valueType();
-
- @Override
- AssociationStateDescriptor state();
}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/core/api/src/main/java/org/apache/polygene/api/value/ValueDeserializer.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueDeserializer.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueDeserializer.java
deleted file mode 100644
index 88afc3a..0000000
--- a/core/api/src/main/java/org/apache/polygene/api/value/ValueDeserializer.java
+++ /dev/null
@@ -1,172 +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.polygene.api.value;
-
-import java.io.InputStream;
-import java.util.function.Function;
-import org.apache.polygene.api.structure.ModuleDescriptor;
-import org.apache.polygene.api.type.ValueType;
-
-/**
- * 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 reference 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.apache.polygene.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 <T> the parametrized function return type
- * @param module the module
- * @param type the value type
- *
- * @return a deserialization function
- */
- <T> Function<String, T> deserialize( ModuleDescriptor module, Class<T> type );
-
- /**
- * Factory method for a typed deserialize function.
- *
- * <p>The returned Function may throw {@link ValueSerializationException}.</p>
- *
- * @param <T> the parametrized function return type
- * @param module the module
- * @param valueType the value type
- *
- * @return a deserialization function
- */
- <T> Function<String, T> deserialize( ModuleDescriptor module, 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> BiFunction<ValueType, String, T> deserialize();
-
- /**
- * Deserialize a value from a state.
- *
- * @param <T> the parametrized returned type
- * @param module the module
- * @param type the value type
- * @param input the state
- *
- * @return the value
- *
- * @throws ValueSerializationException if the deserialization failed
- */
- <T> T deserialize( ModuleDescriptor module, Class<?> type, String input )
- throws ValueSerializationException;
-
- /**
- * Deserialize a value from a state.
- *
- * @param <T> the parametrized returned type
- * @param module the module
- * @param valueType the value type
- * @param input the state
- *
- * @return the value
- *
- * @throws ValueSerializationException if the deserialization failed
- */
- <T> T deserialize( ModuleDescriptor module, ValueType valueType, String input )
- throws ValueSerializationException;
-
- /**
- * Deserialize a value from a state.
- *
- * @param <T> the parametrized returned type
- * @param module the module
- * @param type the value type
- * @param input the state stream
- *
- * @return the value
- *
- * @throws ValueSerializationException if the deserialization failed
- */
- <T> T deserialize( ModuleDescriptor module, Class<?> type, InputStream input )
- throws ValueSerializationException;
-
- /**
- * Deserialize a value from a state.
- *
- * @param <T> the parametrized returned type
- * @param module the module
- * @param valueType the value type
- * @param input the state stream
- *
- * @return the value
- *
- * @throws ValueSerializationException if the deserialization failed
- */
- <T> T deserialize( ModuleDescriptor module, ValueType valueType, InputStream input )
- throws ValueSerializationException;
-}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/core/api/src/main/java/org/apache/polygene/api/value/ValueSerialization.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueSerialization.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueSerialization.java
deleted file mode 100644
index 91c1081..0000000
--- a/core/api/src/main/java/org/apache/polygene/api/value/ValueSerialization.java
+++ /dev/null
@@ -1,56 +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.polygene.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/polygene-java/blob/c9dd7229/core/api/src/main/java/org/apache/polygene/api/value/ValueSerializationException.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueSerializationException.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueSerializationException.java
deleted file mode 100644
index 62faa75..0000000
--- a/core/api/src/main/java/org/apache/polygene/api/value/ValueSerializationException.java
+++ /dev/null
@@ -1,50 +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.polygene.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/polygene-java/blob/c9dd7229/core/api/src/main/java/org/apache/polygene/api/value/ValueSerializer.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/polygene/api/value/ValueSerializer.java b/core/api/src/main/java/org/apache/polygene/api/value/ValueSerializer.java
deleted file mode 100644
index 736df9d..0000000
--- a/core/api/src/main/java/org/apache/polygene/api/value/ValueSerializer.java
+++ /dev/null
@@ -1,293 +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.polygene.api.value;
-
-import java.io.OutputStream;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.function.Function;
-import org.apache.polygene.api.composite.AmbiguousTypeException;
-
-/**
- * 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 reference 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 );
-
- /**
- * 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 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;
-
- /**
- * 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/polygene-java/blob/c9dd7229/core/api/src/test/java/org/apache/polygene/api/type/HasTypesCollectorsTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/polygene/api/type/HasTypesCollectorsTest.java b/core/api/src/test/java/org/apache/polygene/api/type/HasTypesCollectorsTest.java
new file mode 100644
index 0000000..0e92245
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/type/HasTypesCollectorsTest.java
@@ -0,0 +1,131 @@
+package org.apache.polygene.api.type;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import org.apache.polygene.api.identity.Identity;
+import org.apache.polygene.api.identity.StringIdentity;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class HasTypesCollectorsTest
+{
+ @Test
+ public void selectMatchingTypes()
+ {
+ List<ValueType> valueTypes = Arrays.asList(
+ ValueType.of( String.class ),
+ ValueType.of( Integer.class ),
+ ValueType.of( Number.class )
+ );
+
+ List<ValueType> number = valueTypes.stream().collect( HasTypesCollectors.matchingTypes( Number.class ) );
+ assertThat( number.size(), is( 2 ) );
+ assertThat( number.get( 0 ), equalTo( ValueType.of( Number.class ) ) );
+ assertThat( number.get( 1 ), equalTo( ValueType.of( Integer.class ) ) );
+
+ List<ValueType> integer = valueTypes.stream().collect( HasTypesCollectors.matchingTypes( Integer.class ) );
+ assertThat( integer.size(), is( 1 ) );
+ assertThat( integer.get( 0 ), equalTo( ValueType.of( Integer.class ) ) );
+ }
+
+ @Test
+ public void selectMatchingType()
+ {
+ List<ValueType> valueTypes = Arrays.asList(
+ ValueType.of( String.class ),
+ ValueType.of( Double.class ),
+ ValueType.of( Integer.class )
+ );
+
+ Optional<ValueType> number = valueTypes.stream()
+ .collect( HasTypesCollectors.matchingType( Number.class ) );
+ assertTrue( number.isPresent() );
+ assertThat( number.get(), equalTo( ValueType.of( Double.class ) ) );
+
+ Optional<ValueType> integer = valueTypes.stream()
+ .collect( HasTypesCollectors.matchingType( Integer.class ) );
+ assertTrue( integer.isPresent() );
+ assertThat( integer.get(), equalTo( ValueType.of( Integer.class ) ) );
+ }
+
+ @Test
+ public void selectMatchingValueTypes()
+ {
+ List<ValueType> valueTypes = Arrays.asList(
+ ValueType.of( String.class ),
+ ValueType.of( Number.class, Integer.class ),
+ ValueType.of( Integer.class ),
+ ValueType.of( Number.class )
+ );
+
+ List<ValueType> number = valueTypes.stream()
+ .collect( HasTypesCollectors.matchingTypes( ValueType.of( Number.class ) ) );
+ System.out.println( number );
+ assertThat( number.size(), is( 2 ) );
+ assertThat( number.get( 0 ), equalTo( ValueType.of( Number.class ) ) );
+ assertThat( number.get( 1 ), equalTo( ValueType.of( Number.class, Integer.class ) ) );
+
+ List<ValueType> integer = valueTypes.stream()
+ .collect(
+ HasTypesCollectors.matchingTypes( ValueType.of( Integer.class ) ) );
+ assertThat( integer.size(), is( 2 ) );
+ assertThat( integer.get( 0 ), equalTo( ValueType.of( Integer.class ) ) );
+ assertThat( integer.get( 1 ), equalTo( ValueType.of( Number.class, Integer.class ) ) );
+
+ List<ValueType> both = valueTypes.stream()
+ .collect( HasTypesCollectors.matchingTypes( ValueType.of( Number.class,
+ Integer.class ) ) );
+ assertThat( both.size(), is( 1 ) );
+ assertThat( both.get( 0 ), equalTo( ValueType.of( Number.class, Integer.class ) ) );
+ }
+
+ @Test
+ public void selectMatchingValueType()
+ {
+ List<ValueType> valueTypes = Arrays.asList(
+ ValueType.of( String.class ),
+ ValueType.of( Number.class, Integer.class ),
+ ValueType.of( Integer.class ),
+ ValueType.of( Number.class )
+ );
+
+ Optional<ValueType> number = valueTypes.stream()
+ .collect(
+ HasTypesCollectors.matchingType( ValueType.of( Number.class ) ) );
+ assertTrue( number.isPresent() );
+ assertThat( number.get(), equalTo( ValueType.of( Number.class ) ) );
+
+ Optional<ValueType> integer = valueTypes.stream()
+ .collect(
+ HasTypesCollectors.matchingType( ValueType.of( Integer.class ) ) );
+ assertTrue( integer.isPresent() );
+ assertThat( integer.get(), equalTo( ValueType.of( Integer.class ) ) );
+
+ Optional<ValueType> both = valueTypes.stream()
+ .collect( HasTypesCollectors.matchingType( ValueType.of( Number.class,
+ Integer.class ) ) );
+ assertTrue( both.isPresent() );
+ assertThat( both.get(), equalTo( ValueType.of( Number.class, Integer.class ) ) );
+ }
+
+ @Test
+ public void selectClosestValueTypes()
+ {
+ List<ValueType> list = new ArrayList<ValueType>()
+ {{
+ add( ValueType.of( String.class ) );
+ add( ValueType.of( Identity.class ) );
+ }};
+
+ List<ValueType> result = list.stream()
+ .collect( HasTypesCollectors.closestTypes( StringIdentity.class ) );
+ assertThat( result.size(), is( 1 ) );
+ assertThat( result.get( 0 ), equalTo( ValueType.of( Identity.class ) ) );
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/core/api/src/test/java/org/apache/polygene/api/type/HasTypesPredicatesTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/polygene/api/type/HasTypesPredicatesTest.java b/core/api/src/test/java/org/apache/polygene/api/type/HasTypesPredicatesTest.java
new file mode 100644
index 0000000..fc87ae6
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/type/HasTypesPredicatesTest.java
@@ -0,0 +1,54 @@
+package org.apache.polygene.api.type;
+
+import java.time.LocalDate;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class HasTypesPredicatesTest
+{
+ @Test
+ public void hasEqualTypePredicate()
+ {
+ assertTrue( new HasEqualType<>( Integer.class )
+ .test( ValueType.of( Integer.class ) ) );
+ assertTrue( new HasEqualType<>( Integer.class )
+ .test( ValueType.of( String.class, Integer.class ) ) );
+ assertFalse( new HasEqualType<>( Number.class )
+ .test( ValueType.of( String.class, Integer.class ) ) );
+ assertFalse( new HasEqualType<>( String.class )
+ .test( ValueType.of( LocalDate.class, Integer.class ) ) );
+
+ assertTrue( new HasEqualType<>( ValueType.of( Integer.class ) )
+ .test( ValueType.of( Integer.class ) ) );
+ assertTrue( new HasEqualType<>( ValueType.of( Integer.class ) )
+ .test( ValueType.of( String.class, Integer.class ) ) );
+ assertFalse( new HasEqualType<>( ValueType.of( Number.class ) )
+ .test( ValueType.of( String.class, Integer.class ) ) );
+ assertFalse( new HasEqualType<>( ValueType.of( String.class ) )
+ .test( ValueType.of( LocalDate.class, Integer.class ) ) );
+ }
+
+ @Test
+ public void hasAssignableTypePredicate()
+ {
+ assertTrue( new HasAssignableFromType<>( Number.class )
+ .test( ValueType.of( String.class, Integer.class ) ) );
+ assertFalse( new HasAssignableFromType<>( Integer.class )
+ .test( ValueType.of( Integer.class ) ) );
+ assertFalse( new HasAssignableFromType<>( String.class )
+ .test( ValueType.of( LocalDate.class, Integer.class ) ) );
+ }
+
+ @Test
+ public void hasEqualOrAssignablePredicate()
+ {
+ assertTrue( new HasEqualOrAssignableFromType<>( Number.class )
+ .test( ValueType.of( String.class, Integer.class ) ) );
+ assertTrue( new HasEqualOrAssignableFromType<>( Integer.class )
+ .test( ValueType.of( Integer.class ) ) );
+ assertFalse( new HasEqualOrAssignableFromType<>( String.class )
+ .test( ValueType.of( LocalDate.class, Integer.class ) ) );
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/core/api/src/test/java/org/apache/polygene/api/type/ValueTypeFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/polygene/api/type/ValueTypeFactoryTest.java b/core/api/src/test/java/org/apache/polygene/api/type/ValueTypeFactoryTest.java
new file mode 100644
index 0000000..5b70078
--- /dev/null
+++ b/core/api/src/test/java/org/apache/polygene/api/type/ValueTypeFactoryTest.java
@@ -0,0 +1,105 @@
+package org.apache.polygene.api.type;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
+import org.apache.polygene.api.common.UseDefaults;
+import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.value.ValueDescriptor;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.spi.module.ModuleSpi;
+import org.apache.polygene.spi.type.ValueTypeFactory;
+import org.apache.polygene.test.AbstractPolygeneTest;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.junit.Assert.assertThat;
+
+public class ValueTypeFactoryTest extends AbstractPolygeneTest
+{
+ private ValueTypeFactory valueTypeFactory;
+
+ @Override
+ public void assemble( ModuleAssembly module )
+ {
+ module.values( SomeValue.class );
+ }
+
+ interface SomeValue
+ {
+ @UseDefaults
+ Property<List<String>> list();
+
+ @UseDefaults
+ Property<Map<String, Integer>> map();
+ }
+
+ @Before
+ public void setup()
+ {
+ valueTypeFactory = ( (ModuleSpi) module.instance() ).valueTypeFactory();
+ }
+
+ @Test
+ public void plainValues()
+ {
+ assertThat( valueTypeFactory.valueTypeOf( module, String.class ), equalTo( ValueType.STRING ) );
+ assertThat( valueTypeFactory.valueTypeOf( module, "" ), equalTo( ValueType.STRING ) );
+ }
+
+ @Test
+ public void enums()
+ {
+ assertThat( valueTypeFactory.valueTypeOf( module, TimeUnit.class ), instanceOf( EnumType.class ) );
+ assertThat( valueTypeFactory.valueTypeOf( module, TimeUnit.DAYS ), instanceOf( EnumType.class ) );
+ }
+
+ @Test
+ public void collections()
+ {
+ assertThat( valueTypeFactory.valueTypeOf( module, LinkedHashSet.class ),
+ instanceOf( CollectionType.class ) );
+
+ List<String> list = new ArrayList<>();
+ ValueType listValueType = valueTypeFactory.valueTypeOf( module, list );
+ assertThat( listValueType, instanceOf( CollectionType.class ) );
+ assertThat( ( (CollectionType) listValueType ).collectedType(), equalTo( ValueType.OBJECT ) );
+ }
+
+ @Test
+ public void maps()
+ {
+ assertThat( valueTypeFactory.valueTypeOf( module, TreeMap.class ), instanceOf( MapType.class ) );
+
+ HashMap<String, Integer> map = new HashMap<>();
+ ValueType mapValueType = valueTypeFactory.valueTypeOf( module, map );
+ assertThat( mapValueType, instanceOf( MapType.class ) );
+ assertThat( ( (MapType) mapValueType ).keyType(), equalTo( ValueType.OBJECT ) );
+ assertThat( ( (MapType) mapValueType ).valueType(), equalTo( ValueType.OBJECT ) );
+ }
+
+ @Test
+ public void valueComposites()
+ {
+ assertThat( valueTypeFactory.valueTypeOf( module, SomeValue.class ),
+ instanceOf( ValueCompositeType.class ) );
+ assertThat( valueTypeFactory.valueTypeOf( module, valueBuilderFactory.newValue( SomeValue.class ) ),
+ instanceOf( ValueCompositeType.class ) );
+ }
+
+ @Test
+ public void genericsAreResolvedOnValueCompositeProperties()
+ {
+ ValueDescriptor descriptor = module.typeLookup().lookupValueModel( SomeValue.class );
+ assertThat( descriptor.state().findPropertyModelByName( "list" ).valueType(),
+ equalTo( CollectionType.listOf( ValueType.STRING ) ) );
+ assertThat( descriptor.state().findPropertyModelByName( "map" ).valueType(),
+ equalTo( MapType.of( ValueType.STRING, ValueType.INTEGER ) ) );
+ }
+}
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/c9dd7229/core/api/src/test/java/org/apache/polygene/api/util/CollectorsTest.java
----------------------------------------------------------------------
diff --git a/core/api/src/test/java/org/apache/polygene/api/util/CollectorsTest.java b/core/api/src/test/java/org/apache/polygene/api/util/CollectorsTest.java
index 5521b93..1beb26a 100644
--- a/core/api/src/test/java/org/apache/polygene/api/util/CollectorsTest.java
+++ b/core/api/src/test/java/org/apache/polygene/api/util/CollectorsTest.java
@@ -17,59 +17,99 @@
*/
package org.apache.polygene.api.util;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
import org.junit.Test;
+import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
public class CollectorsTest
{
- @Test
- public void single()
+@Test
+public void single()
+{
+ assertThat( Stream.of( 1L ).collect( Collectors.single() ), is( 1L ) );
+
+ try
+ {
+ Stream.of().collect( Collectors.single() );
+ fail( "Should have failed" );
+ }
+ catch( IllegalArgumentException ex ) {}
+ try
{
- assertThat( Stream.of( 1L ).collect( Collectors.single() ), is( 1L ) );
+ Stream.of( 1, 1 ).collect( Collectors.single() );
+ fail( "Should have failed" );
+ }
+ catch( IllegalArgumentException ex ) {}
+ try
+ {
+ Stream.of( 1, 1, 1 ).collect( Collectors.single() );
+ fail( "Should have failed" );
+ }
+ catch( IllegalArgumentException ex ) {}
+}
- try
- {
- Stream.of().collect( Collectors.single() );
- fail( "Should have failed" );
- }
- catch( IllegalArgumentException ex ) {}
- try
- {
- Stream.of( 1, 1 ).collect( Collectors.single() );
- fail( "Should have failed" );
- }
- catch( IllegalArgumentException ex ) {}
- try
- {
- Stream.of( 1, 1, 1 ).collect( Collectors.single() );
- fail( "Should have failed" );
- }
- catch( IllegalArgumentException ex ) {}
+@Test
+public void singleOrEmpty()
+{
+ assertEquals( Optional.empty(), Stream.of().collect( Collectors.singleOrEmpty() ) );
+ assertEquals( Optional.of( 1 ), Stream.of( 1 ).collect( Collectors.singleOrEmpty() ) );
+
+ try
+ {
+ Stream.of( 1, 1 ).collect( Collectors.singleOrEmpty() );
+ fail( "Should have failed" );
}
+ catch( IllegalArgumentException ex ) {}
+ try
+ {
+ Stream.of( 1, 1, 1 ).collect( Collectors.singleOrEmpty() );
+ fail( "Should have failed" );
+ }
+ catch( IllegalArgumentException ex ) {}
+}
@Test
- public void singleOrEmpty()
+ public void toMap()
{
- assertEquals( Optional.empty(), Stream.of().collect( Collectors.singleOrEmpty() ) );
- assertEquals( Optional.of( 1 ), Stream.of( 1 ).collect( Collectors.singleOrEmpty() ) );
+ Map<String, String> input = new LinkedHashMap<>();
+ input.put( "foo", "bar" );
+ input.put( "bazar", "cathedral" );
+ Map<String, String> output = input.entrySet().stream().collect( Collectors.toMap() );
+ assertThat( output.get( "foo" ), equalTo( "bar" ) );
+ assertThat( output.get( "bazar" ), equalTo( "cathedral" ) );
+ }
+ @Test
+ public void toMapRejectNullValues()
+ {
+ Map<String, String> input = new LinkedHashMap<>();
+ input.put( "foo", "bar" );
+ input.put( "bazar", null );
try
{
- Stream.of( 1, 1 ).collect( Collectors.singleOrEmpty() );
- fail( "Should have failed" );
- }
- catch( IllegalArgumentException ex ) {}
- try
- {
- Stream.of( 1, 1, 1 ).collect( Collectors.singleOrEmpty() );
- fail( "Should have failed" );
+ input.entrySet().stream().collect( Collectors.toMap() );
+ fail( "Should have failed, that's the default Map::merge behaviour" );
}
- catch( IllegalArgumentException ex ) {}
+ catch( NullPointerException expected ) {}
+ }
+
+ @Test
+ public void toMapWithNullValues()
+ {
+ Map<String, String> input = new LinkedHashMap<>();
+ input.put( "foo", "bar" );
+ input.put( "bazar", null );
+ Map<String, String> output = input.entrySet().stream().collect( Collectors.toMapWithNullValues() );
+ assertThat( output.get( "foo" ), equalTo( "bar" ) );
+ assertThat( output.get( "bazar" ), nullValue() );
}
}