ASTERIXDB-1711: Move test infra from test.aql

Change-Id: I5d631a2028fb80c823fbaafb7269f15d07685dc9
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1512
Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Reviewed-by: abdullah alamoudi <bamou...@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/asterixdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/asterixdb/commit/452ec9f6
Tree: http://git-wip-us.apache.org/repos/asf/asterixdb/tree/452ec9f6
Diff: http://git-wip-us.apache.org/repos/asf/asterixdb/diff/452ec9f6

Branch: refs/heads/master
Commit: 452ec9f6fa25e266713d9eaebb5909edef5c1149
Parents: ea666c9
Author: Till Westmann <ti...@apache.org>
Authored: Thu Feb 23 09:12:50 2017 -0800
Committer: Till Westmann <ti...@apache.org>
Committed: Thu Feb 23 16:48:32 2017 -0800

----------------------------------------------------------------------
 asterixdb/asterix-app/pom.xml                   |    4 +
 .../asterix/app/external/TestLibrarian.java     |    2 +-
 .../test/common/ComparisonException.java        |   27 +
 .../asterix/test/common/ITestLibrarian.java     |   31 +
 .../asterix/test/common/ResultExtractor.java    |  126 ++
 .../test/common/SingleLinePrettyPrinter.java    |  405 ++++++
 .../asterix/test/common/TestExecutor.java       | 1258 +++++++++++++++++
 .../org/apache/asterix/test/dml/DmlTest.java    |    2 +-
 .../asterix/test/metadata/MetadataTest.java     |    2 +-
 .../asterix/test/runtime/LangExecutionUtil.java |    2 +-
 .../asterix/test/sqlpp/ParserTestExecutor.java  |    4 +-
 .../asterix/test/sqlpp/RuntimeParserTest.java   |    2 +-
 asterixdb/asterix-common/pom.xml                |   22 +-
 .../apache/asterix/test/aql/ITestLibrarian.java |   31 -
 .../asterix/test/aql/ResultExtractor.java       |  127 --
 .../test/aql/SingleLinePrettyPrinter.java       |  404 ------
 .../apache/asterix/test/aql/TestExecutor.java   | 1259 ------------------
 .../asterix/test/base/ComparisonException.java  |   27 -
 .../installer/test/AbstractExecutionIT.java     |    2 +-
 .../test/AsterixClusterLifeCycleIT.java         |    2 +-
 .../test/AsterixExternalLibraryIT.java          |    2 +-
 .../installer/test/AsterixLifecycleIT.java      |    2 +-
 .../installer/test/AsterixRestartIT.java        |    2 +-
 .../installer/test/ClusterExecutionIT.java      |    2 +-
 .../installer/test/MetadataReplicationIT.java   |    2 +-
 .../asterix/installer/test/ReplicationIT.java   |    2 +-
 .../installer/transaction/DmlRecoveryIT.java    |    2 +-
 .../installer/transaction/RecoveryIT.java       |    2 +-
 .../server/test/NCServiceExecutionIT.java       |    2 +-
 .../server/test/SampleLocalClusterIT.java       |    2 +-
 asterixdb/asterix-yarn/pom.xml                  |    2 +-
 .../aoya/test/AsterixYARNLibraryTestIT.java     |    2 +-
 32 files changed, 1873 insertions(+), 1890 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/asterixdb/blob/452ec9f6/asterixdb/asterix-app/pom.xml
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/pom.xml b/asterixdb/asterix-app/pom.xml
index 7ce71b7..74102a1 100644
--- a/asterixdb/asterix-app/pom.xml
+++ b/asterixdb/asterix-app/pom.xml
@@ -357,6 +357,10 @@
       <artifactId>httpcore</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpclient</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.asterix</groupId>
       <artifactId>asterix-lang-common</artifactId>
       <version>${project.version}</version>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/452ec9f6/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/external/TestLibrarian.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/external/TestLibrarian.java
 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/external/TestLibrarian.java
index ba34024..e92b5e8 100644
--- 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/external/TestLibrarian.java
+++ 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/external/TestLibrarian.java
@@ -28,7 +28,7 @@ import org.apache.asterix.common.exceptions.ACIDException;
 import org.apache.asterix.common.exceptions.AsterixException;
 import org.apache.asterix.common.library.ILibraryManager;
 import org.apache.asterix.event.service.AsterixEventServiceUtil;
-import org.apache.asterix.test.aql.ITestLibrarian;
+import org.apache.asterix.test.common.ITestLibrarian;
 import org.apache.commons.io.FileUtils;
 import org.apache.hyracks.algebricks.common.utils.Pair;
 import org.apache.hyracks.api.exceptions.HyracksDataException;

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/452ec9f6/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ComparisonException.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ComparisonException.java
 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ComparisonException.java
new file mode 100644
index 0000000..da5c8f6
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ComparisonException.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.test.common;
+
+public class ComparisonException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    public ComparisonException(String message) {
+        super(message);
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/452ec9f6/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ITestLibrarian.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ITestLibrarian.java
 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ITestLibrarian.java
new file mode 100644
index 0000000..d661710
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ITestLibrarian.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.test.common;
+
+import java.io.IOException;
+import java.rmi.RemoteException;
+
+import org.apache.asterix.common.exceptions.ACIDException;
+import org.apache.asterix.common.exceptions.AsterixException;
+
+public interface ITestLibrarian {
+    public void install(String dvName, String libName, String libPath) throws 
IOException, Exception;
+
+    public void uninstall(String dvName, String libName) throws 
RemoteException, AsterixException, ACIDException;
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/452ec9f6/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
new file mode 100644
index 0000000..3531211
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/ResultExtractor.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.test.common;
+
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.nio.charset.Charset;
+import java.util.Iterator;
+import java.util.logging.Logger;
+
+import org.apache.asterix.common.exceptions.AsterixException;
+import org.apache.commons.io.IOUtils;
+
+import com.fasterxml.jackson.core.PrettyPrinter;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Iterators;
+
+/**
+ * extracts results from the response of the QueryServiceServlet.
+ * As the response is not necessarily valid JSON, non-JSON content has to be 
extracted in some cases.
+ * The current implementation creates a toomany copies of the data to be 
usable for larger results.
+ */
+public class ResultExtractor {
+
+    private static final Logger LOGGER = 
Logger.getLogger(ResultExtractor.class.getName());
+
+    public static InputStream extract(InputStream resultStream) throws 
Exception {
+        ObjectMapper om = new ObjectMapper();
+        String resultStr = IOUtils.toString(resultStream, 
Charset.defaultCharset());
+        PrettyPrinter singleLine = new SingleLinePrettyPrinter();
+        ObjectNode result = om.readValue(resultStr, ObjectNode.class);
+
+        LOGGER.fine("+++++++\n" + result + "\n+++++++\n");
+
+        String type = "";
+        String status = "";
+        String results = "";
+        String field = "";
+        for (Iterator<String> sIter = result.fieldNames(); sIter.hasNext();) {
+            field = sIter.next();
+            switch (field) {
+                case "requestID":
+                    break;
+                case "signature":
+                    break;
+                case "status":
+                    status = om.writeValueAsString(result.get(field));
+                    break;
+                case "type":
+                    type = om.writeValueAsString(result.get(field));
+                    break;
+                case "metrics":
+                    LOGGER.fine(om.writeValueAsString(result.get(field)));
+                    break;
+                case "errors":
+                    JsonNode errors = result.get(field).get(0).get("msg");
+                    throw new AsterixException(errors.asText());
+                case "results":
+                    if (result.get(field).size() <= 1) {
+                        if (result.get(field).size() == 0) {
+                            results = "";
+                        } else if (result.get(field).isArray()) {
+                            if (result.get(field).get(0).isTextual()) {
+                                results = result.get(field).get(0).asText();
+                            } else {
+                                ObjectMapper omm = new ObjectMapper();
+                                omm.setDefaultPrettyPrinter(singleLine);
+                                omm.enable(SerializationFeature.INDENT_OUTPUT);
+                                results = 
omm.writer(singleLine).writeValueAsString(result.get(field));
+                            }
+                        } else {
+                            results = om.writeValueAsString(result.get(field));
+                        }
+                    } else {
+                        StringBuilder sb = new StringBuilder();
+                        JsonNode[] fields = 
Iterators.toArray(result.get(field).elements(), JsonNode.class);
+                        if (fields.length > 1) {
+                            for (JsonNode f : fields) {
+                                if (f.isObject()) {
+                                    sb.append(om.writeValueAsString(f));
+                                } else {
+                                    sb.append(f.asText());
+                                }
+                            }
+                        }
+                        results = sb.toString();
+                    }
+                    break;
+                default:
+                    throw new AsterixException(field + "unanticipated field");
+            }
+        }
+
+        return IOUtils.toInputStream(results);
+    }
+
+    public static String extractHandle(InputStream resultStream) throws 
Exception {
+        final Charset utf8 = Charset.forName("UTF-8");
+        ObjectMapper om = new ObjectMapper();
+        String result = IOUtils.toString(resultStream, utf8);
+        ObjectNode resultJson = om.readValue(result, ObjectNode.class);
+        JsonNode handle = resultJson.get("handle");
+        ObjectNode res = om.createObjectNode();
+        res.set("handle", handle);
+        return om.writeValueAsString(res);
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/452ec9f6/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/SingleLinePrettyPrinter.java
----------------------------------------------------------------------
diff --git 
a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/SingleLinePrettyPrinter.java
 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/SingleLinePrettyPrinter.java
new file mode 100644
index 0000000..2932ca4
--- /dev/null
+++ 
b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/SingleLinePrettyPrinter.java
@@ -0,0 +1,405 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.asterix.test.common;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.PrettyPrinter;
+import com.fasterxml.jackson.core.SerializableString;
+import com.fasterxml.jackson.core.io.SerializedString;
+import com.fasterxml.jackson.core.util.Instantiatable;
+
+/**
+ * Default {@link PrettyPrinter} implementation that uses 2-space
+ * indentation with platform-default linefeeds.
+ * Usually this class is not instantiated directly, but instead
+ * method {@link JsonGenerator#useSingleLinePrettyPrinter} is
+ * used, which will use an instance of this class for operation.
+ */
+@SuppressWarnings("serial")
+public class SingleLinePrettyPrinter
+        implements PrettyPrinter, Instantiatable<SingleLinePrettyPrinter>, 
java.io.Serializable {
+    private static final long serialVersionUID = 1;
+
+    /**
+     * Constant that specifies default "root-level" separator to use between
+     * root values: a single space character.
+     *
+     * @since 2.1
+     */
+    public final static SerializedString DEFAULT_ROOT_VALUE_SEPARATOR = new 
SerializedString(" ");
+
+    /**
+     * Interface that defines objects that can produce indentation used
+     * to separate object entries and array values. Indentation in this
+     * context just means insertion of white space, independent of whether
+     * linefeeds are output.
+     */
+    public interface Indenter {
+        void writeIndentation(JsonGenerator jg, int level) throws IOException;
+
+        /**
+         * @return True if indenter is considered inline (does not add 
linefeeds),
+         *         false otherwise
+         */
+        boolean isInline();
+    }
+
+    // // // Config, indentation
+
+    /**
+     * By default, let's use only spaces to separate array values.
+     */
+    protected Indenter _arrayIndenter = FixedSpaceIndenter.instance;
+
+    /**
+     * By default, let's use linefeed-adding indenter for separate
+     * object entries. We'll further configure indenter to use
+     * system-specific linefeeds, and 2 spaces per level (as opposed to,
+     * say, single tabs)
+     */
+    protected Indenter _objectIndenter = new FixedSpaceIndenter();
+
+    /**
+     * String printed between root-level values, if any.
+     */
+    protected final SerializableString _rootSeparator;
+
+    // // // Config, other white space configuration
+
+    /**
+     * By default we will add spaces around colons used to
+     * separate object fields and values.
+     * If disabled, will not use spaces around colon.
+     */
+    protected boolean _spacesInObjectEntries = true;
+
+    // // // State:
+
+    /**
+     * Number of open levels of nesting. Used to determine amount of
+     * indentation to use.
+     */
+    protected transient int _nesting;
+
+    /*
+    /**********************************************************
+    /* Life-cycle (construct, configure)
+    /**********************************************************
+    */
+
+    public SingleLinePrettyPrinter() {
+        this(DEFAULT_ROOT_VALUE_SEPARATOR);
+    }
+
+    /**
+     * Constructor that specifies separator String to use between root values;
+     * if null, no separator is printed.
+     * <p>
+     * Note: simply constructs a {@link SerializedString} out of parameter,
+     * calls {@link #SingleLinePrettyPrinter(SerializableString)}
+     *
+     * @param rootSeparator
+     * @since 2.1
+     */
+    public SingleLinePrettyPrinter(String rootSeparator) {
+        this((rootSeparator == null) ? null : new 
SerializedString(rootSeparator));
+    }
+
+    /**
+     * Constructor that specifies separator String to use between root values;
+     * if null, no separator is printed.
+     *
+     * @param rootSeparator
+     * @since 2.1
+     */
+    public SingleLinePrettyPrinter(SerializableString rootSeparator) {
+        _rootSeparator = rootSeparator;
+    }
+
+    public SingleLinePrettyPrinter(SingleLinePrettyPrinter base) {
+        this(base, base._rootSeparator);
+    }
+
+    public SingleLinePrettyPrinter(SingleLinePrettyPrinter base, 
SerializableString rootSeparator) {
+        _arrayIndenter = base._arrayIndenter;
+        _objectIndenter = base._objectIndenter;
+        _spacesInObjectEntries = base._spacesInObjectEntries;
+        _nesting = base._nesting;
+
+        _rootSeparator = rootSeparator;
+    }
+
+    public SingleLinePrettyPrinter withRootSeparator(SerializableString 
rootSeparator) {
+        if (_rootSeparator == rootSeparator || (rootSeparator != null && 
rootSeparator.equals(_rootSeparator))) {
+            return this;
+        }
+        return new SingleLinePrettyPrinter(this, rootSeparator);
+    }
+
+    /**
+     * @since 2.6.0
+     */
+    public SingleLinePrettyPrinter withRootSeparator(String rootSeparator) {
+        return withRootSeparator((rootSeparator == null) ? null : new 
SerializedString(rootSeparator));
+    }
+
+    public void indentArraysWith(Indenter i) {
+        _arrayIndenter = (i == null) ? NopIndenter.instance : i;
+    }
+
+    public void indentObjectsWith(Indenter i) {
+        _objectIndenter = (i == null) ? NopIndenter.instance : i;
+    }
+
+    /**
+     * @deprecated Since 2.3 use {@link #withSpacesInObjectEntries} and {@link 
#withoutSpacesInObjectEntries()}
+     */
+    @Deprecated
+    public void spacesInObjectEntries(boolean b) {
+        _spacesInObjectEntries = b;
+    }
+
+    /**
+     * @since 2.3
+     */
+    public SingleLinePrettyPrinter withArrayIndenter(Indenter i) {
+        if (i == null) {
+            i = NopIndenter.instance;
+        }
+        if (_arrayIndenter == i) {
+            return this;
+        }
+        SingleLinePrettyPrinter pp = new SingleLinePrettyPrinter(this);
+        pp._arrayIndenter = i;
+        return pp;
+    }
+
+    /**
+     * @since 2.3
+     */
+    public SingleLinePrettyPrinter withObjectIndenter(Indenter i) {
+        if (i == null) {
+            i = NopIndenter.instance;
+        }
+        if (_objectIndenter == i) {
+            return this;
+        }
+        SingleLinePrettyPrinter pp = new SingleLinePrettyPrinter(this);
+        pp._objectIndenter = i;
+        return pp;
+    }
+
+    /**
+     * "Mutant factory" method that will return a pretty printer instance
+     * that does use spaces inside object entries; if 'this' instance already
+     * does this, it is returned; if not, a new instance will be constructed
+     * and returned.
+     *
+     * @since 2.3
+     */
+    public SingleLinePrettyPrinter withSpacesInObjectEntries() {
+        return _withSpaces(true);
+    }
+
+    /**
+     * "Mutant factory" method that will return a pretty printer instance
+     * that does not use spaces inside object entries; if 'this' instance 
already
+     * does this, it is returned; if not, a new instance will be constructed
+     * and returned.
+     *
+     * @since 2.3
+     */
+    public SingleLinePrettyPrinter withoutSpacesInObjectEntries() {
+        return _withSpaces(false);
+    }
+
+    protected SingleLinePrettyPrinter _withSpaces(boolean state) {
+        if (_spacesInObjectEntries == state) {
+            return this;
+        }
+        SingleLinePrettyPrinter pp = new SingleLinePrettyPrinter(this);
+        pp._spacesInObjectEntries = state;
+        return pp;
+    }
+
+    /*
+    /**********************************************************
+    /* Instantiatable impl
+    /**********************************************************
+     */
+
+    @Override
+    public SingleLinePrettyPrinter createInstance() {
+        return new SingleLinePrettyPrinter(this);
+    }
+
+    /*
+    /**********************************************************
+    /* PrettyPrinter impl
+    /**********************************************************
+     */
+
+    @Override
+    public void writeRootValueSeparator(JsonGenerator jg) throws IOException {
+        if (_rootSeparator != null) {
+            jg.writeRaw(_rootSeparator);
+        }
+    }
+
+    @Override
+    public void writeStartObject(JsonGenerator jg) throws IOException {
+        jg.writeRaw('{');
+        ++_nesting;
+    }
+
+    @Override
+    public void beforeObjectEntries(JsonGenerator jg) throws IOException {
+        _objectIndenter.writeIndentation(jg, _nesting);
+    }
+
+    /**
+     * Method called after an object field has been output, but
+     * before the value is output.
+     * <p>
+     * Default handling (without pretty-printing) will output a single
+     * colon to separate the two. Pretty-printer is
+     * to output a colon as well, but can surround that with other
+     * (white-space) decoration.
+     */
+    @Override
+    public void writeObjectFieldValueSeparator(JsonGenerator jg) throws 
IOException {
+        if (_spacesInObjectEntries) {
+            jg.writeRaw(": ");
+        } else {
+            jg.writeRaw(':');
+        }
+    }
+
+    /**
+     * Method called after an object entry (field:value) has been completely
+     * output, and before another value is to be output.
+     * <p>
+     * Default handling (without pretty-printing) will output a single
+     * comma to separate the two. Pretty-printer is
+     * to output a comma as well, but can surround that with other
+     * (white-space) decoration.
+     */
+    @Override
+    public void writeObjectEntrySeparator(JsonGenerator jg) throws IOException 
{
+        jg.writeRaw(',');
+        _objectIndenter.writeIndentation(jg, _nesting);
+    }
+
+    @Override
+    public void writeEndObject(JsonGenerator jg, int nrOfEntries) throws 
IOException {
+        --_nesting;
+        if (nrOfEntries > 1) {
+            _objectIndenter.writeIndentation(jg, _nesting);
+        } else {
+            jg.writeRaw(' ');
+        }
+        jg.writeRaw('}');
+    }
+
+    @Override
+    public void writeStartArray(JsonGenerator jg) throws IOException {
+        ++_nesting;
+        jg.writeRaw('[');
+    }
+
+    @Override
+    public void beforeArrayValues(JsonGenerator jg) throws IOException {
+        _arrayIndenter.writeIndentation(jg, _nesting);
+    }
+
+    /**
+     * Method called after an array value has been completely
+     * output, and before another value is to be output.
+     * <p>
+     * Default handling (without pretty-printing) will output a single
+     * comma to separate the two. Pretty-printer is
+     * to output a comma as well, but can surround that with other
+     * (white-space) decoration.
+     */
+    @Override
+    public void writeArrayValueSeparator(JsonGenerator gen) throws IOException 
{
+        gen.writeRaw(',');
+        _arrayIndenter.writeIndentation(gen, _nesting);
+    }
+
+    @Override
+    public void writeEndArray(JsonGenerator gen, int nrOfValues) throws 
IOException {
+        --_nesting;
+
+        if (_nesting == 0) {
+            gen.writeRaw('\n');
+        }
+        if (nrOfValues > 1) {
+            _arrayIndenter.writeIndentation(gen, _nesting);
+        } else {
+            gen.writeRaw(' ');
+        }
+        gen.writeRaw(']');
+    }
+
+    /*
+    /**********************************************************
+    /* Helper classes
+    /**********************************************************
+     */
+
+    /**
+     * Dummy implementation that adds no indentation whatsoever
+     */
+    public static class NopIndenter implements Indenter, java.io.Serializable {
+        public static final NopIndenter instance = new NopIndenter();
+
+        @Override
+        public void writeIndentation(JsonGenerator jg, int level) throws 
IOException {
+        }
+
+        @Override
+        public boolean isInline() {
+            return true;
+        }
+    }
+
+    /**
+     * This is a very simple indenter that only adds a
+     * single space for indentation. It is used as the default
+     * indenter for array values.
+     */
+    public static class FixedSpaceIndenter extends NopIndenter {
+        @SuppressWarnings("hiding")
+        public static final FixedSpaceIndenter instance = new 
FixedSpaceIndenter();
+
+        @Override
+        public void writeIndentation(JsonGenerator jg, int level) throws 
IOException {
+            jg.writeRaw(' ');
+        }
+
+        @Override
+        public boolean isInline() {
+            return true;
+        }
+    }
+}

Reply via email to