
com.github.fge.jsonschema.expand.SchemaExpander Maven / Gradle / Ivy
/*
* Copyright (c) 2013, Francis Galiegue
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Lesser GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Lesser GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package com.github.fge.jsonschema.expand;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.MissingNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.fge.jackson.JsonNumEquals;
import com.github.fge.jackson.NodeType;
import com.github.fge.jackson.jsonpointer.JsonPointer;
import com.github.fge.jackson.jsonpointer.TokenResolver;
import com.github.fge.jsonschema.exceptions.ProcessingException;
import com.github.fge.jsonschema.ref.JsonRef;
import com.github.fge.jsonschema.report.ProcessingReport;
import com.github.fge.jsonschema.tree.CanonicalSchemaTree;
import com.github.fge.jsonschema.tree.SchemaTree;
import com.github.fge.jsonschema.walk.SchemaListener;
import com.google.common.annotations.Beta;
import com.google.common.base.Equivalence;
import com.google.common.collect.Lists;
import com.google.common.collect.Queues;
import java.util.Deque;
import java.util.List;
@Beta
public final class SchemaExpander
implements SchemaListener
{
private static final Equivalence EQUIVALENCE
= JsonNumEquals.getInstance();
private final JsonRef baseRef;
private JsonNode baseNode = MissingNode.getInstance();
private JsonNode currentNode;
private JsonPointer path = JsonPointer.empty();
private final Deque paths = Queues.newArrayDeque();
public SchemaExpander(final SchemaTree tree)
{
baseRef = tree.getLoadingRef();
baseNode = tree.getBaseNode().deepCopy();
}
@Override
public void enteringPath(final JsonPointer path,
final ProcessingReport report)
throws ProcessingException
{
paths.push(path);
this.path = path;
currentNode = path.get(baseNode);
}
@Override
public void visiting(final SchemaTree schemaTree,
final ProcessingReport report)
throws ProcessingException
{
/*
* Check whether our current node is equal to the current node of the
* provided tree. If it is, nothing to do.
*/
final JsonNode node = schemaTree.getNode();
if (EQUIVALENCE.equivalent(node, currentNode))
return;
/*
* If not, make a copy of it.
*/
final JsonNode newNode = node.deepCopy();
/*
* If this is the root, just replace unconditionally.
*/
if (path.isEmpty()) {
baseNode = currentNode = newNode;
return;
}
/*
* Otherwise, get the parent of the current node, replace it.
*/
final JsonPointer parent = path.parent();
final String token = getLastToken(path);
final JsonNode parentNode = parent.get(baseNode);
final NodeType type = NodeType.getNodeType(parentNode);
switch (type) {
case OBJECT:
((ObjectNode) parentNode).put(token, newNode);
break;
case ARRAY:
((ArrayNode) parentNode).set(Integer.parseInt(token), newNode);
break;
default:
throw new IllegalStateException("was expecting an object or" +
" an array");
}
/*
* Finally, update our current node.
*/
currentNode = path.get(baseNode);
}
@Override
public void exitingPath(final JsonPointer path,
final ProcessingReport report)
throws ProcessingException
{
this.path = paths.pop();
currentNode = this.path.get(baseNode);
}
@Override
public SchemaTree getValue()
{
return new CanonicalSchemaTree(baseRef, baseNode);
}
private static String getLastToken(final JsonPointer ptr)
{
final List> list = Lists.newArrayList(ptr);
final int size = list.size();
return list.get(size - 1).getToken().getRaw();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy