code: /*
   * PDDLPlan.java
   *
   * Copyright (C) 2020 Vladislav Nikolov Vasilev
   *
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program.  If not, see https://www.gnu.org/licenses/gpl-3.0.html.
   */
  
  /**
   * Package that contains the planning agent along with its data structures.
   */
  package controller;
  
  import kong.unirest.json.JSONArray;
  import kong.unirest.json.JSONObject;
  import ontology.Types;
  
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.stream.Collectors;
  
  /**
   * Class that represents a PDDL plan. A PDDLPlan object is made up of a list of
   * PDDL actions. It also contains an iterator which allows to iterate over each
   * one of the actions of the plan.
   *
   * @author Vladislav Nikolov Vasilev
   */
  public class PDDLPlan implements Iterable<PDDLAction> {
      private List<PDDLAction> PDDLActions;
  
      /**
       * Default class constructor. Creates an object with an empty plan.
       */
      public PDDLPlan() {
          this.PDDLActions = new ArrayList<>();
      }
  
      /**
       * Class constructor. Creates an object with a valid plan.
       *
       * @param plannerResponse      JSONObject that represents the planner's response. It must
       *                             be a valid response (a response that contains a valid plan).
       * @param actionCorrespondence Map that represents the correspondence between PDDL and
       *                             GVGAI actions.
       */
      public PDDLPlan(JSONObject plannerResponse, Map<String, Types.ACTIONS> actionCorrespondence) {
          // Get the plan from the JSON object
          JSONArray plan = plannerResponse.getJSONArray("plan");
  
          // Create a new empty list of actions
          ArrayList<PDDLAction> PDDLActionList = new ArrayList<>();
  
          this.PDDLActions = new ArrayList<>();
  
          // Transform each action to a PDDLAction instance
          for (int i = 0; i < plan.length(); i++) {
              // Get the JSON object that represents an action
              JSONObject action = plan.getJSONObject(i);
  
              // Get Strings that represent the action instance and its preconditions
              String actionInstance = action.getString("name");
              String actionDescription = action.getString("action");
  
              // Add the new action to the list
              PDDLActionList.add(new PDDLAction(actionInstance, actionDescription, actionCorrespondence));
          }
  
          // Process resulting list of actions removing all null actions. These actions are the ones
          // that don't have a correspondence
          this.PDDLActions = PDDLActionList
                  .stream()
                  .filter(PDDLAction -> PDDLAction.getGVGAIAction() != null)
                  .collect(Collectors.toList());
      }
  
      public List<PDDLAction> getPDDLActions() {
          return this.PDDLActions;
      }
  
      /**
       * Method used to clear the plan. It removes all the actions from the plan, leaving an
       * empty plan.
       */
      public void clearPlan() {
          this.PDDLActions.clear();
      }
  
      @Override
      public String toString() {
          StringBuilder builder = new StringBuilder();
  
          builder.append("\n--------------------------------------------------------------------------------\n");
          builder.append("\n------------------------------------  PLAN  ------------------------------------\n");
  
          for (PDDLAction action : this.PDDLActions) {
              builder.append(action.toString());
          }
  
          builder.append("\n\n--------------------------------------------------------------------------------\n");
  
          return builder.toString();
      }
  
      /**
       * Method that returns an iterator which allows to iterate over the plan's actions.
       *
       * @return Returns a new PDDLAction iterator.
       */
      @Override
      public Iterator<PDDLAction> iterator() {
          Iterator<PDDLAction> iterator = new Iterator<PDDLAction>() {
              private int currentIdx = 0;
  
              @Override
              public boolean hasNext() {
                  return currentIdx < PDDLActions.size() && PDDLActions.get(currentIdx) != null;
              }
  
              @Override
              public PDDLAction next() {
                  return PDDLActions.get(currentIdx++);
              }
          };
  
          return iterator;
      }
  }
  