@Override
  public void print(JSONObject inputObject, PrintStream outputStream) throws Exception {
    LOG.info("JsonParser is parsing:" + inputObject.toString());
    this.rewriteObject = outputStream == null;
    // outputStream == null means we need to process it for explain formatted
    this.extractStagesAndPlans(inputObject);
    if (rewriteObject) {
      return;
    }
    Printer printer = new Printer();
    // print out the cbo info
    if (inputObject.has("cboInfo")) {
      printer.println(inputObject.getString("cboInfo"));
      printer.println();
    }
    // print out the vertex dependency in root stage
    for (Stage candidate : this.stages.values()) {
      if (candidate.tezStageDependency != null && candidate.tezStageDependency.size() > 0) {
        if (candidate.parentStages.size() == 0) {
          printer.println("Vertex dependency in root stage");
        } else {
          printer.println("Vertex dependency in " + candidate.externalName);
        }
        for (Entry<Vertex, List<Connection>> entry : candidate.tezStageDependency.entrySet()) {
          StringBuilder sb = new StringBuilder();
          sb.append(entry.getKey().name);
          sb.append(" <- ");
          boolean printcomma = false;
          for (Connection connection : entry.getValue()) {
            if (printcomma) {
              sb.append(", ");
            } else {
              printcomma = true;
            }
            sb.append(connection.from.name + " (" + connection.type + ")");
          }
          printer.println(sb.toString());
        }
        printer.println();
      }
    }
    // print out all the stages that have no childStages.
    for (Stage candidate : this.stages.values()) {
      if (candidate.childStages.isEmpty()) {
        candidate.print(printer, 0);
      }
    }
    outputStream.println(printer.toString());
  }
@param indentFlag
@param tail
         help to generate correct indent with a specific tail
@return
common/src/java/org/apache/hadoop/hive/common/jsonexplain/DagJsonParser.java