package com.isencia.passerelle.workbench.model.utils; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TreeSet; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.isencia.passerelle.model.Flow; import com.isencia.passerelle.model.FlowManager; import com.isencia.passerelle.model.util.MoMLParser; /** * Class replaces submodel storage with a proper properties file. This allows * reliable operations where the old comma separated string did not. * * @author gerring * */ public class SubModelUtils { private static Logger logger = LoggerFactory.getLogger(SubModelUtils.class); private static Map<String, Flow> modelMap; public static Map<String, Flow> getSubModels() throws Exception { if (modelMap == null) { return modelMap = SubModelUtils.readSubModels(); } return modelMap; } public static boolean isSubModel(final String name) { return modelMap != null && modelMap.keySet().contains(name); } public static void addSubModel(Flow flow) throws Exception { MoMLParser.putActorClass(flow.getName(), flow); registerSubModel(flow); } private static void registerSubModel(Flow flow) throws Exception { if (modelMap == null) { modelMap = getSubModels(); } String model = flow.getName(); modelMap.put(model, flow); final IFile store = getModelStore(); final Properties models = PropUtils.loadProperties(store.getContents()); models.put(model, ""); PropUtils.storeProperties(models, store.getLocation().toOSString()); store.refreshLocal(IResource.DEPTH_ONE, null); } public static Map<String, Flow> readSubModels() throws Exception { final IProject pass = ModelUtils.getPasserelleProject(); pass.refreshLocal(IResource.DEPTH_INFINITE, null); final Properties models = PropUtils.loadProperties(getModelStore().getContents()); final Set<Object> sorted = new TreeSet<Object>(); sorted.addAll(models.keySet()); // Use map that retains order final Map<String, Flow> modelList = new LinkedHashMap<String, Flow>(); List<String> modelNames = initializeSubmodels(sorted, pass); for (Object modelOb : sorted) { final String modelName = (String)modelOb; if (modelName==null||"".equals(modelName)) continue; final IFile file = pass.getFile(modelName + ".moml"); try { if (file.exists()) { Flow flow = FlowManager.readMoml(new InputStreamReader(file.getContents())); // flow.setSource(file.getLocation().toOSString()); if (flow.isClassDefinition()) { MoMLParser.putActorClass(modelName, flow); flow.setName(modelName); modelList.put(modelName, flow); } } } catch (Exception e1) { logger.error("Cannot read moml file!", e1); } } pass.refreshLocal(IResource.DEPTH_INFINITE, null); return modelList; } // This is hack to make all models known to modelparser so it's possible to // use a submodel in other submodels private static List<String> initializeSubmodels(final Set<Object> sorted, final IProject pass) { List<String> modelNames = new ArrayList<String>(); for (Object modelOb : sorted) { final String modelName = (String) modelOb; if (modelName == null || "".equals(modelName)) continue; final IFile file = pass.getFile(modelName + ".moml"); try { if (file.exists()) { InputStreamReader reader = new InputStreamReader( createEmptySubModel(modelName)); try { Flow flow = FlowManager.readMoml(reader); MoMLParser.putActorClass(modelName, flow); } catch (Exception e) { } modelNames.add(modelName); } } catch (Exception e1) { logger.error("Cannot read moml file!", e1); } } return modelNames; } private static InputStream createEmptySubModel(String subModel) { 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" + "<class name=\"" + subModel + "\" extends=\"ptolemy.actor.TypedCompositeActor\"> </class>"; return new ByteArrayInputStream(contents.getBytes()); } private static IFile getModelStore() throws Exception { final IFile file = ModelUtils.getPasserelleProject().getFile( "submodels.properties"); if (!file.exists()) { file.create( new ByteArrayInputStream("# DAWB Properties".getBytes()), true, null); } return file; } public static void deleteSubModel(final String name) throws Exception { if (modelMap == null) { modelMap = getSubModels(); } modelMap.remove(name); final IFile store = getModelStore(); final Properties models = PropUtils.loadProperties(store.getContents()); models.remove(name); PropUtils.storeProperties(models, store.getLocation().toOSString()); store.refreshLocal(IResource.DEPTH_ONE, null); } }