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 <T> 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 <T> 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 <T> 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 <T> 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 <T> 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 <T> 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",