From cad70e5ef371a0adcf9c7ec80386f5c9c7a172a6 Mon Sep 17 00:00:00 2001
From: Francis Galiegue <fgaliegue@gmail.com>
Date: Sat, 24 May 2014 20:15:19 +0200
Subject: [PATCH] More documentation

Signed-off-by: Francis Galiegue <fgaliegue@gmail.com>
---
 .../validation/InstanceValidator.java         | 120 +++++++++++-------
 .../validation/ObjectSchemaDigester.java      |   2 +-
 2 files changed, 77 insertions(+), 45 deletions(-)

diff --git a/src/main/java/com/github/fge/jsonschema/processors/validation/InstanceValidator.java b/src/main/java/com/github/fge/jsonschema/processors/validation/InstanceValidator.java
index bc062c719..81ef71750 100644
--- a/src/main/java/com/github/fge/jsonschema/processors/validation/InstanceValidator.java
+++ b/src/main/java/com/github/fge/jsonschema/processors/validation/InstanceValidator.java
@@ -31,12 +31,15 @@
 import com.github.fge.jsonschema.core.tree.JsonTree;
 import com.github.fge.jsonschema.core.tree.SchemaTree;
 import com.github.fge.jsonschema.keyword.validator.KeywordValidator;
+import com.github.fge.jsonschema.main.JsonSchema;
+import com.github.fge.jsonschema.main.JsonValidator;
 import com.github.fge.jsonschema.processors.data.FullData;
 import com.github.fge.jsonschema.processors.data.SchemaContext;
 import com.github.fge.jsonschema.processors.data.ValidatorList;
 import com.github.fge.msgsimple.bundle.MessageBundle;
 import com.github.fge.uritemplate.URITemplate;
 import com.github.fge.uritemplate.URITemplateException;
+import com.github.fge.uritemplate.URITemplateParseException;
 import com.github.fge.uritemplate.vars.VariableMap;
 import com.google.common.base.Equivalence;
 import com.google.common.collect.Lists;
@@ -50,7 +53,16 @@
 import java.util.Set;
 
 /**
- * Main validation processor
+ * Processor for validating one schema/instance pair
+ *
+ * <p>One such processor is created for each schema/instance validation.</p>
+ *
+ * <p>Internally, all validation operations provided by the API (whether that
+ * be a {@link JsonSchema}, via {@link JsonValidator} or using {@link
+ * ValidationProcessor} directly) will eventually instantiate one of these. More
+ * precisely, this is instantiated by {@link
+ * ValidationProcessor#process(ProcessingReport, FullData)}.</p>
+ *
  */
 @NotThreadSafe
 @ParametersAreNonnullByDefault
@@ -71,7 +83,7 @@ public final class InstanceValidator
      * Whatever the data, validation will end up validating, for a same pointer
      * into the instance, the following pointers into the schema:
      *
-     * "" -> "/oneOf/0" -> "/oneOf/1" -> "" <-- LOOP
+     * "" -> "/oneOf/0" -> "/oneOf/1" -> "/oneOf/0" <-- LOOP
      *
      * This is not a JSON Reference loop here, but truly a validation loop.
      *
@@ -84,6 +96,13 @@ public final class InstanceValidator
     private final Set<Equivalence.Wrapper<FullData>> visited
         = Sets.newLinkedHashSet();
 
+    /**
+     * Constructor -- do not use directly!
+     *
+     * @param syntaxMessages the syntax message bundle
+     * @param validationMessages the validation message bundle
+     * @param keywordBuilder the keyword builder
+     */
     public InstanceValidator(final MessageBundle syntaxMessages,
         final MessageBundle validationMessages,
         final Processor<SchemaContext, ValidatorList> keywordBuilder)
@@ -98,22 +117,12 @@ public FullData process(final ProcessingReport report,
         final FullData input)
         throws ProcessingException
     {
-        if (!visited.add(FULL_DATA_EQUIVALENCE.wrap(input))) {
-            final String errmsg
-                = validationMessages.getMessage("err.common.validationLoop");
-            final ArrayNode node = JacksonUtils.nodeFactory().arrayNode();
-            for (final Equivalence.Wrapper<FullData> e: visited)
-                //noinspection ConstantConditions
-                node.add(toJson(e.get()));
-            final ProcessingMessage message = input.newMessage()
-                .put("domain", "validation")
-                .setMessage(errmsg)
-                .putArgument("alreadyVisited", toJson(input))
-                .putArgument("instancePointer",
-                    input.getInstance().getPointer().toString())
-                .put("validationPath", node);
-            throw new ProcessingException(message);
-        }
+        /*
+         * We don't want the same validation context to appear twice, see above
+         */
+        if (!visited.add(FULL_DATA_EQUIVALENCE.wrap(input)))
+            throw new ProcessingException(validationLoopMessage(input));
+
 
         /*
          * Build a validation context, attach a report to it
@@ -169,25 +178,10 @@ public FullData process(final ProcessingReport report,
         return input;
     }
 
-    private ProcessingMessage collectSyntaxErrors(final ProcessingReport report)
+    @Override
+    public String toString()
     {
-        /*
-         * OK, that's for issue #99 but that's ugly nevertheless.
-         *
-         * We want syntax error messages to appear in the exception text.
-         */
-        final String msg = syntaxMessages.getMessage("core.invalidSchema");
-        final ArrayNode arrayNode = JacksonUtils.nodeFactory().arrayNode();
-        JsonNode node;
-        for (final ProcessingMessage message: report) {
-            node = message.asJson();
-            if ("syntax".equals(node.path("domain").asText()))
-                arrayNode.add(node);
-        }
-        final StringBuilder sb = new StringBuilder(msg);
-        sb.append("\nSyntax errors:\n");
-        sb.append(JacksonUtils.prettyPrint(arrayNode));
-        return new ProcessingMessage().setMessage(sb.toString());
+        return "instance validator";
     }
 
     private void processArray(final ProcessingReport report,
@@ -200,7 +194,8 @@ private void processArray(final ProcessingReport report,
         final JsonNode schema = tree.getNode();
         final JsonNode node = instance.getNode();
 
-        final JsonNode digest = ArraySchemaDigester.getInstance().digest(schema);
+        final JsonNode digest = ArraySchemaDigester.getInstance()
+            .digest(schema);
         final ArraySchemaSelector selector = new ArraySchemaSelector(digest);
 
         final int size = node.size();
@@ -248,21 +243,58 @@ private void processObject(final ProcessingReport report,
         }
     }
 
-    @Override
-    public String toString()
+    private ProcessingMessage validationLoopMessage(final FullData input)
     {
-        return "instance validator";
+        final String errmsg
+            = validationMessages.getMessage("err.common.validationLoop");
+        final ArrayNode node = JacksonUtils.nodeFactory().arrayNode();
+        for (final Equivalence.Wrapper<FullData> e: visited)
+            //noinspection ConstantConditions
+            node.add(toJson(e.get()));
+        return input.newMessage()
+            .put("domain", "validation")
+            .setMessage(errmsg)
+            .putArgument("alreadyVisited", toJson(input))
+            .putArgument("instancePointer",
+                input.getInstance().getPointer().toString())
+            .put("validationPath", node);
+    }
+
+    private ProcessingMessage collectSyntaxErrors(final ProcessingReport report)
+    {
+        /*
+         * OK, that's for issue #99 but that's ugly nevertheless.
+         *
+         * We want syntax error messages to appear in the exception text.
+         */
+        final String msg = syntaxMessages.getMessage("core.invalidSchema");
+        final ArrayNode arrayNode = JacksonUtils.nodeFactory().arrayNode();
+        JsonNode node;
+        for (final ProcessingMessage message: report) {
+            node = message.asJson();
+            if ("syntax".equals(node.path("domain").asText()))
+                arrayNode.add(node);
+        }
+        final StringBuilder sb = new StringBuilder(msg);
+        sb.append("\nSyntax errors:\n");
+        sb.append(JacksonUtils.prettyPrint(arrayNode));
+        return new ProcessingMessage().setMessage(sb.toString());
     }
 
     private static String toJson(final FullData data)
     {
         final SchemaTree tree = data.getSchema();
         final URI baseUri = tree.getLoadingRef().getLocator();
+        final VariableMap vars = VariableMap.newBuilder().addScalarValue("ptr",
+            tree.getPointer()).freeze();
+        // TODO: there should be an easier way to do that...
+        final URITemplate template;
+        try {
+            template = new URITemplate(baseUri + "{+ptr}");
+        } catch (URITemplateParseException e) {
+            throw new IllegalStateException("wtf??", e);
+        }
         try {
-            // TODO: there should be an easier way to do that...
-            final URITemplate template = new URITemplate(baseUri + "{+ptr}");
-            final VariableMap vars = VariableMap.newBuilder().addScalarValue(
-                "ptr", tree.getPointer()).freeze();
             return template.toString(vars);
         } catch (URITemplateException e) {
             throw new IllegalStateException("wtf??", e);
diff --git a/src/main/java/com/github/fge/jsonschema/processors/validation/ObjectSchemaDigester.java b/src/main/java/com/github/fge/jsonschema/processors/validation/ObjectSchemaDigester.java
index 98891de76..722ea8ac7 100644
--- a/src/main/java/com/github/fge/jsonschema/processors/validation/ObjectSchemaDigester.java
+++ b/src/main/java/com/github/fge/jsonschema/processors/validation/ObjectSchemaDigester.java
@@ -31,7 +31,7 @@
 import java.util.Set;
 
 /**
- * JSON Schema digester for an {@link ObjectSchemaDigester}
+ * JSON Schema digester for an {@link ObjectSchemaSelector}
  */
 public final class ObjectSchemaDigester
     extends AbstractDigester