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

ahuber pushed a commit to branch spring6
in repository https://gitbox.apache.org/repos/asf/causeway.git


The following commit(s) were added to refs/heads/spring6 by this push:
     new 58ef7e08a2 CAUSEWAY-3407: YamlUtils: adds support for Can
58ef7e08a2 is described below

commit 58ef7e08a2a65612be162695d2a1de11ef0209b3
Author: Andi Huber <[email protected]>
AuthorDate: Fri Apr 7 13:23:36 2023 +0200

    CAUSEWAY-3407: YamlUtils: adds support for Can
---
 .../org/apache/causeway/commons/io/YamlUtils.java  | 95 +++++++++++++++++++---
 1 file changed, 84 insertions(+), 11 deletions(-)

diff --git 
a/commons/src/main/java/org/apache/causeway/commons/io/YamlUtils.java 
b/commons/src/main/java/org/apache/causeway/commons/io/YamlUtils.java
index 492ac7f3c3..f29621ec1e 100644
--- a/commons/src/main/java/org/apache/causeway/commons/io/YamlUtils.java
+++ b/commons/src/main/java/org/apache/causeway/commons/io/YamlUtils.java
@@ -22,8 +22,10 @@ import java.beans.IntrospectionException;
 import java.beans.PropertyDescriptor;
 import java.io.InputStream;
 import java.io.OutputStreamWriter;
+import java.lang.reflect.Method;
 import java.lang.reflect.RecordComponent;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.function.UnaryOperator;
@@ -41,11 +43,14 @@ import org.yaml.snakeyaml.introspector.Property;
 import org.yaml.snakeyaml.introspector.PropertyUtils;
 import org.yaml.snakeyaml.representer.Representer;
 
+import org.apache.causeway.commons.collections.Can;
 import org.apache.causeway.commons.functional.Try;
 
+import lombok.Getter;
 import lombok.NonNull;
 import lombok.SneakyThrows;
 import lombok.val;
+import lombok.experimental.Accessors;
 import lombok.experimental.UtilityClass;
 
 /**
@@ -145,23 +150,91 @@ public class YamlUtils {
     // -- REPRESENTING RECORD TYPES
 
     static class PropertyUtils2 extends PropertyUtils {
+
         @Override
         protected Map<String, Property> getPropertiesMap(final Class<?> type, 
final BeanAccess bAccess) {
-            if(!type.isRecord()) {
-                return super.getPropertiesMap(type, bAccess);
+            if(type==Class.class) {
+                setAllowReadOnlyProperties(true);
+                try {
+                    val properties = new LinkedHashMap<String, Property>();
+                    val propertyDescriptor = new PropertyDescriptor("name", 
className(), null);
+                    properties.put("name", new 
MethodProperty(propertyDescriptor));
+                    return properties;
+                } catch (IntrospectionException e) {
+                    throw new YAMLException(e);
+                }
             }
-            setAllowReadOnlyProperties(true);
-            try {
-                val properties = new LinkedHashMap<String, Property>();
-                for(RecordComponent rc: type.getRecordComponents()) {
-                    val propertyDescriptor = new 
PropertyDescriptor(rc.getName(), rc.getAccessor(), null);
-                    properties.put(rc.getName(), new 
MethodProperty(propertyDescriptor));
+            if(type.isRecord()) {
+                setAllowReadOnlyProperties(true);
+                try {
+                    val properties = new LinkedHashMap<String, Property>();
+                    for(RecordComponent rc: type.getRecordComponents()) {
+                        val propertyDescriptor = new 
PropertyDescriptor(rc.getName(), rc.getAccessor(), null);
+                        properties.put(rc.getName(), new 
MethodProperty(propertyDescriptor));
+                    }
+                    return postProcessMap(properties);
+                } catch (IntrospectionException e) {
+                    throw new YAMLException(e);
                 }
-                return properties;
-            } catch (IntrospectionException e) {
-                throw new YAMLException(e);
             }
+            val map = super.getPropertiesMap(type, bAccess);
+            return postProcessMap(map);
+        }
+
+        private Map<String, Property> postProcessMap(final Map<String, 
Property> map) {
+            //debug
+            //System.err.printf("%s map: %s%n", type.getName(), map);
+            map.replaceAll((k, v)->{
+                if(Can.class.isAssignableFrom(v.getType())) {
+                    return MethodPropertyFromCanToList.wrap((MethodProperty)v);
+                }
+                return v;
+            });
+            return map;
+        }
+
+        @Getter(lazy = true) @Accessors(fluent=true)
+        private final static Method className = lookupClassName();
+        @SneakyThrows
+        private static Method lookupClassName() {
+            return Class.class.getMethod("getName");
+        }
+
+        @Getter(lazy = true) @Accessors(fluent=true)
+        private final static Method canToList = lookupCanToList();
+        @SneakyThrows
+        private static Method lookupCanToList() {
+            return Can.class.getMethod("toList");
+        }
+
+    }
+
+    /** Wraps any {@link MethodProperty} that represent a {@link Can} type
+     * and acts as a {@link List} representing MethodProperty facade instead. 
*/
+    static class MethodPropertyFromCanToList extends MethodProperty {
+
+        @SneakyThrows
+        static MethodPropertyFromCanToList wrap(final MethodProperty 
wrappedMethodProperty) {
+            return new MethodPropertyFromCanToList(
+                    wrappedMethodProperty,
+                    new PropertyDescriptor(wrappedMethodProperty.getName(), 
null, null));
+        }
+
+        final MethodProperty wrappedMethodProperty;
+
+        MethodPropertyFromCanToList(
+                final MethodProperty wrappedMethodProperty,
+                final PropertyDescriptor property) {
+            super(property);
+            this.wrappedMethodProperty = wrappedMethodProperty;
         }
+
+        @Override public Object get(final Object object) {
+            return ((Can<?>)wrappedMethodProperty.get(object)).toList();
+        }
+        @Override public Class<?> getType() { return List.class; }
+        @Override public boolean isReadable() { return true; }
+
     }
 
 }

Reply via email to