/**
   * Converts all model blocks of the given subsystem.
   *
   * @param subSys sub system which model references should be converted
   * @param builder builder to use
   */
  protected void convertDeltaModelBlocks(String subSys, DeltaMontiArcModelBuilder builder) {
    String[] modelReferences = getModelReference(subSys);
    for (String modelRef : modelReferences) {
      DeltaOperation op = getDeltaOperationForElement(modelRef);
      String simpleName = matlab.doGetSimpleNameLimiterBased(modelRef);
      switch (op) {
        case ADD:
          builder.printOperation(op);
          String type = getModelType(modelRef);
          // type = MontiArcStringBuilder.EXPORT_PACKAGE + "." + type.trim();
          builder.createComponentReference(type, simpleName);

          break;
        case REPLACE:
          int withIndex = simpleName.indexOf(DeltaSimulinkKeyWords.REPLACE_WITH);
          if (!simpleName.startsWith(DeltaSimulinkKeyWords.REPLACE) || withIndex == -1) {
            handler.addError("Unable to parse replace statement!", simpleName);
          } else {

            String toReplace =
                simpleName.substring(DeltaSimulinkKeyWords.REPLACE.length(), withIndex);
            String with =
                simpleName.substring(withIndex + DeltaSimulinkKeyWords.REPLACE_WITH.length());
            // with = MontiArcStringBuilder.EXPORT_PACKAGE + "." + with.trim();
            builder.createReplaceStatement(toReplace, with);
          }
          break;
        default:
          break;
      }
    }
  }
  /**
   * @param subSys
   * @param builder
   */
  protected void convertDeltaConnectors(String subSys, DeltaMontiArcModelBuilder builder) {
    List<SimulinkSignal> signals = getSignals(subSys);
    for (SimulinkSignal signal : signals) {

      DeltaOperation sourceOp = getDeltaOperationForElement(signal.getQualifiedSrcName());
      DeltaOperation targetOp = getDeltaOperationForElement(signal.getQualifiedDstName());
      DeltaOperation conOp = getConnectorOperation(sourceOp, targetOp, signal);

      String srcBlockName =
          convertConnectorElement(signal.getSrcSimpleName(), signal.getSrcPortName());
      String targetBlockName =
          convertConnectorElement(signal.getDstSimpleName(), signal.getDstPortName());

      switch (conOp) {
        case ADD:
          builder.createConnector(srcBlockName, targetBlockName);
          break;
        case REMOVE:
          builder.createDisconnect(srcBlockName, targetBlockName);
          break;
        default:
          break;
      }
    }
  }
  /** @param deltaModelName */
  protected void convertDeltaSubSystems(String deltaModelName, DeltaMontiArcModelBuilder builder) {
    List<String> subSystems = loadSubSystems(deltaModelName);

    for (String subSys : subSystems) {
      DeltaOperation op = getDeltaOperationForElement(subSys);
      String simpleName = matlab.doGetSimpleNameLimiterBased(subSys);

      // modify block
      if (op == DeltaOperation.MODIFY) {
        modifySubSystemBlock(builder, subSys, simpleName);
      }
      // add subsystem block
      else if (op == DeltaOperation.ADD) {
        builder.printOperation(op);
        convertSubSystemsAndRoot(subSys, builder, true);
      }
      // replace subsystem block
      else if (op == DeltaOperation.REPLACE) {
        int withIndex = simpleName.indexOf(DeltaSimulinkKeyWords.REPLACE_WITH);
        if (!simpleName.startsWith(DeltaSimulinkKeyWords.REPLACE) || withIndex == -1) {
          handler.addError("Unable to parse replace statement!", simpleName);
        } else {
          String toReplace =
              simpleName.substring(DeltaSimulinkKeyWords.REPLACE.length(), withIndex);

          String newName = matlab.doGetSimpleNameLimiterBased(subSys);

          newName =
              newName.substring(
                  newName.indexOf(DeltaSimulinkKeyWords.REPLACE_WITH)
                      + DeltaSimulinkKeyWords.REPLACE_WITH.length());
          newName = newName.trim();

          StringBuffer typeName = new StringBuffer();
          String sep = "";
          for (String part : currentComponentName) {
            typeName.append(sep);
            sep = ".";
            typeName.append(part);
          }
          typeName.append(sep);
          typeName.append(newName);

          // remove old component definition
          builder.addSingleLineComment("replace subsystem " + toReplace);

          builder.printOperation(DeltaOperation.ADD);
          convertSubSystemsAndRoot(subSys, builder, false);
          builder.createReplaceStatement(toReplace, typeName.toString() + " " + newName);
        }
      }
    }
  }
  protected void convertDeltaRemovePorts(String subSys, DeltaMontiArcModelBuilder builder) {
    List<SimulinkPort> inPorts = loadPorts(subSys, true);
    List<SimulinkPort> outPorts = loadPorts(subSys, false);

    List<SimulinkPort> inPortsToRemove = new ArrayList<SimulinkPort>();
    List<SimulinkPort> outPortsToRemove = new ArrayList<SimulinkPort>();

    for (SimulinkPort in : inPorts) {
      DeltaOperation op = getDeltaOperationForElement(in.getQualifiedName());
      switch (op) {
        case REMOVE:
          inPortsToRemove.add(in);
          break;
        default:
          break;
      }
    }
    for (SimulinkPort out : outPorts) {
      DeltaOperation op = getDeltaOperationForElement(out.getQualifiedName());
      switch (op) {
        case REMOVE:
          outPortsToRemove.add(out);
          break;
        default:
          break;
      }
    }
    builder.createPorts(DeltaOperation.REMOVE, inPortsToRemove, outPortsToRemove);
  }
  public String convertDeltaModel(String path, String deltaModelName) {
    if (matlab.isDisconnected()) {
      matlab.connect();
    }
    DeltaMontiArcModelBuilder builder = new DeltaMontiArcModelBuilder();
    matlab.loadModel(path, deltaModelName);

    // create delta head
    String aoc = getApplicationOrderCondition(deltaModelName);
    builder.startCreateDelta(deltaModelName, aoc);

    // create modify blocks at top lvl
    convertDeltaSubSystems(deltaModelName, builder);
    builder.closeBody();

    return builder.getConvertedModel();
  }
  /** @param deltaModelName */
  protected void convertDeltaRemoveSubSystems(
      String deltaModelName, DeltaMontiArcModelBuilder builder) {
    List<String> subSystems = loadSubSystems(deltaModelName);

    for (String subSys : subSystems) {
      DeltaOperation op = getDeltaOperationForElement(subSys);
      String simpleName = matlab.doGetSimpleNameLimiterBased(subSys);
      if (op == DeltaOperation.REMOVE) {
        builder.createRemoveStatement("component", simpleName);
      }
    }
  }
 /**
  * Converts all model blocks of the given subsystem.
  *
  * @param subSys sub system which model references should be converted
  * @param builder builder to use
  */
 protected void convertDeltaRemoveModelBlocks(String subSys, DeltaMontiArcModelBuilder builder) {
   String[] modelReferences = getModelReference(subSys);
   for (String modelRef : modelReferences) {
     DeltaOperation op = getDeltaOperationForElement(modelRef);
     String simpleName = matlab.doGetSimpleNameLimiterBased(modelRef);
     switch (op) {
       case REMOVE:
         builder.createRemoveStatement("component", simpleName);
         break;
       default:
         break;
     }
   }
 }
  /**
   * Creates a modify subsystem block
   *
   * @param builder builder to use
   * @param subSys qualified subsystem name
   * @param simpleName simple name
   */
  protected void modifySubSystemBlock(
      DeltaMontiArcModelBuilder builder, String subSys, String simpleName) {
    String toModify = simpleName;
    int index = toModify.indexOf(DeltaSimulinkKeyWords.AOC);
    if (index != -1) {
      toModify = toModify.substring(0, index);
    }
    if (toModify.startsWith(DeltaSimulinkKeyWords.MODIFY_MODEL)) {
      toModify = toModify.substring(DeltaSimulinkKeyWords.MODIFY_MODEL.length()).trim();
      // add package for models
      toModify = MontiArcStringBuilder.EXPORT_PACKAGE + "." + toModify.trim();
    } else if (toModify.startsWith(DeltaSimulinkKeyWords.MODIFY)) {
      toModify = toModify.substring(DeltaSimulinkKeyWords.MODIFY.length()).trim();
    } else {
      handler.addError("Unable to parse modify statement!", subSys);
      return;
    }
    currentComponentName.push(toModify);
    builder.startCreateModifyComponent(toModify);

    convertDeltaAddPorts(subSys, builder);

    convertDeltaSubSystems(subSys, builder);

    convertDeltaModelBlocks(subSys, builder);

    convertDeltaConnectors(subSys, builder);

    convertDeltaRemovePorts(subSys, builder);

    convertDeltaRemoveSubSystems(subSys, builder);

    convertDeltaRemoveModelBlocks(subSys, builder);

    builder.closeBody();
    currentComponentName.pop();
  }