|
@@ -2,19 +2,15 @@ package net.ranides.assira.reflection.walker;
|
|
|
|
|
|
|
|
import lombok.Data;
|
|
import lombok.Data;
|
|
|
|
|
|
|
|
-import net.ranides.assira.reflection.*;
|
|
|
|
|
|
|
+import net.ranides.assira.reflection.IClass;
|
|
|
import net.ranides.assira.reflection.walker.ObjectVisitor.PrintVisitor;
|
|
import net.ranides.assira.reflection.walker.ObjectVisitor.PrintVisitor;
|
|
|
import net.ranides.assira.reflection.walker.WalkerContexts.ArrayContext;
|
|
import net.ranides.assira.reflection.walker.WalkerContexts.ArrayContext;
|
|
|
import net.ranides.assira.reflection.walker.WalkerContexts.ObjectContext;
|
|
import net.ranides.assira.reflection.walker.WalkerContexts.ObjectContext;
|
|
|
-import net.ranides.assira.text.Charsets;
|
|
|
|
|
|
|
+import net.ranides.assira.reflection.walker.rules.PrintRules;
|
|
|
import net.ranides.assira.text.FormatHex;
|
|
import net.ranides.assira.text.FormatHex;
|
|
|
import net.ranides.assira.text.ResolveFormat;
|
|
import net.ranides.assira.text.ResolveFormat;
|
|
|
|
|
|
|
|
import javax.xml.datatype.XMLGregorianCalendar;
|
|
import javax.xml.datatype.XMLGregorianCalendar;
|
|
|
-import java.io.OutputStream;
|
|
|
|
|
-import java.io.OutputStreamWriter;
|
|
|
|
|
-import java.io.PrintWriter;
|
|
|
|
|
-import java.io.Writer;
|
|
|
|
|
import java.time.temporal.Temporal;
|
|
import java.time.temporal.Temporal;
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
import java.util.Collection;
|
|
import java.util.Collection;
|
|
@@ -28,7 +24,7 @@ import java.util.function.Function;
|
|
|
|
|
|
|
|
public class WalkerRules {
|
|
public class WalkerRules {
|
|
|
|
|
|
|
|
- public static final WalkerRules DEFAULT = new Builder()
|
|
|
|
|
|
|
+ public static final PrintRules PRINTER = new PrintRules.Builder()
|
|
|
.tag("PATH", "{id,text,4}.{namePath,text,-50}")
|
|
.tag("PATH", "{id,text,4}.{namePath,text,-50}")
|
|
|
.rule()
|
|
.rule()
|
|
|
.match(ObjectContext::isVisited)
|
|
.match(ObjectContext::isVisited)
|
|
@@ -71,261 +67,8 @@ public class WalkerRules {
|
|
|
.hint("{PATH} {actual.shortname} = {value}")
|
|
.hint("{PATH} {actual.shortname} = {value}")
|
|
|
.prepare();
|
|
.prepare();
|
|
|
|
|
|
|
|
- private final Map<Object, Object> tags;
|
|
|
|
|
- private final List<RuleEntry> rules;
|
|
|
|
|
-
|
|
|
|
|
- private WalkerRules(Map<Object, Object> tags, List<RuleEntry> rules) {
|
|
|
|
|
- this.tags = new HashMap<>(tags);
|
|
|
|
|
- this.rules = new ArrayList<>(rules);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public static Builder builder() {
|
|
|
|
|
- return new Builder();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public PrintVisitor visitor(OutputStream target) {
|
|
|
|
|
- return visitor(new OutputStreamWriter(target, Charsets.UTF8));
|
|
|
|
|
|
|
+ public static PrintRules.Builder printer() {
|
|
|
|
|
+ return new PrintRules.Builder();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public PrintVisitor visitor(Writer target) {
|
|
|
|
|
- return new RuleVisitor(target);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public static class Builder {
|
|
|
|
|
-
|
|
|
|
|
- private final Map<Object, Object> tags = new HashMap<>();
|
|
|
|
|
- private final List<RuleEntry> rules = new ArrayList<>();
|
|
|
|
|
-
|
|
|
|
|
- public WalkerRules prepare() {
|
|
|
|
|
- return new WalkerRules(tags, rules);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public Builder tag(String name, Object value) {
|
|
|
|
|
- this.tags.put(name, value);
|
|
|
|
|
- return this;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public Builder tag(String name, String value) {
|
|
|
|
|
- this.tags.put(name, ResolveFormat.compile(value));
|
|
|
|
|
- return this;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public RootRule rule() {
|
|
|
|
|
- return new RootRule();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public Builder rules(WalkerRules parent) {
|
|
|
|
|
- this.tags.putAll(parent.tags);
|
|
|
|
|
- this.rules.addAll(parent.rules);
|
|
|
|
|
- return this;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public abstract class AbstractRule<F> {
|
|
|
|
|
-
|
|
|
|
|
- protected final List<RulePredicate<?>> predicates;
|
|
|
|
|
-
|
|
|
|
|
- protected Consumer<ObjectContext<F>> formatter = x -> { };
|
|
|
|
|
-
|
|
|
|
|
- protected AbstractRule(List<RulePredicate<?>> predicates) {
|
|
|
|
|
- this.predicates = predicates;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public Builder text(String text) {
|
|
|
|
|
- ResolveFormat fmt = ResolveFormat.compile(text);
|
|
|
|
|
- return text((target, ctx) -> fmt.format(ctx));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public Builder text(Function<ObjectContext<F>, String> handler) {
|
|
|
|
|
- return text((target, ctx) -> handler.apply(ctx));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public Builder text(BiFunction<PrintVisitor, ObjectContext<F>, String> handler) {
|
|
|
|
|
- return rule(predicates, RuleType.FORMAT, asHandler((v,c) -> c.custom("value", handler.apply(v, c))));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public Builder hint(String text) {
|
|
|
|
|
- ResolveFormat fmt = ResolveFormat.compile(text);
|
|
|
|
|
- return hint((target, ctx) -> target.writer().println(fmt.format(ctx)));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public Builder hint(Consumer<ObjectContext<F>> handler) {
|
|
|
|
|
- return hint((target, ctx) -> handler.accept(ctx));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public Builder hint(BiConsumer<PrintVisitor, ObjectContext<F>> handler) {
|
|
|
|
|
- return rule(predicates, RuleType.HINT, asHandler(handler));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public Builder term(String text) {
|
|
|
|
|
- ResolveFormat fmt = ResolveFormat.compile(text);
|
|
|
|
|
- return term((target, ctx) -> target.writer().println(fmt.format(ctx)));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public Builder term(Consumer<ObjectContext<F>> handler) {
|
|
|
|
|
- return term((target, ctx) -> handler.accept(ctx));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public Builder term(BiConsumer<PrintVisitor, ObjectContext<F>> handler) {
|
|
|
|
|
- return rule(predicates, RuleType.TERM, asHandler(handler));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private RuleHandler<F> asHandler(BiConsumer<PrintVisitor, ObjectContext<F>> handler) {
|
|
|
|
|
- return (target, ctx) -> {
|
|
|
|
|
- formatter.accept(ctx);
|
|
|
|
|
- handler.accept(target, ctx);
|
|
|
|
|
- };
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private <U> Builder rule(List<RulePredicate<?>> predicates, RuleType type, RuleHandler<U> handler) {
|
|
|
|
|
- predicates.forEach(predicate -> rules.add(new RuleEntry(predicate, handler, type)));
|
|
|
|
|
- return Builder.this;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public class RootRule extends AbstractRule<Object> {
|
|
|
|
|
-
|
|
|
|
|
- public RootRule() {
|
|
|
|
|
- super(new ArrayList<>());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public RootRule format(String text) {
|
|
|
|
|
- return format(ResolveFormat.compile(text)::format);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public RootRule format(Function<ObjectContext<Object>, String> formatter) {
|
|
|
|
|
- this.formatter = ctx -> ctx.custom("value", formatter.apply(ctx));
|
|
|
|
|
- return this;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public <T> TypeRule<T> match(Class<T> type) {
|
|
|
|
|
- return match(IClass.typeinfo(type));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public <T> TypeRule<T> match(IClass<T> type) {
|
|
|
|
|
- predicates.add(ctx -> ctx.isSubclass(type));
|
|
|
|
|
- return new TypeRule<>(this);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public MoreRule match(RulePredicate<?> predicate) {
|
|
|
|
|
- predicates.add(predicate);
|
|
|
|
|
- return new MoreRule(this);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public class TypeRule<F> extends AbstractRule<F> {
|
|
|
|
|
-
|
|
|
|
|
- public TypeRule(AbstractRule<?> source) {
|
|
|
|
|
- super(source.predicates);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public TypeRule<F> format(String text) {
|
|
|
|
|
- return format(ResolveFormat.compile(text)::format);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public TypeRule<F> format(Function<ObjectContext<F>, String> formatter) {
|
|
|
|
|
- this.formatter = ctx -> ctx.custom("value", formatter.apply(ctx));
|
|
|
|
|
- return this;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public MoreRule match(Class<?> type) {
|
|
|
|
|
- return match(IClass.typeinfo(type));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public MoreRule match(IClass<?> type) {
|
|
|
|
|
- predicates.add(ctx -> ctx.isSubclass(type));
|
|
|
|
|
- return new MoreRule(this);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public MoreRule match(RulePredicate<?> predicate) {
|
|
|
|
|
- predicates.add(predicate);
|
|
|
|
|
- return new MoreRule(this);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public class MoreRule extends AbstractRule<Object> {
|
|
|
|
|
-
|
|
|
|
|
- public MoreRule(AbstractRule<?> source) {
|
|
|
|
|
- super(source.predicates);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public MoreRule format(String text) {
|
|
|
|
|
- return format(ResolveFormat.compile(text)::format);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public MoreRule format(Function<ObjectContext<Object>, String> formatter) {
|
|
|
|
|
- this.formatter = ctx -> ctx.custom("value", formatter.apply(ctx));
|
|
|
|
|
- return this;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public MoreRule match(Class<?> type) {
|
|
|
|
|
- return match(IClass.typeinfo(type));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public MoreRule match(IClass<?> type) {
|
|
|
|
|
- predicates.add(ctx -> ctx.isSubclass(type));
|
|
|
|
|
- return this;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public MoreRule match(RulePredicate<?> predicate) {
|
|
|
|
|
- predicates.add(predicate);
|
|
|
|
|
- return this;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private class RuleVisitor extends PrintVisitor {
|
|
|
|
|
-
|
|
|
|
|
- public RuleVisitor(Writer target) {
|
|
|
|
|
- super(new PrintWriter(target), tags);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public boolean visitObject(ObjectContext<?> context) {
|
|
|
|
|
- for (RuleEntry rule : rules) {
|
|
|
|
|
- if(rule.test(context)) {
|
|
|
|
|
- rule.consume(this, context);
|
|
|
|
|
- switch (rule.type) {
|
|
|
|
|
- case HINT: return true;
|
|
|
|
|
- case TERM: return false;
|
|
|
|
|
- case FORMAT:
|
|
|
|
|
- // continue processing
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @SuppressWarnings({"rawtypes", "unchecked"})
|
|
|
|
|
- @Data
|
|
|
|
|
- private static class RuleEntry {
|
|
|
|
|
- private final RulePredicate predicate;
|
|
|
|
|
- private final RuleHandler consumer;
|
|
|
|
|
- private final RuleType type;
|
|
|
|
|
-
|
|
|
|
|
- public boolean test(ObjectContext<?> context) {
|
|
|
|
|
- return predicate.test(context);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public void consume(PrintVisitor visitor, ObjectContext<?> context) {
|
|
|
|
|
- consumer.apply(visitor, context);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private enum RuleType {
|
|
|
|
|
- TERM, HINT, FORMAT
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public interface RulePredicate<U> {
|
|
|
|
|
- boolean test(ObjectContext<U> context);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public interface RuleHandler<U> {
|
|
|
|
|
- void apply(PrintVisitor printVisitor, ObjectContext<U> context);
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|