public String convertModel(String path, String modelName) {
    if (matlab.isDisconnected()) {
      matlab.connect();
    }

    MontiArcStringBuilder builder = new MontiArcStringBuilder();

    if (matlab.isConnected()) {
      matlab.loadModel(path, modelName);

      builder.addPackage(MontiArcStringBuilder.EXPORT_PACKAGE);

      builder.startCreateComponent(modelName);

      convertPorts(modelName, builder);

      convertModelReferences(modelName, builder);

      convertSubSystems(modelName, builder);

      convertSignals(modelName, builder);

      builder.endCreateComponent();
    } else {
      // TODO handle
    }

    return builder.getConvertedModel();
  }
  protected DeltaOperation getDeltaOperationForElement(String element) {
    String command = "TEMP_DATA=get_param('DAddPort/modify model ModelToModify','UserData');";
    StringBuilder sb = new StringBuilder("TEMP_DATA=get_param('");
    sb.append(element);
    sb.append("','UserData');");
    command = sb.toString();
    matlab.eval(command);
    Object[] opResult = matlab.reval("TEMP_DATA.opName", 1);

    String operation = "";
    DeltaOperation result;

    if (opResult != null && opResult.length == 1 && opResult[0] instanceof String) {
      operation = (String) opResult[0];
    }

    if (operation.equals("add")) {
      result = DeltaOperation.ADD;
    } else if (operation.equals("remove")) {
      result = DeltaOperation.REMOVE;
    } else if (operation.equals("modify")) {
      result = DeltaOperation.MODIFY;
    } else if (operation.equals("replace")) {
      result = DeltaOperation.REPLACE;
    } else {
      result = DeltaOperation.UNDEFINED;
    }

    return result;
  }
  protected DeltaOperation getConnectorOperation(
      DeltaOperation sourceOp, DeltaOperation targetOp, SimulinkSignal signal) {
    DeltaOperation result = DeltaOperation.UNDEFINED;
    matlab.setvar("TEMP_DOUBLE_VAL", signal.getSrcConnHandle());
    String command =
        "if(exist('TEMP_DOUBLE_VAL','var')) TEMP_VAR=get_param(get_param(TEMP_DOUBLE_VAL,'SrcBlockHandle'),'UserData'); end;";
    matlab.eval(command);
    String command2 =
        "a=''; if(exist('TEMP_VAR','var')) if isKey(TEMP_VAR.lineMap,getfullname(TEMP_DOUBLE_VAL)) a=TEMP_VAR.lineMap(getfullname(TEMP_DOUBLE_VAL)).opName; end; end; a;";
    matlab.eval(command2);
    Object[] opResult = matlab.reval("a", 1);
    // "a=''; if isKey(TEMP_VAR.lineMap,TEMP_DOUBLE_VAL) a=TEMP_VAR.lineMap(TEMP_DOUBLE_VAL).opName;
    // end; a"
    String operation = "";

    if (opResult != null && opResult.length == 1 && opResult[0] instanceof String) {
      operation = (String) opResult[0];
    }

    if (operation.equals("add")) {
      result = DeltaOperation.ADD;
    } else if (operation.equals("remove")) {
      result = DeltaOperation.REMOVE;
    } else if (operation.equals("modify")) {
      result = DeltaOperation.MODIFY;
    } else if (operation.equals("replace")) {
      result = DeltaOperation.REPLACE;
    } else {
      result = DeltaOperation.UNDEFINED;
    }

    return result;
  }
  protected List<SimulinkPort> loadPorts(String rootElement, boolean loadInports) {
    String portType =
        loadInports ? SimulinkBlockType.Inport.toString() : SimulinkBlockType.Outport.toString();

    Object[] loadedPorts =
        matlab.returningFeval(1, find_system, rootElement, SearchDepth, 1, BlockType, portType);

    List<SimulinkPort> qualifiedPorts = new ArrayList<SimulinkPort>();

    if (loadedPorts.length == 1) {
      if (loadedPorts[0] != null) {
        String[] ports = (String[]) loadedPorts[0];
        for (String qp : ports) {
          // get number of port
          int portNumber =
              Integer.valueOf(
                  (String) matlab.returningFeval(get_param, qp, SimulinkParameter.Port));
          SimulinkPort simPort =
              new SimulinkPort(
                  SimulinkNameHelper.getSimpleName(qp),
                  portNumber,
                  SimulinkNameHelper.getQualifierName(qp));

          qualifiedPorts.add(simPort);
        }
      }
    }

    return qualifiedPorts;
  }
  /** @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);
        }
      }
    }
  }
  /**
   * 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;
      }
    }
  }
  protected void convertSubSystemsAndRoot(
      String rootElement, MontiArcStringBuilder builder, boolean instantiate) {
    String simpleName = matlab.doGetSimpleNameLimiterBased(rootElement);

    if (getDeltaOperationForElement(rootElement) == DeltaOperation.REPLACE) {
      simpleName =
          simpleName.substring(
              simpleName.indexOf(DeltaSimulinkKeyWords.REPLACE_WITH)
                  + DeltaSimulinkKeyWords.REPLACE_WITH.length());
    }
    simpleName = simpleName.trim();
    if (instantiate) {
      builder.startCreateInnerComponent(simpleName, simpleName);
    } else {
      builder.startCreateComponent(simpleName);
    }
    convertPorts(rootElement, builder);

    convertSubSystems(rootElement, builder);

    convertModelReferences(rootElement, builder);

    convertSignals(rootElement, builder);

    builder.endCreateInnerComponent();
  }
  protected String getSimpleName(String qualifiedName) {
    // The name is of the type like "(./)*elementName". If it is always like this,
    // it should be ok just to take the string "elementName" to get the searched name.
    // This should be checked. Until then, the slower way to get the element name
    // directly from Matlab is used.

    return (String) matlab.returningFeval("get_param", qualifiedName, "Name");
  }
  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;
     }
   }
 }
  /**
   * @param blockName
   * @return subsystems of the given block
   */
  protected String[] getSubSystems(String blockName) {
    String[] loadedSubSystems =
        (String[])
            matlab.returningFeval(
                "find_system",
                blockName,
                "SearchDepth",
                1,
                "BlockType",
                SimulinkBlockType.SubSystem.toString());
    if (loadedSubSystems == null) {
      loadedSubSystems = new String[] {};
    }

    return loadedSubSystems;
  }
 protected String[] getModelReference(String blockName) {
   String[] result;
   Object[] loadedSubSystems =
       matlab.returningFeval(
           1,
           "find_system",
           blockName,
           "SearchDepth",
           1,
           "BlockType",
           SimulinkBlockType.ModelReference.toString());
   if (loadedSubSystems.length == 1) {
     result = (String[]) loadedSubSystems[0];
   } else {
     result = new String[] {};
   }
   return result;
 }
 protected List<String> loadSubSystems(String blockName) {
   List<String> result = new ArrayList<String>();
   Object loadedSubSystems =
       matlab.returningFeval(
           "find_system",
           blockName,
           "SearchDepth",
           1,
           "BlockType",
           SimulinkBlockType.SubSystem.toString());
   if (loadedSubSystems != null) {
     for (String ss : (String[]) loadedSubSystems) {
       if (!ss.equals(blockName)) {
         result.add(ss);
       }
     }
   }
   return result;
 }
  protected void convertModelReferences(String modelName, MontiArcStringBuilder builder) {
    String[] qualifiedModelReferences =
        (String[])
            matlab.returningFeval(
                "find_system",
                modelName,
                "SearchDepth",
                1,
                "BlockType",
                SimulinkBlockType.ModelReference.toString());

    if (qualifiedModelReferences != null) {
      for (int i = 0; i < qualifiedModelReferences.length; i++) {
        String qualifiedModelReference = qualifiedModelReferences[i];
        String unqualifiedModelReference = getSimpleName(qualifiedModelReference);
        String typeOfReferencedModel = getModelType(qualifiedModelReference);

        builder.createComponentReference(typeOfReferencedModel, unqualifiedModelReference);
      }
    }
  }
 /**
  * @param qualifiedModelReference qualified name of the model reference
  * @return the type name of the given model reference
  */
 protected String getModelType(String qualifiedModelReference) {
   return (String) matlab.returningFeval("get_param", qualifiedModelReference, "ModelName");
 }
  protected List<SimulinkSignal> getSignals(String rootName) {
    List<SimulinkSignal> signals = new ArrayList<SimulinkSignal>();

    // find all (top-level) connectors in the model or block
    Object[] foundConnectors =
        matlab.returningFeval(
            1, find_system, rootName, SearchDepth, 1, FindAll, "on", LineType, SimulinkType.signal);

    if ((foundConnectors != null) && (foundConnectors.length == 1)) {
      // handles (ids) of the connectors
      double[] connHandles = (double[]) foundConnectors[0];

      for (int i = 0; i < connHandles.length; i++) {
        double connHandle = connHandles[i];
        double srcConnHandle = connHandle;

        double[] lineChildren =
            ((double[]) (matlab.returningFeval(1, get_param, connHandle, "LineChildren"))[0]);

        // Signals with children are not handled (directly). This is the case when a
        // block has more than one outgoing signal.
        if (lineChildren.length > 0) {
          continue;
        }

        double lineParent =
            ((double[]) (matlab.returningFeval(1, get_param, connHandle, "LineParent"))[0])[0];

        // If lineParent has another value than -1.0 the source block has more than one outgoing
        // signal.
        // The id of the source block can now only be get by the root line parent...
        if (lineParent != -1.0) {
          // ...Started by the source block every signal fork creates line children for the current
          // signal.
          // These children can also have children of their own (if they have a fork).
          // So to get the source block we need to get the source block of the root line parent.
          double rootLineParent = lineParent;
          do {
            srcConnHandle = rootLineParent;
            rootLineParent =
                ((double[]) (matlab.returningFeval(1, get_param, rootLineParent, "LineParent"))[0])
                    [0];
          } while (rootLineParent != -1.0);
        }

        String srcBlockName = (String) matlab.returningFeval(get_param, srcConnHandle, SrcBlock);
        String srcQualifiedBlockName = rootName + "/" + srcBlockName;
        String srcBlockType =
            (String) matlab.returningFeval(get_param, srcQualifiedBlockName, BlockType);
        String srcPortNumber = (String) matlab.returningFeval(get_param, srcConnHandle, SrcPort);

        String dstBlockName = (String) matlab.returningFeval(get_param, connHandle, DstBlock);
        String dstQualifiedBlockName = rootName + "/" + dstBlockName;
        String dstBlockType =
            (String) matlab.returningFeval(get_param, dstQualifiedBlockName, BlockType);
        String dstPortNumber = (String) matlab.returningFeval(get_param, connHandle, DstPort);

        SimulinkSignal signal =
            new SimulinkSignal(
                srcQualifiedBlockName,
                Integer.valueOf(srcPortNumber),
                dstQualifiedBlockName,
                Integer.valueOf(dstPortNumber),
                srcConnHandle);

        // ====== Handle Source ======= //

        if (srcBlockType.equals(SubSystem.toString())) {
          // src block is a sub system
          String srcPortName = getPortNameByNumber(srcQualifiedBlockName, srcPortNumber, false);
          signal.setSrcPortName(srcPortName);
        } else if (srcBlockType.equals(ModelReference.toString())) {
          // src block is a model reference
          String referencedModelName =
              (String) matlab.returningFeval(get_param, srcQualifiedBlockName, ModelName);
          matlab.loadModel(referencedModelName);

          String srcPortName = getPortNameByNumber(referencedModelName, srcPortNumber, false);
          signal.setSrcPortName(srcPortName);
        }

        // ====== Handle Destination ======= //

        if (dstBlockType.equals(SubSystem.toString())) {
          // dst block is a sub system
          String dstPortName = getPortNameByNumber(dstQualifiedBlockName, dstPortNumber, true);
          signal.setDstPortName(dstPortName);
        } else if (dstBlockType.equals(ModelReference.toString())) {
          // dst block is a model reference
          String referencedModelName =
              (String) matlab.returningFeval(get_param, dstQualifiedBlockName, ModelName);
          matlab.loadModel(referencedModelName);

          String dstPortName = getPortNameByNumber(referencedModelName, dstPortNumber, true);
          signal.setDstPortName(dstPortName);
        }

        signals.add(signal);
      }
    }

    return signals;
  }