/******************************************************************************* * Copyright (c) 2010-2013, Embraer S.A., Budapest University of Technology and Economics * 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, Abel Hegedus, Akos Horvath - initial API and implementation *******************************************************************************/ package hu.bme.mit.massif.simulink.api.adapter.block; import hu.bme.mit.massif.communication.command.MatlabCommand; import hu.bme.mit.massif.communication.command.MatlabCommandFactory; import hu.bme.mit.massif.communication.datatype.MatlabString; import hu.bme.mit.massif.simulink.Block; import hu.bme.mit.massif.simulink.IdentifierReference; import hu.bme.mit.massif.simulink.ModelReference; import hu.bme.mit.massif.simulink.SimulinkFactory; import hu.bme.mit.massif.simulink.SimulinkModel; import hu.bme.mit.massif.simulink.SimulinkReference; import hu.bme.mit.massif.simulink.SubSystem; import hu.bme.mit.massif.simulink.api.Importer; import hu.bme.mit.massif.simulink.api.ModelObject; import hu.bme.mit.massif.simulink.api.exception.SimulinkApiException; import hu.bme.mit.massif.simulink.api.util.ImportMode; import hu.bme.mit.massif.simulink.api.util.SimulinkUtil; import java.util.Map; import org.eclipse.emf.ecore.util.EcoreUtil; /** * Adapter class for the model reference */ public class ModelReferenceAdapter extends DefaultBlockAdapter { @Override public Block getBlock(Importer traverser) { switch (traverser.getImportMode()) { case FLATTENING: return SimulinkFactory.eINSTANCE.createSubSystem(); default: return SimulinkFactory.eINSTANCE.createModelReference(); } } @Override public void process(Importer traverser, SimulinkReference parentSimRef, Block blockToProcess) { super.process(traverser, parentSimRef, blockToProcess); ImportMode importMode = traverser.getImportMode(); String modelReferenceFQN = blockToProcess.getSimulinkRef().getFQN(); MatlabCommandFactory commandFactory = traverser.getCommandFactory(); String referencedModelName = null; SimulinkModel actualReferredModel = null; ModelReference modelReference = null; if(ImportMode.FLATTENING != traverser.getImportMode()){ modelReference = (ModelReference) blockToProcess; } switch (importMode) { case SHALLOW: // Set the referenced model name MatlabCommand getReferencedModelName = commandFactory.getParam().addParam(modelReferenceFQN).addParam("ModelName"); referencedModelName = MatlabString.getMatlabStringData(getReferencedModelName.execute()); referencedModelName = handleSpecialCharacters(referencedModelName); String qualifier = null; String name = null; if (referencedModelName.contains("/")) { qualifier = referencedModelName.substring(referencedModelName.lastIndexOf('/')); name = referencedModelName .substring(referencedModelName.lastIndexOf('/'), referencedModelName.length()); } else { qualifier = ""; name = referencedModelName; } IdentifierReference modelSimRef = SimulinkUtil.createIdentifierReference(name, qualifier); modelReference.setModelRef(modelSimRef); break; case REFERENCING: // fall-through case DEEP: // Create individual EMF models for the referenced models. try { actualReferredModel = traverseReferencedModel(traverser, modelReferenceFQN, commandFactory, ImportMode.DEEP); IdentifierReference actualReferredModelSimRef = EcoreUtil.copy(actualReferredModel.getSimulinkRef()); modelReference.setModelRef(actualReferredModelSimRef); } catch (SimulinkApiException e) { traverser.getLogger().error("Exception occurred while traversing referenced model in deep copy!", e); } break; case FLATTENING: // Import the blocks located in the referenced model to EMF // as though they were in the currently traversed model SubSystem modelReferenceSubSystem = (SubSystem) blockToProcess; try { actualReferredModel = traverseReferencedModel(traverser, modelReferenceFQN, commandFactory, ImportMode.FLATTENING); // Set the level 0 elements of the model as the children of the SubSystem block // so that flattening completes for (Block b : actualReferredModel.getContains()) { modelReferenceSubSystem.getSubBlocks().add(EcoreUtil.copy(b)); } } catch (SimulinkApiException e) { traverser.getLogger().error("Exception occurred while traversing referenced model in flattening copy!", e); } break; default: break; } } private SimulinkModel traverseReferencedModel(final Importer traverser, String modelReferenceFQN, MatlabCommandFactory commandFactory, ImportMode importMode) throws SimulinkApiException { String referencedModelName; ModelObject referencedModel; SimulinkModel actualReferredModel; // Fetch the referenced model's name MatlabCommand getReferencedModelName = commandFactory.getParam().addParam(modelReferenceFQN).addParam("ModelName"); referencedModelName = MatlabString.getMatlabStringData(getReferencedModelName.execute()); referencedModelName = handleSpecialCharacters(referencedModelName); Map<String, SimulinkModel> modelRegistry = traverser.getReferencedModels(); if (modelRegistry.get(referencedModelName) != null) { return modelRegistry.get(referencedModelName); } referencedModel = new ModelObject(referencedModelName, commandFactory.getCommandEvaluator()); Importer referencedModelTraverser = new Importer(referencedModel); referencedModelTraverser.registerFilters(traverser.getFilters()); // Add all already referenced and imported models to the new traverser registry referencedModelTraverser.getReferencedModels().putAll(modelRegistry); // Creates an individual model referencedModelTraverser.traverseAndCreateEMFModel(importMode); actualReferredModel = referencedModelTraverser.getSimulinkModel(); // Add back all recently traversed models to the 'referenced models' set modelRegistry.putAll(referencedModelTraverser.getReferencedModels()); modelRegistry.put(actualReferredModel.getSimulinkRef().getFQN(), actualReferredModel); return actualReferredModel; } /** * Escaping characters in the return value from Matlab * * @param referencedModelName * @return */ private String handleSpecialCharacters(String referencedModelName) { String result = referencedModelName; if (referencedModelName.contains("/")) result = referencedModelName.replace("/", "//"); if (referencedModelName.contains("\n")) result = referencedModelName.replace("\n", " "); return result; } }