blob: c58524f21a259a919a197f52b130bb4bd2de2e8b [file] [log] [blame]
package org.eclipse.epsilon.emc.simulink.model.element;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import org.eclipse.epsilon.emc.simulink.engine.MatlabEngine;
import org.eclipse.epsilon.emc.simulink.engine.MatlabException;
import org.eclipse.epsilon.emc.simulink.model.SimulinkModel;
import org.eclipse.epsilon.emc.simulink.util.SimulinkUtil;
import org.eclipse.epsilon.emc.simulink.util.StateflowUtil;
import org.eclipse.epsilon.eol.exceptions.EolIllegalPropertyException;
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
public class StateflowBlock extends SimulinkModelElement {
/** CONSTANTS */
//public static final String STATEFLOW_LIB = "sflib/";
private static final String SIMPLE_TYPE = "?.classhandle.get('Name');";
private static final String DELETE_SF = "?.delete;";
/** FIELDS */
private Double id;
private HashMap<String, Object> properties = new HashMap<String, Object>();
/** CONSTRUCTORS */
// From StateflowBlock Parent
public StateflowBlock(SimulinkModel model, MatlabEngine engine, String type, StateflowBlock parent) throws MatlabException, EolRuntimeException {
super(model, engine);
setType(type);
buildFromStateflow(parent);
}
/** PARENT-LESS CONSTRUCTORS */
public StateflowBlock(SimulinkModel model, MatlabEngine engine, String type) throws MatlabException {
super(model, engine);
setType(type);
}
/** FROM ID */
// From known StateflowBlock Id
public StateflowBlock(SimulinkModel model, MatlabEngine engine, Double stateflowId) throws MatlabException {
super(model, engine);
this.id = stateflowId;
setType();
}
// From known StateflowBlock Id as Integer
public StateflowBlock(SimulinkModel model, MatlabEngine engine, Integer stateflowId) throws MatlabException {
this(model, engine, stateflowId.doubleValue());
}
// From known StateflowBlock Id
public StateflowBlock(SimulinkModel model, MatlabEngine engine, String type, Double stateflowId) throws MatlabException {
super(model, engine);
this.id = stateflowId;
setType();
}
// From known StateflowBlock Id as Integer
public StateflowBlock(SimulinkModel model, MatlabEngine engine, String type, Integer stateflowId) throws MatlabException {
this(model, engine, type, stateflowId.doubleValue());
}
/** TYPE */
private void setType(String type) throws MatlabException {
if (type != null && type.startsWith(SimulinkModel.STATEFLOW)) {
this.type = type;
} else {
setType();
}
}
private void setType() throws MatlabException {
if (this.id != null) {
String handle = StateflowUtil.getBlockHandleFromId(model, engine, this.id);
this.type = SimulinkModel.STATEFLOW + "." + (String) engine.evalWithResult(SIMPLE_TYPE, handle);
}
}
@Override
public String getType() { // RETURNS E.G. "STATE"
return this.type;
}
/** PROPERTIES **/
private boolean isUnset() {
return id == null;
}
@Override
public Object getProperty(String property) throws EolIllegalPropertyException{
if (isUnset()) {
return properties.get(property.toLowerCase());
} else {
if (property.equalsIgnoreCase("parent") || property.equalsIgnoreCase("up")) {
try {
return getParent();
} catch (EolRuntimeException e) {
throw new EolIllegalPropertyException(this, property, null, null);
}
} else {
String h;
try {
h = StateflowUtil.getBlockHandle(this);
return engine.evalWithResult("?.?;", h, property);
} catch (MatlabException e) {
throw new EolIllegalPropertyException(this, property, null, null);
}
}
}
}
@Override
public void setProperty(String property, Object value) throws EolIllegalPropertyException {
try {
if (property.equalsIgnoreCase("parent") || property.equalsIgnoreCase("up")) {
if (value instanceof StateflowBlock) {
try {
setParent((StateflowBlock)value);
} catch (EolRuntimeException e) {
e.printStackTrace();
throw new EolIllegalPropertyException(this, property, null, null);
}
} else {
throw new EolIllegalPropertyException(this, property, null, null);
}
} else {
if (isUnset()) {
properties.put(property.toLowerCase(), value);
} else {
String escaped = "?";
String randomHandle = "";
if (value instanceof StateflowBlock) {
randomHandle = StateflowUtil.getBlockHandle(((StateflowBlock) value));
value = randomHandle;
}
if (value instanceof String && !value.equals(randomHandle)) {
String valueStr = (String) value;
if ( !(
( valueStr.startsWith("'") && valueStr.endsWith("'") ) ||
( valueStr.startsWith("[") && valueStr.endsWith("]") )
))
{
escaped = "'" + escaped + "'";
}
}
String cmd = "?.? = " + escaped + ";";
String h = StateflowUtil.getBlockHandle(this);
engine.eval(cmd, h, property, value);
}
}
} catch (MatlabException e) {
e.printStackTrace();
throw new EolIllegalPropertyException(this, property, null, null);
}
}
/** IDENTIFIER */
public Double getId() {
if (this.id == null) {
System.err.println("ID WAS NULL");
}
return this.id;
}
public String getPath() {
if (this.id != null) {
try {
String handle = StateflowUtil.getBlockHandleFromId(model, engine, id);
return (String) engine.evalWithResult("?.path;", handle);
} catch (MatlabException e) {}
}
return null;
}
// PARENT CHILDREN
public ISimulinkModelElement getParent() throws EolRuntimeException {
try {
String h = StateflowUtil.getBlockHandle(this);
try {
Double parentId = (Double) engine.evalWithResult("?.up.id;",h);
return new StateflowBlock(model, engine, parentId);
} catch (MatlabException e) {
String path = (String) engine.evalWithResult("?.path;",h);
return new SimulinkBlock(path, model, engine);
}
} catch (MatlabException e1) {
throw new EolRuntimeException(e1.getMessage());
}
}
public void setParent(StateflowBlock parent) throws EolRuntimeException, MatlabException {
if (!this.isUnset()) {
changeParent(parent);
} else {
buildFromStateflow(parent);
applyProperties();
}
}
private void applyProperties() throws EolIllegalPropertyException {
Iterator<String> keys = properties.keySet().iterator();
while (keys.hasNext()) {
String key = keys.next();
setProperty(key, properties.get(key));
}
properties.clear();
}
private void changeParent(StateflowBlock parent) throws EolRuntimeException { // TODO
throw new EolRuntimeException("Changing parent is not yet implemented");
/*try {
String positionProperty = "Position";
Object position = getProperty(positionProperty);
Object newParentPosition = parent.getProperty(positionProperty);
Object newPosition = newParentPosition;
// setProperty(positionProperty, newPosition);
} catch (MatlabException e) {
e.printStackTrace();
}*/
}
/** BUILDER */
private void buildFromStateflow(StateflowBlock parent) throws EolRuntimeException {
if (!parent.isUnset()) {
try {
String parentHandle = StateflowUtil.getBlockHandle(parent);
engine.eval("block = ?(?);", getType(), parentHandle);
this.id = (Double) engine.evalWithResult("block.id;");
} catch (MatlabException e) {
throw new EolRuntimeException(e.getMessage());
}
} else {
throw new EolRuntimeException("Parent was not a valid entity");
}
}
public Collection<StateflowBlock> getChildren() {
try {
String handle = StateflowUtil.getBlockHandle(this);
Object children = (Object) this.engine.evalWithSetupAndResult("list = ?.find('-depth',1); list = setdiff(list, ?);", "get(list,'Id');", handle, handle);
return StateflowUtil.getStateflowBlocks(model, engine, children);
} catch (MatlabException e) {
return Collections.<StateflowBlock>emptyList();
}
}
public StateflowBlock inspect() {
try {
String h = StateflowUtil.getBlockHandle(this);
engine.eval("get(?);", h);
} catch (MatlabException e) {
}
return this;
}
@Override
public boolean equals(Object other) {
return (other instanceof StateflowBlock) && ((StateflowBlock) other).getId().equals(this.getId());
}
@Override
public String toString() {
return getType() + "[ id = " + getId() + ", path = " + getPath() + " ]";
}
@Override
public Collection<String> getAllTypeNamesOf() {
return Arrays.asList(SimulinkModel.BLOCK, SimulinkModel.STATEFLOW, getType());
}
@Override
public boolean deleteElementInModel() throws EolRuntimeException {
try {
engine.eval(DELETE_SF, StateflowUtil.getBlockHandle(this));
return true;
} catch (MatlabException e) {
return false;
}
}
public StateflowBlock add(StateflowBlock block) throws EolRuntimeException {
try {
block.setParent(this);
} catch (MatlabException e) {
e.printStackTrace();
}
return this;
}
public SimulinkBlock asSimulink() throws EolRuntimeException {
Double h = SimulinkUtil.getHandle(this.getPath(), this.engine);
if (h >= 0)
return new SimulinkBlock(model, engine, h);
throw new EolRuntimeException("This block does not have a simulink Nature");
}
}