Bläddra i källkod

new: PrototypeMap

Signed-off-by: Ranides Atterwim <ranides@gmail.com>
Mariusz Czarnowski 5 år sedan
förälder
incheckning
9e61ef61cc

+ 58 - 0
assira/src/main/java/net/ranides/assira/collection/prototype/AbstractPrototype.java

@@ -18,8 +18,66 @@ import java.util.stream.Collectors;
 @UtilityClass
 public class AbstractPrototype {
 
+    public static class MapWrapper extends DeclaredMap {
+
+        private final Map<Object, Object> data;
+
+        public MapWrapper(PrototypeMap parent, Map<Object, Object> data) {
+            super(parent);
+            this.data = data;
+        }
+
+        @Override
+        public Set<Object> keys() {
+            return data.keySet();
+        }
+
+        @Override
+        public boolean has(String key) {
+            return data.containsKey(key);
+        }
+
+        @Override
+        public boolean has(PrototypeField<?> key) {
+            return data.containsKey(key);
+        }
+
+        @Override
+        public Optional<Object> get(String key) {
+            return Optional.ofNullable(data.get(key));
+        }
+
+        @Override
+        public <V> Optional<V> get(PrototypeField<V> key) {
+            return Optional.ofNullable(data.get(key)).map(key.type()::cast);
+        }
+
+        @Override
+        public boolean set(String key, Object value) {
+            data.put(key, value);
+            return true;
+        }
+
+        @Override
+        public <V> boolean set(PrototypeField<V> key, V value) {
+            data.put(key, value);
+            return true;
+        }
+    }
+
     public static abstract class DeclaredMap implements PrototypeMap {
 
+        private final PrototypeMap parent;
+
+        public DeclaredMap(PrototypeMap parent) {
+            this.parent = parent;
+        }
+
+        @Override
+        public PrototypeMap parent() {
+            return parent;
+        }
+
         @Override
         public PrototypeMap declared() {
             return this;

+ 12 - 50
assira/src/main/java/net/ranides/assira/collection/prototype/PrototypeHashMap.java

@@ -1,22 +1,30 @@
 package net.ranides.assira.collection.prototype;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
 
 public class PrototypeHashMap extends AbstractPrototype.BaseMap {
 
     private final PrototypeMap parent;
 
-    private final PrototypeMap declared = new HashWrapper();
+    private final PrototypeMap declared;
 
     public PrototypeHashMap() {
-        this(null);
+        this(null, Collections.emptyMap());
     }
 
     public PrototypeHashMap(PrototypeMap parent) {
+        this(parent, Collections.emptyMap());
+    }
+
+    public PrototypeHashMap(Map<Object, ?> content) {
+        this(null, content);
+    }
+
+    public PrototypeHashMap(PrototypeMap parent, Map<Object, ?> content) {
         this.parent = parent;
+        this.declared = new AbstractPrototype.MapWrapper(this, new HashMap<>(content));
     }
 
     @Override
@@ -29,50 +37,4 @@ public class PrototypeHashMap extends AbstractPrototype.BaseMap {
         return declared;
     }
 
-    private class HashWrapper extends AbstractPrototype.DeclaredMap {
-        private final Map<Object, Object> data = new HashMap<>();
-
-        @Override
-        public PrototypeMap parent() {
-            return PrototypeHashMap.this.parent;
-        }
-
-        @Override
-        public Set<Object> keys() {
-            return data.keySet();
-        }
-
-        @Override
-        public boolean has(String key) {
-            return data.containsKey(key);
-        }
-
-        @Override
-        public boolean has(PrototypeField<?> key) {
-            return data.containsKey(key);
-        }
-
-        @Override
-        public Optional<Object> get(String key) {
-            return Optional.ofNullable(data.get(key));
-        }
-
-        @Override
-        public <V> Optional<V> get(PrototypeField<V> key) {
-            return Optional.ofNullable(data.get(key)).map(key.type()::cast);
-        }
-
-        @Override
-        public boolean set(String key, Object value) {
-            data.put(key, value);
-            return true;
-        }
-
-        @Override
-        public <V> boolean set(PrototypeField<V> key, V value) {
-            data.put(key, value);
-            return true;
-        }
-    }
-
 }

+ 3 - 0
assira/src/main/java/net/ranides/assira/collection/prototype/PrototypeMap.java

@@ -3,11 +3,14 @@ package net.ranides.assira.collection.prototype;
 import net.ranides.assira.reflection.IClass;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Optional;
 import java.util.Set;
 
 public interface PrototypeMap {
 
+    PrototypeMap EMPTY = new AbstractPrototype.MapWrapper(null, Collections.emptyMap());
+
     PrototypeMap parent();
 
     PrototypeMap declared();

+ 3 - 37
assira/src/main/java/net/ranides/assira/reflection/ResolveContext.java

@@ -1,45 +1,11 @@
 package net.ranides.assira.reflection;
 
-import java.util.Collections;
-import java.util.Map;
-import java.util.Optional;
+import net.ranides.assira.collection.prototype.PrototypeMap;
 
 public interface ResolveContext {
 
-    ResolveContext EMPTY = of(Collections.emptyMap());
+    ResolveContext EMPTY = () -> PrototypeMap.EMPTY;
 
-    ResolveContext getResolveParent();
-
-    Map<String, ?> getResolveMap();
-
-    default Optional<Object> getResolveProperty(String name) {
-        Map<String, ?> map = getResolveMap();
-        if(map.containsKey(name)) {
-            return Optional.of(map.get(name));
-        }
-        ResolveContext parent = getResolveParent();
-        if(parent != null) {
-            return parent.getResolveProperty(name);
-        }
-        return Optional.empty();
-    }
-
-    default boolean hasResolveProperty(String name) {
-        return getResolveProperty(name).isPresent();
-    }
-
-    static ResolveContext of(Map<String, ?> map) {
-        return new ResolveContext() {
-            @Override
-            public ResolveContext getResolveParent() {
-                return null;
-            }
-
-            @Override
-            public Map<String, ?> getResolveMap() {
-                return map;
-            }
-        };
-    }
+    PrototypeMap getResolveMap();
 
 }

+ 2 - 3
assira/src/main/java/net/ranides/assira/reflection/ResolveModel.java

@@ -295,8 +295,7 @@ public abstract class ResolveModel extends SerializableCode {
     public static ResolveModel CONTEXT = new ResolveModel() {
         @Override
         public boolean matches(Object that, String name) {
-            return (that instanceof ResolveContext) &&
-                ((ResolveContext) that).hasResolveProperty(name);
+            return (that instanceof ResolveContext) && ((ResolveContext) that).getResolveMap().has(name);
         }
 
         @Override
@@ -306,7 +305,7 @@ public abstract class ResolveModel extends SerializableCode {
 
         @Override
         public Object get(ResolveStatus status, Object that, String name) {
-            Optional<Object> out = ((ResolveContext) that).getResolveProperty(name);
+            Optional<Object> out = ((ResolveContext) that).getResolveMap().get(name);
             if(out.isPresent()) {
                 Object result = out.get();
                 if(result instanceof ResolvePattern) {

+ 7 - 4
assira/src/main/java/net/ranides/assira/reflection/walker/ObjectVisitor.java

@@ -1,9 +1,12 @@
 package net.ranides.assira.reflection.walker;
 
+import net.ranides.assira.collection.prototype.PrototypeHashMap;
+import net.ranides.assira.collection.prototype.PrototypeMap;
 import net.ranides.assira.reflection.ResolveContext;
 import net.ranides.assira.reflection.walker.WalkerContexts.ObjectContext;
 
 import java.io.PrintWriter;
+import java.util.Map;
 import java.util.function.Predicate;
 
 public interface ObjectVisitor {
@@ -63,11 +66,11 @@ public interface ObjectVisitor {
 
     abstract class PrintVisitor implements ObjectVisitor {
         private final PrintWriter target;
-        private final ResolveContext scope;
+        private final PrototypeHashMap scope;
 
-        protected PrintVisitor(PrintWriter target, ResolveContext scope) {
+        protected PrintVisitor(PrintWriter target, Map<Object, ?> map) {
             this.target = target;
-            this.scope = scope;
+            this.scope = new PrototypeHashMap(map);
         }
 
         public PrintWriter writer() {
@@ -76,7 +79,7 @@ public interface ObjectVisitor {
 
         @Override
         public ResolveContext scope() {
-            return scope;
+            return () -> scope;
         }
 
         @Override

+ 9 - 8
assira/src/main/java/net/ranides/assira/reflection/walker/ObjectWalker.java

@@ -1,6 +1,8 @@
 package net.ranides.assira.reflection.walker;
 
 import net.ranides.assira.collection.arrays.NativeArray;
+import net.ranides.assira.collection.prototype.PrototypeHashMap;
+import net.ranides.assira.collection.prototype.PrototypeMap;
 import net.ranides.assira.functional.special.LazyFunction;
 import net.ranides.assira.generic.LazyReference;
 import net.ranides.assira.generic.ValueUtils;
@@ -73,7 +75,9 @@ public class ObjectWalker {
         private final LazyFunction<String> namePath = LazyReference.concurrent();
         private final LazyFunction<String> idPath = LazyReference.concurrent();
 
-        private final Supplier<Map<String, Object>> custom = LazyReference.concurrent(HashMap::new);
+        private final Supplier<PrototypeMap> custom = LazyReference.concurrent(() -> {
+            return new PrototypeHashMap(visitor.scope().getResolveMap());
+        });
 
         public CAbstract(ObjectContext<?> parent, IField field, Object value) {
             this.field = Optional.of(field);
@@ -185,24 +189,21 @@ public class ObjectWalker {
             return (T)value;
         }
 
-        @Override
-        public ResolveContext getResolveParent() {
-            return visitor.scope();
-        }
 
         @Override
-        public Map<String, Object> getResolveMap() {
+        public PrototypeMap getResolveMap() {
             return custom.get();
         }
 
         @Override
         public void custom(Map<String, ?> values) {
-            custom.get().putAll(values);
+            PrototypeMap map = custom.get();
+            values.forEach((key, value) -> map.set(key, value));
         }
 
         @Override
         public void custom(String key, Object value) {
-            custom.get().put(key, value);
+            custom.get().set(key, value);
         }
 
         @Override

+ 5 - 5
assira/src/main/java/net/ranides/assira/reflection/walker/WalkerRules.java

@@ -2,8 +2,8 @@ package net.ranides.assira.reflection.walker;
 
 import lombok.Data;
 
+import net.ranides.assira.collection.prototype.PrototypeHashMap;
 import net.ranides.assira.reflection.IClass;
-import net.ranides.assira.reflection.ResolveContext;
 import net.ranides.assira.reflection.walker.ObjectVisitor.PrintVisitor;
 import net.ranides.assira.reflection.walker.WalkerContexts.ArrayContext;
 import net.ranides.assira.reflection.walker.WalkerContexts.ObjectContext;
@@ -72,10 +72,10 @@ public class WalkerRules {
             .hint("{PATH} {actual.shortname} = {value}")
         .prepare();
 
-    private final Map<String, ResolveFormat> tags;
+    private final Map<Object, ResolveFormat> tags;
     private final List<RuleEntry> rules;
 
-    private WalkerRules(Map<String, ResolveFormat> tags, List<RuleEntry> rules) {
+    private WalkerRules(Map<Object, ResolveFormat> tags, List<RuleEntry> rules) {
         this.tags = new HashMap<>(tags);
         this.rules = new ArrayList<>(rules);
     }
@@ -94,7 +94,7 @@ public class WalkerRules {
 
     public static class Builder {
 
-        private final Map<String, ResolveFormat> tags = new HashMap<>();
+        private final Map<Object, ResolveFormat> tags = new HashMap<>();
         private final List<RuleEntry> rules = new ArrayList<>();
 
         public WalkerRules prepare() {
@@ -277,7 +277,7 @@ public class WalkerRules {
     private class RuleVisitor extends PrintVisitor {
 
         public RuleVisitor(Writer target) {
-            super(new PrintWriter(target), ResolveContext.of(tags));
+            super(new PrintWriter(target), tags);
         }
 
         @Override

+ 6 - 6
assira/src/test/java/net/ranides/assira/reflection/ResolvePatternTest.java

@@ -388,12 +388,12 @@ public class ResolvePatternTest {
     public void testContext() {
         APlus data = new APlus();
 
-        data.getResolveMap().put("customized", 77);
-        data.getResolveMap().put("customized/big", 99);
-        data.getResolveMap().put("innerlink", new A());
-        data.getResolveMap().put("other.dot", 99);
-        data.getResolveMap().put("alias", ResolvePattern.compile("array.1.name"));
-        data.getResolveMap().put("template", ResolveFormat.compile("({array.1.name}:{content.item.height}:{customized})"));
+        data.getResolveMap().set("customized", 77);
+        data.getResolveMap().set("customized/big", 99);
+        data.getResolveMap().set("innerlink", new A());
+        data.getResolveMap().set("other.dot", 99);
+        data.getResolveMap().set("alias", ResolvePattern.compile("array.1.name"));
+        data.getResolveMap().set("template", ResolveFormat.compile("({array.1.name}:{content.item.height}:{customized})"));
 
         assertEquals(16, ResolveUtils.get(data, "content.item.height"));
         assertEquals("b", ResolveUtils.get(data, "array.1.name"));

+ 4 - 7
assira/src/test/java/net/ranides/assira/reflection/mockup/ForResolver.java

@@ -8,6 +8,8 @@
 package net.ranides.assira.reflection.mockup;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import net.ranides.assira.collection.prototype.PrototypeHashMap;
+import net.ranides.assira.collection.prototype.PrototypeMap;
 import net.ranides.assira.reflection.ResolveContext;
 
 import java.util.Arrays;
@@ -47,15 +49,10 @@ public final class ForResolver {
     }
 
     public static class APlus extends A implements ResolveContext {
-        private final Map<String, Object> context = new HashMap<>();
+        private final PrototypeMap context = new PrototypeHashMap();
 
         @Override
-        public ResolveContext getResolveParent() {
-            return null;
-        }
-
-        @Override
-        public Map<String, Object> getResolveMap() {
+        public PrototypeMap getResolveMap() {
             return context;
         }
     }