Start experiment with Sream and Function on our own classes.
Project: http://git-wip-us.apache.org/repos/asf/zest-qi4j/repo Commit: http://git-wip-us.apache.org/repos/asf/zest-qi4j/commit/caa62018 Tree: http://git-wip-us.apache.org/repos/asf/zest-qi4j/tree/caa62018 Diff: http://git-wip-us.apache.org/repos/asf/zest-qi4j/diff/caa62018 Branch: refs/heads/3.0 Commit: caa62018a19bee3673d2607c3f49664ac99e5316 Parents: 1dfbffc Author: Niclas Hedhman <[email protected]> Authored: Sat Oct 4 17:15:27 2014 +0800 Committer: Niclas Hedhman <[email protected]> Committed: Sat Oct 4 17:15:27 2014 +0800 ---------------------------------------------------------------------- .../qi4j/api/association/ManyAssociation.java | 3 ++ .../api/association/ManyAssociationWrapper.java | 7 +++ .../qi4j/api/association/NamedAssociation.java | 2 + .../association/NamedAssociationWrapper.java | 7 +++ .../property/InvalidPropertyTypeException.java | 6 ++- .../java/org/qi4j/api/property/Numbers.java | 21 +++++++- .../java/org/qi4j/api/property/Property.java | 13 +++++ .../runtime/association/GenericSpliterator.java | 40 ++++++++++++++ .../association/ManyAssociationInstance.java | 14 +++++ .../association/NamedAssociationInstance.java | 56 ++++++++++++++++++-- .../qi4j/spi/entity/NamedAssociationState.java | 1 + .../samples/forum/context/view/ViewBoard.java | 3 +- .../samples/forum/context/view/ViewPost.java | 3 +- .../binding/internal/BoundManyAssociation.java | 9 +++- .../binding/internal/BoundNamedAssociation.java | 8 +++ 15 files changed, 182 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/core/api/src/main/java/org/qi4j/api/association/ManyAssociation.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/association/ManyAssociation.java b/core/api/src/main/java/org/qi4j/api/association/ManyAssociation.java index 707d53a..0e1134d 100644 --- a/core/api/src/main/java/org/qi4j/api/association/ManyAssociation.java +++ b/core/api/src/main/java/org/qi4j/api/association/ManyAssociation.java @@ -16,6 +16,7 @@ package org.qi4j.api.association; import java.util.List; import java.util.Set; +import java.util.stream.Stream; /** * Association to a collection of entities. @@ -37,4 +38,6 @@ public interface ManyAssociation<T> extends Iterable<T>, AbstractAssociation List<T> toList(); Set<T> toSet(); + + Stream<T> stream(); } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/core/api/src/main/java/org/qi4j/api/association/ManyAssociationWrapper.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/association/ManyAssociationWrapper.java b/core/api/src/main/java/org/qi4j/api/association/ManyAssociationWrapper.java index 748af83..85e7bce 100644 --- a/core/api/src/main/java/org/qi4j/api/association/ManyAssociationWrapper.java +++ b/core/api/src/main/java/org/qi4j/api/association/ManyAssociationWrapper.java @@ -3,6 +3,7 @@ package org.qi4j.api.association; import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.stream.Stream; /** * If you want to catch calls to ManyAssociations, then create a GenericConcern @@ -73,6 +74,12 @@ public class ManyAssociationWrapper } @Override + public Stream<Object> stream() + { + return next.stream(); + } + + @Override public Iterator<Object> iterator() { return next.iterator(); http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/core/api/src/main/java/org/qi4j/api/association/NamedAssociation.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/association/NamedAssociation.java b/core/api/src/main/java/org/qi4j/api/association/NamedAssociation.java index e8abe32..86a61a6 100644 --- a/core/api/src/main/java/org/qi4j/api/association/NamedAssociation.java +++ b/core/api/src/main/java/org/qi4j/api/association/NamedAssociation.java @@ -19,6 +19,7 @@ package org.qi4j.api.association; import java.util.Map; +import java.util.stream.Stream; /** * Association to named Entities. @@ -75,4 +76,5 @@ public interface NamedAssociation<T> */ Map<String, T> toMap(); + Stream<Map.Entry<String,T>> stream(); } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/core/api/src/main/java/org/qi4j/api/association/NamedAssociationWrapper.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/association/NamedAssociationWrapper.java b/core/api/src/main/java/org/qi4j/api/association/NamedAssociationWrapper.java index 581948e..a033cae 100644 --- a/core/api/src/main/java/org/qi4j/api/association/NamedAssociationWrapper.java +++ b/core/api/src/main/java/org/qi4j/api/association/NamedAssociationWrapper.java @@ -20,6 +20,7 @@ package org.qi4j.api.association; import java.util.Iterator; import java.util.Map; +import java.util.stream.Stream; /** * If you want to catch calls to NamedAssociations, then create a GenericConcern @@ -90,6 +91,12 @@ public class NamedAssociationWrapper } @Override + public Stream<Map.Entry<String, Object>> stream() + { + return next.stream(); + } + + @Override public int hashCode() { return next.hashCode(); http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/core/api/src/main/java/org/qi4j/api/property/InvalidPropertyTypeException.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/property/InvalidPropertyTypeException.java b/core/api/src/main/java/org/qi4j/api/property/InvalidPropertyTypeException.java index c98007e..6c81509 100644 --- a/core/api/src/main/java/org/qi4j/api/property/InvalidPropertyTypeException.java +++ b/core/api/src/main/java/org/qi4j/api/property/InvalidPropertyTypeException.java @@ -16,7 +16,11 @@ public class InvalidPropertyTypeException extends ConstructionException private static String createMessage( AccessibleObject accessor ) { StringBuilder builder = new StringBuilder(); - builder.append( "Not allowed to subclass " + Property.class.getName() + ". Property accessor " + accessor + " is returning a Property subclass." ); + builder.append( "Not allowed to subclass " ) + .append( Property.class.getName() ) + .append( ". Property accessor " ) + .append( accessor ) + .append( " is returning a Property subclass." ); return builder.toString(); } } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/core/api/src/main/java/org/qi4j/api/property/Numbers.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/property/Numbers.java b/core/api/src/main/java/org/qi4j/api/property/Numbers.java index 00c0e5f..070dff0 100644 --- a/core/api/src/main/java/org/qi4j/api/property/Numbers.java +++ b/core/api/src/main/java/org/qi4j/api/property/Numbers.java @@ -15,6 +15,7 @@ package org.qi4j.api.property; import java.math.BigDecimal; +import java.util.function.Function; /** * Convenience class for mathematical operations on numerical properties. @@ -24,8 +25,14 @@ import java.math.BigDecimal; */ public final class Numbers { - // Integer operations + public static <T> Property<T> f( Property<T> property, Function<T,T> function ) + { + property.set( function.apply( property.get() )); + return property; + } + + // Integer operations public static Property<Integer> add( Property<Integer> property, int amount ) { property.set( property.get() + amount ); @@ -50,6 +57,18 @@ public final class Numbers return property; } + public static Property<Integer> inc( Property<Integer> property ) + { + property.set( property.get() + 1 ); + return property; + } + + public static Property<Integer> dec( Property<Integer> property ) + { + property.set( property.get() - 1 ); + return property; + } + // Long operations public static Property<Long> add( Property<Long> property, long amount ) http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/core/api/src/main/java/org/qi4j/api/property/Property.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/qi4j/api/property/Property.java b/core/api/src/main/java/org/qi4j/api/property/Property.java index 9c9cfa8..a40a126 100644 --- a/core/api/src/main/java/org/qi4j/api/property/Property.java +++ b/core/api/src/main/java/org/qi4j/api/property/Property.java @@ -17,6 +17,8 @@ */ package org.qi4j.api.property; +import java.util.function.UnaryOperator; + /** * Properties are declared in Composite interfaces by using this interface. * <p> @@ -58,4 +60,15 @@ public interface Property<T> */ void set( T newValue ) throws IllegalArgumentException, IllegalStateException; + + /** + * Applies the function to the property. + * + * @param function The input to the function is the current value, and the return value is the value to be set + * to the property. + */ + default void f( UnaryOperator<T> function ) + { + set( function.apply( get() ) ); + } } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/core/runtime/src/main/java/org/qi4j/runtime/association/GenericSpliterator.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/GenericSpliterator.java b/core/runtime/src/main/java/org/qi4j/runtime/association/GenericSpliterator.java new file mode 100644 index 0000000..c51ee57 --- /dev/null +++ b/core/runtime/src/main/java/org/qi4j/runtime/association/GenericSpliterator.java @@ -0,0 +1,40 @@ +package org.qi4j.runtime.association; + +import java.util.Iterator; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.function.Consumer; +import java.util.function.Function; + +public class GenericSpliterator<T, R> extends Spliterators.AbstractSpliterator<R> +{ + private final Iterator<T> it; + private final Function<T, R> mapping; + + public GenericSpliterator( Iterator<T> it, Function<T, R> mapping ) + { + super( 0L, Spliterator.IMMUTABLE ); + this.it = it; + if( mapping == null ) + { + //noinspection unchecked + this.mapping = t -> (R) t; + } + else + { + this.mapping = mapping; + } + } + + @Override + public boolean tryAdvance( Consumer<? super R> action ) + { + if( it.hasNext() ) + { + T value = it.next(); + action.accept( mapping.apply( value ) ); + return true; + } + return false; + } +} http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationInstance.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationInstance.java index b28b7cb..09eac1a 100644 --- a/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationInstance.java +++ b/core/runtime/src/main/java/org/qi4j/runtime/association/ManyAssociationInstance.java @@ -5,8 +5,14 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.Spliterator; +import java.util.Spliterators; import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; import org.qi4j.api.association.AssociationDescriptor; import org.qi4j.api.association.ManyAssociation; import org.qi4j.api.association.ManyAssociationWrapper; @@ -111,6 +117,14 @@ public class ManyAssociationInstance<T> } @Override + public Stream<T> stream() + { + final Iterator<T> it = iterator(); + Spliterator<T> entrySpliterator = new GenericSpliterator<>( it, null ); + return StreamSupport.stream( entrySpliterator, false ); + } + + @Override public boolean equals( Object o ) { if( this == o ) http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationInstance.java ---------------------------------------------------------------------- diff --git a/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationInstance.java b/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationInstance.java index f606f79..d22be74 100644 --- a/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationInstance.java +++ b/core/runtime/src/main/java/org/qi4j/runtime/association/NamedAssociationInstance.java @@ -23,9 +23,10 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.function.BiFunction; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; import org.qi4j.api.association.NamedAssociation; import org.qi4j.api.entity.EntityReference; -import org.qi4j.runtime.composite.ConstraintsCheck; import org.qi4j.spi.entity.NamedAssociationState; public class NamedAssociationInstance<T> @@ -37,7 +38,8 @@ public class NamedAssociationInstance<T> public NamedAssociationInstance( AssociationInfo associationInfo, BiFunction<EntityReference, Type, Object> associationFunction, - NamedAssociationState namedAssociationState ) + NamedAssociationState namedAssociationState + ) { super( associationInfo, associationFunction ); this.namedAssociationState = namedAssociationState; @@ -66,7 +68,7 @@ public class NamedAssociationInstance<T> { checkImmutable(); checkType( entity ); - ( (ConstraintsCheck) associationInfo ).checkConstraints( entity ); + associationInfo.checkConstraints( entity ); return namedAssociationState.put( name, getEntityReference( entity ) ); } @@ -80,7 +82,7 @@ public class NamedAssociationInstance<T> @Override public T get( String name ) { - return getEntity( namedAssociationState.get( name ) ); + return getEntityByName( name ); } @Override @@ -95,9 +97,53 @@ public class NamedAssociationInstance<T> Map<String, T> map = new HashMap<>(); for( String name : namedAssociationState ) { - map.put( name, getEntity( namedAssociationState.get( name ) ) ); + map.put( name, getEntityByName( name ) ); } return map; } + @Override + public Stream<Map.Entry<String, T>> stream() + { + final Iterator<String> it = namedAssociationState.iterator(); + return StreamSupport.stream( new GenericSpliterator<>( it, key -> new Entry<>( key, getEntityByName( key ) ) ), + false ); + } + + private T getEntityByName( String name ) + { + return getEntity( namedAssociationState.get( name ) ); + } + + private static final class Entry<K, V> + implements Map.Entry<K, V> + { + + private final K key; + private final V value; + + private Entry( K key, V value ) + { + this.key = key; + this.value = value; + } + + @Override + public K getKey() + { + return key; + } + + @Override + public V getValue() + { + return value; + } + + @Override + public V setValue( V value ) + { + throw new UnsupportedOperationException(); + } + } } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/core/spi/src/main/java/org/qi4j/spi/entity/NamedAssociationState.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/qi4j/spi/entity/NamedAssociationState.java b/core/spi/src/main/java/org/qi4j/spi/entity/NamedAssociationState.java index 5cf3257..90790a2 100644 --- a/core/spi/src/main/java/org/qi4j/spi/entity/NamedAssociationState.java +++ b/core/spi/src/main/java/org/qi4j/spi/entity/NamedAssociationState.java @@ -18,6 +18,7 @@ */ package org.qi4j.spi.entity; +import java.util.Spliterators; import org.qi4j.api.entity.EntityReference; /** http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewBoard.java ---------------------------------------------------------------------- diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewBoard.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewBoard.java index 120dcea..cc8829a 100644 --- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewBoard.java +++ b/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewBoard.java @@ -13,6 +13,7 @@ import org.qi4j.samples.forum.data.entity.Topic; import org.qi4j.samples.forum.data.entity.User; import static org.qi4j.api.property.Numbers.add; +import static org.qi4j.api.property.Numbers.f; /** * TODO @@ -94,7 +95,7 @@ public class ViewBoard self.lastPost().set( post ); add( self.topicCount(), 1 ); - add( self.postCount(), 1 ); + f( self.postCount(), c -> c + 1 ); return topic; } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewPost.java ---------------------------------------------------------------------- diff --git a/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewPost.java b/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewPost.java index 45d4802..b060b29 100644 --- a/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewPost.java +++ b/samples/forum/src/main/java/org/qi4j/samples/forum/context/view/ViewPost.java @@ -3,7 +3,6 @@ package org.qi4j.samples.forum.context.view; import java.time.ZoneId; import org.qi4j.api.injection.scope.Structure; import org.qi4j.api.injection.scope.Uses; -import org.qi4j.api.property.Numbers; import org.qi4j.api.structure.Module; import org.qi4j.library.rest.server.api.ResourceIndex; import org.qi4j.library.rest.server.api.dci.Role; @@ -55,7 +54,7 @@ public class ViewPost post.replyTo().set( viewPost.self() ); self().lastPost().set( post ); - Numbers.add( self().postCount(), 1 ); + self().postCount().f( c -> c + 1 ); return post; } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundManyAssociation.java ---------------------------------------------------------------------- diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundManyAssociation.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundManyAssociation.java index a7dcb0f..a71cb4b 100644 --- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundManyAssociation.java +++ b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundManyAssociation.java @@ -4,6 +4,7 @@ import java.lang.reflect.Method; import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.stream.Stream; import org.qi4j.api.association.ManyAssociation; import org.qi4j.api.injection.scope.Service; import org.qi4j.api.injection.scope.Structure; @@ -78,6 +79,12 @@ public class BoundManyAssociation<T> extends AbstractBinding<T> @Override public Iterator<T> iterator() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return actualAssociations.iterator(); + } + + @Override + public Stream<T> stream() + { + return actualAssociations.stream(); } } http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/caa62018/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundNamedAssociation.java ---------------------------------------------------------------------- diff --git a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundNamedAssociation.java b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundNamedAssociation.java index 8e9f187..c5d6292 100644 --- a/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundNamedAssociation.java +++ b/samples/swing/src/main/java/org/qi4j/lib/swing/binding/internal/BoundNamedAssociation.java @@ -3,6 +3,7 @@ package org.qi4j.lib.swing.binding.internal; import java.lang.reflect.Method; import java.util.Iterator; import java.util.Map; +import java.util.stream.Stream; import org.qi4j.api.association.NamedAssociation; import org.qi4j.api.injection.scope.Service; import org.qi4j.api.injection.scope.Structure; @@ -80,4 +81,11 @@ public class BoundNamedAssociation<T> return actualAssociations.iterator(); } + @Override + public Stream<Map.Entry<String, T>> stream() + { + return actualAssociations.stream(); + } + + }
