/**
   * This method is going to return a ParsedOutputObject from arrays of bytes
   *
   * @param parseInputObject
   * @return
   */
  public static ParseOutputObject parse(ParseInputObject parseInputObject) {
    ParseOutputObject res = new ParseOutputObject();
    boolean error = false;

    if (parseInputObject == null || parseInputObject.getStatusMessagingList() == null) {
      throw new IllegalArgumentException(
          "Rp3UtilityParser.parse parseInputObject is invalid : " + parseInputObject);
    }

    if (LOG.isDebugEnabled()) {
      LOG.debug(
          "Rp3UtilityParser parse beginning parseInputObject.getParseType() 			: "
              + parseInputObject.getParseType());
      LOG.debug("Rp3UtilityParser parse beginning FileName 			: " + parseInputObject.getFileName());
      LOG.debug(
          "Rp3UtilityParser parse beginning parseInputObject.getStatusMessagingList() : "
              + parseInputObject.getStatusMessagingList());
    }

    try {
      if (parseInputObject.getData() != null && parseInputObject.getData().length > 0) {
        String stringContent = new String(parseInputObject.getData());
        Scanner sc = new Scanner(stringContent);
        Integer contRow = 0;
        Integer contCol = 0;
        Map<String, List<DataObject>> mapDataByCol = new LinkedHashMap<String, List<DataObject>>();
        Map<String, List<DataObject>> mapDataByRow = new LinkedHashMap<String, List<DataObject>>();
        Map<Integer, List<DataObject>> mapDataByMatrix =
            new LinkedHashMap<Integer, List<DataObject>>();
        List<String> listColumnsNames = new ArrayList<String>();

        if (parseInputObject.getParseType() == PARSE_TYPES.QQ) {
          Rp3UtilityParser.parseQqLayout(res, sc, contRow, listColumnsNames);
        } else {
          Rp3UtilityParser.parseRowColumIdxLayout(
              parseInputObject,
              sc,
              contRow,
              contCol,
              mapDataByCol,
              mapDataByRow,
              mapDataByMatrix,
              listColumnsNames);
        }

        res.setMapDataByColName(mapDataByCol);
        res.setMapDataByRowFieldName(mapDataByRow);
        res.setMapDataByRowIndex(mapDataByMatrix);

      } else {
        StatusMessage statusMessaging =
            new StatusMessage(
                Rp3Constants.CODES_MSG.STATUS_MSG_LEVEL_METHOD.toString(),
                "util_b_001",
                Arrays.asList(
                    parseInputObject.getParseType().toString(), parseInputObject.getFileName()),
                1);
        parseInputObject.getStatusMessagingList().add(statusMessaging);
      }

    } catch (RuntimeException e) {
      error = true;
      LOG.error("Rp3UtilityParser parse error " + e.getMessage(), e);
      StatusMessage statusMessaging =
          new StatusMessage(
              Rp3Constants.CODES_MSG.STATUS_MSG_LEVEL_METHOD.toString(),
              "util_b_002",
              Arrays.asList(
                  parseInputObject.getParseType().toString(),
                  parseInputObject.getFileName(),
                  e.getMessage()),
              2);
      parseInputObject.getStatusMessagingList().add(statusMessaging);
    }

    if (!error) {
      StatusMessage statusMessaging =
          new StatusMessage(
              Rp3Constants.CODES_MSG.STATUS_MSG_LEVEL_METHOD.toString(),
              "util_b_003",
              Arrays.asList(
                  parseInputObject.getParseType().toString(), parseInputObject.getFileName()),
              0);
      parseInputObject.getStatusMessagingList().add(statusMessaging);
    }

    if (LOG.isDebugEnabled()) {
      LOG.debug(
          "Rp3UtilityParser parse end parseInputObject.getStatusMessagingList() : "
              + parseInputObject.getStatusMessagingList());
      LOG.debug(
          "Rp3UtilityParser parse end parseInputObject.getParseType() : "
              + parseInputObject.getParseType());
    }

    return res;
  }
  /**
   * This method process the information for the txt files layouts that are not related with the
   * Qualifying questions layout.
   *
   * @param parseInputObject
   * @param sc
   * @param contRow
   * @param contCol
   * @param mapDataByCol
   * @param mapDataByRow
   * @param mapDataByMatrix
   * @param listColumnsNames
   */
  private static void parseRowColumIdxLayout(
      ParseInputObject parseInputObject,
      Scanner sc,
      Integer contRow,
      Integer contCol,
      Map<String, List<DataObject>> mapDataByCol,
      Map<String, List<DataObject>> mapDataByRow,
      Map<Integer, List<DataObject>> mapDataByMatrix,
      List<String> listColumnsNames) {
    Map<Integer, String> dataMap = new HashMap<Integer, String>();

    while (sc.hasNextLine()) {
      String valueX = sc.nextLine();
      List<DataObject> listMapDataByRow = new ArrayList<DataObject>();
      String rowName = "";

      if (valueX.isEmpty() == false) {
        Scanner sc1 = new Scanner(valueX);
        sc1.useDelimiter("\\t");
        while (sc1.hasNext()) {
          String valueY = sc1.next();
          boolean validated = false;

          if ((parseInputObject.getParseType() == PARSE_TYPES.BYCOLUMNNAME
                  && valueY.isEmpty() == false)
              || (parseInputObject.getParseType() == PARSE_TYPES.BYROWFIELD)
              || parseInputObject.getParseType() == PARSE_TYPES.ROWINDEX) {
            validated = true;
          }

          if (validated) {
            /*
             * LOG.debug("valueX3 : " + Pattern.compile("\\t").matcher(valueX).replaceAll("").length());
             */
            DataObject dataObject = new DataObject();
            dataObject.setColPos(contCol);
            dataObject.setRowNum(contRow);
            dataObject.setData(valueY);

            if (contRow == 0 && parseInputObject.getParseType() == PARSE_TYPES.BYCOLUMNNAME) {
              mapDataByCol.put(valueY, new ArrayList<DataObject>());
              dataMap.put(contCol, valueY);
            } else if (contCol == 0 && parseInputObject.getParseType() == PARSE_TYPES.BYROWFIELD) {
              rowName = valueY;
            }

            if (parseInputObject.getParseType() == PARSE_TYPES.BYROWFIELD && contCol > 0) {
              listMapDataByRow.add(dataObject);
            } else if (parseInputObject.getParseType() == PARSE_TYPES.BYCOLUMNNAME && contRow > 0) {
              String value = dataMap.get(contCol);

              if (mapDataByCol.containsKey(value)) {
                List<DataObject> listColumns = mapDataByCol.get(value);
                listColumns.add(dataObject);
                mapDataByCol.put(value, listColumns);
              }

            } else if (parseInputObject.getParseType() == PARSE_TYPES.ROWINDEX && contRow == 0) {
              listColumnsNames.add(valueY);
              /*
               *LOG.debug("listColumnsNames : " + listColumnsNames);
               */
            } else if (parseInputObject.getParseType() == PARSE_TYPES.ROWINDEX && contRow > 0) {
              dataObject.setColumnName(listColumnsNames.get(contCol));
              listMapDataByRow.add(dataObject);
            }
          }
          contCol++;
        }
      }

      if (parseInputObject.getParseType() == PARSE_TYPES.BYROWFIELD
          && !rowName.isEmpty()
          && !listMapDataByRow.isEmpty()) {
        if (LOG.isDebugEnabled()) {
          LOG.debug("Rp3UtilityParser parse rowName : " + rowName);
        }
        mapDataByRow.put(rowName, listMapDataByRow);
      } else if (parseInputObject.getParseType() == PARSE_TYPES.ROWINDEX) {
        mapDataByMatrix.put(contRow, listMapDataByRow);
      }

      contRow++;
      contCol = 0;
    }
  }