This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch CAUSEWAY-3676
in repository https://gitbox.apache.org/repos/asf/causeway.git


The following commit(s) were added to refs/heads/CAUSEWAY-3676 by this push:
     new 752cdc6744 CAUSEWAY-3676: behaviour iterates by map
752cdc6744 is described below

commit 752cdc67443986d953ed867c519aef3d0d4aa644
Author: danhaywood <[email protected]>
AuthorDate: Fri Jan 19 16:45:00 2024 +0000

    CAUSEWAY-3676: behaviour iterates by map
---
 incubator/viewers/graphql/viewer/pom.xml           | 12 ++-
 .../graphql/viewer/src/main/java/module-info.java  |  1 +
 .../graphql/viewer/source/GqlvObjectBehaviour.java | 22 +++--
 .../graphql/viewer/source/GqlvObjectStructure.java | 27 +++++-
 .../viewer/graphql/viewer/util/_BiMap.java         | 48 +++++++++++
 .../viewer/graphql/viewer/util/_BiMap_Test.java    | 98 ++++++++++++++++++++++
 6 files changed, 191 insertions(+), 17 deletions(-)

diff --git a/incubator/viewers/graphql/viewer/pom.xml 
b/incubator/viewers/graphql/viewer/pom.xml
index 48e4150842..c63762fee6 100644
--- a/incubator/viewers/graphql/viewer/pom.xml
+++ b/incubator/viewers/graphql/viewer/pom.xml
@@ -67,8 +67,18 @@
                                </exclusion>
                        </exclusions>
                </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <scope>test</scope>
+        </dependency>
 
-       </dependencies>
+    </dependencies>
 
 
 </project>
diff --git a/incubator/viewers/graphql/viewer/src/main/java/module-info.java 
b/incubator/viewers/graphql/viewer/src/main/java/module-info.java
index a1bf0e3120..c6a090775f 100644
--- a/incubator/viewers/graphql/viewer/src/main/java/module-info.java
+++ b/incubator/viewers/graphql/viewer/src/main/java/module-info.java
@@ -2,6 +2,7 @@ module org.apache.causeway.incubator.viewer.graphql.viewer {
     exports org.apache.causeway.viewer.graphql.viewer;
     exports org.apache.causeway.viewer.graphql.viewer.source;
     exports org.apache.causeway.viewer.graphql.viewer.integration;
+    exports org.apache.causeway.viewer.graphql.viewer.util;
 
     requires com.fasterxml.jackson.core;
     requires com.fasterxml.jackson.databind;
diff --git 
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectBehaviour.java
 
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectBehaviour.java
index fca594cad5..00c315dc64 100644
--- 
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectBehaviour.java
+++ 
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectBehaviour.java
@@ -1,6 +1,7 @@
 package org.apache.causeway.viewer.graphql.viewer.source;
 
 
+import java.util.Map;
 import java.util.Set;
 
 import org.apache.causeway.applib.services.bookmark.BookmarkService;
@@ -12,6 +13,8 @@ import 
org.apache.causeway.core.metamodel.spec.feature.MixedIn;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.causeway.core.metamodel.specloader.SpecificationLoader;
 
+import graphql.schema.GraphQLFieldDefinition;
+
 import lombok.RequiredArgsConstructor;
 
 import graphql.schema.DataFetcher;
@@ -69,21 +72,19 @@ public class GqlvObjectBehaviour {
 
 
     public void createAndRegisterDataFetchersForField() {
-        structure.getObjectSpec().streamProperties(MixedIn.INCLUDED)
-                
.forEach(this::createAndRegisterDataFetcherForObjectAssociation);
+        
structure.getProperties().entrySet().forEach(this::createAndRegisterDataFetcherForAssociation);
     }
 
     void createAndRegisterDataFetchersForCollection() {
-        structure.getObjectSpec().streamCollections(MixedIn.INCLUDED)
-                
.forEach(this::createAndRegisterDataFetcherForObjectAssociation);
+        
structure.getCollections().entrySet().forEach(this::createAndRegisterDataFetcherForAssociation);
     }
 
-
-    private void createAndRegisterDataFetcherForObjectAssociation(final 
ObjectAssociation otom) {
+    private void createAndRegisterDataFetcherForAssociation(
+            final Map.Entry<? extends ObjectAssociation, 
GraphQLFieldDefinition> propertyAndField) {
 
         final GraphQLObjectType graphQLObjectType = 
structure.getGqlObjectType();
 
-        ObjectSpecification fieldObjectSpecification = otom.getElementType();
+        ObjectSpecification fieldObjectSpecification = 
propertyAndField.getKey().getElementType();
         BeanSort beanSort = fieldObjectSpecification.getBeanSort();
         switch (beanSort) {
 
@@ -95,7 +96,7 @@ public class GqlvObjectBehaviour {
 
                 codeRegistryBuilder
                         .dataFetcher(
-                                
FieldCoordinates.coordinates(graphQLObjectType, otom.getId()),
+                                
FieldCoordinates.coordinates(graphQLObjectType, 
propertyAndField.getKey().getId()),
                                 (DataFetcher<Object>) environment -> {
 
                                     Object domainObjectInstance = 
environment.getSource();
@@ -104,14 +105,11 @@ public class GqlvObjectBehaviour {
                                     ObjectSpecification specification = 
specificationLoader.loadSpecification(domainObjectInstanceClass);
 
                                     ManagedObject owner = 
ManagedObject.adaptSingular(specification, domainObjectInstance);
-
-                                    ManagedObject managedObject = 
otom.get(owner);
+                                    ManagedObject managedObject = 
propertyAndField.getKey().get(owner);
 
                                     return managedObject!=null ? 
managedObject.getPojo() : null;
-
                                 });
 
-
                 break;
 
         }
diff --git 
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectStructure.java
 
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectStructure.java
index c40d9d3087..cb307d506e 100644
--- 
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectStructure.java
+++ 
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectStructure.java
@@ -1,6 +1,7 @@
 package org.apache.causeway.viewer.graphql.viewer.source;
 
 import graphql.Scalars;
+import graphql.com.google.common.collect.BiMap;
 import graphql.schema.GraphQLArgument;
 import graphql.schema.GraphQLFieldDefinition;
 import graphql.schema.GraphQLInputObjectType;
@@ -12,6 +13,7 @@ import graphql.schema.GraphQLType;
 import graphql.schema.GraphQLTypeReference;
 
 import lombok.Getter;
+import lombok.Synchronized;
 import lombok.experimental.UtilityClass;
 import lombok.val;
 
@@ -31,6 +33,7 @@ import 
org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectActionParameter;
 import org.apache.causeway.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.causeway.viewer.graphql.viewer.util._BiMap;
 
 import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition;
 import static graphql.schema.GraphQLInputObjectField.newInputObjectField;
@@ -91,10 +94,26 @@ public class GqlvObjectStructure {
 
     final GraphQLObjectType.Builder mutatorsTypeBuilder;
 
-    private final Map<OneToOneAssociation, GraphQLFieldDefinition> 
propertyToField = new LinkedHashMap<>();
-    private final Map<OneToManyAssociation, GraphQLFieldDefinition> 
collectionToField = new LinkedHashMap<>();
-    private final Map<ObjectAction, GraphQLFieldDefinition> safeActionToField 
= new LinkedHashMap<>();
-    private final Map<ObjectAction, GraphQLFieldDefinition> 
mutatorActionToField = new LinkedHashMap<>();
+    private final _BiMap<OneToOneAssociation, GraphQLFieldDefinition> 
propertyToField = new _BiMap<>();
+    private final _BiMap<OneToManyAssociation, GraphQLFieldDefinition> 
collectionToField = new _BiMap<>();
+    private final _BiMap<ObjectAction, GraphQLFieldDefinition> 
safeActionToField = new _BiMap<>();
+    private final _BiMap<ObjectAction, GraphQLFieldDefinition> 
mutatorActionToField = new _BiMap<>();
+
+    Map<OneToOneAssociation, GraphQLFieldDefinition> getProperties() {
+        return propertyToField.getForwardMapAsImmutable();
+    }
+
+    Map<OneToManyAssociation, GraphQLFieldDefinition> getCollections() {
+        return collectionToField.getForwardMapAsImmutable();
+    }
+
+    Map<ObjectAction, GraphQLFieldDefinition> getSafeActions() {
+        return safeActionToField.getForwardMapAsImmutable();
+    }
+
+    Map<ObjectAction, GraphQLFieldDefinition> getMutatorActions() {
+        return mutatorActionToField.getForwardMapAsImmutable();
+    }
 
     /**
      * Built using {@link #buildGqlObjectType()}
diff --git 
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/util/_BiMap.java
 
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/util/_BiMap.java
new file mode 100644
index 0000000000..c3b7bba68c
--- /dev/null
+++ 
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/util/_BiMap.java
@@ -0,0 +1,48 @@
+package org.apache.causeway.viewer.graphql.viewer.util;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class _BiMap<K, V> {
+    private final Map<K, V> forwardMap = new LinkedHashMap<>();
+    private final Map<V, K> inverseMap = new LinkedHashMap<>();
+
+    public void put(K key, V value) {
+        forwardMap.put(key, value);
+        inverseMap.put(value, key);
+    }
+
+    public V get(K key) {
+        return forwardMap.get(key);
+    }
+
+    public _BiMap<V, K> inverse() {
+        _BiMap<V, K> inverseBiMap = new _BiMap<>();
+        inverseBiMap.forwardMap.putAll(inverseMap);
+        inverseBiMap.inverseMap.putAll(forwardMap);
+        return inverseBiMap;
+    }
+
+    public boolean isEmpty() {
+        return forwardMap.isEmpty();
+    }
+
+    public Set<Map.Entry<K, V>> entrySet() {
+        return forwardMap.entrySet();
+    }
+
+    public Set<K> keySet() {
+        return forwardMap.keySet();
+    }
+
+    public Collection<V> values() {
+        return forwardMap.values();
+    }
+
+    public Map<K, V> getForwardMapAsImmutable() {
+        return Collections.unmodifiableMap(forwardMap);
+    }
+}
\ No newline at end of file
diff --git 
a/incubator/viewers/graphql/viewer/src/test/java/org/apache/causeway/viewer/graphql/viewer/util/_BiMap_Test.java
 
b/incubator/viewers/graphql/viewer/src/test/java/org/apache/causeway/viewer/graphql/viewer/util/_BiMap_Test.java
new file mode 100644
index 0000000000..71ba72b992
--- /dev/null
+++ 
b/incubator/viewers/graphql/viewer/src/test/java/org/apache/causeway/viewer/graphql/viewer/util/_BiMap_Test.java
@@ -0,0 +1,98 @@
+package org.apache.causeway.viewer.graphql.viewer.util;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.jupiter.api.Test;
+import static org.assertj.core.api.Assertions.*;
+
+public class _BiMap_Test {
+
+    @Test
+    public void testPutAndGet() {
+        _BiMap<String, Integer> biMap = new _BiMap<>();
+        biMap.put("one", 1);
+        biMap.put("two", 2);
+
+        assertThat(biMap.get("one")).isEqualTo(1);
+        assertThat(biMap.get("two")).isEqualTo(2);
+        assertThat(biMap.get("nonexistent")).isNull();
+    }
+
+    @Test
+    public void testInverse() {
+        _BiMap<String, Integer> biMap = new _BiMap<>();
+        biMap.put("one", 1);
+        biMap.put("two", 2);
+
+        _BiMap<Integer, String> inverseBiMap = biMap.inverse();
+
+        assertThat(inverseBiMap.get(1)).isEqualTo("one");
+        assertThat(inverseBiMap.get(2)).isEqualTo("two");
+        assertThat(inverseBiMap.get(3)).isNull();
+    }
+
+    @Test
+    public void testIsEmpty() {
+        _BiMap<String, Integer> biMap = new _BiMap<>();
+        assertThat(biMap.isEmpty()).isTrue();
+
+        biMap.put("one", 1);
+        assertThat(biMap.isEmpty()).isFalse();
+    }
+
+    @Test
+    public void testEntrySet() {
+        _BiMap<String, Integer> biMap = new _BiMap<>();
+        biMap.put("one", 1);
+        biMap.put("two", 2);
+
+        Set<Map.Entry<String, Integer>> entrySet = biMap.entrySet();
+
+        assertThat(entrySet).containsExactlyInAnyOrder(
+                Map.entry("one", 1),
+                Map.entry("two", 2)
+        );
+    }
+
+    @Test
+    public void testKeySet() {
+        _BiMap<String, Integer> biMap = new _BiMap<>();
+        biMap.put("one", 1);
+        biMap.put("two", 2);
+
+        Set<String> keySet = biMap.keySet();
+
+        assertThat(keySet).containsExactlyInAnyOrder("one", "two");
+    }
+
+    @Test
+    public void testValues() {
+        _BiMap<String, Integer> biMap = new _BiMap<>();
+        biMap.put("one", 1);
+        biMap.put("two", 2);
+
+        Collection<Integer> values = biMap.values();
+
+        assertThat(values).containsExactlyInAnyOrder(1, 2);
+    }
+
+    @Test
+    public void testGetForwardMapAsImmutable() {
+        _BiMap<String, Integer> biMap = new _BiMap<>();
+        biMap.put("one", 1);
+        biMap.put("two", 2);
+
+        Map<String, Integer> immutableForwardMap = 
biMap.getForwardMapAsImmutable();
+
+        assertThat(immutableForwardMap).containsExactly(
+                Map.entry("one", 1),
+                Map.entry("two", 2)
+        );
+
+        // Ensure the immutable map cannot be modified
+        assertThatThrownBy(() -> immutableForwardMap.put("three", 3))
+                .isInstanceOf(UnsupportedOperationException.class);
+    }
+}

Reply via email to