package com.isencia.passerelle.workbench.model.utils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.digester.substitution.MultiVariableExpander;
import org.apache.commons.digester.substitution.VariableSubstitutor;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.preference.PreferenceStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ptolemy.actor.Actor;
import ptolemy.actor.CompositeActor;
import ptolemy.actor.IOPort;
import ptolemy.actor.TypedIOPort;
import ptolemy.kernel.ComponentEntity;
import ptolemy.kernel.CompositeEntity;
import ptolemy.kernel.Port;
import ptolemy.kernel.Relation;
import ptolemy.kernel.util.Attribute;
import ptolemy.kernel.util.IllegalActionException;
import ptolemy.kernel.util.Locatable;
import ptolemy.kernel.util.Location;
import ptolemy.kernel.util.NameDuplicationException;
import ptolemy.kernel.util.Nameable;
import ptolemy.kernel.util.NamedObj;
import ptolemy.kernel.util.Workspace;
import ptolemy.moml.Vertex;
import com.isencia.passerelle.editor.common.utils.EditorUtils;
import com.isencia.passerelle.resources.util.ResourceUtils;
public class ModelUtils {
public static Logger logger = LoggerFactory.getLogger(ModelUtils.class);
private static PreferenceStore store;
public static PreferenceStore getFavouritesStore() throws Exception {
if (store == null) {
store = new PreferenceStore();
final IProject pass = getPasserelleProject();
store.setFilename(pass.getLocation().toOSString() + "/favorites.properties");
try {
store.load();
} catch (IOException e) {
return store;
}
}
return store;
}
public static enum ConnectionType {
SOURCE, TARGET
};
public static boolean isClassDefinition(Object model) {
if (model instanceof CompositeActor) {
return ((CompositeActor) model).isClassDefinition();
}
return false;
}
public static List<IOPort> getPorts(Relation relation, NamedObj obj) {
List<IOPort> ports = new ArrayList<IOPort>();
for (Object o : relation.linkedPortList()) {
if (((Port) o).getContainer().equals(obj)) {
ports.add((IOPort) o);
}
}
return ports;
}
public static Set<Relation> getConnectedRelations(Nameable model, ConnectionType connectionType, boolean fullList) {
Set<Relation> connections = new HashSet<Relation>();
if (model.getContainer() == null || !(model.getContainer() instanceof CompositeEntity))
return Collections.EMPTY_SET;
CompositeEntity composite = (CompositeEntity) model.getContainer();
List<Relation> relationList = new ArrayList<Relation>();
relationList.addAll(composite.relationList());
if (model instanceof TypedIOPort) {
if (fullList && composite != null && composite.getContainer() != null) {
relationList.addAll(((CompositeEntity) composite.getContainer()).relationList());
}
}
if (relationList == null || relationList.size() == 0)
return Collections.EMPTY_SET;
for (Relation relation : relationList) {
List linkedObjectsList = relation.linkedObjectsList();
if (linkedObjectsList == null || linkedObjectsList.size() == 0)
continue;
for (Object o : linkedObjectsList) {
if (o instanceof Port) {
Port port = (Port) o;
if (port.getContainer().equals(model) || (model instanceof IOPort && (port.equals(((IOPort) model))))) {
if (connectionType.equals(ConnectionType.SOURCE)) {
if (port instanceof IOPort && (!(model instanceof IOPort) && ((IOPort) port).isOutput()) || ((model instanceof IOPort) && ((IOPort) port).isInput()))
connections.add(relation);
} else {
if (port instanceof IOPort && (!(model instanceof IOPort) && ((IOPort) port).isInput()) || ((model instanceof IOPort) && ((IOPort) port).isOutput()))
connections.add(relation);
}
}
}
}
}
return connections;
}
public static List<Relation> getRelations(NamedObj model) {
ArrayList<Relation> relations = new ArrayList<Relation>();
if (model == null || !(model instanceof CompositeEntity))
return Collections.EMPTY_LIST;
List<Relation> relationList = ((CompositeEntity) model).relationList();
return relationList;
}
@SuppressWarnings("unchecked")
public static double[] getLocation(NamedObj model) {
if (model instanceof Locatable) {
Locatable locationAttribute = (Locatable) model;
return locationAttribute.getLocation();
}
List<Attribute> attributes = model.attributeList(Locatable.class);
if (attributes == null || attributes.size() == 0) {
return new double[] { 0.0D, 0.0D };
}
Locatable locationAttribute = (Locatable) attributes.get(0);
return locationAttribute.getLocation();
}
@SuppressWarnings("unchecked")
public static void setLocation(NamedObj model, double[] location) {
if (model instanceof Locatable) {
try {
((Locatable) model).setLocation(location);
NamedObj cont = model.getContainer();
cont.attributeChanged((Attribute) model);
} catch (IllegalActionException e) {
// TODO Auto-generated catch block
logger.error("Unable to change location of component", e);
}
}
List<Attribute> attributes = model.attributeList(Locatable.class);
if (attributes == null)
return;
if (attributes.size() > 0) {
Locatable locationAttribute = (Locatable) attributes.get(0);
try {
locationAttribute.setLocation(location);
model.attributeChanged(attributes.get(0));
} catch (IllegalActionException e) {
logger.error("Unable to change location of component", e);
}
} else {
try {
new Location(model, "_location").setLocation(location);
} catch (IllegalActionException e) {
logger.error("Unable to change location of component", e);
} catch (NameDuplicationException e) {
logger.error("Duplicate name encountered during change location of component", e);
}
}
}
public static boolean isPortOfActor(IOPort port, Actor actor) {
for (Object o : actor.inputPortList()) {
if (o == port) {
return true;
}
}
for (Object o : actor.outputPortList()) {
if (o == port) {
return true;
}
}
return false;
}
public static String findUniqueActorName(CompositeEntity parentModel, String name) {
String newName = name;
if (parentModel == null)
return newName;
List entityList = parentModel.entityList();
if (entityList == null || entityList.size() == 0)
return newName;
ComponentEntity entity = parentModel.getEntity(newName);
int i = 1;
while (entity != null) {
newName = name + "(" + i++ + ")";
entity = parentModel.getEntity(newName);
}
return newName;
}
/**
* Attempts to clean up names in the event that they are not compatible
*
* @param newName
* @return
*/
public static String getLegalName(final String name) {
String newName = name;
// newName = newName.replace(' ', '_');
if (name.indexOf('.') > -1) {
newName = newName.substring(0, newName.lastIndexOf('.'));
}
newName = newName.replace('.', '_');
return newName;
}
public static boolean isNameLegal(String text) {
if (text == null)
return false;
if ("".equals(text))
return false;
if (text.indexOf('.') > -1)
return false;
return true;
}
public static String findUniqueName(CompositeEntity parentModel, Class clazz, String startName, String actorName) {
return EditorUtils.findUniqueName(parentModel, clazz, startName, actorName);
}
/**
* Currently does not do much as toplevel.getEntity(...) does this search.
*
* @param toplevel
* @param actorName
* @return
*/
public static ComponentEntity findEntityByName(CompositeActor toplevel, String actorName) {
ComponentEntity entity = toplevel.getEntity(actorName);
if (entity != null)
return entity;
return null;
}
public static IFile getProjectFile(final String modelPath) {
return ResourceUtils.getProjectFile(modelPath);
}
/**
* Attempts to find the project from the top CompositeActor by using the workspace name.
*
* @param actor
* @return
* @throws Exception
*/
public static IProject getProject(final NamedObj actor) throws Exception {
return ResourceUtils.getProject(actor);
}
/**
* substutes variables in the string as determined from the actor.
*
* @param filePath
* @param dataExportTransformer
* @throws Exception
*/
public static String substitute(final String sub, final NamedObj actor) throws Exception {
final Map<String, Object> variables = new HashMap<String, Object>(3);
variables.put("project_name", getProject(actor).getName());
variables.put("actor_name", actor.getName());
MultiVariableExpander expander = new MultiVariableExpander();
expander.addSource("$", variables);
// Create a substitutor with the expander
VariableSubstitutor substitutor = new VariableSubstitutor(expander);
return substitutor.substitute(sub);
}
/**
* We will initialize file contents with a sample text.
*/
public static InputStream getEmptyWorkflowStream(final String fileName) {
String contents = "<?xml version=\"1.0\" standalone=\"no\"?> \r\n"
+ "<!DOCTYPE entity PUBLIC \"-//UC Berkeley//DTD MoML 1//EN\" \"http://ptolemy.eecs.berkeley.edu/xml/dtd/MoML_1.dtd\"> \r\n" + "<entity name=\""
+ fileName.substring(0, fileName.length() - 5) + "\" class=\"ptolemy.actor.TypedCompositeActor\"> \r\n"
+ " <property name=\"_createdBy\" class=\"ptolemy.kernel.attributes.VersionAttribute\" value=\"7.0.1.4\" /> \r\n"
+ " <property name=\"_workbenchVersion\" class=\"ptolemy.kernel.attributes.VersionAttribute\" value=\"" + System.getProperty("passerelle.workbench.version")
+ "\" /> \r\n" + " <property name=\"Director\" class=\"com.isencia.passerelle.domain.cap.Director\" > \r\n"
+ " <property name=\"_location\" class=\"ptolemy.kernel.util.Location\" value=\"{20, 20}\" /> \r\n" + " </property> \r\n" + "</entity>";
return new ByteArrayInputStream(contents.getBytes());
}
public static InputStream getEmptyCompositeStream(String name) throws UnsupportedEncodingException {
String momlTemplate = "<?xml version=\"1.0\" standalone=\"no\"?> \r\n"
+ "<!DOCTYPE entity PUBLIC \"-//UC Berkeley//DTD MoML 1//EN\" \"http://ptolemy.eecs.berkeley.edu/xml/dtd/MoML_1.dtd\"> \r\n"
+ "<class name=\"$modelName\" extends=\"ptolemy.actor.TypedCompositeActor\"> \r\n </class >";
momlTemplate = momlTemplate.replace("$modelName", name);
return new ByteArrayInputStream(momlTemplate.getBytes("UTF-8"));
}
public static IProject getPasserelleProject() throws Exception {
return ResourceUtils.getPasserelleProject();
}
/**
* @param modelPath
* @return
*/
public static Workspace getWorkspace(final String modelPath) {
IFile projFile = ModelUtils.getProjectFile(modelPath);
if (projFile != null) {
logger.debug("Running project file {}", projFile);
return new Workspace(projFile.getProject().getName());
}
final String workspacePath = ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString();
// We must tell the composite actor the containing project name
String relPath = modelPath.substring(workspacePath.length());
projFile = (IFile) ResourcesPlugin.getWorkspace().getRoot().findMember(relPath);
if (projFile != null) {
logger.debug("Running project file {}", projFile);
return new Workspace(projFile.getProject().getName());
}
String fileSep = System.getProperty("file.separator");
if (relPath.startsWith(fileSep)) relPath = relPath.substring(1);
final String projectName = relPath.substring(0, relPath.indexOf(fileSep));
logger.debug("Using project {}", projectName);
return new Workspace(projectName);
}
}