com.github.fge.jsonschema.walk.SchemaWalker.java Source code

Java tutorial

Introduction

Here is the source code for com.github.fge.jsonschema.walk.SchemaWalker.java

Source

/*
 * Copyright (c) 2013, Francis Galiegue <fgaliegue@gmail.com>
 *
 * 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 <http://www.gnu.org/licenses/>.
 */

package com.github.fge.jsonschema.walk;

import com.github.fge.jackson.jsonpointer.JsonPointer;
import com.github.fge.jsonschema.exceptions.ProcessingException;
import com.github.fge.jsonschema.keyword.SchemaDescriptor;
import com.github.fge.jsonschema.report.ProcessingReport;
import com.github.fge.jsonschema.tree.SchemaTree;
import com.github.fge.jsonschema.walk.collectors.PointerCollector;
import com.google.common.annotations.Beta;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import java.util.List;
import java.util.Map;

/**
 * Main schema walker class
 *
 * <p>This class walks a JSON Schema (in the shape of a {@link SchemaTree}
 * recursively. In order to visit subschemas, it relies on a series of {@link
 * PointerCollector} instances (provided by a dictionary) to get the knowledge
 * of what schemas to visit next.</p>
 *
 * <p>Only subschemas are visited: unknown keywords, or keywords not having any
 * subschemas, are ignored.</p>
 *
 * <p><b>Important</b>: the initial schema <b>must</b> be syntactically valid.
 * </p>
 */
@Beta
public abstract class SchemaWalker {
    /**
     * The list of pointer collectors
     */
    private final Map<String, PointerCollector> collectors;

    protected SchemaWalker(final SchemaDescriptor descriptor) {
        collectors = descriptor.getPointerCollectors();
    }

    /**
     * Walk a tree with a listener
     *
     * @param tree the schema tree to walk
     * @param listener the listener
     * @param report the processing report to use
     * @param <T> the value type produced by the listener
     * @throws ProcessingException processing failure
     */
    public final <T> void walk(final SchemaTree tree, final SchemaListener<T> listener,
            final ProcessingReport report) throws ProcessingException {
        walkTree(JsonPointer.empty(), tree, listener, report);
    }

    protected abstract SchemaTree resolveTree(final SchemaTree tree, final ProcessingReport report)
            throws ProcessingException;

    private <T> void walkTree(final JsonPointer pwd, final SchemaTree tree, final SchemaListener<T> listener,
            final ProcessingReport report) throws ProcessingException {
        listener.enteringPath(pwd, report);
        final SchemaTree resolvedTree = resolveTree(tree, report);
        listener.visiting(resolvedTree, report);

        /*
         * Grab pointer collectors
         */
        final Map<String, PointerCollector> map = Maps.newTreeMap();

        map.putAll(collectors);
        map.keySet().retainAll(Sets.newHashSet(resolvedTree.getNode().fieldNames()));

        /*
         * Collect pointers to visit next
         */
        final List<JsonPointer> pointers = Lists.newArrayList();
        for (final PointerCollector collector : map.values())
            collector.collect(pointers, resolvedTree);

        /*
         * Now, visit the collected set of pointers
         */
        for (final JsonPointer ptr : pointers) {
            walkTree(pwd.append(ptr), resolvedTree.append(ptr), listener, report);
        }
        listener.exitingPath(pwd, report);
    }

    @Override
    public abstract String toString();
}