Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Batch export of block parameters #136

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
3 changes: 2 additions & 1 deletion Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ pipeline {
steps {
configFileProvider([configFile(fileId: 'default-maven-toolchains', variable: 'TOOLCHAIN'), configFile(fileId: 'default-maven-settings', variable: 'MAVEN_SETTINGS')]) {
sh "mvn clean install -B -t $TOOLCHAIN -s $MAVEN_SETTINGS -f releng/hu.bme.mit.massif.parent/pom.xml -Dmaven.repo.local=$WORKSPACE/.repository"
sh "mvn clean deploy -B -t $TOOLCHAIN -s $MAVEN_SETTINGS -f releng/hu.bme.mit.massif.parent/pom.xml -Dmaven.repo.local=$WORKSPACE/.repository"
// Do not deploy from this branch, only from master
//sh "mvn clean deploy -B -t $TOOLCHAIN -s $MAVEN_SETTINGS -f releng/hu.bme.mit.massif.parent/pom.xml -Dmaven.repo.local=$WORKSPACE/.repository"
}
sh './releng/massif.commandevaluation.server-package/prepareMatlabServerPackage.sh'
sh './releng/hu.bme.mit.massif.simulink.cli-package/prepareCLIPackage.sh'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
% Detailed explanation goes here

massif.library_collector=@library_collector;
massif.get_all_block_parameters=@get_all_block_parameters;
massif.get_all_parameters=@get_all_parameters;

end

Expand Down Expand Up @@ -72,18 +72,18 @@
libraryNames = libraryNames(2:length(libraryNames));
end

function s = get_all_block_parameters(blockId)
%get_all_block_parameters Gathers all block parameters to a struct
function s = get_all_parameters(id)
%get_all_parameters Gathers all parameters to a struct
% The following block parameters are skipped because of connector limitations:
% * Capabilities
% * MaskObject

s=struct();
TmpObjParams=get_param(blockId,'ObjectParameters');
TmpObjParams=get_param(id,'ObjectParameters');
names=fieldnames(TmpObjParams);
for i = 1:numel(names)
if strcmpi(names{i},'Capabilities') == 0 && strcmpi(names{i},'MaskObject') == 0
TmpParamValue=get_param(blockId,names{i});
TmpParamValue=get_param(id,names{i});
isReadOnly = sum(strcmp(TmpObjParams.(names{i}).Attributes,'read-only'));
isNeverSave = sum(strcmp(TmpObjParams.(names{i}).Attributes,'never-save'));
if (isReadOnly + isNeverSave) > 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,14 @@
package hu.bme.mit.massif.simulink.api;

import java.io.File;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;

import org.eclipse.core.internal.resources.ProjectPathVariableManager;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
Expand All @@ -45,7 +43,6 @@
import hu.bme.mit.massif.communication.datatype.IVisitableMatlabData;
import hu.bme.mit.massif.communication.datatype.MatlabString;
import hu.bme.mit.massif.communication.datatype.StructMatlabData;
import hu.bme.mit.massif.communication.datavisitor.IMatlabDataVisitor;
import hu.bme.mit.massif.simulink.Block;
import hu.bme.mit.massif.simulink.BusCreator;
import hu.bme.mit.massif.simulink.BusSelector;
Expand Down Expand Up @@ -203,6 +200,7 @@ public void saveSimulinkModel(String modelNameWithPath, String fileExtension) th

// Save the current directory
String currentWorkdirectory = MatlabString.getMatlabStringData(commandFactory.cd().execute());

String separator = FileSystems.getDefault().getSeparator();
String[] savePathSegments;
if(separator.equals("\\")){
Expand All @@ -224,10 +222,10 @@ public void saveSimulinkModel(String modelNameWithPath, String fileExtension) th
saveSystem.execute();

// Navigate back to the original working directory
String[] workDirSegments = currentWorkdirectory.split("\\\\");
String[] workDirSegments = currentWorkdirectory.split(File.separator);
for (int i = 0; i < workDirSegments.length; i++) {
String segment = workDirSegments[i];
MatlabCommand changeToWorkDir = commandFactory.cd().addParam(segment + "\\");
MatlabCommand changeToWorkDir = commandFactory.cd().addParam(segment + File.separator);
changeToWorkDir.execute();
}

Expand Down Expand Up @@ -504,12 +502,15 @@ private void exportBlocks(EList<Block> sameLevelBlocks) throws SimulinkApiExcept
// Block type specific processing part END
// //////////////////////////////////////////////////////////

// Set block dialog/mask parameters
// Set block parameters
EList<Parameter> parameters = block.getParameters();
boolean isMaskOn = false;
StringJoiner joiner = new StringJoiner(";");
for (Parameter parameter : parameters) {
if(parameter.getName().equals("Mask")) {
isMaskOn = parameter.getValue().equals("on");
// Ensure that the mask is turned on first
joiner.add(prepareParameterSetterCommand(block, parameter));
}
}
for (Parameter parameter : parameters) {
Expand All @@ -519,11 +520,11 @@ private void exportBlocks(EList<Block> sameLevelBlocks) throws SimulinkApiExcept
// Explanation: if the mask is off, mask parameters should be ignored
if(!parameter.isReadOnly() && (isMaskOn || !parameter.getName().startsWith("Mask"))) {
String commandString = prepareParameterSetterCommand(block, parameter);
ICommandEvaluator commandEvaluator = commandFactory.getCommandEvaluator();
commandEvaluator.evaluateCommand(commandString, 0);
joiner.add(commandString);
}
// TODO compile command string into a single command - see issue #120
}
ICommandEvaluator commandEvaluator = commandFactory.getCommandEvaluator();
commandEvaluator.evaluateCommand(joiner.toString(), 0);
}

// When there is at least one block on the same level, check that only blocks are there on the same level will be present in the exported model
Expand Down Expand Up @@ -558,30 +559,33 @@ private void exportBlocks(EList<Block> sameLevelBlocks) throws SimulinkApiExcept

private String prepareParameterSetterCommand(Block block, Parameter parameter) {
String commandString = generateSetParamCommandStub(block, parameter);
if("char".equals(parameter.getType())) {
commandString= commandString.concat("'" + parameter.getValue() + "'");
// @formatter\:off
// A problematic case: empty string as parameter value
// We don't know what the type was originally, so we use try-catch to retry with a different type
if (parameter.getValue().equals("")) {
commandString = "try " + commandString + "); " +
"catch " +
"try " + commandString.replaceFirst("''", "") + "cell.empty()); " +
"catch " +
"try " + commandString.replaceFirst("''", "") + "[]); " +
"catch " +
// TODO add proper logging here
"fprintf('Failed to set parameter " + parameter.getName() + "'); " +
"end; " +
"end; " +
"end";
// @formatter\:off
// A problematic case: empty string as parameter value
// We don't know what the type was originally, so we use try-catch to retry with a different type
if (parameter.getValue().equals("")) {
commandString = "try " + commandString + "''); " +
"catch " +
"try " + commandString.replaceFirst("''", "") + "cell.empty()); " +
"catch " +
"try " + commandString.replaceFirst("''", "") + "[]); " +
"catch " +
// TODO add proper logging to catch here
"fprintf('Failed to set parameter " + parameter.getName() + "'); " +
"end; " +
"end; " +
"end";
}
// @formatter\:on
else {
if("char".equals(parameter.getType())) {
commandString= commandString.concat("'" + parameter.getValue() + "'");
} else {
commandString = "try " + commandString + "); catch "+ "fprintf('Failed to set parameter " + parameter.getName() + "'); end ";
commandString = commandString.concat(parameter.getValue());
}
// @formatter\:off
// TODO add proper logging to catch here
commandString = "try " + commandString + "); catch "+ "fprintf('Failed to set parameter " + parameter.getName() + "'); end ";
// @formatter\:on
} else {
commandString = commandString.concat(parameter.getValue());
commandString = commandString.concat(")");
}
return commandString;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ public class Importer {
// TODO maps for caching EMF objects now could also be stored in a map for <IVisistableData,Block>
// TODO maps using Doubles should be replaced

private Map<String, Handle> blockHandleCache;
/**
* Block cache for easier EMF model creation
*/
Expand Down Expand Up @@ -268,6 +269,13 @@ public Map<InPortBlock, MatlabString> getShadowInports() {
return shadowInports;
}

/**
* @return a cache that contains the block FQN - handle mappings
*/
public Map<String, Handle> getBlockHandleCache() {
return blockHandleCache;
}

/* Caches end */

/* Constants */
Expand Down Expand Up @@ -433,6 +441,7 @@ public Importer(ModelObject model, ISimulinkAPILogger logger) {
this.logger = logger;
referencedLibraries = new HashMap<String, SimulinkModel>();
librariesBeingImported = new HashSet<String>();
blockHandleCache = new HashMap<String, Handle>();

referencesFolderName = model.getFullyQualifiedName();

Expand Down Expand Up @@ -794,12 +803,15 @@ private void createBlocksFromTopLevel(SimulinkModel simulinkModel) throws Simuli

// Get the handle of the model itself
MatlabCommand getModelHandle = commandFactory.getParam().addParam(modelFQN).addParam("Handle");
Double modelHandle = Handle.getHandleData(getModelHandle.execute());
IVisitableMatlabData modelHandle = getModelHandle.execute();
Double modelHandleValue = Handle.getHandleData(modelHandle);

blockHandleCache.put(modelFQN, (Handle) modelHandle);

// Traversing from each block
for (IVisitableMatlabData currentBlockHandle : CellMatlabData.getCellMatlabDataData(toplevelBlockHandles)) {
// If the handle refers to the subsystem block we are traversing, continue
if (Handle.getHandleData(currentBlockHandle) == modelHandle)
if (Handle.getHandleData(currentBlockHandle) == modelHandleValue)
continue;
createBlock(simulinkModel, (Handle) currentBlockHandle);
}
Expand Down Expand Up @@ -865,6 +877,7 @@ private void createBlock(SimulinkElement parentSimulinkElement, Handle currentBl
// Escape the character '/' in the name. It is needed in order to differentiate hierarchy level changes and
// slashes in names
blockName = blockName.replace("/", "//");
blockHandleCache.put(parentSimulinkElement.getSimulinkRef().getFQN() + '/' + blockName, currentBlockHandle);

// Create the block instance
Block block = createBlockInstance(blockType, blockName, parentSimulinkElement.getSimulinkRef());
Expand Down Expand Up @@ -1187,12 +1200,12 @@ private void createAndAddPort(Block parent, PortProvider portProvider, Handle po
Port port;
// State is a special outport kind
if ("outport".equalsIgnoreCase(portType) || "state".equalsIgnoreCase(portType)) {
port = portAdapter.createPort(parent, portHandle, outPorts);
port = portAdapter.createPort(this, parent, portHandle, outPorts);
createAndSetSimulinkRef("outport." + portNumber.toString(), parent.getSimulinkRef(), port);
cachedOutPortHandles.put((OutPort) port, Handle.getHandleData(portHandle));
} else {
// The case for Inport, Trigger, Enable, Ifact
port = portAdapter.createPort(parent, portHandle, inPorts);
port = portAdapter.createPort(this, parent, portHandle, inPorts);
createAndSetSimulinkRef("inport." + portNumber.toString(), parent.getSimulinkRef(), port);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*******************************************************************************
* Copyright (c) 2010-2018, IncQuery Labs Ltd., logi.cals GmbH, McGill University
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Marton Bur - initial API and implementation
*******************************************************************************/
package hu.bme.mit.massif.simulink.api.adapter;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import hu.bme.mit.massif.communication.command.MatlabCommand;
import hu.bme.mit.massif.communication.command.MatlabCommandFactory;
import hu.bme.mit.massif.communication.datatype.CellMatlabData;
import hu.bme.mit.massif.communication.datatype.Handle;
import hu.bme.mit.massif.communication.datatype.IVisitableMatlabData;
import hu.bme.mit.massif.communication.datatype.MatlabString;
import hu.bme.mit.massif.communication.datatype.StructMatlabData;
import hu.bme.mit.massif.simulink.Parameter;
import hu.bme.mit.massif.simulink.SimulinkFactory;
import hu.bme.mit.massif.simulink.api.Importer;
import hu.bme.mit.massif.simulink.api.extension.IParameterImportFilter;

public class ParameterHelper {

public static List<Parameter> collectParameters(Importer traverser, MatlabCommandFactory commandFactory, Handle objectHandle) {
List<Parameter> blockProperties = new LinkedList<Parameter>();

MatlabCommand getAllBlockParameters = commandFactory.customCommand("massif.get_all_parameters", 1).addParam(objectHandle);
Map<String, IVisitableMatlabData> blockPropsMap = StructMatlabData.getStructMatlabDataData(getAllBlockParameters.execute());

Set<IParameterImportFilter> parameterFilters = traverser.getParameterFilters();

Set<Entry<String, IVisitableMatlabData>> entries = blockPropsMap.entrySet();
for (Entry<String, IVisitableMatlabData> entry : entries) {
String propertyName = entry.getKey();

boolean isFiltered = false;
for (IParameterImportFilter paramFilter : parameterFilters) {
isFiltered |= paramFilter.filter(commandFactory, propertyName);
}

if (isFiltered) {
continue;
}

IVisitableMatlabData value = entry.getValue();
Parameter prop = SimulinkFactory.eINSTANCE.createParameter();
if (propertyName.matches(".*READONLY$")) {
propertyName = propertyName.replace("_READONLY", "");
prop.setReadOnly(true);
}
prop.setName(propertyName);

if (value == null) {
// Default: empty string
prop.setType("char");
prop.setValue("");
blockProperties.add(prop);
} else {
if (value instanceof MatlabString) {
prop.setType("char");
prop.setValue(value.toString().replaceFirst("'", "").replaceAll("'$", ""));
} else if (value instanceof Handle) {
prop.setType("handle");
prop.setValue(value.toString());
} else if (value instanceof CellMatlabData) {
prop.setType("cell");
prop.setValue(value.toString());
} else if (value instanceof StructMatlabData) {
prop.setType("struct");
prop.setValue(value.toString());
}
blockProperties.add(prop);
}
}
return blockProperties;
}

}
Loading