private ArrayList<String> addToBill(ArrayList<String> finalBill, RMResult result) {
    ArrayList<String> tempBill = new ArrayList<>(Arrays.asList(result.AsString().split("\n")));

    if (finalBill.size() == 0) {
      finalBill.add(0, tempBill.get(0));
    }

    tempBill.remove(0);
    tempBill.remove(tempBill.size() - 1);
    finalBill.addAll(tempBill);

    return finalBill;
  }
  private RMResult processAtomicCustomerRequest(String requestString) {
    // Process the given request by first checking that the given customer
    // exists, and if yes creating it at the relevant RM as necessary.

    Integer cid = getCustomerId(requestString);
    RMResult existenceCheck =
        processAtomicRequest(Command.SERVER_CHECK_CUSTOMER_EXISTS + ",1," + cid);
    if (existenceCheck.IsError()) {
      return existenceCheck;
    }

    if (!existenceCheck.AsBool()) {
      RMResult failure = new RMResult(new Exception("Customer " + cid + " does not exist."));
      return failure;
    }

    // Create the customer on the given RM (no side-effects if customer already exists.
    int rmId = getRMIndexForRequest(requestString);
    processAtomicRequest("newcustomerid,1," + cid, _rmIps[rmId], _rmPorts[rmId]);

    // Actually execute the request
    return processAtomicRequest(requestString, _rmIps[rmId], _rmPorts[rmId]);
  }
  private RMResult processIfComposite(String requestString) {
    // Execute a composite method for this request if necessary.
    // Returns a result, or null if the request corresponds to
    // no composite action.
    RMResult result = null;
    String[] parts = requestString.split(",");

    switch (parts[0]) {
      case Command.INTERFACE_DELETE_CUSTOMER:
        {
          for (int i = 0; i < 4; ++i) {
            result = processAtomicRequest(requestString, _rmIps[i], _rmPorts[i]);
          }
        }
        break;
      case Command.INTERFACE_RESERVE_ITINERARY:
        {
          // requestString = "command, id, cid, flight1, ..., flightn, location, isCarDesired,
          // isRoomDesired"
          ArrayList<String> flightNumbers =
              new ArrayList<>(Arrays.asList(requestString.split(",")));
          flightNumbers.remove(0);
          String id = flightNumbers.remove(0).trim();
          String customerId = flightNumbers.remove(0).trim();
          boolean isRoomDesired =
              Boolean.parseBoolean(flightNumbers.remove(flightNumbers.size() - 1).trim());
          boolean isCarDesired =
              Boolean.parseBoolean(flightNumbers.remove(flightNumbers.size() - 1).trim());
          String location = flightNumbers.remove(flightNumbers.size() - 1).trim();

          for (String flightNumber : flightNumbers) {
            result =
                processAtomicRequest(
                    Command.INTERFACE_QUERY_FLIGHT + ", " + id + ", " + flightNumber.trim(),
                    _rmIps[0],
                    _rmPorts[0]);
            if (result.AsInt() <= 0) {
              return new RMResult(false);
            }
          }

          if (isCarDesired) {
            result =
                processAtomicRequest(
                    Command.INTERFACE_QUERY_CARS + ", " + id + ", " + location,
                    _rmIps[1],
                    _rmPorts[1]);
            if (result.AsInt() <= 0) {
              return new RMResult(false);
            }
          }

          if (isRoomDesired) {
            result =
                processAtomicRequest(
                    Command.INTERFACE_QUERY_ROOMS + ", " + id + ", " + location,
                    _rmIps[2],
                    _rmPorts[2]);
            if (result.AsInt() <= 0) {
              return new RMResult(false);
            }
          }

          for (String flightNumber : flightNumbers) {
            String command =
                Command.INTERFACE_RESERVE_FLIGHT
                    + ", "
                    + id
                    + ", "
                    + customerId
                    + ", "
                    + flightNumber.trim();
            result = processIfCIDRequired(command);
            if (!result.AsBool()) {
              return result;
            }
          }

          if (isCarDesired) {
            String command =
                Command.INTERFACE_RESERVE_CAR + ", " + id + ", " + customerId + ", " + location;
            result = processIfCIDRequired(command);
            if (!result.AsBool()) {
              return result;
            }
          }

          if (isRoomDesired) {
            String command =
                Command.INTERFACE_RESERVE_ROOM + ", " + id + ", " + customerId + ", " + location;
            result = processIfCIDRequired(command);
            if (!result.AsBool()) {
              return result;
            }
          }
        }
        break;
      case Command.INTERFACE_QUERY_CUSTOMER_INFO:
        {
          ArrayList<String> finalBill = new ArrayList<>();

          // i < 3 to exclude customer rm
          for (int i = 0; i < 3; ++i) {
            result = processAtomicRequest(requestString, _rmIps[i], _rmPorts[i]);
            if (!(result.AsString().equals(""))) {
              finalBill = addToBill(finalBill, result);
            }
          }

          String resultString =
              "Customer either does not exist or has not made any reservation yet.";

          if (finalBill.size() != 0) {
            finalBill = addBillTotal(finalBill);

            finalBill.add(finalBill.size(), "}");

            resultString = String.join("\n", finalBill);
          }

          result = new RMResult(resultString);
        }
        break;
      default:
        break;
    }

    return result;
  }