You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by ni...@apache.org on 2016/09/03 03:24:56 UTC

zest-java git commit: ZEST-173 - Adding test cases, and fixing issue in Core which seems to be a JDK bug.

Repository: zest-java
Updated Branches:
  refs/heads/develop bbeb6d514 -> 20771538f


 ZEST-173 - Adding test cases, and fixing issue in Core which seems to be a JDK bug.


Project: http://git-wip-us.apache.org/repos/asf/zest-java/repo
Commit: http://git-wip-us.apache.org/repos/asf/zest-java/commit/20771538
Tree: http://git-wip-us.apache.org/repos/asf/zest-java/tree/20771538
Diff: http://git-wip-us.apache.org/repos/asf/zest-java/diff/20771538

Branch: refs/heads/develop
Commit: 20771538f10d802b373b7b0250c911282e329879
Parents: bbeb6d5
Author: Niclas Hedhman <ni...@hedhman.org>
Authored: Sat Sep 3 11:24:47 2016 +0800
Committer: Niclas Hedhman <ni...@hedhman.org>
Committed: Sat Sep 3 11:24:47 2016 +0800

----------------------------------------------------------------------
 .../apache/zest/api/unitofwork/UnitOfWork.java  |  25 ++-
 core/runtime/build.gradle                       |   1 +
 .../runtime/composite/CompositeMethodModel.java |  11 +-
 .../runtime/value/AssociationToValueTest.java   | 215 +++++++++++++++++++
 libraries.gradle                                |   5 +
 5 files changed, 244 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zest-java/blob/20771538/core/api/src/main/java/org/apache/zest/api/unitofwork/UnitOfWork.java
----------------------------------------------------------------------
diff --git a/core/api/src/main/java/org/apache/zest/api/unitofwork/UnitOfWork.java b/core/api/src/main/java/org/apache/zest/api/unitofwork/UnitOfWork.java
index 15b3b84..309ca58 100644
--- a/core/api/src/main/java/org/apache/zest/api/unitofwork/UnitOfWork.java
+++ b/core/api/src/main/java/org/apache/zest/api/unitofwork/UnitOfWork.java
@@ -404,14 +404,15 @@ public interface UnitOfWork extends MetaInfoHolder, AutoCloseable
      *
      * <p>
      * All the referenced entities inside the association will be fetched from the underlying entity store,
-     * which is potentially very expensive operation.
+     * which is potentially very expensive operation. Each of the fetched entities will be passed to
+     * {@link #toValue(Class, Identity)}, and its associations will NOT be converted into values, but remain
+     * {@link EntityReference} values. Hence there is no problem with circular references.
      * </p>
      *
      * <p>
-     *     For this to work, the type &lt;T&gt; must be registered at bootstrap as both an Entity and a Value, and
-     *     as seen in the method signature, also be sub-type of {@link Identity}.
+     * For this to work, the type &lt;T&gt; must be registered at bootstrap as both an Entity and a Value, and
+     * as seen in the method signature, also be sub-type of {@link Identity}.
      * </p>
-
      *
      * @param association The association of entities to be converted into values.
      * @param <T>         The primary type of the association.
@@ -428,12 +429,14 @@ public interface UnitOfWork extends MetaInfoHolder, AutoCloseable
      * <p>
      * All the referenced entities inside the association will be fetched from the underlying entity store,
      * which is potentially very expensive operation. However, any duplicate EntityReferences in the association
-     * will be dropped before the fetch occurs.
+     * will be dropped before the fetch occurs. Each of the fetched entities will be passed to
+     * {@link #toValue(Class, Identity)}, and its associations will NOT be converted into values, but remain
+     * {@link EntityReference} values. Hence there is no problem with circular references.
      * </p>
      *
      * <p>
-     *     For this to work, the type &lt;T&gt; must be registered at bootstrap as both an Entity and a Value, and
-     *     as seen in the method signature, also be sub-type of {@link Identity}.
+     * For this to work, the type &lt;T&gt; must be registered at bootstrap as both an Entity and a Value, and
+     * as seen in the method signature, also be sub-type of {@link Identity}.
      * </p>
      *
      * @param association The association of entities to be converted into values.
@@ -450,11 +453,13 @@ public interface UnitOfWork extends MetaInfoHolder, AutoCloseable
      *
      * <p>
      * A {@link NamedAssociation} is effectively a Map with a String key and an EntityReference as the value. The
-     * EntityReference is fetched from the entity store and converted into a value of the same type.
+     * EntityReference is fetched from the entity store and converted into a value of the same type.Each of the fetched
+     * entities will be passed to {@link #toValue(Class, Identity)}, and its associations will NOT be converted into
+     * values, but remain {@link EntityReference} values. Hence there is no problem with circular references.
      * </p>
      * <p>
-     *     For this to work, the type &lt;T&gt; must be registered at bootstrap as both an Entity and a Value, and
-     *     as seen in the method signature, also be sub-type of {@link Identity}.
+     * For this to work, the type &lt;T&gt; must be registered at bootstrap as both an Entity and a Value, and
+     * as seen in the method signature, also be sub-type of {@link Identity}.
      * </p>
      *
      * @param association The association of entities to be converted into values.

http://git-wip-us.apache.org/repos/asf/zest-java/blob/20771538/core/runtime/build.gradle
----------------------------------------------------------------------
diff --git a/core/runtime/build.gradle b/core/runtime/build.gradle
index 3cd2da4..25db8e2 100644
--- a/core/runtime/build.gradle
+++ b/core/runtime/build.gradle
@@ -31,4 +31,5 @@ dependencies {
 
   testCompile project( ":org.apache.zest.core:org.apache.zest.core.testsupport" )
   testCompile project( ":org.apache.zest.libraries:org.apache.zest.library.constraints" )
+  testCompile libraries.hamcrest
 }

http://git-wip-us.apache.org/repos/asf/zest-java/blob/20771538/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodModel.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodModel.java b/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodModel.java
index 237b023..be8a07c 100644
--- a/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodModel.java
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/composite/CompositeMethodModel.java
@@ -100,9 +100,14 @@ public final class CompositeMethodModel
     @SuppressWarnings( "unchecked" )
     public Stream<DependencyModel> dependencies()
     {
-        return Stream.of( concerns, sideEffects ).filter( e -> e != null ).flatMap( Dependencies::dependencies );
-//        return flattenIterables( filter( notNull(), iterable( concerns != null ? concerns.dependencies() : null,
-//                                                              sideEffects != null ? sideEffects.dependencies() : null ) ) );
+        // For some unknown reason, the following lines can not be put into a single expression.
+        // This is possibly due to a compiler or JVM bug. The problem manifests itself in
+        // failure inside the AssociationToValueTest and possibly others.
+        // java.lang.invoke.LambdaConversionException: Invalid receiver type interface org.apache.zest.functional.VisitableHierarchy; not a subtype of implementation type interface org.apache.zest.runtime.injection.Dependencies
+        // Since it is a runtime bug, we should not change this in Java 8, but if the problem is gone in Java 9,
+        // we can collapse these into a single expression.
+        Stream<? extends Dependencies> deps = Stream.of( this.concerns, sideEffects );
+        return deps.filter( e -> e != null ).flatMap( Dependencies::dependencies );
     }
 
     // Context

http://git-wip-us.apache.org/repos/asf/zest-java/blob/20771538/core/runtime/src/test/java/org/apache/zest/runtime/value/AssociationToValueTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/zest/runtime/value/AssociationToValueTest.java b/core/runtime/src/test/java/org/apache/zest/runtime/value/AssociationToValueTest.java
new file mode 100644
index 0000000..e9dfdf3
--- /dev/null
+++ b/core/runtime/src/test/java/org/apache/zest/runtime/value/AssociationToValueTest.java
@@ -0,0 +1,215 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.apache.zest.runtime.value;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BiFunction;
+import org.apache.zest.api.association.ManyAssociation;
+import org.apache.zest.api.association.NamedAssociation;
+import org.apache.zest.api.entity.Identity;
+import org.apache.zest.api.injection.scope.Service;
+import org.apache.zest.api.injection.scope.Structure;
+import org.apache.zest.api.mixin.Mixins;
+import org.apache.zest.api.unitofwork.UnitOfWork;
+import org.apache.zest.api.unitofwork.UnitOfWorkFactory;
+import org.apache.zest.api.unitofwork.concern.UnitOfWorkConcern;
+import org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation;
+import org.apache.zest.api.value.ValueSerialization;
+import org.apache.zest.bootstrap.AssemblyException;
+import org.apache.zest.bootstrap.ModuleAssembly;
+import org.apache.zest.entitystore.memory.MemoryEntityStoreService;
+import org.apache.zest.spi.uuid.UuidIdentityGeneratorService;
+import org.apache.zest.test.AbstractZestTest;
+import org.apache.zest.valueserialization.orgjson.OrgJsonValueSerializationService;
+import org.junit.Test;
+
+import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
+import static org.junit.Assert.assertThat;
+
+public class AssociationToValueTest extends AbstractZestTest
+{
+    @Service
+    PersonRepository repo;
+
+    @Test
+    public void givenAdamWhenRequestingChildrenListExpectAbelAndKain()
+    {
+        Person adam = repo.findPersonByName( "Adam" );
+        Person abel = repo.findPersonByName( "Abel" );
+        Person kain = repo.findPersonByName( "Kain" );
+        List<Person> children = repo.transact( adam, ( p, uow ) -> uow.toValueList( p.children() ) );
+        assertThat( children, containsInAnyOrder( kain, abel ) );
+    }
+
+    @Test
+    public void givenAbelWhenRequestingChildrenSetExpectAdamAndEve()
+    {
+        Person abel = repo.findPersonByName( "Abel" );
+        Person adam = repo.findPersonByName( "Adam" );
+        Person eve = repo.findPersonByName( "Eve" );
+        Set<Person> children = repo.transact( abel, ( p, uow ) -> uow.toValueSet( p.children() ) );
+        assertThat( children, containsInAnyOrder( adam, eve ) );
+    }
+
+    @Test
+    public void givenBobWhenRequestingRolesExpectAllRolesWithCorrectPerson()
+    {
+        Person bob = repo.findPersonByName( "Bob" );
+        Person alice = repo.findPersonByName( "Alice" );
+        Person john = repo.findPersonByName( "John" );
+        Person jane = repo.findPersonByName( "Jane" );
+        Person kim = repo.findPersonByName( "Kim" );
+        Person robin = repo.findPersonByName( "Robin" );
+        Map<String, Person> roles = repo.transact( bob, ( p, uow ) -> uow.toValueMap( p.roles() ) );
+        assertThat( roles.keySet(), containsInAnyOrder( "spouse", "mechanic", "maid", "plumber", "electrician" ) );
+        assertThat( roles.values(), containsInAnyOrder( alice, john, jane, kim, robin ) );
+    }
+
+    @Test
+    public void givenLouisWhenRequestingRolesExpectAllRolesOfMarie()
+    {
+        Person louis = repo.findPersonByName( "Louis" );
+        Person marie = repo.findPersonByName( "Marie" );
+        Map<String, Person> roles = repo.transact( louis, ( p, uow ) -> uow.toValueMap( p.roles() ) );
+        assertThat( roles.keySet(), containsInAnyOrder( "spouse", "lover", "death-mate" ) );
+        assertThat( roles.values(), containsInAnyOrder( marie, marie, marie ) );
+    }
+
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        module.entities( Person.class );
+        module.values( Person.class );
+        module.services( PersonRepository.class ).withConcerns( UnitOfWorkConcern.class );
+        module.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
+        module.services( UuidIdentityGeneratorService.class );
+        module.services( MemoryEntityStoreService.class );
+
+        module.services( Runnable.class )
+            .withMixins( LoadData.class )
+            .withConcerns( UnitOfWorkConcern.class )
+            .instantiateOnStartup();
+    }
+
+    @Override
+    public void setUp()
+        throws Exception
+    {
+        super.setUp();
+        serviceFinder.findService( Runnable.class ).get().run();
+    }
+
+    public interface Person extends Identity
+    {
+        ManyAssociation<Person> children();
+
+        NamedAssociation<Person> roles();
+    }
+
+    @Mixins( PersonRepositoryMixin.class )
+    public interface PersonRepository
+    {
+        @UnitOfWorkPropagation
+        <T, R> R transact( T arg, BiFunction<T, UnitOfWork, R> closure );
+
+        @UnitOfWorkPropagation
+        Person findPersonByName( String name );
+    }
+
+    protected static class PersonRepositoryMixin
+        implements PersonRepository
+    {
+        @Structure
+        UnitOfWorkFactory unitOfWorkFactory;
+
+        @Override
+        public <T, R> R transact( T arg, BiFunction<T, UnitOfWork, R> closure )
+        {
+            UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+            return closure.apply( arg, uow );
+        }
+
+        @Override
+        public Person findPersonByName( String name )
+        {
+            UnitOfWork uow = unitOfWorkFactory.currentUnitOfWork();
+            return uow.toValue( Person.class, uow.get( Person.class, name ) );
+        }
+    }
+
+    public static class LoadData
+        implements Runnable
+    {
+        @Structure
+        UnitOfWorkFactory uowf;
+
+        @Override
+        @UnitOfWorkPropagation
+        public void run()
+        {
+            Person bob = createPerson( "Bob" );
+            Person alice = createPerson( "Alice" );
+            Person john = createPerson( "John" );
+            Person jane = createPerson( "Jane" );
+            Person kim = createPerson( "Kim" );
+            Person robin = createPerson( "Robin" );
+            Person william = createPerson( "William" );
+            Person adam = createPerson( "Adam" );
+            Person eve = createPerson( "Eve" );
+            Person abel = createPerson( "Abel" );
+            Person kain = createPerson( "Kain" );
+            Person louis = createPerson( "Louis" );
+            Person marie = createPerson( "Marie" );
+            Person romeo = createPerson( "Romeo" );
+            Person juliette = createPerson( "Juliette" );
+            adam.children().add( abel );
+            adam.children().add( kain );
+            eve.children().add( abel );
+            eve.children().add( kain );
+            abel.children().add( adam );
+            abel.children().add( eve );
+            abel.children().add( adam );
+            abel.children().add( eve );
+            abel.children().add( eve );
+            bob.roles().put( "spouse", alice );
+            bob.roles().put( "mechanic", john );
+            bob.roles().put( "maid", jane );
+            bob.roles().put( "plumber", kim );
+            bob.roles().put( "electrician", robin );
+            louis.roles().put( "spouse", marie );
+            louis.roles().put( "lover", marie );
+            louis.roles().put( "death-mate", marie );
+            juliette.roles().put( "lover", romeo );
+            juliette.roles().put( "author", william );
+            romeo.roles().put( "lover", juliette );
+            romeo.roles().put( "author", william );
+        }
+
+        private Person createPerson( String name )
+        {
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            return uow.newEntity( Person.class, name );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/20771538/libraries.gradle
----------------------------------------------------------------------
diff --git a/libraries.gradle b/libraries.gradle
index 31930f5..5f8fd5e 100644
--- a/libraries.gradle
+++ b/libraries.gradle
@@ -33,6 +33,7 @@ def geodeVersion = '1.0.0-incubating.M2'
 def groovyVersion = '2.4.7'
 def h2Version = '1.4.192'
 def hazelcastVersion = '3.6.3'
+def hamcrestVersion = '1.3'
 def httpClientVersion = '4.5.2'
 def jacksonVersion = '2.7.5'
 def javascriptVersion = '1.7.7.1'
@@ -227,6 +228,10 @@ rootProject.ext {
 
           // Testing
           junit: "junit:junit:$junitVersion",
+          hamcrest: [
+                  "org.hamcrest:hamcrest-core:$hamcrestVersion",
+                  "org.hamcrest:hamcrest-library:$hamcrestVersion"
+          ],
           awaitility: "com.jayway.awaitility:awaitility:$awaitilityVersion",
           easymock: "org.easymock:easymock:$easyMockVersion",
           mockito: "org.mockito:mockito-core:$mockitoVersion",