/**
   * Constructs a configuration file from a past configuration file that was saved to the disk.
   *
   * @param fileName - the path to the file on disk
   * @throws IOException - if there is any problem reading the file
   */
  public Configuration(final String fileName) throws IOException {
    final JsonFactory jf = new JsonFactory();
    final JsonParser jp = jf.createParser(new File(fileName));
    jp.nextToken();

    while (jp.nextToken() != JsonToken.END_OBJECT) {
      final String fieldName = jp.getCurrentName();
      jp.nextToken();
      switch (fieldName) {
        case IN_FILE_KEY:
          this.inputFileName = jp.getText();
          break;
        case IN_FILE_DIR_KEY:
          this.inputFileDirName = jp.getText();
          break;
        case SPLIT_PATTERN_KEY:
          this.splitPattern = jp.getText();
          break;
        case OUT_FILE_KEY:
          this.outDirName = jp.getText();
          break;
        case EXEC_LOC_KEY:
          this.execPath = jp.getText();
          break;
        case NUM_PROCESSES_KEY:
          this.numberOfThreads = jp.getIntValue();
          break;
        case STATS_KEY:
          this.makeStats = jp.getBooleanValue();
          break;
        case NUM_HEADER_KEY:
          this.numberOfHeaderLines = jp.getIntValue();
          break;
        case DEFAULT_MERGE_KEY:
          if (jp.getBooleanValue()) {
            this.mergeMethod = 0;
          }
          break;
        case CUSTOM_MERGE_KEY:
          if (jp.getBooleanValue()) {
            this.mergeMethod = 1;
          }
          break;
        case EXTERNAL_MERGE_KEY:
          if (jp.getBooleanValue()) {
            this.mergeMethod = 2;
          }
          break;
        case ARGUMENT_KEY:
          this.argument = jp.getText();
          break;
        case OUTPUT_FMT_KEY:
          this.outputFmt = jp.getBooleanValue();
          break;
        default:
          assert (false);
      }
    }
    jp.close();
  }
  public streamParser(CommandLine line) {
    try {

      JsonFactory jfactory = new JsonFactory();
      JsonParser jParser = null;

      if (line.hasOption("f")) {
        jParser = jfactory.createJsonParser(new File(line.getOptionValue("file")));
      } else {
        jParser = jfactory.createJsonParser(System.in);
      }

      String idElement = null;
      String idValue = null;

      if (line.hasOption("key")) idElement = line.getOptionValue("key");

      String[] remainingArguments = line.getArgs();
      if (remainingArguments.length != 1) {
        throw new IOException("table name not provided or too many table arguments");
      }
      Table table = MapRDB.getTable(remainingArguments[0]); // get the table
      DocumentBuilder b = MapRDB.newDocumentBuilder();

      while (jParser.nextToken() != null) {
        String fieldName = jParser.getCurrentName();

        switch (jParser.getCurrentToken()) {
          case END_ARRAY:
            depth--;
            b.endArray();
            break;
          case END_OBJECT:
            b.endMap();
            depth--;
            // When the depth reaches zero on an end of object, this means we
            // have constructed a complete JSON object in the DocumentBuilder.
            // At this point, we can call insert() or insertandreplace()
            if (depth == 0) {
              System.out.println(b.getDocument().asJsonString());
              if (idElement != null) table.insert(idValue, b.getDocument());
              else table.insert(b.getDocument());
            }
            break;
          case START_ARRAY:
            if (fieldName == null) {
              b.addNewArray();
            } else {
              b.putNewArray(fieldName);
            }
            depth++;
            break;
          case START_OBJECT:
            if (fieldName == null) {
              b.addNewMap();
            } else {
              b.putNewMap(fieldName);
            }
            depth++;
            break;

            // Not sure about these guys
          case FIELD_NAME:
          case NOT_AVAILABLE:
          case VALUE_EMBEDDED_OBJECT:
            break;

            // These actually add things to the array or object
          case VALUE_NULL:
            if (fieldName != null) {
              b.putNull(fieldName);
            } else {
              b.addNull();
            }
            break;
          case VALUE_NUMBER_FLOAT:
            if (fieldName != null) {
              b.put(fieldName, jParser.getDoubleValue());
            } else {
              b.add(jParser.getDoubleValue());
            }
            break;
          case VALUE_NUMBER_INT:
            if (fieldName != null) {
              b.put(fieldName, jParser.getLongValue());
            } else {
              b.add(jParser.getLongValue());
            }
            break;
          case VALUE_STRING:
            if (fieldName != null) {
              if (fieldName.equals(idElement)) idValue = jParser.getText();
              b.put(fieldName, jParser.getText());
            } else {
              b.add(jParser.getText());
            }
            break;
          case VALUE_FALSE:
          case VALUE_TRUE:
            if (fieldName != null) {
              b.put(fieldName, jParser.getBooleanValue());
            } else {
              b.add(jParser.getBooleanValue());
            }
            break;
        }
        System.out.println(
            "["
                + depth
                + "]   "
                + jParser.getCurrentToken().toString()
                + ": "
                + fieldName); // display mkyong
      }
      jParser.close();

    } catch (JsonGenerationException e) {
      e.printStackTrace();
    } catch (JsonMappingException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
    @Override
    public Record deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
      JsonToken t = jp.getCurrentToken();

      SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");
      sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
      String id = null;
      String type = null;
      Date creationDate = null;
      JsonToken currentToken = null;
      Map<String, Field> fields = new HashMap<>();

      boolean processingFields = false;
      while ((currentToken = jp.nextValue()) != null) {

        switch (currentToken) {
          case START_OBJECT:
            processingFields = true;
            break;
          case END_OBJECT:
            processingFields = true;
            break;
          case VALUE_NUMBER_INT:
            try {
              fields.put(
                  jp.getCurrentName(),
                  new Field(jp.getCurrentName(), FieldType.INT, jp.getIntValue()));
            } catch (JsonParseException ex) {
              fields.put(
                  jp.getCurrentName(),
                  new Field(jp.getCurrentName(), FieldType.LONG, jp.getLongValue()));
            }
            break;

          case VALUE_NUMBER_FLOAT:
            try {
              fields.put(
                  jp.getCurrentName(),
                  new Field(jp.getCurrentName(), FieldType.FLOAT, jp.getFloatValue()));
            } catch (JsonParseException ex) {
              fields.put(
                  jp.getCurrentName(),
                  new Field(jp.getCurrentName(), FieldType.DOUBLE, jp.getDoubleValue()));
            }
            break;
          case VALUE_FALSE:
          case VALUE_TRUE:
            fields.put(
                jp.getCurrentName(),
                new Field(jp.getCurrentName(), FieldType.BOOLEAN, jp.getBooleanValue()));
            break;
          case START_ARRAY:
            logger.info(jp.getCurrentName());
            break;

          case END_ARRAY:
            break;
          case VALUE_STRING:
            if (jp.getCurrentName() != null) {
              switch (jp.getCurrentName()) {
                case "id":
                  id = jp.getValueAsString();
                  break;
                case "type":
                  type = jp.getValueAsString();
                  break;
                case "creationDate":
                  try {
                    creationDate =
                        sdf.parse(jp.getValueAsString()); // "Thu Sep 08 12:11:08 CEST 2016\"
                  } catch (ParseException e) {
                    e.printStackTrace();
                  }
                  break;
                default:
                  fields.put(
                      jp.getCurrentName(),
                      new Field(jp.getCurrentName(), FieldType.STRING, jp.getValueAsString()));

                  break;
              }
            }

            break;
          default:
            break;
        }
      }

      Record record = new StandardRecord(type);
      record.setId(id);
      record.setType(type);
      record.setTime(creationDate);
      record.setFields(fields);

      return record;
    }