WEPSParser.java [src/parsers] Revision: default  Date:
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package parsers;

import config.ConfigParser;
import config.nodes.Identity;
import config.nodes.ManActionFormat;
import config.nodes.ParamFormatLine;
import csip.api.server.ServiceException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import nodes.WEPSAction;
import nodes.WEPSCrop;
import nodes.WEPSOperation;

/**
 *
 * @author Brad
 */
public class WEPSParser {

  RandomAccessFile raf;
  ParseTypes currentType;
  int rotationYears;
  LocalDate date;
  WEPSOperation op;
  WEPSAction action;
  WEPSCrop crop;

  public WEPSParser(String fileName) throws FileNotFoundException {
    raf = new RandomAccessFile(new File(fileName), "r");
  }

  public ParseTypes readNext() throws ParserException, IOException, ServiceException {
    String line;
    String[] parts;
    if (raf == null) {
      throw new ParserException("Reader was not initilized");
    }

    currentType = ParseTypes.NONE;
    while ((line = raf.readLine()) != null) {
      if (line.charAt(0) == '*') {
        parts = line.split(" ");
        if (parts[0].equals("*START")) {
          currentType = ParseTypes.START;
          rotationYears = Integer.parseInt(parts[1]);
          break;
        }

        if (parts[0].equals("*END")) {
          currentType = ParseTypes.END;
          break;
        }
      }

      if (line.charAt(0) == 'D') {
        // Do date things
        currentType = ParseTypes.DATE;
        parts = line.split(" ", 2);
        date = LocalDate.parse(parts[1], DateTimeFormatter.ofPattern("dd/MM/yy"));
        break;
      }

      if (line.charAt(0) == 'O') {
        // Do operation things
        currentType = ParseTypes.OPERATION;
        parseOperation(line);
        break;
      }

      // only crop
      if (line.charAt(0) == 'G') {
        // Do crop things
        parts = line.split(" ");
        if ((parts[0] + " " + parts[1]).equals(ConfigParser.getInstance().getManFormat().getcropIdentiy().toString())) { // found a crop go do crop things
          currentType = ParseTypes.CROP;
          parseCrop(line);
          break;
        }
      }

      if (line.charAt(0) == 'G' || line.charAt(0) == 'P') { // assume that if this was a crop it would have been caught already
        currentType = ParseTypes.ACTION;
        parts = line.split(" ");
        parseAction(line);
        break;
      }

      if (line.equals("#------------")) {
        currentType = ParseTypes.ENDOP;
        break;
      }

    }

    return currentType;
  }

  private String parseOperation(String line) throws ServiceException, IOException, ParserException {

    String[] parts = line.split(" ", 3);
    op = new WEPSOperation(parts[2]);

    WEPSAction first_action;

    first_action = parseAction(line);
    op.addAction(first_action);

    return line;
  }

  private WEPSAction parseAction(String line) throws ServiceException, IOException, ParserException {
    action = new WEPSAction();
    Identity id = new Identity();
    String[] parts = line.split(" ");
    ManActionFormat actionFormat;
    String value = "";

    id.setCode(parts[0]);
    id.setId(Integer.parseInt(parts[1]));

    action.setIdentity(id);

    actionFormat = ConfigParser.getInstance().getManFormat().getManActionFormat(id);

    for (ParamFormatLine fline : actionFormat.getFormatLines()) {
      if ((line = peakLine()) != null && (line.toUpperCase().charAt(0)) == 'T' || line.charAt(0) == '+') {
        line = raf.readLine();
        parts = line.split(" ");

        for (int i = 0; i < fline.getParameterNames().size(); i++) {
          switch (line.charAt(0)) {
            case 'T':
            case 't':
              value = line.replaceFirst(String.valueOf(line.charAt(0)), "");
              value += readComments(line.charAt(0));
              break;
            case '+':
              if (i < parts.length - 1) {
                value = parts[i + 1];

              } else // The value was empty in the weps man
              {
                value = "";
              }

          }
          action.addParameter(fline.getParameterNames().get(i), value);
        }
      }
    }

    return action;
  }

  private String readComments(char com) throws IOException, ParserException {
    String comment = "";
    String line;

    while ((line = peakLine()) != null && line.charAt(0) == com) {

      if (line.charAt(0) == com) {
        comment += raf.readLine().replaceFirst(String.valueOf(com), "");
      }
    }

    return comment;
  }

  private void parseCrop(String line) throws IOException, ServiceException, ParserException {
    String[] parts;
    Identity id = new Identity();
    ManActionFormat actionFormat;
    String value = "";

    // get crop name
    if ((line = raf.readLine()) != null) {
      parts = line.split(" ", 2);
      crop = new WEPSCrop(parts[1]);
    }

    // get crop action/data
    if ((line = raf.readLine()) != null) {
      parts = line.split(" ");
      id.setCode(parts[0]);
      id.setId(Integer.parseInt(parts[1]));

      actionFormat = ConfigParser.getInstance().getManFormat().getManActionFormat(id);

      for (ParamFormatLine fline : actionFormat.getFormatLines()) {
        if ((line = peakLine()) != null && (line.toUpperCase().charAt(0)) == 'T' || line.charAt(0) == '+') {
          line = raf.readLine();
          parts = line.split(" ");

          for (int i = 0; i < fline.getParameterNames().size(); i++) {
            switch (line.charAt(0)) {
              case 'T':
              case 't':
                value = line.replaceFirst(String.valueOf(line.charAt(0)), "");
                value += readComments(line.charAt(0));
                break;
              case '+':
                if (i < parts.length - 1) {
                  value = parts[i + 1];
                  if (fline.getParameterNames().get(i).equals("tgtyield")) {
                    crop.setYield(Double.parseDouble(value));
                  }
                  if (fline.getParameterNames().get(i).equals("rflatmass")) {
                    // assuming that this crop(residue) value belongs to the last op made. may be dangerous so I am putting this warning.
                    op.setResidueAmount(Double.parseDouble(value) * 8921.79); // kg/m^2 to lbs/acre
                  }
                } else // The value was empty in the weps man
                {
                  value = "";
                }

            }
            crop.addParameter(fline.getParameterNames().get(i), value);
          }
        }
      }
    }
  }

  private String peakLine() throws IOException {
    String line;
    long start;

    start = raf.getFilePointer();
    line = raf.readLine();
    raf.seek(start);

    return line;
  }

  public int getRotationYears() throws ParserException {
    if (currentType != ParseTypes.START) {
      throw new ParserException("Cannot get rotation years from type: " + currentType.toString());
    }
    return rotationYears;
  }

  public LocalDate getDate() throws ParserException {
    if (currentType != ParseTypes.DATE) {
      throw new ParserException("Cannot get date from type: " + currentType.toString());
    }
    return date;
  }

  public WEPSOperation getOperation() throws ParserException {
    if (currentType != ParseTypes.OPERATION) {
      throw new ParserException("Cannot get operation from type: " + currentType.toString());
    }
    return op;
  }

  public WEPSCrop getCrop() throws ParserException {
    if (currentType != ParseTypes.CROP) {
      throw new ParserException("Cannot get crop from type: " + currentType.toString());
    }
    return crop;
  }

  public WEPSAction getAction() throws ParserException {
    if (currentType != ParseTypes.ACTION) {
      throw new ParserException("Cannot get action from type: " + currentType.toString());
    }
    return action;
  }

}