ソースを参照

FormatVisitor: better rules

Ranides Atterwim 5 年 前
コミット
0a6c5b8ff2

+ 23 - 19
assira/src/main/java/net/ranides/assira/reflection/visit/ObjectVisitor.java

@@ -1,5 +1,6 @@
 package net.ranides.assira.reflection.visit;
 
+import lombok.Data;
 import lombok.RequiredArgsConstructor;
 import net.ranides.assira.reflection.IClass;
 import net.ranides.assira.reflection.visit.WalkerContexts.ObjectContext;
@@ -63,11 +64,18 @@ public interface ObjectVisitor {
     }
 
     class FormatRules {
-        private final List<Predicate<ObjectContext>> termC = new ArrayList<>();
-        private final List<ResolveFormat> termF = new ArrayList<>();
+        enum RuleType {
+            HINT, TERM
+        }
+
+        @Data
+        static class RuleEntry {
+            private final RuleType type;
+            private final Predicate<ObjectContext> predicate;
+            private final ResolveFormat pattern;
+        }
 
-        private final List<Predicate<ObjectContext>> hintC = new ArrayList<>();
-        private final List<ResolveFormat> hintF = new ArrayList<>();
+        private final List<RuleEntry> rules = new ArrayList<>();
 
         public FormatVisitor visitor() {
             return visitor(new StringWriter());
@@ -77,6 +85,11 @@ public interface ObjectVisitor {
             return new FormatVisitor(this, target);
         }
 
+        public FormatRules inherit(FormatRules parent) {
+            this.rules.addAll(parent.rules);
+            return this;
+        }
+
         public FormatRules term(Class<?> type, String text) {
             return term(IClass.typeinfo(type), text);
         }
@@ -86,8 +99,7 @@ public interface ObjectVisitor {
         }
 
         public FormatRules term(Predicate<ObjectContext> predicate, String text) {
-            this.termC.add(predicate);
-            this.termF.add(ResolveFormat.compile(text));
+            rules.add(new RuleEntry(RuleType.TERM, predicate, ResolveFormat.compile(text)));
             return this;
         }
 
@@ -100,23 +112,15 @@ public interface ObjectVisitor {
         }
 
         public FormatRules hint(Predicate<ObjectContext> predicate, String text) {
-            this.hintC.add(predicate);
-            this.hintF.add(ResolveFormat.compile(text));
+            rules.add(new RuleEntry(RuleType.HINT, predicate, ResolveFormat.compile(text)));
             return this;
         }
 
         private boolean apply(Appendable target, ObjectContext ctx) {
-            for(int i = 0, n = termC.size(); i<n; i++) {
-                if(termC.get(i).test(ctx)) {
-                    append(target, termF.get(i).format(ctx));
-                    return false;
-                }
-            }
-
-            for(int i = 0, n = hintC.size(); i<n; i++) {
-                if(hintC.get(i).test(ctx)) {
-                    append(target, hintF.get(i).format(ctx));
-                    return true;
+            for (RuleEntry rule : rules) {
+                if(rule.predicate.test(ctx)) {
+                    append(target, rule.pattern.format(ctx));
+                    return rule.type == RuleType.HINT;
                 }
             }
 

+ 73 - 65
assira/src/test/java/net/ranides/assira/reflection/ObjectWalkerTest.java

@@ -12,40 +12,63 @@ import org.junit.Test;
 
 import java.io.StringWriter;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
 public class ObjectWalkerTest {
 
+    Foo foo0 = Foo.builder()
+        .bar(new Bar("456", "0xFAD"))
+        .name("John")
+        .name("Jenny")
+        .name("Adam")
+        .point(17, new Point(21,6,4))
+        .point(18, new Point(21,6,4))
+        .point(3, new Point(9,9,9))
+        .point(8, new Point(9,9,9))
+        .point(21, new Point(9,9,9))
+        .point(88, new Point(21,6,4))
+        .build();
+
+    Foo foo1 = Foo.builder()
+        .bar(new Bar("456", "0xFAD"))
+        .name("John")
+        .name("Jenny")
+        .name("Adam")
+        .point(17, new Point(21,6,4))
+        .point(18, new Point(21,6,4))
+        .point(88, new Point(21,6,4))
+        .build();
+
+    Foo foo2 = Foo.builder()
+        .bar(new Bar("55", "0xEE"))
+        .name("Tom")
+        .point(33, new Point(3,3,3))
+        .build();
+
+    Foo foo3 = Foo.builder()
+        .bar(new Bar("66", "0x11"))
+        .name("Ann")
+        .point(77, new Point(7,7,7))
+        .build();
+
     @Test
     public void basic() {
-        Foo foo = Foo.builder()
-            .bar(new Bar("456", "0xFAD"))
-            .name("John")
-            .name("Jenny")
-            .name("Adam")
-            .point(17, new Point(21,6,4))
-            .point(18, new Point(21,6,4))
-            .point(3, new Point(9,9,9))
-            .point(8, new Point(9,9,9))
-            .point(21, new Point(9,9,9))
-            .point(88, new Point(21,6,4))
-            .build();
-
-        ObjectWalker.walk(foo, new ObjectVisitor.AbstractVisitor() {
+        ObjectWalker.walk(foo0, new ObjectVisitor.AbstractVisitor() {
             @Override
             public boolean visitObject(ObjectContext ctx) {
-                System.out.printf(" - [%-12s] %-40s | %s = %s%n",
+                System.out.printf(
+                    " - [%-12s] %-40s | %s = %s%n",
                     ctx.getClass().getSimpleName(),
                     ctx.typePath(),
                     ctx.namePath(),
                     ctx.value()
                 );
 
-                if(ctx.value() instanceof String) {
+                if (ctx.value() instanceof String) {
                     return false;
                 }
-
                 return true;
             }
         });
@@ -53,27 +76,14 @@ public class ObjectWalkerTest {
 
     @Test
     public void format() {
-        Foo foo = Foo.builder()
-            .bar(new Bar("456", "0xFAD"))
-            .name("John")
-            .name("Jenny")
-            .name("Adam")
-            .point(17, new Point(21,6,4))
-            .point(18, new Point(21,6,4))
-            .point(3, new Point(9,9,9))
-            .point(8, new Point(9,9,9))
-            .point(21, new Point(9,9,9))
-            .point(88, new Point(21,6,4))
-            .build();
-
         FormatVisitor visitor = new FormatRules()
             .hint(Object.class, "{namePath,text} = {value}")
             .term(ObjectContext::isNull, "{namePath,text} = <null>")
             .term(String.class, "{namePath,text} = '{value}'")
             .visitor(new StringWriter());
 
-        ObjectWalker.walk(foo, "foo1", visitor);
-        ObjectWalker.walk(foo, "foo2", visitor);
+        ObjectWalker.walk(foo0, "foo1", visitor);
+        ObjectWalker.walk(foo0, "foo2", visitor);
 
         System.out.println("===");
         System.out.println(visitor.toString());
@@ -81,17 +91,7 @@ public class ObjectWalkerTest {
 
     @Test
     public void visitors() {
-        Foo foo = Foo.builder()
-            .bar(new Bar("456", "0xFAD"))
-            .name("John")
-            .name("Jenny")
-            .name("Adam")
-            .point(17, new Point(21,6,4))
-            .point(18, new Point(21,6,4))
-            .point(88, new Point(21,6,4))
-            .build();
-
-        ObjectWalker.walk(foo, new ObjectVisitor.AbstractVisitor() {
+        ObjectWalker.walk(foo0, new ObjectVisitor.AbstractVisitor() {
             @Override
             public boolean visitObject(ObjectContext ctx) {
                 System.out.printf(" - [%-12s] %-40s | %s = %s%n",
@@ -112,28 +112,6 @@ public class ObjectWalkerTest {
 
     @Test
     public void recursive() {
-        Foo foo1 = Foo.builder()
-            .bar(new Bar("456", "0xFAD"))
-            .name("John")
-            .name("Jenny")
-            .name("Adam")
-            .point(17, new Point(21,6,4))
-            .point(18, new Point(21,6,4))
-            .point(88, new Point(21,6,4))
-            .build();
-
-        Foo foo2 = Foo.builder()
-            .bar(new Bar("55", "0xEE"))
-            .name("Tom")
-            .point(33, new Point(3,3,3))
-            .build();
-
-        Foo foo3 = Foo.builder()
-            .bar(new Bar("66", "0x11"))
-            .name("Ann")
-            .point(77, new Point(7,7,7))
-            .build();
-
         List<Foo> list = Arrays.asList(foo1, foo2, foo1, foo3);
 
         ObjectWalker.walk(list, ctx -> {
@@ -155,6 +133,36 @@ public class ObjectWalkerTest {
         });
     }
 
+    @Test
+    public void recursiveFormat() {
+        List<Foo> list = Arrays.asList(foo1, foo2, foo1, foo3);
+
+        FormatVisitor visitor = new FormatRules()
+            .hint(List.class,
+                "{id,text,4}.{namePath,text,-50} {typeName}")
+            .hint(Collection.class,
+                "{id,text,4}.{namePath,text,-50} {typeName}")
+            .hint(Map.class,
+                "{id,text,4}.{namePath,text,-50} {typeName}")
+
+            .term(ObjectContext::isNull,
+                "{id,text,4}.{namePath,text,-50} <null>")
+            .term(String.class,
+                "{id,text,4}.{namePath,text,-50} String = '{value}'")
+
+            .term(ObjectContext::isVisited,
+                "{id,text,4}.{namePath,text,-50} <ref> = #{ref}")
+            .hint(Object.class,
+                "{id,text,4}.{namePath,text,-50} {actual.shortname} = {value}")
+
+            .visitor(new StringWriter());
+
+        ObjectWalker.walk(list, "list", visitor);
+        System.out.println(visitor.toString());
+    }
+
+
+
     @Builder
     public static class Foo {
         private final Bar bar;