TreePruner pruner = (tree!=null) ? new NamedPathPruner(tree) : new ByDepth(1 - depth); p.writeTo(bean,pruner,Flavor.XML.createDataWriter(bean,sw));
/** * Constructs a pruner by parsing a textual specification. * This lists the properties which should be included at each level of the hierarchy. * Properties are separated by commas and nested objects are inside square braces. * For example, {@code a,b[c,d]} will emit the top-level property {@code a} but * none of its children, and the top-level property {@code b} and only those * of its children named {@code c} and {@code d}. * @param spec textual specification of tree * @throws IllegalArgumentException if the syntax is incorrect */ public NamedPathPruner(String spec) throws IllegalArgumentException { this(parse(spec)); }
private static void node(Reader r, Tree t) throws IllegalArgumentException { Object actual = r.peek(); if (actual instanceof Token) { throw new IllegalArgumentException("expected name at " + r.pos); } r.advance(); Tree subtree = new Tree(); t.children.put((String) actual, subtree); if (r.accept(Token.LBRACE)) { list(r, subtree); r.expect(Token.RBRACE); } if (r.accept(Token.QLBRACE)) { subtree.range = parseRange(r); r.expect(Token.QRBRACE); } } static Range parseRange(Reader r) {
static Tree parse(String spec) throws IllegalArgumentException { Reader r = new Reader(spec); Tree t = new Tree(); list(r, t); r.expect(Token.EOF); return t; } private static void list(Reader r, Tree t) throws IllegalArgumentException {
/** * Constructs a pruner by parsing a textual specification. * This lists the properties which should be included at each level of the hierarchy. * Properties are separated by commas and nested objects are inside square braces. * For example, {@code a,b[c,d]} will emit the top-level property {@code a} but * none of its children, and the top-level property {@code b} and only those * of its children named {@code c} and {@code d}. * @param spec textual specification of tree * @throws IllegalArgumentException if the syntax is incorrect */ public NamedPathPruner(String spec) throws IllegalArgumentException { this(parse(spec)); }
private static void node(Reader r, Tree t) throws IllegalArgumentException { Object actual = r.peek(); if (actual instanceof Token) { throw new IllegalArgumentException("expected name at " + r.pos); } r.advance(); Tree subtree = new Tree(); t.children.put((String) actual, subtree); if (r.accept(Token.LBRACE)) { list(r, subtree); r.expect(Token.RBRACE); } if (r.accept(Token.QLBRACE)) { subtree.range = parseRange(r); r.expect(Token.QRBRACE); } } static Range parseRange(Reader r) {
static Tree parse(String spec) throws IllegalArgumentException { Reader r = new Reader(spec); Tree t = new Tree(); list(r, t); r.expect(Token.EOF); return t; } private static void list(Reader r, Tree t) throws IllegalArgumentException {
public @Override TreePruner accept(Object node, Property prop) { Tree subtree = tree.children.get(prop.name); return subtree != null ? new NamedPathPruner(subtree) : null; }
/** * Constructs a pruner by parsing a textual specification. * This lists the properties which should be included at each level of the hierarchy. * Properties are separated by commas and nested objects are inside square braces. * For example, {@code a,b[c,d]} will emit the top-level property {@code a} but * none of its children, and the top-level property {@code b} and only those * of its children named {@code c} and {@code d}. * @param spec textual specification of tree * @throws IllegalArgumentException if the syntax is incorrect */ public NamedPathPruner(String spec) throws IllegalArgumentException { this(parse(spec)); }
static Tree parse(String spec) throws IllegalArgumentException { Reader r = new Reader(spec); Tree t = new Tree(); list(r, t); r.expect(Token.EOF); return t; } private static void list(Reader r, Tree t) throws IllegalArgumentException {
public @Override TreePruner accept(Object node, Property prop) { if (prop.merge) return this; Tree subtree = tree.children.get(prop.name); if (subtree==null) subtree=tree.children.get("*"); return subtree != null ? new NamedPathPruner(subtree) : null; }
private static void assertParseError(String spec) { try { NamedPathPruner.parse(spec); fail(); } catch (IllegalArgumentException x) { // pass } }
private static void node(Reader r, Tree t) throws IllegalArgumentException { Object actual = r.peek(); if (actual instanceof Token) { throw new IllegalArgumentException("expected name at " + r.pos); } r.advance(); Tree subtree = new Tree(); t.children.put((String) actual, subtree); if (r.accept(Token.LBRACE)) { list(r, subtree); r.expect(Token.RBRACE); } } private enum Token {COMMA, LBRACE, RBRACE, EOF}
public @Override TreePruner accept(Object node, Property prop) { if (prop.merge) return this; Tree subtree = tree.children.get(prop.name); if (subtree==null) subtree=tree.children.get("*"); return subtree != null ? new NamedPathPruner(subtree) : null; }
public void testParse() throws Exception { assertEquals("{a={}, b={c={}}}", NamedPathPruner.parse("a,b[c]").toString()); assertEquals("{a={}, b={c={}, d={}}}", NamedPathPruner.parse("a,b[c,d]").toString()); assertEquals("{a={}, b={c={}, d={}}, e={}}", NamedPathPruner.parse("a,b[c,d],e").toString()); assertEquals("{a={}, b={c={}, d={}}, e={}}", NamedPathPruner.parse("a,b[c,d]{,10},e").toString()); assertParseError(""); assertParseError("a,"); assertParseError(",b"); assertParseError("a["); assertParseError("a[b,c"); assertParseError("a[]"); assertParseError("a[b,,]"); assertParseError("a]"); assertParseError("a{}"); assertParseError("a{b}"); } private static void assertParseError(String spec) {
if (tree != null) { try { pruner = new NamedPathPruner(tree); } catch (IllegalArgumentException x) { throw new ServletException("Malformed tree expression: " + x, x);
@SuppressWarnings({"unchecked", "rawtypes"}) // API design flaw prevents this from type-checking private static void assertResult(String expected, Object bean, String spec) throws Exception { Model model = new ModelBuilder().get(bean.getClass()); StringWriter w = new StringWriter(); model.writeTo(bean, new NamedPathPruner(spec), Flavor.JSON.createDataWriter(bean, w, config)); assertEquals(expected, w.toString().replace("\\\"", "").replace("\"", "")); }