Previous Next JavaScript must be enabled to correctly display this content

## The `LoadJsonExample` Program Source

The following `LoadJsonExample` java program creates and populates an Oracle NoSQL Database table with rows whose elements are JSON documents read from a text file.

    package es.table;

    import java.nio.file.Path;
    import java.nio.file.Files;
    import java.nio.file.FileSystems;

    import java.io.FileNotFoundException;
    import java.io.IOException;

    import java.util.List;
    import java.util.ArrayList;

    import oracle.kv.FaultException;
    import oracle.kv.KVStore;
    import oracle.kv.KVStoreConfig;
    import oracle.kv.KVStoreFactory;
    import oracle.kv.StatementResult;

    import oracle.kv.table.PrimaryKey;
    import oracle.kv.table.Row;
    import oracle.kv.table.Table;
    import oracle.kv.table.TableAPI;
    import oracle.kv.table.TableIterator;

    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.core.JsonToken;

    import oracle.kv.impl.tif.esclient.jsonContent.ESJsonUtil;

    /**
     * Class that creates an example table in a given Oracle NoSQL Database store and
     * then uses the Oracle NoSQL Database Table API to populate the table with
     * sample records consisting of JSON documents retrieved from a file. The
     * table that is created consists of only two Oracle NoSQL Database data types: an
     * INTEGER type and a JSON type.
     *
     * The file from which the desired JSON documents are retrieved must be of
     * form:
     * <pre>
     {
        "meta": {
            "limit": n,
            "offset": 0,
            "total_count": n
        },
        "objects": [
            {
                JSON DOCUMENT 1
            },
            {
                JSON DOCUMENT 2
            },
            ....
            {
                JSON DOCUMENT n
            },
        ]
     }
     * </pre>
     */
    public final class LoadJsonExample {

        final boolean debugWithNoStore = false;
        final boolean debugAll = false;
        final boolean debugTopLevelJsonArrayObject = false;
        final boolean debugAddDoc = false;
        final boolean debugJsonToStringTop = false;
        final boolean debugJsonToStringArray = false;
        final boolean debugDocByDoc = false;

        private final KVStore store;
        private final TableAPI tableAPI;
        private final Table table;

        private Path jsonPath;

        private boolean deleteExisting = false;

        private static final String TABLE_NAME_DEFAULT = "jsonTable";
        private static final String ID_FIELD_NAME = "id";
        private static final String JSON_FIELD_NAME = "jsonField";

        public static void main(final String[] args) {
            try {
                final LoadJsonExample loadData = new LoadJsonExample(args);
                loadData.run();
            } catch (FaultException e) {
                e.printStackTrace();
                System.out.println("Please make sure a store is running.");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        /**
         * Parses command line args and opens the KVStore.
         */
        private LoadJsonExample(final String[] argv) {

            String storeName = "";
            String hostName = "";
            String hostPort = "";

            final int nArgs = argv.length;
            int argc = 0;
            String tableName = null;

            if (nArgs == 0) {
                usage(null);
            }

            while (argc < nArgs) {
                final String thisArg = argv[argc++];

                if ("-store".equals(thisArg)) {
                    if (argc < nArgs) {
                        storeName = argv[argc++];
                    } else {
                        usage("-store requires an argument");
                    }
                } else if ("-host".equals(thisArg)) {
                    if (argc < nArgs) {
                        hostName = argv[argc++];
                    } else {
                        usage("-host requires an argument");
                    }
                } else if ("-port".equals(thisArg)) {
                    if (argc < nArgs) {
                        hostPort = argv[argc++];
                    } else {
                        usage("-port requires an argument");
                    }
                } else if ("-file".equals(thisArg)) {
                    if (argc < nArgs) {
                        jsonPath = FileSystems.getDefault().getPath(argv[argc++]);
                    } else {
                        usage("-file requires an argument");
                    }
                } else if ("-table".equals(thisArg)) {
                    if (argc < nArgs) {
                        tableName = argv[argc++];
                    }
                } else if ("-security".equals(thisArg)) {
                    if (argc < nArgs) {
                        System.setProperty(
                            KVSecurityConstants.SECURITY_FILE_PROPERTY,
                            argv[argc++]);
                    } else {
                        usage(“-security requires an argument”);
                    }

                } else if ("-delete".equals(thisArg)) {
                    deleteExisting = true;
                } else {
                    usage("Unknown argument: " + thisArg);
                }
            }

            if (storeName == null) {
                usage("Missing argument: -store <store-name>");
            }

            if (hostName == null) {
                usage("Missing argument: -host <host>");
            }

            if (hostPort == null) {
                usage("Missing argument: -port <port>");
            }

            if (jsonPath == null) {
                usage("Missing argument: -file <path-to-file>");
            }

            /* When the table name is not specified, construct the name of
             * the table from the file name, minus the suffix. That is strip
             * off the path and the suffix and use file name's 'base' as
             * the name of the table.
             */
            if (tableName == null) {
                final Path flnmElement = jsonPath.getFileName();
                if (flnmElement == null) {
                    tableName = TABLE_NAME_DEFAULT;
                } else {
                    final String tmpTblName = flnmElement.toString();
                    final String suffixDelim = ".";
                    if (tmpTblName.contains(suffixDelim)) {
                        final int suffixIndx = tmpTblName.indexOf(suffixDelim);
                        if (suffixIndx > 0) {
                            tableName = tmpTblName.substring(0, suffixIndx);
                        } else {
                            tableName = tmpTblName;
                        }
                    } else {
                        tableName = tmpTblName;
                    }
                }
            }

            System.out.println("\n--------------------------------------------");
            System.out.println("Table to create and load = " + tableName);
            System.out.println("--------------------------------------------\n");

            if (debugWithNoStore) {
                store = null;
                tableAPI = null;
                table = null;
            } else {
                store = KVStoreFactory.getStore
                    (new KVStoreConfig(storeName, hostName + ":" + hostPort));

                tableAPI = store.getTableAPI();
                createTable(tableName);
                table = tableAPI.getTable(tableName);
                if (table == null) {
                    final String msg =
                        "Store does not contain table [name=" + tableName + "]";
                    throw new RuntimeException(msg);
                }
            }
        }

        private void usage(final String message) {
            if (message != null) {
                System.out.println("\n" + message + "\n");
            }

            System.out.println("usage: " + getClass().getName());
            System.out.println
                ("\t-store <instance name>\n" +
                 "\t-host <host name>\n" +
                 "\t-port <port number>\n" +
                 "\t[-file <path to file with json objects to add to table> |\n" +
                 "\t[-table <name of table to create and load>]\n" +
                 "\t-delete (default: false) [delete all existing data first]\n");
            System.exit(1);
        }

        private void run() throws FileNotFoundException, IOException {
            if (deleteExisting) {
                deleteExistingData();
            }
            doLoad(jsonPath);
        }

        private void createTable(final String tableName) {

            final String statement =
                "CREATE TABLE IF NOT EXISTS " + tableName +
                " (" +
                   ID_FIELD_NAME + " INTEGER," +
                   JSON_FIELD_NAME + " JSON," +
                "PRIMARY KEY (" + ID_FIELD_NAME + "))";

            try {
                final StatementResult result = store.executeSync(statement);
                if (result.isSuccessful()) {
                    System.out.println("table created [" + tableName + "]");
                } else if (result.isCancelled()) {
                    System.out.println("table creation CANCELLED [" +
                                       tableName + "]");
                } else {
                    if (result.isDone()) {
                        System.out.println("table creation FAILED:\n\t" +
                                           statement);
                        System.out.println("ERROR:\n\t" +
                                           result.getErrorMessage());
                    } else {
                        System.out.println("table creation IN PROGRESS:\n\t" +
                                           statement);
                        System.out.println("STATUS:\n\t" + result.getInfo());
                    }
                }
            } catch (IllegalArgumentException e) {
                System.out.println("Invalid statement:");
                e.printStackTrace();
            } catch (FaultException e) {
                System.out.println("Failure on statement execution:");
                e.printStackTrace();
            }
        }

        private void doLoad(final Path filePath)
                         throws FileNotFoundException, IOException {

            try {
                loadJsonDocs(filePath);
            } finally {
                if (store != null) {
                    store.close();
                }
            }
        }

        private void loadJsonDocs(final Path filePath)
                         throws FileNotFoundException, IOException {

            try {
    	    final byte[] jsonBytes = Files.readAllBytes(filePath);
                final int nDocsToAdd = getIntFieldValue(
                    "meta", "total_count", ESJsonUtil.createParser(jsonBytes));

                if (debugAll || debugTopLevelJsonArrayObject) {

                    System.out.println("BEGIN Top Level Array Object: 'objects'");

                    final String objectsJsonStr =
                        getTopLevelJsonArrayObject(
                            "objects", ESJsonUtil.createParser(jsonBytes));

                    System.out.println(objectsJsonStr);
                    System.out.println("END Top Level Array Object: 'objects'");
                    System.out.println("\nBEGIN Top Level Array Object: 'meta'");

                    final String metaJsonStr =
                        getTopLevelJsonArrayObject(
                            "meta", ESJsonUtil.createParser(jsonBytes));

                    System.out.println(metaJsonStr);
                    System.out.println("END Top Level Array Object: 'meta'");

                } /* endif (debugAll || debugTopLevelJsonArrayObject) */

                final String[] jsonArray =
                    getJsonArrayElements(
                        "objects", ESJsonUtil.createParser(jsonBytes), nDocsToAdd);

                for (int i = 0; i < nDocsToAdd; i++) {

                    if (debugAll || debugAddDoc) {
                        System.out.println("Adding JSON Row[" + i +
                                           "] to table:\n" + jsonArray[i]);
                    }
                    addDoc(i, jsonArray[i]);
                }
            } catch (FileNotFoundException e) {
                System.out.println("File not found [" +
                                   filePath.getFileName() + "]: " + e);
                throw e;
            } catch (IOException e) {
                System.out.println("IOException [file=" +
                                   filePath.getFileName() + "]: " + e);
                throw e;
            }
        }

        private void addDoc(final Integer id, final String jsonDoc) {

            final Row row = table.createRow();

            row.put(ID_FIELD_NAME, id);
            row.putJson(JSON_FIELD_NAME, jsonDoc);

            tableAPI.putIfAbsent(row, null, null);
        }

        private void deleteExistingData() {

            /* Get an iterator over all the primary keys in the table. */
            final TableIterator<PrimaryKey> itr =
                tableAPI.tableKeysIterator(table.createPrimaryKey(), null, null);

            /* Delete each row from the table. */
            long cnt = 0;
            while (itr.hasNext()) {
                tableAPI.delete(itr.next(), null, null);
                cnt++;
            }
            itr.close();
            System.out.println(cnt + " records deleted");
        }

        /*
         * Convenience method for displaying output when debugging.
         */
        private void displayRow(Table tbl) {
            final TableIterator<Row> itr =
                tableAPI.tableIterator(tbl.createPrimaryKey(), null, null);
            while (itr.hasNext()) {
                System.out.println(itr.next());
            }
            itr.close();
        }

        /*
         * Supporting methods for parsing the various attributes in the given file.
         */

        private String[] getJsonArrayElements(final String arrayName,
                                              final JsonParser parser,
                                              final int nElements)
                                                  throws IOException {

            final List<String> arrayList = new ArrayList<String>();

            JsonToken token = parser.nextToken();
            while (token != null) {
                final String curFieldName = parser.getCurrentName();

                if (!arrayName.equals(curFieldName)) {
                    token = parser.nextToken();
                    continue;
                }
                break;
            }

            if (debugAll || debugDocByDoc) {
                System.out.println(
                    "getJsonArrayElements loop: curToken = " + token +
                    ", curFieldName = " + parser.getCurrentName());
            }

            token = parser.nextToken();

            if (debugAll || debugDocByDoc) {
                System.out.println(
                    "getJsonArrayElements loop: nextToken = " + token +
                    ", nextFieldName = " + parser.getCurrentName());
            }

            if (token == null) {
                System.out.println("getJsonArrayElements loop: " +
                                   "*** WARNING - null first token from parser");

                return arrayList.toArray(new String[nElements]);
            }

            if (token != JsonToken.START_ARRAY) {
                System.out.println("getJsonArrayElements loop: *** WARNING - " +
                    "first token from parser != " + "START_ARRAY [" + token + "]");

                return arrayList.toArray(new String[nElements]);
            }

            for (int i = 0; i < nElements; i++) {
                final StringBuilder strBldr = new StringBuilder();
                if (i > 0) {
                    strBldr.append("{\n");
                }
                final String arrayElement =
                    jsonToString(arrayName, null, parser, strBldr, false);
                arrayList.add(arrayElement);

                if (debugAll || debugDocByDoc) {
                    System.out.println(
                        "getJsonArrayElements loop: arrayElement[" + i + "] =\n" +
                        arrayElement);
                }

            }/* end loop */

            return arrayList.toArray(new String[nElements]);
        }

        private String getTopLevelJsonArrayObject(
                           final String fieldName,
                           final JsonParser parser) throws IOException {

            final StringBuilder strBldr = new StringBuilder();
            JsonToken token = parser.nextToken();
            while (token != null) {
                final String curFieldName = parser.getCurrentName();

                if (!fieldName.equals(curFieldName)) {
                    token = parser.nextToken();
                    continue;
                }
                break;
            }
            final String jsonStr =
                jsonToString(fieldName, null, parser, strBldr, false);
            return strBldr.toString();
        }

        private String jsonToString(final String stopField,
                                    final JsonToken prevToken,
                                    final JsonParser parser,
                                    final StringBuilder strBldr,
                                    final boolean fromObjectArray)
                                                      throws IOException {

            JsonToken token = parser.nextToken();

            if (token == null) {

                if (debugAll || debugJsonToStringTop) {
                    System.out.println("TOP of jsonToString: prevToken = " +
                                       prevToken + ", curToken = " + token +
                                       ", RETURNING because input token == null");
                }
                return strBldr.toString();
            }

            final String curFieldName = parser.getCurrentName();

            if (debugAll || debugJsonToStringTop) {

                System.out.println("\nTOP of jsonToString");
                System.out.println("prevToken = " + prevToken +
                                   ", curToken = " + token +
                                   ", curFieldName = " + curFieldName +
                                   ", stopField = " + stopField + ", isScalar = " +
                                   token.isScalarValue() + ", fromObjectArray = " +
                                   fromObjectArray);
            }

            if (prevToken != null) {

                if (prevToken == JsonToken.END_ARRAY ||
                    prevToken == JsonToken.END_OBJECT) {

                    if (debugAll || debugJsonToStringTop) {
                        System.out.println(
                            "*** TOP of jsonToString: prevToken != null [" +
                            prevToken + "] && " + "[END_ARRAY || END_OBJECT]");
                    }

                    if (stopField != null && stopField.equals(curFieldName)) {

                        if (token == JsonToken.END_ARRAY) {

                            if (debugAll || debugJsonToStringTop) {
                                System.out.println(
                                    "*** STOP-BY-FIELD_NAME [END_ARRAY]: " +
                                    "prevToken = " + prevToken + ", curToken = " +
                                    token + ", curFieldName = " + curFieldName +
                                    ", stopField = " + stopField +
                                    " ... RETURN string, do not recurse, " +
                                    "do not terminate outer array with ']' ..." +
                                    " RETURN STR =\n" + strBldr.toString());
                            }
                            return strBldr.toString();
                        }

                        if (token == JsonToken.END_OBJECT) {

                            if (debugAll || debugJsonToStringTop) {
                                System.out.println(
                                    "*** STOP-BY-FIELD_NAME [END_OBJECT]: " +
                                    "prevToken = " + prevToken + ", curToken = " +
                                    token + ", curFieldName = " + curFieldName +
                                    ", stopField = " + stopField +
                                    " ... RETURN string, do not recurse, " +
                                    "but DO terminate outer array with '}' ..." +
                                    " RETURN STR =\n" + strBldr.toString());
                            }
                            strBldr.append("\n}");
                            return strBldr.toString();
                        }
                    } /* endif (STOP-BY-FIELD) */

                    if (prevToken == JsonToken.END_OBJECT &&
                        token == JsonToken.START_OBJECT &&
                        curFieldName == null) {

                        if (fromObjectArray) {
                            if (debugAll || debugJsonToStringTop) {
                                System.out.println(
                                    "*** END_OBJECT && START_OBJECT && " +
                                    "curFieldName=null && is OBJECT_ARRAY: " +
                                    "prevToken = " + prevToken + ", curToken = " +
                                    token + ", curFieldName = " + curFieldName +
                                    ", stopField = " + stopField +
                                    ", fromObjectArray = " + fromObjectArray +
                                    " ... add ',{' and RECURSE");
                            }
                            strBldr.append(",\n{\n");
                            return jsonToString(
                              stopField, token, parser, strBldr, fromObjectArray);
                        }

                        if (debugAll || debugJsonToStringTop) {
                            System.out.println(
                                "*** END_OBJECT && START_OBJECT && " +
                                "curFieldName=null && not OBJECT_ARRAY: " +
                                "prevToken = " + prevToken + ", curToken = " +
                                token + ", curFieldName = " + curFieldName +
                                ", stopField = " + stopField +
                                ", fromObjectArray = " + fromObjectArray +
                                " ... simply return string, do not recurse");
                        }
                        return strBldr.toString();

                    } else if (prevToken == JsonToken.END_OBJECT &&
                               token == JsonToken.END_ARRAY &&
                               curFieldName != null) {

                        if (fromObjectArray) {

                            strBldr.append("\n]\n");

                            if (debugAll || debugJsonToStringTop) {
                                System.out.println(
                                    "*** END_OBJECT && END_ARRAY && " +
                                    "curFieldName != null && is OBJECT_ARRAY: " +
                                    "prevToken = " + prevToken + ", curToken = " +
                                    token + ", curFieldName = " + curFieldName +
                                    ", stopField = " + stopField +
                                    " terminate OBJECT_ARRAY with ']' ... " +
                                    "do NOT RECURSE ... RETURN subString =\n" +
                                    strBldr.toString());
                            }

                        } else { /* NOT fromObjectArray */

                            if (debugAll || debugJsonToStringTop) {
                                System.out.println(
                                    "*** END_OBJECT && END_ARRAY && " +
                                    "curFieldName != null && NOT OBJECT_ARRAY: " +
                                    "prevToken = " + prevToken + ", curToken = " +
                                    token + ", curFieldName = " + curFieldName +
                                    ", stopField = " + stopField +
                                    " do NOT terminate OBJECT_ARRAY ... " +
                                    "do NOT RECURSE ... RETURN subString =\n" +
                                    strBldr.toString());
                            }

                        } /* endif (fromObjectArray) */

                        return strBldr.toString();

                    } else if (prevToken == JsonToken.END_OBJECT &&
                               token == JsonToken.END_OBJECT &&
                               (curFieldName != null || fromObjectArray)) {

                        strBldr.append("}\n");

                        if (debugAll || debugJsonToStringTop) {
                            System.out.println(
                                "*** END_OBJECT && END_ARRAY && " +
                                "curFieldName != null OR is OBJECT_ARRAY: " +
                                "prevToken = " + prevToken + ", curToken = " +
                                token + ", curFieldName = " + curFieldName +
                                ", stopField = " + stopField +
                                " , fromObjectArray = " + fromObjectArray +
                                " terminate object in OBJECT_ARRAY with '}' and " +
                                "RECURSE ...");
                        }
                        return jsonToString(
                              stopField, token, parser, strBldr, fromObjectArray);

                    } else if (prevToken == JsonToken.END_ARRAY &&
                               token == JsonToken.END_OBJECT &&
                               curFieldName != null) {

                        strBldr.append("}\n");

                        if (debugAll || debugJsonToStringTop) {
                            System.out.println(
                                "*** END_ARRAY then END_OBJECT && " +
                                "curFieldName != null: " +
                                "prevToken = " + prevToken + ", curToken = " +
                                token + ", curFieldName = " + curFieldName +
                                ", stopField = " + stopField +
                                " , fromObjectArray = " + fromObjectArray +
                                " terminate object with '}' and RECURSE ...");
                        }
                        return jsonToString(
                              stopField, token, parser, strBldr, fromObjectArray);

                    } else { /* DEFAULT: all other cases */

                        strBldr.append(",\n");

                        if (debugAll || debugJsonToStringTop) {
                            System.out.println(
                                "*** ELSE BLOCK *** prevToken = " + prevToken +
                                ", curToken = " + token + ", curFieldName = " +
                                curFieldName + ", stopField = " + stopField +
                                " , fromObjectArray = " + fromObjectArray +
                                " add COMMA and RECURSE ...\n" +
                                strBldr.toString());
                        }
                        return jsonToString(
                              stopField, token, parser, strBldr, fromObjectArray);

                    } /* endif (prevToken, inputToken, curFieldName */

                } /* endif (prevToken == END_ARRAY || END_OBJECT) */

                if (prevToken.isScalarValue()) {

                    if (token != JsonToken.END_ARRAY &&
                        token != JsonToken.END_OBJECT) {

                        strBldr.append(",\n");
                        return jsonToString(
                              stopField, token, parser, strBldr, fromObjectArray);
                    }

                    if (stopField != null && stopField.equals(curFieldName)) {

                        if (token == JsonToken.END_ARRAY) {

                            strBldr.append("\n]");

                            if (debugAll || debugJsonToStringTop) {
                                System.out.println(
                                    "*** prev SCALAR && STOP-BY-FIELD_NAME " +
                                    "[END_ARRAY]: prevToken = " + prevToken +
                                    ", curToken = " + token + ", curFieldName = " +
                                    curFieldName + ", stopField = " + stopField +
                                    " ... terminate with ']' and RETURN string");
                            }
                            return strBldr.toString();
                        }

                        if (token == JsonToken.END_OBJECT) {

                            strBldr.append("\n}");

                            if (debugAll || debugJsonToStringTop) {
                                System.out.println(
                                    "*** prev SCALAR && STOP-BY-FIELD_NAME " +
                                    "[END_ARRAY]: prevToken = " + prevToken +
                                    ", curToken = " + token + ", curFieldName = " +
                                    curFieldName + ", stopField = " + stopField +
                                    " ... terminate with '}' and RETURN string");
                            }
                            return strBldr.toString();
                        }

                    } /* endif (prevToken isScalar && STOP-BY-FIELD) */

                } /* endif (prevToken isScalar) */

            } /* endif (prevToken != null) */

            /* Done with prevToken, process current input token next */

            if (token.isScalarValue()) { /* current token is SCALAR */

                strBldr.append("\"" + curFieldName + "\": " + objectValue(parser));
                return jsonToString(
                           stopField, token, parser, strBldr, fromObjectArray);
            }

            if (JsonToken.START_OBJECT == token) { /* input token is OBJECT */

                if (curFieldName != null) {
                    strBldr.append("\"" + curFieldName + "\": {\n");
                } else {
                    strBldr.append("{\n");
                }
                return jsonToString(
                           stopField, token, parser, strBldr, fromObjectArray);

            } else if (JsonToken.START_ARRAY == token) { /* input Token is ARRAY */

                if (debugAll || debugJsonToStringArray) {
                    System.out.println(
                        "--- START_ARRAY --- prevToken = " + prevToken +
                        ", curToken = " + token + ", curFieldName = " +
                        curFieldName + ", stopField = " + stopField +
                        ", isScalar = " + token.isScalarValue() +
                        ", fromObjectArray = " + fromObjectArray +
                        " ... get NEXT TOKEN");
                }

                token = parser.nextToken();

                if (debugAll || debugJsonToStringArray) {
                    System.out.println(
                        "--- START_ARRAY --- nextToken = " + token +
                        ", curFieldName = " + curFieldName + ", stopField = " +
                        stopField + ", isScalar = " + token.isScalarValue() +
                        ", fromObjectArray = " + fromObjectArray);
                }

                if (token == null) {
                    System.out.println(
                        "*** WARNING: null next token after START_ARRAY. " +
                        "Invalid json document?");
                    return strBldr.toString();
                }

                /* START_ARRAY then START_OBJECT: Handle ARRAY OF OBJECTS */

                if (JsonToken.START_OBJECT == token) {

                    if (debugAll || debugJsonToStringArray) {
                        System.out.println("--- START_ARRAY then START_OBJECT: " +
                                           "Handle ARRAY_OF_OBJECTS ---");
                    }

                    final StringBuilder tmpBldr = new StringBuilder();
                    final String curArrayName = curFieldName;

                    if (curArrayName != null) {
                        if (!curArrayName.equals(stopField)) {
                            tmpBldr.append("\"" + curFieldName + "\": [\n");
                        }
                    }
                    tmpBldr.append("{\n");

                    while (token != null && JsonToken.END_ARRAY != token) {

                        /*
                         * When at the top of this loop, we know we're handling an
                         * array of objects. We know that we're done with that
                         * array of objects (has already been terminated with ']')
                         * and so should terminate the object containing the
                         * array (with '}') if the following conditions are met:
                         *
                         * 1. The previous token is a FIELD_NAME.
                         * 2. The current field name corresponding to the current
                         *    token is the same as the name of the current array.
                         * 3. The current token is END_OBJECT (meaning we're at
                         *    the end of the object containing the array).
                         */
                        if (JsonToken.FIELD_NAME == prevToken &&
                            JsonToken.END_OBJECT == token &&
                            curFieldName != null &&
                            curFieldName.equals(curArrayName)) {

                            tmpBldr.append("}\n");

                            if (debugAll || debugJsonToStringArray) {
                                System.out.println(
                                    "--- TOP ARRAY_OF_OBJECTS LOOP: " +
                                    "array element END_OBJECT - " +
                                    "terminate with '}' - prevToken = " +
                                    prevToken + ", curToken = " + token +
                                    ", curFieldName = " + curFieldName +
                                    ", stopField = " + stopField +
                                    " , fromObjectArray = " + fromObjectArray +
                                    " ... loop to continue or end of DOC");
                            }

                            String nextFieldName = curFieldName;
                            while(token != null) {

                                token = parser.nextToken();
                                nextFieldName = parser.getCurrentName();

                                if (debugAll || debugJsonToStringArray) {
                                    System.out.println(
                                        "--- TOP ARRAY_OF_OBJECTS LOOP: " +
                                        "array termination inner loop - " +
                                        "nextToken = " + token +
                                        ", nextFieldName = " + nextFieldName);
                                }

                                if (token.isScalarValue()) {

                                    tmpBldr.append(",\n");
                                    tmpBldr.append("\"" + nextFieldName +
                                                   "\": " + objectValue(parser));
                                    break;
                                }

                                if (JsonToken.START_OBJECT == token) {

                                    tmpBldr.append(",\n");
                                    if (nextFieldName != null) {
                                        tmpBldr.append("\"" + nextFieldName +
                                                       "\": { kkkk\n");
                                    } else {
                                        tmpBldr.append("{ kkkk\n");
                                    }
                                    break;
                                }

                                if (JsonToken.START_ARRAY == token) {

                                    tmpBldr.append(",\n");
                                    if (nextFieldName != null) {
                                        tmpBldr.append("\"" + nextFieldName +
                                                       "\": [ kkkk\n");
                                    } else {
                                        tmpBldr.append("[ kkkk\n");
                                    }
                                    break;
                                }

                                if ((nextFieldName != null &&
    				 nextFieldName.equals(stopField)) ||
                                    (nextFieldName == null &&
                                     JsonToken.END_OBJECT == token)) {

                                    final String finalRetStr =
                                    strBldr.append(tmpBldr.toString()).toString();

                                    if (debugAll || debugJsonToStringArray) {
                                        System.out.println(
                                            "--- TOP ARRAY_OF_OBJECTS LOOP: " +
                                            "DONE - RETURN FINAL STRING =\n" +
                                            finalRetStr);
                                    }
                                    return finalRetStr;
                                }

                            } /* end loop */

                            /* More tokens to process. Recurse. */

                            if (debugAll || debugJsonToStringArray) {
                                System.out.println(
                                    "--- TOP ARRAY_OF_OBJECTS LOOP: " +
                                    "curToken = " + token + ", curFieldName = " +
                                    nextFieldName + ", stopField = " + stopField +
                                    " , fromObjectArray = " + fromObjectArray +
                                    "-  more tokens to process ... RECURSE");
                            }
                            jsonToString(stopField, token, parser, tmpBldr, false);

                        } else { /* Not end of outer object containing objArray */

                            if (debugAll || debugJsonToStringArray) {
                                System.out.println(
                                    "--- TOP ARRAY_OF_OBJECTS LOOP: " +
                                    "prevToken = " + prevToken + ", curToken = " +
                                    token + ", curFieldName = " +
                                    curFieldName + ", stopField = " + stopField +
                                    " , fromObjectArray = " + fromObjectArray +
                                    "-  NOT END OF ARRAY ... RECURSE");
                            }
                            jsonToString(stopField, token, parser, tmpBldr, true);

                        } /* endif (FIELD_NAME then END_OBJECT && array name) */

                        if (debugAll || debugJsonToStringArray) {
                            System.out.println(
                                "--- TOP ARRAY_OF_OBJECTS LOOP: " +
                                "EXIT jsonToString() - prevToken = " +
                                prevToken + ", curToken = " + token +
                                ", curFieldName = " + curFieldName +
                                ", stopField = " + stopField +
                                " , fromObjectArray = " + fromObjectArray +
                                " ... loop to continue or end of DOC");
                        }

                        if (JsonToken.FIELD_NAME == prevToken &&
                            JsonToken.FIELD_NAME == token &&
                            curFieldName != null) {

                            if (debugAll || debugJsonToStringArray) {
                                System.out.println(
                                    "--- IN ARRAY_OF_OBJECTS LOOP: " +
                                    "FIELD_NAME then FIELD_NAME - " +
                                    "curToken = " + token +
                                    ", curFieldName = " + curFieldName +
                                    " ... get NEXT TOKEN");
                            }

                            token = parser.nextToken();

                            if (debugAll || debugJsonToStringArray) {
                                System.out.println(
                                    "--- IN ARRAY_OF_OBJECTS LOOP: " +
                                    "FIELD_NAME then FIELD_NAME - " +
                                    "nextToken = " + token + ", nextFieldName = " +
                                    parser.getCurrentName());
                            }

                            if (JsonToken.END_OBJECT == token) {

                                if (debugAll || debugJsonToStringArray) {
                                     System.out.println(
                                       "--- IN ARRAY_OF_OBJECTS LOOP: " +
                                       "FIELD_NAME then FIELD_NAME - " +
                                       "nextToken = END_OBJECT ... BREAK " +
                                       "out of loop ... subString =\n" +
                                       tmpBldr.toString());
                                }
                                break;

                            } else { /* nextToken NOT END_OBJECT */

                                final String finalRetStr = strBldr.append(
                                    tmpBldr.toString()).toString();

                                if (debugAll || debugJsonToStringArray) {
                                     System.out.println(
                                       "--- IN ARRAY_OF_OBJECTS LOOP: " +
                                       "FIELD_NAME then FIELD_NAME - " +
                                       "nextToken = " + token +
                                       "(NOT END_OBJECT) ... DONE - " +
                                       "RETURN FINAL STRING = \n" + finalRetStr);
                                }
                                return finalRetStr;

                            } /* endif (nextToken END_OBJECT or NOT) */

                        } else if (JsonToken.FIELD_NAME == prevToken &&
                                   JsonToken.START_OBJECT == token &&
                                   curFieldName != null) {

                            if (debugAll || debugJsonToStringArray) {
                                 System.out.println(
                                   "--- IN ARRAY_OF_OBJECTS LOOP: " +
                                   "FIELD_NAME then START_OBJECT - " +
                                   "curToken = " + token + ", curFieldName = " +
                                   parser.getCurrentName());
                            }

                            token = parser.nextToken();
                            final String nextFieldName = parser.getCurrentName();

                            if (JsonToken.FIELD_NAME == token &&
                                nextFieldName != null) {
                                tmpBldr.append(",\n");

                            } else if (JsonToken.END_OBJECT == token &&
                                       nextFieldName != null) {
                                tmpBldr.append("}\n");
                            }

                            if (debugAll || debugJsonToStringArray) {
                                 System.out.println(
                                   "--- IN ARRAY_OF_OBJECTS LOOP: " +
                                   "FIELD_NAME then START_OBJECT - " +
                                   "nextToken = " + token + ", nextFieldName = " +
                                   nextFieldName + " ... current subString =\n" +
                                   tmpBldr.toString());
                            }

                        } else {

                            token = parser.nextToken();

                            if (debugAll || debugJsonToStringArray) {
                                 System.out.println(
                                   "--- IN ARRAY_OF_OBJECTS LOOP: " +
                                   "*** ELSE *** nextToken = " + token +
                                   ", nextFieldName = " +
                                   parser.getCurrentName() +
                                   " ... current subString =\n" +
                                   tmpBldr.toString());
                            }

                        }/* endif FIELD_NAME && FIELD_NAME && fieldName != null */

                        if (debugAll || debugJsonToStringArray) {
                             System.out.println(
                               "--- IN ARRAY_OF_OBJECTS LOOP: " +
                               "END OF LOOP - CONTINUE TO TOP OF LOOP" );
                        }

                    } /* end ARRAY_OF_OBJECTS loop */

                    if (debugAll || debugJsonToStringArray) {
                         System.out.println(
                           "--- OUT ARRAY_OF_OBJECTS LOOP:  " +
                           "current subString = \n" + tmpBldr.toString());
                    }

                    final String tmpStr = tmpBldr.toString();
                    final String retStr = strBldr.append(tmpStr).toString();

                    if (debugAll || debugJsonToStringArray) {
                         System.out.println(
                           "--- OUT ARRAY_OF_OBJECTS LOOP:  " +
                           "ENTER jsonToString() - BEGIN FINAL RETURN string ...");
                    }

                    final String finalRetStr =
                        jsonToString(stopField, token, parser, strBldr, false);

                    if (debugAll || debugJsonToStringArray) {
                         System.out.println(
                           "--- OUT ARRAY_OF_OBJECTS LOOP:  EXIT " +
                           "jsonToString() - RETURN FINAL RETURN string = \n" +
                           finalRetStr);
                    }
                    return finalRetStr;

                } /* endif START_OBJECT after START_ARRAY & ARRAY OF OBJECTS */

                /* -- START_ARRAY then NOT START_OBJECT: ARRAY OF SCALARS -- */

                if (debugAll || debugJsonToStringArray) {
                    System.out.println("--- START_ARRAY then SCALAR: " +
                                       "Enter ARRAY_OF_SCALARS loop ---");
                }

                strBldr.append("\"" + curFieldName + "\": [\n");
                while (token != null && JsonToken.END_ARRAY != token) {
                    strBldr.append(objectValue(parser));
                    token = parser.nextToken();
                    if (JsonToken.END_ARRAY == token) {
                        strBldr.append("\n]");
                    } else {
                        strBldr.append(",\n");
                    }
                }/* end loop: ARRAY_OF_SCALARS */

                return jsonToString(stopField, token, parser, strBldr, false);

            } else if(JsonToken.END_OBJECT == token) {

                strBldr.append("\n}");
                return jsonToString(
                           stopField, token, parser, strBldr, fromObjectArray);

            } else  { /* DEFAULT: all other values of current input token */

                return jsonToString(
                           stopField, token, parser, strBldr, fromObjectArray);

            } /* endif (START_OBJECT else START_ARRAY else END_OBJECT) */
        }

        private Object objectValue(JsonParser parser) throws IOException {
            final JsonToken currentToken = parser.getCurrentToken();
            if (currentToken == JsonToken.VALUE_STRING) {
                return "\"" + parser.getText() + "\"";
            } else if (currentToken == JsonToken.VALUE_NUMBER_INT ||
                    currentToken == JsonToken.VALUE_NUMBER_FLOAT) {
                return parser.getNumberValue();
            } else if (currentToken == JsonToken.VALUE_TRUE) {
                return Boolean.TRUE;
            } else if (currentToken == JsonToken.VALUE_FALSE) {
                return Boolean.FALSE;
            } else if (currentToken == JsonToken.VALUE_NULL) {
                return null;
            } else {
                return "\"" + parser.getText() + "\"";
            }
        }

        private int getIntFieldValue(final String objectName,
                                     final String fieldName,
                                     final JsonParser parser) throws IOException {
            int nObjects = 0;
            JsonToken token = parser.nextToken();
            while (token != null) {
                String curFieldName = parser.getCurrentName();
                if (objectName.equals(curFieldName)) {
                    token = parser.nextToken();
                    while (token != null) {
                        curFieldName = parser.getCurrentName();
                        if (fieldName.equals(curFieldName)) {
                            token = parser.nextToken();
                            if (token != JsonToken.VALUE_NUMBER_INT) {
                                System.out.println("getIntFieldValue: WARNING - " +
                                    "for object " + objectName + ", value of " +
                                    "field " + fieldName + " is NOT an integer [" +
                                    parser.getText() + "]");
                                return nObjects;
                            }
                            nObjects = parser.getNumberValue().intValue();
                            return nObjects;
                        }
                        token = parser.nextToken();
                    }
                }
                token = parser.nextToken();
            }
            System.out.println("getIntFieldValue: WARNING - could not find " +
                               "field in given object [object=" + objectName +
                               ", field=" + fieldName + "]");
            return nObjects;
        }
    }