Skip to content

Commit ef31bdd

Browse files
committed
First version of RefExpander
UGLY AS HELL. But first answer to issue #41. I need a mutable tree, this really won't do. Signed-off-by: Francis Galiegue <[email protected]>
1 parent 15f9a42 commit ef31bdd

File tree

4 files changed

+133
-0
lines changed

4 files changed

+133
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* Copyright (c) 2013, Francis Galiegue <[email protected]>
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the Lesser GNU General Public License as
6+
* published by the Free Software Foundation, either version 3 of the
7+
* License, or (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* Lesser GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.github.fge.jsonschema.processors.refexpand;
19+
20+
import com.fasterxml.jackson.databind.JsonNode;
21+
import com.fasterxml.jackson.databind.node.ObjectNode;
22+
import com.github.fge.jsonschema.cfg.LoadingConfiguration;
23+
import com.github.fge.jsonschema.cfg.ValidationConfiguration;
24+
import com.github.fge.jsonschema.exceptions.ProcessingException;
25+
import com.github.fge.jsonschema.jsonpointer.JsonPointer;
26+
import com.github.fge.jsonschema.load.SchemaLoader;
27+
import com.github.fge.jsonschema.processing.Processor;
28+
import com.github.fge.jsonschema.processing.ProcessorChain;
29+
import com.github.fge.jsonschema.processors.data.SchemaHolder;
30+
import com.github.fge.jsonschema.processors.ref.RefResolver;
31+
import com.github.fge.jsonschema.processors.syntax.SyntaxValidator;
32+
import com.github.fge.jsonschema.processors.validation.SchemaTreeEquivalence;
33+
import com.github.fge.jsonschema.processors.walk.DraftV4PointerCollectorDictionary;
34+
import com.github.fge.jsonschema.processors.walk.SchemaWalker;
35+
import com.github.fge.jsonschema.report.DevNullProcessingReport;
36+
import com.github.fge.jsonschema.report.ProcessingReport;
37+
import com.github.fge.jsonschema.tree.CanonicalSchemaTree;
38+
import com.github.fge.jsonschema.tree.SchemaTree;
39+
import com.github.fge.jsonschema.util.JacksonUtils;
40+
import com.github.fge.jsonschema.util.JsonLoader;
41+
import com.google.common.base.Equivalence;
42+
import com.google.common.collect.ImmutableList;
43+
44+
import java.io.IOException;
45+
46+
public final class RefExpander
47+
extends SchemaWalker
48+
{
49+
private static final Equivalence<SchemaTree> EQUIVALENCE
50+
= SchemaTreeEquivalence.getInstance();
51+
52+
private final Processor<SchemaHolder, SchemaHolder> refSyntax;
53+
54+
public RefExpander(final LoadingConfiguration cfg)
55+
{
56+
super(DraftV4PointerCollectorDictionary.get());
57+
final SyntaxValidator syntaxValidator
58+
= new SyntaxValidator(ValidationConfiguration.byDefault());
59+
final RefResolver refResolver = new RefResolver(new SchemaLoader(cfg));
60+
refSyntax = ProcessorChain.startWith(syntaxValidator.getProcessor())
61+
.chainWith(refResolver).getProcessor();
62+
}
63+
64+
@Override
65+
public SchemaTree processCurrent(final ProcessingReport report,
66+
final SchemaTree tree)
67+
throws ProcessingException
68+
{
69+
final SchemaHolder input = new SchemaHolder(tree);
70+
final SchemaTree newTree = refSyntax.process(report, input).getValue();
71+
return EQUIVALENCE.equivalent(tree, newTree) ? tree
72+
: modify(tree, newTree);
73+
}
74+
75+
@Override
76+
public String toString()
77+
{
78+
return "$ref expander";
79+
}
80+
81+
private static SchemaTree modify(final SchemaTree tree,
82+
final SchemaTree newTree)
83+
{
84+
final JsonPointer pwd = tree.getPointer();
85+
if (pwd.isEmpty())
86+
return newTree;
87+
final ObjectNode newNode = newTree.getNode().deepCopy();
88+
final ObjectNode victim = (ObjectNode) tree.getNode();
89+
victim.removeAll();
90+
victim.putAll(newNode);
91+
victim.remove(ImmutableList.of("$schema", "id"));
92+
return tree;
93+
}
94+
95+
public static void main(final String... args)
96+
throws IOException, ProcessingException
97+
{
98+
final JsonNode schema = JsonLoader.fromResource("/main.json");
99+
final SchemaTree tree = new CanonicalSchemaTree(schema);
100+
final SchemaHolder input = new SchemaHolder(tree);
101+
102+
final LoadingConfiguration cfg = LoadingConfiguration.newBuilder()
103+
.preloadSchema(schema)
104+
.preloadSchema(JsonLoader.fromResource("/sub1.json"))
105+
.preloadSchema(JsonLoader.fromResource("/sub2.json"))
106+
.freeze();
107+
108+
final RefExpander expander = new RefExpander(cfg);
109+
final ProcessingReport report = new DevNullProcessingReport();
110+
final SchemaHolder output = expander.process(report, input);
111+
System.out.println(JacksonUtils.prettyPrint(output.getValue()
112+
.getBaseNode()));
113+
}
114+
}

src/main/resources/main.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"id": "my://schemas/main.json",
4+
"properties": {
5+
"p1": { "$ref": "sub1.json" },
6+
"p2": { "$ref": "sub2.json" }
7+
}
8+
}

src/main/resources/sub1.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"id": "my://schemas/sub1.json",
4+
"type": "integer",
5+
"default": 21
6+
}

src/main/resources/sub2.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"id": "my://schemas/sub2.json",
4+
"type": "string"
5+
}

0 commit comments

Comments
 (0)