diff --git a/plugins/org.polarsys.chess.OSSImporter/.classpath b/plugins/org.polarsys.chess.OSSImporter/.classpath new file mode 100644 index 0000000000000000000000000000000000000000..eca7bdba8f03f22510b7980a94dbfe10c16c0901 --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/plugins/org.polarsys.chess.OSSImporter/.gitignore b/plugins/org.polarsys.chess.OSSImporter/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..ae3c1726048cd06b9a143e0376ed46dd9b9a8d53 --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/plugins/org.polarsys.chess.OSSImporter/.project b/plugins/org.polarsys.chess.OSSImporter/.project new file mode 100644 index 0000000000000000000000000000000000000000..42f74f29c7f9129274b7cd8118a75a387a9e7894 --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.polarsys.chess.OSSImporter</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/plugins/org.polarsys.chess.OSSImporter/.settings/org.eclipse.jdt.core.prefs b/plugins/org.polarsys.chess.OSSImporter/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000000000000000000000000000000000..0c68a61dca867ceb49e79d2402935261ec3e3809 --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/plugins/org.polarsys.chess.OSSImporter/META-INF/MANIFEST.MF b/plugins/org.polarsys.chess.OSSImporter/META-INF/MANIFEST.MF new file mode 100644 index 0000000000000000000000000000000000000000..18a1ffe7c937f58932449342c39345fa5a1ac370 --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/META-INF/MANIFEST.MF @@ -0,0 +1,20 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: org.polarsys.chess.OSSImporter +Bundle-SymbolicName: org.polarsys.chess.OSSImporter;singleton:=true +Bundle-Version: 1.0.0.qualifier +Require-Bundle: eu.fbk.eclipse.standardtools.ModelTranslatorToOcra;bundle-version="1.0.0", + org.eclipse.xtext, + eu.fbk.tools.editor.oss, + org.eclipse.papyrus.uml.tools, + eu.fbk.eclipse.standardtools.utils;bundle-version="1.0.0", + eu.fbk.tools.editor.contract.expression, + eu.fbk.tools.editor.basetype, + org.polarsys.chess.contracts.profile, + eu.fbk.tools.editor.contract, + org.polarsys.chess.core, + org.eclipse.papyrus.uml.tools.utils, + org.polarsys.chess.service;bundle-version="0.11.0" +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Import-Package: com.google.inject +Bundle-Vendor: Fondazione Bruno Kessler diff --git a/plugins/org.polarsys.chess.OSSImporter/build.properties b/plugins/org.polarsys.chess.OSSImporter/build.properties new file mode 100644 index 0000000000000000000000000000000000000000..caaec514ba877b82792437cca4694c6742df99ac --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/build.properties @@ -0,0 +1,7 @@ +source.. = src/ +output.. = bin/ +bin.includes = plugin.xml,\ + META-INF/,\ + .,\ + icons/,\ + contexts.xml diff --git a/plugins/org.polarsys.chess.OSSImporter/contexts.xml b/plugins/org.polarsys.chess.OSSImporter/contexts.xml new file mode 100644 index 0000000000000000000000000000000000000000..b3b18ae3d68e453331461ba19680808d7cbbcd29 --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/contexts.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<contexts> + <context id="viewer" title="Sample View"> + <description>This is the context help for the sample view with a table viewer. It was generated by a PDE template.</description> + <topic href="/PLUGINS_ROOT/org.eclipse.platform.doc.isv/guide/ua_help_context.htm" label="Context-sensitive help"> + <enablement> + <with variable="platform"> + <test property="org.eclipse.core.runtime.isBundleInstalled" args="org.eclipse.platform.doc.isv"/> + </with> + </enablement> + </topic> + </context> +</contexts> diff --git a/plugins/org.polarsys.chess.OSSImporter/icons/.gitignore b/plugins/org.polarsys.chess.OSSImporter/icons/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..7e9917447976a12e362999dfd47563ae54c16d63 --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/icons/.gitignore @@ -0,0 +1 @@ +/sample.gif diff --git a/plugins/org.polarsys.chess.OSSImporter/plugin.xml b/plugins/org.polarsys.chess.OSSImporter/plugin.xml new file mode 100644 index 0000000000000000000000000000000000000000..91ef2bdf52440ca71e6abefab8d21acc865e8db0 --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/plugin.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.4"?> +<plugin> + + <extension + point="org.eclipse.ui.menus"> + <menuContribution + allPopups="false" + locationURI="popup:org.polarsys.chess.modelexplorerpopupmenu.id"> + <menu + id="org.eclipse.ui.main.diagramEditorMenu.CHESS.basicOperations" + label="Basic Operations"> + <command + commandId="org.polarsys.chess.OSSImporter.commands.AddOSSFile" + label="Import <<SystemView>> components from .oss file" + style="push"> + <visibleWhen + checkEnabled="false"> + <iterate + ifEmpty="false" + operator="and"> + <adapt + type="org.eclipse.emf.ecore.EObject"> + <instanceof + value="org.eclipse.uml2.uml.Package"> + </instanceof> + </adapt> + </iterate> + </visibleWhen> + </command> + </menu> + </menuContribution> + </extension> + <extension + point="org.eclipse.ui.commands"> + <command + defaultHandler="org.polarsys.chess.OSSImporter.commands.AddOSSFileCommand" + id="org.polarsys.chess.OSSImporter.commands.AddOSSFile" + name="Add System View components from .oss file"> + </command> + </extension> + +</plugin> diff --git a/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/actions/ImportOSSFileAction.java b/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/actions/ImportOSSFileAction.java new file mode 100644 index 0000000000000000000000000000000000000000..6cbdfcd5f886dc876c1bcc899c271f347e2bfaf9 --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/actions/ImportOSSFileAction.java @@ -0,0 +1,1446 @@ +package org.polarsys.chess.OSSImporter.actions; + +import org.eclipse.emf.ecore.resource.*; +import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.uml2.uml.AggregationKind; +import org.eclipse.uml2.uml.Class; +import org.eclipse.uml2.uml.Classifier; +import org.eclipse.uml2.uml.DataType; +import org.eclipse.uml2.uml.Enumeration; +import org.eclipse.uml2.uml.EnumerationLiteral; +import org.eclipse.uml2.uml.LiteralString; +import org.eclipse.uml2.uml.Model; +import org.eclipse.uml2.uml.NamedElement; +import org.eclipse.uml2.uml.Package; +import org.eclipse.uml2.uml.Profile; +import org.eclipse.uml2.uml.Property; +import org.eclipse.uml2.uml.Signal; +import org.eclipse.uml2.uml.Stereotype; +import org.eclipse.uml2.uml.Type; +import org.eclipse.uml2.uml.UMLFactory; +import org.eclipse.uml2.uml.UMLPackage; +import org.eclipse.uml2.uml.resource.UMLResource; +import org.eclipse.uml2.uml.Connector; +import org.eclipse.uml2.uml.ConnectorEnd; +import org.eclipse.uml2.uml.Constraint; +import org.eclipse.xtext.serializer.ISerializer; +import org.polarsys.chess.OSSImporter.parser.ParseHelper; +import org.polarsys.chess.contracts.profile.chesscontract.ContractProperty; +import org.polarsys.chess.contracts.profile.chesscontract.ContractRefinement; +import org.polarsys.chess.contracts.profile.chesscontract.util.ContractEntityUtil; +import org.polarsys.chess.contracts.profile.chesscontract.util.EntityUtil; +import org.polarsys.chess.core.util.uml.UMLUtils; + +import com.google.inject.Injector; + +import eu.fbk.eclipse.standardtools.utils.FileSystemUtil; +import eu.fbk.tools.editor.basetype.baseType.*; +import eu.fbk.tools.editor.contract.contract.Assumption; +import eu.fbk.tools.editor.contract.contract.Contract; +import eu.fbk.tools.editor.contract.contract.Guarantee; +import eu.fbk.tools.editor.contract.expression.expression.*; +import eu.fbk.tools.editor.oss.OssStandaloneSetup; +import eu.fbk.tools.editor.oss.oss.SystemComponent; +import eu.fbk.tools.editor.oss.oss.Variable; +import eu.fbk.tools.editor.oss.oss.AbstractComponent; +import eu.fbk.tools.editor.oss.oss.Component; +import eu.fbk.tools.editor.oss.oss.Connection; +import eu.fbk.tools.editor.oss.oss.ContractId; +import eu.fbk.tools.editor.oss.oss.InputPort; +import eu.fbk.tools.editor.oss.oss.Interface; +import eu.fbk.tools.editor.oss.oss.InterfaceInstance; +import eu.fbk.tools.editor.oss.oss.OSS; +import eu.fbk.tools.editor.oss.oss.OutputPort; +import eu.fbk.tools.editor.oss.oss.Port; +import eu.fbk.tools.editor.oss.oss.RefinedBy; +import eu.fbk.tools.editor.oss.oss.Operation; +import eu.fbk.tools.editor.oss.oss.Parameter; +import eu.fbk.tools.editor.oss.oss.Refinement; +import eu.fbk.tools.editor.oss.oss.RefinementInstance; + +import org.eclipse.papyrus.MARTE.MARTE_Annexes.VSL.DataTypes.BoundedSubtype; +import org.eclipse.papyrus.sysml.portandflows.FlowDirection; +import org.eclipse.papyrus.sysml.portandflows.FlowPort; +import org.eclipse.papyrus.uml.tools.model.UmlModel; +import org.eclipse.papyrus.uml.tools.model.UmlUtils; +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import org.eclipse.core.runtime.Platform; +import org.eclipse.emf.common.util.BasicEList; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.TreeIterator; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.common.util.WrappedException; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.transaction.RecordingCommand; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.emf.transaction.util.TransactionUtil; +import org.eclipse.jface.dialogs.MessageDialog; + +/** + */ +public class ImportOSSFileAction { + + private static ImportOSSFileAction sampleView; + + /** + * Gets an instance of the class if already present, or a new one if not + * @return the instance of this class + */ + public static ImportOSSFileAction getInstance() { + if (sampleView == null) { + sampleView = new ImportOSSFileAction(); + } + return sampleView; + } + +// private static final String SUFFIX = "_test"; // It could be possible to add a suffix to block names + private static final String DELEGATION_PREFIX = "Define_"; + private static final String DELEGATION_CONSTRAINT_NAME = "constraintSpec"; + private static final String CONNECTOR_NAME = "connector"; + private static final String ENUMERATION_NAME = "Enumeration"; + private static final String SIGNAL_NAME = "Signal"; + +// private static final String INTEGER_TYPE = "PrimitiveTypes::Integer"; +// private static final String REAL_TYPE = "PrimitiveTypes::Real"; +// private static final String BOOLEAN_TYPE = "PrimitiveTypes::Boolean"; + +// private static final String CHESS_CONTINUOUS_TYPE = "CHESSContract::DataTypes::Continuous"; + + private static final String BOUNDED_TYPE = "MARTE::MARTE_Annexes::VSL::DataTypes::BoundedSubtype"; + + private static final String CONTRACT = "CHESSContract::Contract"; + private static final String CONTRACT_PROP = "CHESSContract::ContractProperty"; + private static final String DELEGATION_CONST = "CHESSContract::DelegationConstraint"; +// private static final String FORMAL_PROP = "CHESSContract::FormalProperty"; + private static final String CONTRACT_REFINEMENT = "CHESSContract::ContractRefinement"; + private static final String SYSTEM = "CHESSContract::System"; + private static final String COMPINST = "CHESSContract::ComponentInstance"; + + private static final String SYSVIEW = "CHESS::Core::CHESSViews::SystemView"; + private static final String COMPVIEW = "CHESS::Core::CHESSViews::ComponentView"; +// private static final String CHESS = "CHESS::Core::CHESS"; + + private static final String BLOCK = "SysML::Blocks::Block"; + + private static final String FLOWPORT = "SysML::PortAndFlows::FlowPort"; + + /* + + private static final String SUBSYSTEM = "CHESSContract::SubSystem"; + public static final String COLLECTIONTYPE = "MARTE::MARTE_Annexes::VSL::DataTypes::CollectionType"; + private static final String MARTE_BOOLEAN_TYPE = "MARTE_Library::MARTE_PrimitivesTypes::Boolean"; + private static final String MARTE_REAL_TYPE = "MARTE_Library::MARTE_PrimitivesTypes::Real"; + private static final String MARTE_INTEGER_TYPE = "MARTE_Library::MARTE_PrimitivesTypes::Integer"; + + */ + + final Injector injector = new OssStandaloneSetup().createInjector(); + private final ISerializer serializer = injector.getInstance(ISerializer.class); +// private ContractEntityUtil contractEntityUtil = ContractEntityUtil.getInstance(); +// private EntityUtil entityUtil = EntityUtil.getInstance(); + private Package sysView = null; +// private Package compView = null; + + // Map the name of the component with the Component object + private final Map<String, Class> dslTypeToComponent = new HashMap<String, Class>(); + + /** + * The constructor + */ + public ImportOSSFileAction() { + } + + /** + * Utility dialog to display a message on screen + * @param message the text to display + */ + private void showMessage(String message) { + + Display defaultDisplay = Display.getDefault(); + + defaultDisplay.syncExec(new Runnable() { + @Override + public void run() { + Shell currShell = defaultDisplay.getActiveShell(); + MessageDialog.openInformation(currShell, "OSS parser", message); + } + }); + } + + /** + * Print a message on the console + * @param message the message to print + */ + private void printMessageOnOut(String message) { +// System.out.println(message); // Comment to avoid printing + } + + /** + * Creates a OSS Model + * @param ossFile a File containing the OCRA model + * @return the OSS object + */ + private OSS getOssModel(File ossFile) throws Exception { + String ossDefinition = FileSystemUtil.getFileContent(ossFile); + final ParseHelper<?> parseHelper = injector.getInstance(ParseHelper.class); + OSS result = (OSS) parseHelper.parse(ossDefinition); + + return result; + } + + /** + * Creates and adds a Component Instance to the model + * @param owner the parent Class + * @param elementName the name of the property to create + * @param elementType the type of the property to create + * @return the created Property + */ + private Property createComponentInstance(Class owner, String elementName, Type elementType) { + + printMessageOnOut("\n\n\n Creating property " + elementName + " for owner " + owner + " with type " + elementType); + printMessageOnOut("\n\n\n"); + + TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(owner); + domain.getCommandStack().execute(new RecordingCommand(domain) { + + @Override + protected void doExecute() { + Property newUMLProperty = owner.createOwnedAttribute(elementName, elementType); + UMLUtils.applyStereotype(newUMLProperty, COMPINST); + newUMLProperty.setAggregation(AggregationKind.get(AggregationKind.COMPOSITE)); //FIXME: e' sempre cosi? + } + }); + + printMessageOnOut("\n\nCreated " + elementName + " Property\n\n"); + return owner.getOwnedAttribute(elementName, elementType); + } + + /** + * Creates and adds a Contract Property to the model + * @param owner the parent Class + * @param elementName the name of the property to create + * @param elementType the type of the property to create + * @return the created Property + */ + private Property createContractProperty(Class owner, String elementName, Type elementType) { + + printMessageOnOut("\n\n\n Creating contract property " + elementName + " for owner " + owner + " with type " + elementType); + printMessageOnOut("\n\n\n"); + + TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(owner); + domain.getCommandStack().execute(new RecordingCommand(domain) { + + @Override + protected void doExecute() { + Property newUMLProperty = owner.createOwnedAttribute(elementName, elementType); + UMLUtils.applyStereotype(newUMLProperty, CONTRACT_PROP); + } + }); + + printMessageOnOut("\n\nCreated " + elementName + " Property\n\n"); + return owner.getOwnedAttribute(elementName, elementType); + } + + /** + * Creates the Delegation Constraint value + * @param variable the left part of the expression + * @param constraint the right part of the expression + * @return a string with the expression + */ + private String createDelegationConstraintText(VariableId variable, Expression constraint) { + final StringBuffer delegationText = new StringBuffer(); + + if (variable.getComponentName() != null) + delegationText.append(variable.getComponentName() + "."); + + delegationText.append(variable.getName() + " := " + getConstraintText(constraint)); + + return delegationText.toString(); + } + + /** + * Creates and adds a Delegation Constraint to the model + * @param owner the parent Class + * @param connection the Connection defining the delegation + * @param variable the target of the connection + * @param constraint the source of the connection + * @return the created delegation constraint + */ + private Constraint createDelegationConstraint(Class owner, VariableId variable, Expression constraint) { + + final StringBuffer delegationName = new StringBuffer(DELEGATION_PREFIX); + + if (variable.getComponentName() != null) + delegationName.append(variable.getComponentName() + "."); + + delegationName.append(variable.getName()); + + printMessageOnOut("\n\n\n Creating delegation constraint " + delegationName + " for owner " + owner); + printMessageOnOut("\n\n\n"); + + TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(owner); + domain.getCommandStack().execute(new RecordingCommand(domain) { + + @Override + protected void doExecute() { + + Constraint newUMLConstraint = owner.createOwnedRule(delegationName.toString()); + UMLUtils.applyStereotype(newUMLConstraint, DELEGATION_CONST); + + LiteralString literalString = UMLFactory.eINSTANCE.createLiteralString(); + literalString.setName(DELEGATION_CONSTRAINT_NAME); + final String formalPropertyText = createDelegationConstraintText(variable, constraint); + literalString.setValue(formalPropertyText); + newUMLConstraint.setSpecification(literalString); + } + }); + + printMessageOnOut("\n\nCreated " + delegationName + " Delegation Constraint\n\n"); + return owner.getOwnedRule(delegationName.toString()); + } + + /** + * Returns the contract with the given name + * @param umlComponent the component containing the contract + * @param contractName the name of the contract + * @return the UML class of the contract + */ + private Class getUMLContractFromContractName(Class umlComponent, String contractName) { + return (Class) umlComponent.getNestedClassifier(contractName); + } + + //FIXME: questa funzione si puo' ignorare ed usare il codice di Alberto, getUmlContractPropertyOfUmlComponentFromContractPropertyType + // da sistemare quando fisso il tipo delle porte + /** + * Returns the contract property generated by the given contract name + * @param component the component containing the contract + * @param contractName the name of the contract + * @return the associated Contract Property + */ + private ContractProperty getContractPropertyFromContract(Class component, String contractName) { + + // Get the contract definition from the component + final Class umlContract = getUMLContractFromContractName(component, contractName); + + // Get the contract property name, derived from the contract name + final String contractPropertyName = getContractPropertyName(umlContract); + + // Get the contract property from the component, generic type + final Property umlProperty = component.getOwnedAttribute(contractPropertyName, umlContract); + + // Return the correct type of object + return ContractEntityUtil.getInstance().getContractProperty(umlProperty); + } + + /** + * Returns the refinement associated to the component + * @param owner of the refinement + * @param refinementName the name of the refinement + * @return the umlRefinement + */ + private DataType getUMLRefinement(Class owner, String refinementName) { + return (DataType) owner.getNestedClassifier(refinementName); + } + + /** + * Returns the component instance with the given name + * @param owner the class owning the instance + * @param componentName the name of the instance + * @return the UML property representing the component instance + */ + private Property getUMLComponentInstance(Class owner, String componentName) { + + final Set<Property> componentInstances = EntityUtil.getInstance().getSubComponentsInstances(owner); + for (Property property : componentInstances) { + if (property.getAppliedStereotype(COMPINST) != null && property.getName().equals(componentName)) { + return property; + } + } + return null; + } + + /** + * Creates a ContractRefinement for the given owner component. + * The refinement should specify the component instance that contains the original contract property + * and the contract property itself + * + * @param owner the containter of the refinement + * @param componentName the component instance containing the contract property + * @param contractName the type of the contract + * @return the created DataType + */ + private DataType createContractRefinement(Class owner, String componentName, String contractName) { + + final Property componentInstance = getUMLComponentInstance(owner, componentName); + + // Get the type of the component instance + String typeName = componentInstance.getType().getName(); + + printMessageOnOut("\n\n\n Creating contract refinement for componentName = " + componentName + " of contract " + contractName); + printMessageOnOut("\n\n\n"); + + // Remove the optional suffix +// typeName = typeName.substring(0, typeName.indexOf(SUFFIX)); + + // Get the component type where the contract property is defined + final Class component = dslTypeToComponent.get(typeName); + + final ContractProperty contractProperty = getContractPropertyFromContract(component, contractName); + + // FIXME: Potrei usare la ContractEntityUtil.getInstance().getUmlContractPropertyOfUmlComponentFromContractPropertyType()component, contractName; + +// Property p = ContractEntityUtil.getInstance().getUmlContractPropertyOfUmlComponentFromContractPropertyType(component, contractName); +// ContractProperty cp = ContractEntityUtil.getInstance().getContractProperty(p); + + // Compose the correct name of the contract refinement + final String refinementName = componentName + "." + contractProperty.getBase_Property().getName(); + + // Check if the refinement is already present + final DataType umlRefinement = getUMLRefinement(owner, refinementName); + + if (umlRefinement != null) { + return umlRefinement; + } else { + printMessageOnOut("\n\n Creating contract refinement " + refinementName + " for owner " + owner.getName()); + printMessageOnOut("\n\n"); + + TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(owner); + domain.getCommandStack().execute(new RecordingCommand(domain) { + + @Override + protected void doExecute() { + DataType newUmlDataType = UMLFactory.eINSTANCE.createDataType(); + Classifier newClass = owner.createNestedClassifier(refinementName, newUmlDataType.eClass()); + Stereotype stereotype = UMLUtils.applyStereotype(newClass, CONTRACT_REFINEMENT); + ContractRefinement contractRefinement = (ContractRefinement) newClass.getStereotypeApplication(stereotype); + + // Set the correct links for the refinement + contractRefinement.setInstance(componentInstance); // The component instance containing the definition + contractRefinement.setContract(contractProperty); // The contract property that refines the contract + } + }); + + printMessageOnOut("\n\nCreated " + refinementName + " Contract Refinement\n\n"); + return (DataType) owner.getNestedClassifier(refinementName); + } + } + + /** + * Loads a package from the given resource + * @param uri the URI of the resource to load + * @return the retrieved package + */ + private static Package load(URI uri) { + Package package_ = null; + + try { + final ResourceSet resourceSet = new ResourceSetImpl(); + final Resource resource = resourceSet.getResource(uri, true); + package_ = (Package) EcoreUtil.getObjectByType(resource.getContents(), UMLPackage.Literals.PACKAGE); + } catch (WrappedException we) { + System.err.println(we.getMessage()); + System.exit(1); + } + return package_; + } + + /** + * Returns the primitive type from the standard primitive library + * @param name the name of the Type + * @return the requested primitive type + */ + private Type getPrimitiveType(String name) { + + // Load the correct library + final Model umlLibrary = (Model) load(URI.createURI(UMLResource.UML_PRIMITIVE_TYPES_LIBRARY_URI)); + + // Get the correct type + final Type type = umlLibrary.getOwnedType(name); + + if (type != null) { + printMessageOnOut("Type '" + type.getQualifiedName() + "' found."); + return type; + } + return null; + } + + /** + * Returns the primitive type from another UML library + * @param name the name of the Type + * @return the requested primitive type + */ + private Type getUMLPrimitiveType(String name) { + + // Get the correct model + final Model chessContract = (Model) load(URI.createURI("pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml")); + + // Get the correct type + final Type type = chessContract.getOwnedType(name); + + if (type != null) { + printMessageOnOut("Type '" + type.getQualifiedName() + "' found."); + return type; + } + return null; + } + + /** + * Returns the Type Continuous + * @param name the name of the Type + * @return the requested Type + */ + private Type getContinuousType(String name) { + + // The Continuous type is defined here: CHESSContract::DataTypes::Continuous + + // Get the correct profile + final Profile chessContract = (Profile) load(URI.createURI("pathmap://CHESSContract/CHESSContract.profile.uml")); + + // Get the correct package inside the profile + final Package dataTypes = chessContract.getNestedPackage("DataTypes"); + + // Get the correct type + final Type type = dataTypes.getOwnedType(name); + + if (type != null) { + printMessageOnOut("Type '" + type.getQualifiedName() + "' found."); + return type; + } + return null; + } + + /** + * Creates a new BoundedSubType as requested + * @param pkg the package where to create the Enumeration + * @param typeName the name of the type + * @param lowerBound the lower bound + * @param upperBound the upper bound + * @return the created type + */ + private Type createBoundedSubType(Package pkg, String typeName, int lowerBound, int upperBound) { + + TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(pkg); + domain.getCommandStack().execute(new RecordingCommand(domain) { + + @Override + protected void doExecute() { + + // Create a data type to the component view and apply the stereotype + Type dataType = pkg.createOwnedType(typeName, UMLPackage.Literals.DATA_TYPE); + Stereotype stereotype = UMLUtils.applyStereotype(dataType, BOUNDED_TYPE); + + // Extract the stereotiped type and configure it + BoundedSubtype boundedType = (BoundedSubtype) dataType.getStereotypeApplication(stereotype); + boundedType.setMinValue(String.valueOf(lowerBound)); + boundedType.setMaxValue(String.valueOf(upperBound)); + boundedType.setBaseType((DataType) getPrimitiveType("Integer")); +// boundedType.setBaseType((DataType) getUMLPrimitiveType("Integer")); // Alternative version + } + }); + + Type type = pkg.getOwnedType(typeName); + printMessageOnOut("Type '" + type.getQualifiedName() + "' created."); + return type; + } + + /** + * Returns a BoundedSubType as requested + * @param rangeType the type containing the specifications + * @return the requested type + */ + private Type getBoundedSubType(RangeType rangeType) { + + Package pkg = sysView; // Or compView, where to look for and create the type + int lowerBound = 0, upperBound = 0; + Type type = null; + + // Check to see if boundaries are integer values and extract them + if (rangeType.getLowerBound() instanceof IntegerLiteral && rangeType.getUpperBound() instanceof IntegerLiteral) { + IntegerLiteral intLit = (IntegerLiteral) rangeType.getLowerBound(); + lowerBound = Integer.parseInt(intLit.getValue()); + intLit = (IntegerLiteral) rangeType.getUpperBound(); + upperBound = Integer.parseInt(intLit.getValue()); + } else { + System.err.println("Import Error: Cannot understand the Bounded type limits! " + rangeType); + return type; + } + + // Generate a suitable type name + final String typeName = "BoundedInteger_" + lowerBound + "_" + upperBound; + + // Look for that type in the ComponentView + type = pkg.getOwnedType(typeName); + if (type != null) { + + // The type has been found in the package, use it + printMessageOnOut("Type '" + type.getQualifiedName() + "' found."); + return type; + } else { + return (Type) createBoundedSubType(pkg, typeName, lowerBound, upperBound); + } + } + + /** + * Retrieves all the Enumerations owned by the package + * @param pkg the package to be searched + * @return + */ + private EList<Enumeration> getEnumerations(Package pkg) { + EList<Enumeration> enumerations = new BasicEList<Enumeration>(); + + EList<Type> types = pkg.getOwnedTypes(); + for (Type type : types) { + if (type instanceof Enumeration) { + enumerations.add((Enumeration) type); + } + } + return enumerations; + } + + /** + * Returns the list of the values inside a given Enumeration + * @param enumeration the Enumeration to be analysed + * @return the list of contained values + */ + private Set<String> getListValuesForEnumeration(Enumeration enumeration) { + Set<String> enumValuesNames = new TreeSet<String>(); // Ordered list of values +// Set<String> enumValuesNames = new HashSet<String>(); // Original order of values + for(EnumerationLiteral enumLit : enumeration.getOwnedLiterals()) { + enumValuesNames.add(enumLit.getName()); + } + return enumValuesNames; + } + + /** + * Returns the list of the values inside a given EnumType + * @param enumType the EnumType to be analysed + * @return the list of contained values + */ + private Set<String> getListValuesForEnumType(EnumType enumType) { + Set<String> enumValuesNames = new TreeSet<String>(); // Ordered set + + for(EObject object : enumType.getValues()) { + enumValuesNames.add(((Identifier) object).getValue() ); + } + return enumValuesNames; + } + + /** + * Looks for a specific enumeration among existing enumerations of the given package + * @param pkg the package in which look for the Enumeration + * @param enumType the enumeration to match + * @return the enumeration already defined + */ + private Enumeration getExistingEnumerationForEnumType(Package pkg, EnumType enumType) { + + EList<Enumeration> enumerations = getEnumerations(pkg); + + if (enumerations.size() > 0) { + Set<String> enumValues = getListValuesForEnumType(enumType); + + for (Enumeration enumeration : enumerations) { + if (enumValues.equals(getListValuesForEnumeration(enumeration))) { + return enumeration; + } + } + } + return null; + } + + /** + * Creates a new Enumeration as requested + * @param pkg the package where to create the Enumeration + * @param enumType the type specifying the values + * @return the created Enumeration + */ + private Enumeration createEnumerationFromEnumType(Package pkg, EnumType enumType) { + + // Create the name using an incremental value + final String enumerationName = ENUMERATION_NAME + (getEnumerations(pkg).size() + 1); + + TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(pkg); + domain.getCommandStack().execute(new RecordingCommand(domain) { + + @Override + protected void doExecute() { + + Enumeration enumeration = pkg.createOwnedEnumeration(enumerationName); + Set<String> values = getListValuesForEnumType(enumType); + for (String string : values) { + enumeration.createOwnedLiteral(string); + } + } + }); + + Type type = pkg.getOwnedType(enumerationName); + printMessageOnOut("Type '" + type.getQualifiedName() + "' created."); + return (Enumeration) type; + } + + /** + * Returns an Enumeration as requested + * @param enumType the type containing the specifications + * @return the requested type + */ + private Type getEnumerationType(EnumType enumType) { + Type type = null; + Package pkg = sysView; // Or compView, where to look for and create the type + + // Look for existing Enumerations in the package + type = getExistingEnumerationForEnumType(pkg, enumType); + + if (type != null) { + + // The type has been found in the package, use it + printMessageOnOut("Type '" + type.getQualifiedName() + "' found."); + return type; + } else { + return createEnumerationFromEnumType(pkg, enumType); + } + } + + /** + * Looks for a Signal already defined in the package + * @param pkg the package in which look for the Signal + * @return the Signal already defined + */ + private Signal getExistingSignalType(Package pkg) { + final EList<Type> types = pkg.getOwnedTypes(); + + for (Type type : types) { + if (type instanceof Signal) { + return (Signal) type; + } + } + return null; + } + + /** + * Creates a Signal type in the given package + * @param pkg the package where to create the Enumeration + * @return the newly created type + */ + private Signal createSignalType(Package pkg) { + final String signalName = SIGNAL_NAME; + + TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(pkg); + domain.getCommandStack().execute(new RecordingCommand(domain) { + + @Override + protected void doExecute() { + + pkg.createOwnedType(signalName, UMLPackage.Literals.SIGNAL); + } + }); + + Type type = pkg.getOwnedType(signalName); + printMessageOnOut("Type '" + type.getQualifiedName() + "' created."); + return (Signal) type; + } + + /** + * Returns a Signal as requested (Only a Signal can be defined in the package) + * @return the requested type + */ + private Type getSignalType() { + Type type = null; + Package pkg = sysView; // Or compView, where to look for and create the type + + // Look for existing Signal Type in the package + type = getExistingSignalType(pkg); + + if (type != null) { + + // The type has been found in the package, use it + printMessageOnOut("Type '" + type.getQualifiedName() + "' found."); + return type; + } else { + return createSignalType(pkg); + } + } + + /** + * Returns the correct Type given the DSL SimpleType + * @param dslSimpleType the type from OSS + * @return the UML Type + */ + private Type getTypeFromDSLType(SimpleType dslSimpleType) { + + if (dslSimpleType instanceof BooleanType) { + printMessageOnOut("BooleanType"); + return getPrimitiveType("Boolean"); + } else if (dslSimpleType instanceof IntegerType) { + printMessageOnOut("IntegerType"); + return getPrimitiveType("Integer"); + } else if (dslSimpleType instanceof RealType) { + printMessageOnOut("RealType"); + return getPrimitiveType("Real"); + } else if (dslSimpleType instanceof WordType) { + printMessageOnOut("WordType"); + } else if (dslSimpleType instanceof UnsignedWordType) { + printMessageOnOut("UnsignedWordType"); + } else if (dslSimpleType instanceof SignedWordType) { + printMessageOnOut("SignedWordType"); + } else if (dslSimpleType instanceof ContinuousType) { + printMessageOnOut("ContinuousType"); + return getContinuousType("Continuous"); + } else if (dslSimpleType instanceof EventType) { + printMessageOnOut("EventType"); + return getSignalType(); + } else if (dslSimpleType instanceof RangeType) { + printMessageOnOut("RangeType"); + return getBoundedSubType((RangeType) dslSimpleType); + } else if (dslSimpleType instanceof EnumType) { + printMessageOnOut("EnumType"); + return getEnumerationType((EnumType) dslSimpleType); + } else if (dslSimpleType instanceof ArrayType) { + printMessageOnOut("ArrayType"); + } else if (dslSimpleType instanceof IntegerArrayType) { + printMessageOnOut("IntegerArrayType"); + } else if (dslSimpleType instanceof WordArrayType) { + printMessageOnOut("WordArrayType"); + } + System.err.println("Import Error: Not able to map the requested DSL type!"); + return null; + } + + /** + * Creates and adds a Port to the model + * @param owner the parent Class + * @param elementName the name of the port to create + * @param elementType the type of the port to create + * @param isInput tells the direction of the flow + * @return the created Port + */ + private org.eclipse.uml2.uml.Port createPort(Class owner, VariableId elementName, SimpleType elementType, boolean isInput) { + final String portName = elementName.getName(); + final Type portType = getTypeFromDSLType(elementType); + + if(portType == null) { + showMessage("Not able to map the requested type for port : " + portName); +// return null; // Create the port anyway, without type + } + + TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(owner); + domain.getCommandStack().execute(new RecordingCommand(domain) { + + @Override + protected void doExecute() { + org.eclipse.uml2.uml.Port umlPort = owner.createOwnedPort(portName, portType); + Stereotype stereotype = UMLUtils.applyStereotype(umlPort, FLOWPORT); + umlPort.setAggregation(AggregationKind.get(AggregationKind.COMPOSITE)); //FIXME: e' sempre cosi? + FlowPort flowPort = (FlowPort) umlPort.getStereotypeApplication(stereotype); + flowPort.setDirection(isInput? FlowDirection.IN: FlowDirection.OUT); + } + }); + + printMessageOnOut("\n\nCreated " + portName + " Port\n\n"); + return owner.getOwnedPort(portName, portType); + } + + /** + * Creates a System Block element in the given package + * @param owner the Package that will contain the element + * @param elementName the name of the new System Block + * @return the created Class + */ + private Class createSystemBlock(Package owner, final String elementName) { + + TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(owner); + domain.getCommandStack().execute(new RecordingCommand(domain) { + + @Override + protected void doExecute() { + Class sysBlock = owner.createOwnedClass(elementName, false); + UMLUtils.applyStereotype(sysBlock, BLOCK); + UMLUtils.applyStereotype(sysBlock, SYSTEM); + } + }); + + printMessageOnOut("\n\nCreated " + elementName + " System Block\n\n"); + return (Class) owner.getPackagedElement(elementName); + } + + /** + * Creates a Contract element + * @param owner the Class that will contain the element + * @param contractName the name of the new Contract + * @return the newly created Class + */ + private Class createContract(Class owner, String contractName) { + + printMessageOnOut("\n\n\n Creating contract " + contractName + " for owner " + owner); + printMessageOnOut("\n\n\n"); + + TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(owner); + domain.getCommandStack().execute(new RecordingCommand(domain) { + + @Override + protected void doExecute() { + Class newUmlClass = UMLFactory.eINSTANCE.createClass(); + Classifier newClass = owner.createNestedClassifier(contractName, newUmlClass.eClass()); + UMLUtils.applyStereotype(newClass, CONTRACT); + } + }); + + printMessageOnOut("\n\nCreated " + contractName + " Property\n\n"); + + return (Class) owner.getNestedClassifier(contractName); + } + + /** + * Creates a Block element in the given package + * @param owner the Package that will contain the element + * @param elementName the name of the new Block + * @return the newly created Class + */ + private Class createBlock(Package owner, final String elementName) { + + TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(owner); + domain.getCommandStack().execute(new RecordingCommand(domain) { + + @Override + protected void doExecute() { + Class out = owner.createOwnedClass(elementName, false); + UMLUtils.applyStereotype(out, BLOCK); + +// owner.createPackagedElement(elementName, newUMLClass.eClass()); This also works... +// owner.getPackagedElements().add(newUMLClass); // This works too! + } + }); + + printMessageOnOut("\n\nCreated " + elementName + " Block\n\n"); + return (Class) owner.getPackagedElement(elementName); // Return the first occurence + } + + /** + * Adds a contract refinement to a contract property + * @param contractProperty the property to be enriched + * @param umlRefinement the refinement to add + */ + private void addContractRefinementToContractProperty(ContractProperty contractProperty, DataType umlRefinement) { + final Stereotype stereotype = umlRefinement.getAppliedStereotype(CONTRACT_REFINEMENT); + final ContractRefinement contractRefinement = (ContractRefinement) umlRefinement.getStereotypeApplication(stereotype); + + TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(contractProperty); + domain.getCommandStack().execute(new RecordingCommand(domain) { + + @Override + protected void doExecute() { + + // Add the new refinement to the list + contractProperty.getRefinedBy().add(contractRefinement); + } + }); + } + + /** + * Creates a connector, but doesn't add it to the owner + * @param owner the owner element + * @return the created Connector + */ + private Connector createConnector(Class owner) { + + // Create the name using an incremental value + final String connectorName = CONNECTOR_NAME + (owner.getOwnedConnectors().size() + 1); + + printMessageOnOut("\n\n\n Creating connector " + connectorName + " for owner " + owner); + printMessageOnOut("\n\n\n"); + + Connector connector = UMLFactory.eINSTANCE.createConnector(); + connector.setName(connectorName); + + printMessageOnOut("\n\nCreated " + connectorName + " Connector\n\n"); + return connector; + } + + /** + * Adds a connector to the given element + * @param owner the owner element + * @param connector the conne + */ + private void addConnector(Class owner, Connector connector) { + + TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(owner); + domain.getCommandStack().execute(new RecordingCommand(domain) { + + @Override + protected void doExecute() { + + // Add the new connector to the list + owner.getOwnedConnectors().add(connector); + } + }); + } + + /** + * Creates an end to the given connector. + * @param owner the owner element + * @param connector the owner Connector + * @param sourceOwner the name of component instance owning the port + * @param sourcePort the name of the port to be connected + * @return the Connector End + */ + private ConnectorEnd createConnectorEnd(Class owner, Connector connector, String sourceOwner, String sourcePort) { + + ConnectorEnd end = connector.createEnd(); + + if (sourceOwner == null) { + + // I'm the owner of the port + org.eclipse.uml2.uml.Port port = owner.getOwnedPort(sourcePort, null); + end.setRole(port); + end.setPartWithPort(null); + } else { + + // Retrieve the component instance containing the port and set it + Property componentInstance = getUMLComponentInstance(owner, sourceOwner); + end.setPartWithPort(componentInstance); + + // Now I have to get the port object from the owning element + // Get the component type + String typeName = componentInstance.getType().getName(); + + // Remove the optional suffix +// typeName = typeName.substring(0, typeName.indexOf(SUFFIX)); + + // Get the component object containing the definition of the port + final Class portOwner = dslTypeToComponent.get(typeName); + + // Get the port and set it + org.eclipse.uml2.uml.Port port = portOwner.getOwnedPort(sourcePort, null); + end.setRole(port); + } + + return end; + } + + /** + * Parses the Refinements of the component + * @param dslParentComponent the AST Component owning the refinement + * @param dslComponentRefinement the Refinement element to be parsed + */ + private void parseRefinements(AbstractComponent dslParentComponent, Refinement dslComponentRefinement) { + + // Get all the RefinementInstances of the Refinement + final EList<RefinementInstance> dslRefInstances = dslComponentRefinement.getRefinements(); + + // If some RefinementInstances are present, loop on them + if ((dslRefInstances != null) && !dslRefInstances.isEmpty()) { + for (RefinementInstance dslRefInstance : dslRefInstances) { + + // Process the different types of refinements + if (dslRefInstance != null && dslRefInstance.getSubcomponent() != null) { + + // SUB processing + final String subName = dslRefInstance.getSubcomponent().getName(); + final String subType = dslRefInstance.getSubcomponent().getType(); + + printMessageOnOut("\tsubcomponent name = " + subName); + printMessageOnOut("\tsubcomponent type = " + subType); + + createComponentInstance(dslTypeToComponent.get(dslParentComponent.getType()), subName, (Type) dslTypeToComponent.get(subType)); + } else if (dslRefInstance != null && dslRefInstance.getConnection() != null) { + + // CONNECTION processing + final Connection connection = dslRefInstance.getConnection(); + final VariableId variable = connection.getVariable(); + final Expression constraint = connection.getConstraint(); + Connector connector = null; + + // Create the source end + if (constraint instanceof PortId) { //FIXME: c'e' anche il ParameterId + + // Create a connector, but only after I'm sure it isn't a delegation constraint + connector = createConnector(dslTypeToComponent.get(dslParentComponent.getType())); + + final String portOwner = ((PortId) constraint).getComponentName(); + final String portName = ((PortId) constraint).getName(); + printMessageOnOut("Creating source end " + portOwner + ":" + portName); + createConnectorEnd(dslTypeToComponent.get(dslParentComponent.getType()), connector, portOwner, portName); + } else if (constraint instanceof Expression) { + + // Create a delegation constraint, can be a LogicalExpression, IntegerLiteral, AddSubExpression, ... + createDelegationConstraint(dslTypeToComponent.get(dslParentComponent.getType()), variable, constraint); + continue; // No need to go ahead in the processing + } else { + + // Unknown type of connection + System.err.println("Constraint = " + constraint); + showMessage("Import Error: Not able to recognize the connection type " + constraint.getValue()); + continue; + } + + // Create the target end + if (variable instanceof PortId) { + final String portOwner = ((PortId) variable).getComponentName(); + final String portName = ((PortId) variable).getName(); + printMessageOnOut("Creating target end " + portOwner + ":" + portName); + createConnectorEnd(dslTypeToComponent.get(dslParentComponent.getType()), connector, portOwner, portName); + } + + // At last, add the connector to the owner + addConnector(dslTypeToComponent.get(dslParentComponent.getType()), connector); + + } else if (dslRefInstance != null && dslRefInstance.getRefinedby() != null) { + + // REFINEDBY processing + final RefinedBy refinement = dslRefInstance.getRefinedby(); + final String refinedContract = refinement.getName(); + + printMessageOnOut("\n\n\nContract name = " + refinedContract + " from " + dslTypeToComponent.get(dslParentComponent.getType()).getName()); + + ContractProperty contractProperty = getContractPropertyFromContract(dslTypeToComponent.get(dslParentComponent.getType()), refinedContract); + + // Alternative version using a library function +// Property p = ContractEntityUtil.getInstance().getUmlContractPropertyOfUmlComponentFromContractPropertyType(dslTypeToComponent.get(dslParentComponent.getType()), refinedContract); +// ContractProperty cp = ContractEntityUtil.getInstance().getContractProperty(p); + + // Create a ContractRefinement for each ContractId found + final EList<ContractId> contractIds = refinement.getContractIds(); + for (ContractId contractId : contractIds) { + printMessageOnOut("\n\tContractID = " + contractId.getComponentName() + "." + contractId.getName()); + final DataType umlRefinement = createContractRefinement(dslTypeToComponent.get(dslParentComponent.getType()), contractId.getComponentName(), contractId.getName()); + addContractRefinementToContractProperty(contractProperty, umlRefinement); + } + } else if (dslRefInstance != null && dslRefInstance.getFormula() != null) { + + // CONSTRAINT processing + //TODO: implement this +// showMessage("Found a CONSTRAINT tag, don't know how to handle it!"); + System.err.println("Import Error: Found a CONSTRAINT tag, don't know how to handle it!"); + } else if (dslRefInstance != null && dslRefInstance.getProp() != null) { + + // PROP processing + //TODO: implement this +// showMessage("Found a PROP tag, don't know how to handle it!"); + System.err.println("Import Error: Found a PROP tag, don't know how to handle it!"); + } + } + } + } + + /** + * Gets the expression string from the Expression constraint + * @param constraint the expression to convert + */ + private String getConstraintText(Expression constraint) { + final String text = serializer.serialize(constraint); + + return text.trim(); + } + + /** + * Returns a name for the ContractProperty, deriving it from the Contract type + * @param contract the contract from which it derives + * @return a derived name, going lowercase + */ + private String getContractPropertyName(Class contract) { + String contractName = contract.getName(); +// contractName = contractName.substring(contractName.indexOf('_') + 1); + + if (contractName.length() > 0) { + return contractName.toLowerCase(); + } else { + return ((Contract) contract).getName().toLowerCase(); + } + } + + /** + * Parses the Interfaces of the component + * @param dslParentComponent the AST Component owning the refinement + * @param dslComponentInterface the Interface element to be parsed + */ + private void parseInterfaces(AbstractComponent dslParentComponent, Interface dslComponentInterface) { + + // Get all the InterfaceInstances of the Interface + final EList<InterfaceInstance> dslIntInstances = dslComponentInterface.getInterfaces(); + + // If some InterfaceInstances are present, loop on them + if ((dslIntInstances != null) && !dslIntInstances.isEmpty()) { + for (InterfaceInstance dslIntInstance : dslIntInstances) { + + // Process the different types of interfaces + if (dslIntInstance != null && dslIntInstance.getVariable() != null) { + + final Variable dslVariable = dslIntInstance.getVariable(); + + if (dslVariable instanceof Port) { + + // PORT processing + final VariableId dslVariableID = dslVariable.getId(); + final SimpleType dslVariableType = dslVariable.getType(); + + if (dslVariable instanceof InputPort) { + createPort(dslTypeToComponent.get(dslParentComponent.getType()), dslVariableID, dslVariableType, true); + } else if (dslVariable instanceof OutputPort) { + createPort(dslTypeToComponent.get(dslParentComponent.getType()), dslVariableID, dslVariableType, false); + } + + } else if (dslVariable instanceof Parameter) { + + // PARAMETER processing + //TODO: implement this +// showMessage("Found a PARAMETER tag, don't know how to handle it!"); + System.err.println("Import Error: Found a PARAMETER tag, don't know how to handle it!"); + } else if (dslVariable instanceof Operation) { + + // PROVIDED OPERATION processing + //TODO: implement this +// showMessage("Found a OPERATION tag, don't know how to handle it!"); + System.err.println("Import Error: Found a OPERATION tag, don't know how to handle it!"); + } + } else if (dslIntInstance != null && dslIntInstance.getDefine() != null) { + + // DEFINE processing + //TODO: implement this +// showMessage("Found a DEFINE tag, don't know how to handle it!"); + System.err.println("Import Error: Found a DEFINE tag, don't know how to handle it!"); + } else if (dslIntInstance != null && dslIntInstance.getContract() != null) { + + // CONTRACT processing + final Contract dslContract = dslIntInstance.getContract(); + final Assumption dslAssumption = dslContract.getAssumption(); + final Guarantee dslGuarantee = dslContract.getGuarantee(); + + // Create an empty Contract + Class contract = createContract(dslTypeToComponent.get(dslParentComponent.getType()), dslContract.getName()); + + // Add the two Formal Properties + ContractEntityUtil.getInstance().saveFormalProperty("Assume", getConstraintText(dslAssumption.getConstraint()), contract); + ContractEntityUtil.getInstance().saveFormalProperty("Guarantee", getConstraintText(dslGuarantee.getConstraint()), contract); + + // Create a Contract Property + String contractPropertyName = getContractPropertyName(contract); + createContractProperty(dslTypeToComponent.get(dslParentComponent.getType()), contractPropertyName, (Type) contract); + } + } + } + } + + /** Navigates the component and processes its interfaces + * @param dslParentComponent the element in the tree + */ + private void parseComponentInterfaces(AbstractComponent dslParentComponent) { + + printMessageOnOut("\n\n\nParsing Interfaces for " + dslParentComponent.getType() + "\n"); + + // Get the Interfaces, if any + final Interface dslComponentInterface = dslParentComponent.getInterface(); + if (dslComponentInterface != null) { + parseInterfaces(dslParentComponent, dslComponentInterface); + } + } + + /** Navigates the component and processes its refinements + * @param dslParentComponent the element in the tree + */ + private void parseComponentRefinements(AbstractComponent dslParentComponent) { + + printMessageOnOut("\n\n\nParsing Refinements for " + dslParentComponent.getType() + "\n"); + + // Get the Refinement, if any + final Refinement dslComponentRefinement = dslParentComponent.getRefinement(); + if (dslComponentRefinement != null) { + parseRefinements(dslParentComponent, dslComponentRefinement); + } + } + + /** + * Converts an Iterator to a Collection + */ + private <T> Collection<T> iterator2Collection(final Iterator<T> iter) { + ArrayList<T> list = new ArrayList<T>(); + for (; iter.hasNext();) { + T item = iter.next(); + list.add(item); + } + return list; + } + + /** + * Returns the package having the stereotype CHESS::Core::CHESSViews::SystemView + * @return org.eclipse.uml2.uml.Package + */ + private Package getSystemView() { + + Platform.getBundle(" "); //? + UmlModel umlModel = UmlUtils.getUmlModel(); + + printMessageOnOut("UML Model name = " + umlModel.getIdentifier()); + + TreeIterator<EObject> allElements = umlModel.getResource().getAllContents(); + if (allElements != null) { + Collection<Package> packages = + EcoreUtil.getObjectsByType(iterator2Collection(allElements), UMLPackage.eINSTANCE.getPackage()); + + for (Package p : packages) { + if(p.getAppliedStereotype(SYSVIEW) != null){ + printMessageOnOut("Found systemView!"); + navigatePackage(p); + return p; + } + } + } + System.err.println("Import Error: SystemView not found!"); + return null; + } + + /** + * Returns the package having the stereotype CHESS::Core::CHESSViews::SystemView + * @return org.eclipse.uml2.uml.Package + */ + private Package getComponentView() { + + Platform.getBundle(" "); //? + UmlModel umlModel = UmlUtils.getUmlModel(); + + printMessageOnOut("UML Model name = " + umlModel.getIdentifier()); + + TreeIterator<EObject> allElements = umlModel.getResource().getAllContents(); + if (allElements != null) { + Collection<Package> packages = + EcoreUtil.getObjectsByType(iterator2Collection(allElements), UMLPackage.eINSTANCE.getPackage()); + + for (Package p : packages) { + if(p.getAppliedStereotype(COMPVIEW) != null){ + printMessageOnOut("Found componentView!"); + navigatePackage(p); + return p; + } + } + } + System.err.println("Import Error: ComponentView not found!"); + return null; + } + + /* Utility to browse a package */ + private void navigatePackage(Package pkg) { + printMessageOnOut("Package name = " + pkg.getName()); + + // Display profiles + EList<Profile> profs = pkg.getAppliedProfiles(); + for(Profile prof : profs) { + printMessageOnOut("\tprofile.name = " + prof.getName()); + } + + // Display stereotypes + EList<Stereotype> stList = pkg.getAppliedStereotypes(); + for (Stereotype stereotype : stList) { + printMessageOnOut("\tstereotype.name = " + stereotype.getName()); + } + + // Display members and their stereotypes + EList<NamedElement> namedList = pkg.getMembers(); + for (NamedElement namedElement : namedList) { + printMessageOnOut("\tmember.name = " + namedElement.getName()); + + EList<Stereotype> nStList = namedElement.getAppliedStereotypes(); + for (Stereotype stereotype : nStList) { + printMessageOnOut("\t\tstereotype.name = " + stereotype.getName()); + } + } + + // Loop on its nested packages + EList<Package> pkgList = pkg.getNestedPackages(); + for (Package p : pkgList) { + navigatePackage(p); + } + } + + /** + * Main method to be invoked to parse an OSS file + * @throws Exception + */ + public void startParsing(Package pkg, File ossFile) throws Exception { + + OSS ocraOssFile; +// File ossFile; + + sysView = pkg; // Set the given package as working package + +// ossFile = new File("/hardmnt/nemesis0/home/cristofo/Downloads/System.oss"); +// ossFile = getOSSFile(); + if (ossFile != null) { + ocraOssFile = getOssModel(ossFile); + } else { + return; + } + + // Retrieve the SystemComponent + SystemComponent dslSystemComponent = ocraOssFile.getSystem(); + + if (dslSystemComponent == null) { + System.err.println("Import Error: System component is missing"); + showMessage("System component is missing"); + return; + } + + //Retrieve SystemView and ComponentView packages +// sysView = getSystemView(); +// compView = getComponentView(); + + // For the specific WBS example, go inside a particular package +// EList<Package> pkgList = sysView.getNestedPackages(); +// for (Package p : pkgList) { +// if (p.getName().equals("PhysicalArchitecture")) { +// sysView = p; +// break; +// } +// } + + // If the OCRA system component type is not defined, set it to 'System' + final String dslSystemComponentName = dslSystemComponent.getType() == null ? "System" : dslSystemComponent.getType(); + dslSystemComponent.setType(dslSystemComponentName); + + printMessageOnOut("dslSystemComponent.type = " + dslSystemComponentName); + + // Add the systemComponent to the package + Class systemComponent = createSystemBlock(sysView, dslSystemComponent.getType()); +// Class systemComponent = createSystemBlock(sysView, dslSystemComponent.getType() + SUFFIX); + + // Store the systemComponent in a hash with its name + dslTypeToComponent.put(dslSystemComponentName, systemComponent); + + // Populate the map and the package with the other Component elements + for (Component dslComponent : ocraOssFile.getComponents()) { + Class component = createBlock(sysView, dslComponent.getType()); +// Class component = createBlock(sysView, dslComponent.getType() + SUFFIX); + if(dslTypeToComponent.put(dslComponent.getType(), component) != null) { + printMessageOnOut("Duplicated component type, not added: " + dslComponent.getType()); + } else { + printMessageOnOut("component.type = " + dslComponent.getType()); + } + } + + // Now I have created all the Blocks in the package, loop on them, but not getting them from + // the package (it may be polluted with other blocks), but from the OSS model again. + + // parse the system component + parseComponentInterfaces(dslSystemComponent); + + // Parse all the other components + for (Component dslComponent : ocraOssFile.getComponents()) { + parseComponentInterfaces(dslComponent); + } + + // parse the system component + parseComponentRefinements(dslSystemComponent); + + // Parse all the other components + for (Component dslComponent : ocraOssFile.getComponents()) { + parseComponentRefinements(dslComponent); + } + } +} diff --git a/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/commands/.gitignore b/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/commands/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e7b16a14daeac40293a07d1a5fd5c4c7b1d5d578 --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/commands/.gitignore @@ -0,0 +1 @@ +/CreateIBDSingleCommand_app.java diff --git a/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/commands/AddOSSFileCommand.java b/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/commands/AddOSSFileCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..bf45328eb31bdb5cf7a5479a6959cc61db801f0c --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/commands/AddOSSFileCommand.java @@ -0,0 +1,241 @@ +package org.polarsys.chess.OSSImporter.commands; + +import java.io.File; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.IHandler; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.emf.common.util.Diagnostic; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.Diagnostician; +import org.eclipse.emf.edit.ui.action.ValidateAction.EclipseResourcesUtil; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.HandlerUtil; +import org.polarsys.chess.OSSImporter.actions.ImportOSSFileAction; +import org.polarsys.chess.service.utils.SelectionUtil; +import org.eclipse.uml2.uml.Package; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.resource.XtextResourceSet; + +import eu.fbk.eclipse.standardtools.ModelTranslatorToOcra.exceptions.NoResourceException; +import eu.fbk.eclipse.standardtools.ModelTranslatorToOcra.utils.OCRARuntimeErrorsDialogUtil; +import eu.fbk.eclipse.standardtools.commands.AbstractJobCommand; + + +public class AddOSSFileCommand extends AbstractJobCommand implements IHandler { + private static final String SYSVIEW = "CHESS::Core::CHESSViews::SystemView"; + private static final String PROBLEMS_VIEW = "org.eclipse.ui.views.ProblemView"; + + private ImportOSSFileAction sampleView; + private Object umlObject; + private File ossFile; + private Resource modelResource; + private boolean showNoErrorPopup = true; + private OCRARuntimeErrorsDialogUtil ocraRuntimeErrorsDialogUtil = OCRARuntimeErrorsDialogUtil.getInstance(); + private SelectionUtil selectionUtil = SelectionUtil.getInstance(); + + public AddOSSFileCommand() { + super("Add content from OSS file"); + } + + public String[] showOSSRuntimeErrors(Resource resource, File file, boolean showNoErrorPopup, IProgressMonitor monitor) throws NoResourceException { + if (resource != null) { + if (file != null) { + if (file.exists()) { + monitor.subTask("show Runtime Errors"); + String[] errors = showRuntimeErrors(resource, file); + ocraRuntimeErrorsDialogUtil.showMessage_RuntimeErrors(file.getName(), errors, showNoErrorPopup); + monitor.worked(1); + + return errors; + } + } + } else { + throw new NoResourceException(); + } + return null; + } + /** + * It visualizes all the errors in the error view of Eclipse. + */ + private String[] showRuntimeErrors(Resource resource, File ossFile) { + + XtextResource xTextRes = getXtextResourceFromFile(ossFile.getPath()); + + EclipseResourcesUtil eclipseResourcesUtil = new EclipseResourcesUtil(); + eclipseResourcesUtil.deleteMarkers(resource); + Diagnostic diagnostic = Diagnostician.INSTANCE.validate(xTextRes.getContents().get(0)); + if (diagnostic.getChildren().size() > 0) { + + for (Diagnostic d : diagnostic.getChildren()) { + eclipseResourcesUtil.createMarkers(resource, d); + } + + openProblemsView(); + + return getErrorsString(diagnostic); + } + return null; + } + + private void openProblemsView() { + Display defaultDisplay = Display.getDefault(); + + defaultDisplay.syncExec(new Runnable() { + @Override + public void run() { + try { + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(PROBLEMS_VIEW); + } catch (PartInitException e) { + e.printStackTrace(); + } + } + }); + } + + private String[] getErrorsString(Diagnostic diagnostic) { + String[] errors = new String[diagnostic.getChildren().size()]; + int i = 0; + for (Diagnostic d : diagnostic.getChildren()) { + errors[i] = d.getMessage(); + i++; + } + return errors; + } + + /** + * @param path + * the path of the oss file + * @return the XTextResource of the oss model + */ + private XtextResource getXtextResourceFromFile(String path) { + final XtextResourceSet resourceSet = new XtextResourceSet(); + resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE); + return (XtextResource) resourceSet.getResource(URI.createFileURI(path), true); + + } + + + /** + * Checks if the given OSS file is valid or contains errors + */ + private String[] showRuntimeErrors(Resource resource, File ossFile, boolean showNoErrorPopup, IProgressMonitor monitor) throws Exception { + + monitor.beginTask("Show Runtime Errors", 1); + + String[] errors = showOSSRuntimeErrors(resource, ossFile,showNoErrorPopup, monitor); + + monitor.done(); + + return errors; + } + + /** + * Utility dialog to display a message on screen + * @param message the text to display + */ + private void showMessage(String message) { + MessageDialog.openInformation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "OSS parser", message); + } + + /** + * Displays a file dialog to select the OSS file + * @return the selected File + */ + private File getOSSFile() { + File ossFile = null; + + FileDialog dialog = new FileDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), SWT.OPEN); + dialog.setFilterExtensions(new String [] {"*.oss", "*.OSS"}); + String result = dialog.open(); + + try { + ossFile = new File(result); + } catch (NullPointerException e) { + e.printStackTrace(); + showMessage("File not valid!"); + } + return ossFile; + } + + /** + * Checks if the selected object is a package in the <<SystemView>> branch + * @param pkg the selected object + * @return true if the package is valid + */ + private boolean objectIsSystemViewPackage(Object obj) { + if (obj instanceof Package) { + final Package pkg = (Package) obj; + if(pkg.getAppliedStereotype(SYSVIEW) != null) { + return true; + } else { + EList<Package> owningPackages = pkg.allOwningPackages(); + for (Package owningPackage : owningPackages) { + if (owningPackage.getAppliedStereotype(SYSVIEW) != null) { + return true; + } + } + } + } + return false; + } + + @Override + public void execPreJobOperations(ExecutionEvent event, IProgressMonitor monitor) throws Exception { + + final ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().getSelection(); + umlObject = selectionUtil.getUmlSelectedObject(selection); + modelResource = selectionUtil.getSelectedModelResource(); + + System.out.println("selectedUmlElement: " + umlObject); + + if (objectIsSystemViewPackage(umlObject)) { + ossFile = getOSSFile(); +// ossFile = new File("/hardmnt/nemesis0/home/cristofo/Downloads/System_simple.oss"); + + String[] errors = showRuntimeErrors(modelResource, ossFile, showNoErrorPopup, monitor); + + monitor.beginTask("Importing elements from OSS file", 1); + + sampleView = ImportOSSFileAction.getInstance(); + + if (errors == null && sampleView != null) { + IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + activePage.setEditorAreaVisible(false); + sampleView.startParsing((Package) umlObject, ossFile); + activePage.setEditorAreaVisible(true); + } + + monitor.done(); + + showMessage("Import done!"); + + return; + + } + showMessage("Please select a package from <<SystemView>>"); + } + + @Override + public void execJobCommand(ExecutionEvent event, IProgressMonitor monitor) throws Exception { + +// String[] errors = showRuntimeErrors(modelResource, ossFile, showNoErrorPopup, monitor); +// +// monitor.beginTask("Importing elements from OSS file", 1); +// +// if (errors == null && sampleView != null) { +// sampleView.startParsing((Package) umlObject, ossFile); +// } +// +// monitor.done(); + } +} diff --git a/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/parser/LazyStringInputStream.java b/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/parser/LazyStringInputStream.java new file mode 100644 index 0000000000000000000000000000000000000000..90311dffd0bf8e7f6e9167753292613e22d5fdee --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/parser/LazyStringInputStream.java @@ -0,0 +1,108 @@ +package org.polarsys.chess.OSSImporter.parser; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; + + +/** + * An input stream based on a string that keeps a reference to the string + * itself and converts it to bytes only on demand. + * + * @author Sebastian Zarnekow - Initial contribution and API + * + * @since 2.5 + */ +public class LazyStringInputStream extends InputStream { + + private InputStream delegate; + private String string; + private String encoding; + + public LazyStringInputStream(String string) { + this(string, Charset.defaultCharset().name()); + } + + public LazyStringInputStream(String string, Charset encoding) { + this(string, encoding.name()); + } + + public LazyStringInputStream(String string, String encoding) { + this.string = string; + this.encoding = encoding; + } + + @Override + public int read() throws IOException { + return delegate().read(); + } + + private InputStream delegate() throws IOException { + if (delegate == null) { + delegate = new StringInputStream(string, encoding); + } + return delegate; + } + + @Override + public int read(byte[] b) throws IOException { + return delegate().read(b); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return delegate().read(b, off, len); + } + + @Override + public long skip(long n) throws IOException { + return delegate().skip(n); + } + + @Override + public int available() throws IOException { + return delegate().available(); + } + + @Override + public void close() throws IOException { + delegate().close(); + } + + @Override + public synchronized void mark(int readlimit) { + try { + delegate().mark(readlimit); + } catch (IOException e) { + throw new RuntimeException(); + } + } + + @Override + public synchronized void reset() throws IOException { + delegate().reset(); + } + + @Override + public boolean markSupported() { + try { + return delegate().markSupported(); + } catch (IOException e) { + return false; + } + } + + @Override + public String toString() { + return string; + } + + public String getString() { + return string; + } + + public String getEncoding() { + return encoding; + } + +} diff --git a/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/parser/ParseHelper.java b/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/parser/ParseHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..e34218713785214722782b0c83fcff43691bcfad --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/parser/ParseHelper.java @@ -0,0 +1,68 @@ +package org.polarsys.chess.OSSImporter.parser; + +/******************************************************************************* + * Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others. + * 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 + *******************************************************************************/ + + +import java.io.InputStream; +import java.util.Map; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.xtext.resource.FileExtensionProvider; + +import com.google.inject.Inject; + +/** + * Some convenience methods for parsing (i.e. testing, etc.) + * + * @author Sven Efftinge - Initial contribution and API + */ +public class ParseHelper<T extends EObject> { + + @Inject + private ResourceHelper resourceHelper; + + public String fileExtension; + + @Inject + public void setFileExtensionProvider(FileExtensionProvider extensionProvider) { + fileExtension = extensionProvider.getPrimaryFileExtension(); + } + + @SuppressWarnings("unchecked") + public T parse(InputStream in, URI uriToUse, Map<?, ?> options, ResourceSet resourceSet) { + resourceHelper.setFileExtension(fileExtension); + Resource resource = resourceHelper.resource(in, uriToUse, options, resourceSet); + final T root = (T) (resource.getContents().isEmpty() ? null : resource.getContents().get(0)); + return root; + } + + public T parse(CharSequence text) throws Exception { + return parse(text, resourceHelper.createResourceSet()); + } + + public T parse(CharSequence text, ResourceSet resourceSetToUse) throws Exception { + return parse(getAsStream(text), computeUnusedUri(resourceSetToUse), null, resourceSetToUse); + } + + public T parse(CharSequence text, URI uriToUse, ResourceSet resourceSetToUse) throws Exception { + return parse(getAsStream(text), uriToUse, null, resourceSetToUse); + } + + protected URI computeUnusedUri(ResourceSet resourceSet) { + return resourceHelper.computeUnusedUri(resourceSet); + } + + protected InputStream getAsStream(CharSequence text) { + return resourceHelper.getAsStream(text); + } + +} diff --git a/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/parser/ResourceHelper.java b/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/parser/ResourceHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..c0e37fbdc59e874ae09160624cc8194b8045d20a --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/parser/ResourceHelper.java @@ -0,0 +1,94 @@ +package org.polarsys.chess.OSSImporter.parser; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.common.util.WrappedException; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.xtext.resource.FileExtensionProvider; +import org.eclipse.xtext.resource.IResourceFactory; +import org.eclipse.xtext.resource.XtextResourceSet; +//import org.eclipse.xtext.util.LazyStringInputStream; + +import com.google.inject.Inject; +import com.google.inject.Provider; + +/** + * Convenience to create resource from text. + * Useful if you want to avoid calls to {@link Resource#getContents()} before + * all resources are available in the resource set. + * + * @author Sebastian Zarnekow - Initial contribution and API + */ +public class ResourceHelper { + + @Inject + private Provider<XtextResourceSet> resourceSetProvider; + + @Inject + private IResourceFactory resourceFactory; + + private String fileExtension; + + @Inject + public void setFileExtensionProvider(FileExtensionProvider extensionProvider) { + fileExtension = extensionProvider.getPrimaryFileExtension(); + } + + void setFileExtension(String fileExtension) { + this.fileExtension = fileExtension; + } + + public Resource resource(InputStream in, URI uriToUse, Map<?, ?> options, ResourceSet resourceSet) { + Resource resource = resourceFactory.createResource(uriToUse); + resourceSet.getResources().add(resource); + try { + resource.load(in, options); + return resource; + } catch (IOException e) { + throw new WrappedException(e); + } + } + + public Resource resource(CharSequence text) throws Exception { + return resource(text, createResourceSet()); + } + + public Resource resource(CharSequence text, ResourceSet resourceSetToUse) throws Exception { + return resource(getAsStream(text), computeUnusedUri(resourceSetToUse), null, resourceSetToUse); + } + + public Resource resource(CharSequence text, URI uriToUse, ResourceSet resourceSetToUse) throws Exception { + return resource(getAsStream(text), uriToUse, null, resourceSetToUse); + } + + public Resource resource(CharSequence text, URI uriToUse) throws Exception { + return resource(getAsStream(text), uriToUse, null, createResourceSet()); + } + + protected URI computeUnusedUri(ResourceSet resourceSet) { + String name = "__synthetic"; + for (int i = 0; i < Integer.MAX_VALUE; i++) { + URI syntheticUri = URI.createURI(name + i + "." + fileExtension); + if (resourceSet.getResource(syntheticUri, false) == null) + return syntheticUri; + } + throw new IllegalStateException(); + } + + protected InputStream getAsStream(CharSequence text) { + return new LazyStringInputStream(text == null ? "" : text.toString()); + } + + protected String getFileExtension() { + return fileExtension; + } + + protected XtextResourceSet createResourceSet() { + return resourceSetProvider.get(); + } + +} diff --git a/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/parser/StringInputStream.java b/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/parser/StringInputStream.java new file mode 100644 index 0000000000000000000000000000000000000000..79dbfaba1bbd209102b5d8c027552aaf72361dc2 --- /dev/null +++ b/plugins/org.polarsys.chess.OSSImporter/src/org/polarsys/chess/OSSImporter/parser/StringInputStream.java @@ -0,0 +1,20 @@ +package org.polarsys.chess.OSSImporter.parser; + +import java.io.ByteArrayInputStream; +import java.io.UnsupportedEncodingException; + +/** + * @author Dennis H�bner - Initial contribution and API + * @author Jan Koehnlein + */ +public class StringInputStream extends ByteArrayInputStream { + + public StringInputStream(String string) { + super(string.getBytes()); + } + + public StringInputStream(String content, String encoding) throws UnsupportedEncodingException { + super(content.getBytes(encoding)); + } + +}