/* * Copyright (C) 2009 by Claas Wilke (claaswilke@gmx.net) This file is part of * the Meta Model Architecture of Dresden OCL2 for Eclipse. Dresden OCL2 for * Eclipse is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. Dresden OCL2 for Eclipse is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with Dresden OCL2 for Eclipse. If * not, see <http://www.gnu.org/licenses/>. */ package org.dresdenocl.metamodels.test; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.dresdenocl.facade.Ocl2ForEclipseFacade; import org.dresdenocl.model.IModel; import org.dresdenocl.model.ModelAccessException; import org.dresdenocl.model.ModelConstants; import org.dresdenocl.model.metamodel.IMetamodel; import org.dresdenocl.pivotmodel.EnumerationLiteral; import org.dresdenocl.pivotmodel.Namespace; import org.dresdenocl.pivotmodel.Operation; import org.dresdenocl.pivotmodel.Parameter; import org.dresdenocl.pivotmodel.PrimitiveType; import org.dresdenocl.pivotmodel.PrimitiveTypeKind; import org.dresdenocl.pivotmodel.Property; import org.dresdenocl.pivotmodel.Type; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Platform; import org.osgi.framework.Bundle; /** * <p> * This class provides some services required for {@link IMetamodel} testing. * </p> * * <p> * This class implements the <code>Singleton</code> pattern. * </p> * * @author Claas Wilke */ public final class MetaModelTestServices { /** The name of the {@link Namespace} <code>package1</code>. */ public static final String NAMESPACE_NAME_PACKAGE1 = "package1"; /** The name of the {@link Namespace} <code>package2</code>. */ public static final String NAMESPACE_NAME_PACKAGE2 = "package2"; /** The name of the {@link Namespace} <code>package1</code>. */ public static final String NAMESPACE_QUALIFIED_NAME_PACKAGE1 = ModelConstants.ROOT_PACKAGE_NAME + "::" + NAMESPACE_NAME_PACKAGE1; /** The name of the {@link Namespace} <code>package2</code>. */ public static final String NAMESPACE_QUALIFIED_NAME_PACKAGE2 = NAMESPACE_QUALIFIED_NAME_PACKAGE1 + "::" + NAMESPACE_NAME_PACKAGE2; /** The name of the {@link Type} <code>TestTypeClass1</code>. */ public static final String TYPE_NAME_TESTTYPECLASS1 = "TestTypeClass1"; /** The name of the {@link Type} <code>TestTypeClass2</code>. */ public static final String TYPE_NAME_TESTTYPECLASS2 = "TestTypeClass2"; /** The name of the {@link Type} <code>TestPropertyClass</code>. */ public static final String TYPE_NAME_TESTPROPERTYCLASS = "TestPropertyClass"; /** * The name of the {@link Type} <code>TestOperationAndParameterClass</code>. */ public static final String TYPE_NAME_TESTOPERATIONANDPARAMETERCLASS = "TestOperationAndParameterClass"; /** The name of the {@link Type} <code>TestPrimitiveTypeClass</code>. */ public static final String TYPE_NAME_TESTPRIMITIVETYPECLASS = "TestPrimitiveTypeClass"; /** The name of the {@link Type} <code>TestTypeInterface1</code>. */ public static final String TYPE_NAME_TESTTYPEINTERFACE1 = "TestTypeInterface1"; /** The name of the {@link Type} <code>TestTypeInterface2</code>. */ public static final String TYPE_NAME_TESTTYPEINTERFACE2 = "TestTypeInterface2"; /** The qualified name of the {@link Type} <code>TestTypeClass1</code>. */ public static final String TYPE_QUALIFIED_NAME_TESTTYPECLASS1 = NAMESPACE_QUALIFIED_NAME_PACKAGE1 + "::" + TYPE_NAME_TESTTYPECLASS1; /** The qualified name of the {@link Type} <code>TestTypeClass2</code>. */ public static final String TYPE_QUALIFIED_NAME_TESTTYPECLASS2 = NAMESPACE_QUALIFIED_NAME_PACKAGE1 + "::" + TYPE_NAME_TESTTYPECLASS2; /** The qualified name of the {@link Type} <code>TestPropertyClass</code>. */ public static final String TYPE_QUALIFIED_NAME_TESTPROPERTYCLASS = NAMESPACE_QUALIFIED_NAME_PACKAGE1 + "::" + TYPE_NAME_TESTPROPERTYCLASS; /** * The qualified name of the {@link Type} * <code>TestOperationAndParameterClass</code>. */ public static final String TYPE_QUALIFIED_NAME_TESTOPERATIONANDPARAMETERCLASS = NAMESPACE_QUALIFIED_NAME_PACKAGE1 + "::" + TYPE_NAME_TESTOPERATIONANDPARAMETERCLASS; /** * The qualified name of the {@link Type} * <code>TestPrimitiveTypeClass</code>. */ public static final String TYPE_QUALIFIED_NAME_TESTPRIMITIVETYPECLASS = NAMESPACE_QUALIFIED_NAME_PACKAGE1 + "::" + TYPE_NAME_TESTPRIMITIVETYPECLASS; /** The qualified name of the {@link Type} <code>TestTypeInterface1</code>. */ public static final String TYPE_QUALIFIED_NAME_TESTTYPEINTERFACE1 = NAMESPACE_QUALIFIED_NAME_PACKAGE1 + "::" + TYPE_NAME_TESTTYPEINTERFACE1; /** The qualified name of the {@link Type} <code>TestTypeInterface2</code>. */ public static final String TYPE_QUALIFIED_NAME_TESTTYPEINTERFACE2 = NAMESPACE_QUALIFIED_NAME_PACKAGE1 + "::" + TYPE_NAME_TESTTYPEINTERFACE2; /** The name of the {@link Type} <code>TestEnumeration</code>. */ public static final String ENUMERATION_NAME_ENUMERATION1 = "TestEnumeration"; /** The qualified name of the {@link Type} <code>TestEnumeration</code>. */ public static final String ENUMERATION_QUALIFIED_NAME_ENUMERATION1 = NAMESPACE_QUALIFIED_NAME_PACKAGE1 + "::" + ENUMERATION_NAME_ENUMERATION1; /** * The name of the {@link EnumerationLiteral} <code>TestLiteral1</code>. */ public static final String ENUMERATIONLITERAL_NAME_ENUMERATIONLITERAL1 = "TestLiteral1"; /** * The name of the {@link EnumerationLiteral} <code>TestLiteral2</code>. */ public static final String ENUMERATIONLITERAL_NAME_ENUMERATIONLITERAL2 = "TestLiteral2"; /** * The qualified name of the {@link EnumerationLiteral} * <code>TestLiteral1</code>. */ public static final String ENUMERATIONLITERAL_QUALIFIED_NAME_ENUMERATIONLITERAL1 = ENUMERATION_QUALIFIED_NAME_ENUMERATION1 + "::" + ENUMERATIONLITERAL_NAME_ENUMERATIONLITERAL1; /** * The qualified name of the {@link EnumerationLiteral} * <code>TestLiteral2</code>. */ public static final String ENUMERATIONLITERAL_QUALIFIED_NAME_ENUMERATIONLITERAL2 = ENUMERATION_QUALIFIED_NAME_ENUMERATION1 + "::" + ENUMERATIONLITERAL_NAME_ENUMERATIONLITERAL2; /** The name of the {@link Operation} <code>operation1</code>. */ public static final String OPERATION_NAME_OPERATION1 = "operation1"; /** The name of the {@link Operation} <code>operation2</code>. */ public static final String OPERATION_NAME_OPERATION2 = "operation2"; /** * The name of the {@link Operation} <code>operationWithoutParameters</code> * . */ public static final String OPERATION_NAME_OPERATIONWITHOUTPARAMETERS = "operationWithoutParameters"; /** * The name of the {@link Operation} <code>voidOperationWithParameter</code> * . */ public static final String OPERATION_NAME_VOIDOPERATIONWITHPARAMETER = "voidOperationWithParameter"; /** * The name of the {@link Operation} * <code>inputOutputParameterOperation</code>. */ public static final String OPERATION_NAME_INPUTOUTPUTPARAMETEROPERATION = "inputOutputParameterOperation"; /** The name of the {@link Operation} <code>outputParameterOperation</code>. */ public static final String OPERATION_NAME_OUTPUTPARAMETEROPERATION = "outputParameterOperation"; /** The name of the {@link Operation} <code>staticOperation</code>. */ public static final String OPERATION_NAME_STATICOPERATION = "staticOperation"; /** The name of the {@link Operation} <code>multipleOperation</code>. */ public static final String OPERATION_NAME_MULTIPLEOPERATION = "multipleOperation"; /** The name of the {@link Operation} <code>orderedMultipleOperation</code>. */ public static final String OPERATION_NAME_ORDEREDMULTIPLEOPERATION = "orderedMultipleOperation"; /** * The name of the {@link Operation} <code>unorderedMultipleOperation</code> * . */ public static final String OPERATION_NAME_UNORDEREDMULTIPLEOPERATION = "unorderedMultipleOperation"; /** The name of the {@link Operation} <code>uniqueMultipleOperation</code>. */ public static final String OPERATION_NAME_UNIQUEMULTIPLEOPERATION = "uniqueMultipleOperation"; /** * The name of the {@link Operation} <code>nonuniqueMultipleOperation</code> * . */ public static final String OPERATION_NAME_NONUNIQUEMULTIPLEOPERATION = "nonuniqueMultipleOperation"; /** * The name of the {@link Operation} <code>operationWithoutParameters</code> * . */ public static final String OPERATION_QUALIFIED_NAME_OPERATIONWITHOUTPARAMETERS = TYPE_QUALIFIED_NAME_TESTOPERATIONANDPARAMETERCLASS + "::" + OPERATION_NAME_OPERATIONWITHOUTPARAMETERS + "()"; /** * The name of the {@link Operation} <code>voidOperationWithParameter</code> * . */ public static final String OPERATION_QUALIFIED_NAME_VOIDOPERATIONWITHPARAMETER = TYPE_QUALIFIED_NAME_TESTOPERATIONANDPARAMETERCLASS + "::" + OPERATION_NAME_VOIDOPERATIONWITHPARAMETER + "(" + TYPE_QUALIFIED_NAME_TESTTYPECLASS1 + ")"; /** The name of the {@link Property} <code>associationEnd1</code>. */ public static final String PROPERTY_NAME_ASSOCIATONEND1 = "associationEnd1"; /** The name of the {@link Property} <code>associationEnd</code>. */ public static final String PROPERTY_NAME_NONMULTIPLEASSOCIATONEND = "nonmultipleAssociationEnd"; /** The name of the {@link Property} <code>property1</code>. */ public static final String PROPERTY_NAME_PROPERTY1 = "property1"; /** The name of the {@link Property} <code>property2</code>. */ public static final String PROPERTY_NAME_PROPERTY2 = "property2"; /** The name of the {@link Property} <code>nonmultipleProperty</code>. */ public static final String PROPERTY_NAME_NONMULTIPLEPROPERTY = "nonmultipleProperty"; /** The name of the {@link Property} <code>staticAssociationEnd</code>. */ public static final String PROPERTY_NAME_STATICASSOCIATONEND = "staticAssociationEnd"; /** The name of the {@link Property} <code>staticProperty</code>. */ public static final String PROPERTY_NAME_STATICPROPERTY = "staticProperty"; /** * The name of the {@link Property} * <code>orderedMultipleAssociationEnd</code> . */ public static final String PROPERTY_NAME_ORDEREDMULTIPLEASSOCIATONEND = "orderedMultipleAssociationEnd"; /** The name of the {@link Property} <code>orderedMultipleProperty</code>. */ public static final String PROPERTY_NAME_ORDEREDMULTIPLEPROPERTY = "orderedMultipleProperty"; /** * The name of the {@link Property} * <code>unorderedMultipleAssociationEnd</code>. */ public static final String PROPERTY_NAME_UNORDEREDMULTIPLEASSOCIATONEND = "unorderedMultipleAssociationEnd"; /** The name of the {@link Property} <code>unorderedMultipleProperty</code>. */ public static final String PROPERTY_NAME_UNORDEREDMULTIPLEPROPERTY = "unorderedMultipleProperty"; /** * The name of the {@link Property} * <code>uniqueMultipleAssociationEnd</code>. */ public static final String PROPERTY_NAME_UNIQUEMULTIPLEASSOCIATONEND = "uniqueMultipleAssociationEnd"; /** The name of the {@link Property} <code>uniqueMultipleProperty</code>. */ public static final String PROPERTY_NAME_UNIQUEMULTIPLEPROPERTY = "uniqueMultipleProperty"; /** * The name of the {@link Property} * <code>nonuniqueMultipleAssociationEnd</code>. */ public static final String PROPERTY_NAME_NONUNIQUEMULTIPLEASSOCIATONEND = "nonuniqueMultipleAssociationEnd"; /** The name of the {@link Property} <code>nonuniqueMultipleProperty</code>. */ public static final String PROPERTY_NAME_NONUNIQUEMULTIPLEPROPERTY = "nonuniqueMultipleProperty"; /** The name of the {@link Property} <code>nonmultipleProperty</code>. */ public static final String PROPERTY_QUALIFIED_NAME_NONMULTIPLEPROPERTY = TYPE_QUALIFIED_NAME_TESTPROPERTYCLASS + "::" + PROPERTY_NAME_NONMULTIPLEPROPERTY; /** The name of the {@link Property} <code>nonmultipleAssociationEnd</code>. */ public static final String PROPERTY_QUALIFIED_NAME_NONMULTIPLEASSOCIATIONEND = TYPE_QUALIFIED_NAME_TESTPROPERTYCLASS + "::" + PROPERTY_NAME_NONMULTIPLEASSOCIATONEND; /** * The name of the {@link Property} * <code>unorderedMultipleAssociationEnd</code>. */ public static final String PROPERTY_NAME_IDENTIFIER = "identifierProperty"; /** The name of the {@link Property} <code>unorderedMultipleProperty</code>. */ public static final String PROPERTY_NAME_NONIDENTIFIER = "nonidentifierProperty"; /** The name of the {@link Parameter} <code>in1</code>. */ public static final String PARAMETER_NAME_INPUTPARAMETER1 = "in1"; /** The name of the {@link Parameter} <code>in1</code>. */ public static final String PARAMETER_QUALIFIED_NAME_INPUTPARAMETER1 = OPERATION_QUALIFIED_NAME_VOIDOPERATIONWITHPARAMETER + "::" + PARAMETER_NAME_INPUTPARAMETER1; /** * The prefix of {@link Property}s that represent a {@link PrimitiveType} of * the {@link PrimitiveTypeKind#BOOLEAN} which shall be tested. */ public static final String PRIMITIVETYPE_BOOLEAN_PROPERTY_PREFIX = "aBoolean"; /** * The prefix of {@link Property}s that represent a {@link PrimitiveType} of * the {@link PrimitiveTypeKind#INTEGER} which shall be tested. */ public static final String PRIMITIVETYPE_INTEGER_PROPERTY_PREFIX = "anInteger"; /** * The prefix of {@link Property}s that represent a {@link PrimitiveType} of * the {@link PrimitiveTypeKind#REAL} which shall be tested. */ public static final String PRIMITIVETYPE_REAL_PROPERTY_PREFIX = "aReal"; /** * The prefix of {@link Property}s that represent a {@link PrimitiveType} of * the {@link PrimitiveTypeKind#STRING} which shall be tested. */ public static final String PRIMITIVETYPE_STRING_PROPERTY_PREFIX = "aString"; /** * Indicates whether or not the first letter of a package name must be * capitalized. */ public static boolean capitalizePackageNames = false; /** * Indicates whether or not an adapted metamodel supports operations. */ public static boolean supportsNoOperations = false; /** * Indicates whether or not an adapted metamodel supports inheritance. */ public static boolean supportsNoInheritances = false; /** The only instance of {@link MetaModelTestServices}. */ private static MetaModelTestServices myInstance; /** * Contains the already loaded {@link IModel}s identified by their * {@link File} represented as a {@link String}. */ private Map<String, IModel> myCachedModels; /** The ID of the {@link IMetamodel} which shall be tested. */ private String myMetaModelId; /** * The ID of the {@link Bundle} providing the {@link IModel} which shall be * tested. */ private String myTestModelBundleId; /** The path of the {@link IModel} which shall be tested. */ private String myTestModelPath; /** * <p> * The private constructor. * </p> */ private MetaModelTestServices() { this.myCachedModels = new HashMap<String, IModel>(); } public static MetaModelTestServices getInstance() { /* Eventually create the instance. */ if (myInstance == null) { myInstance = new MetaModelTestServices(); } // no else. return myInstance; } /** * Helper method that lower cases a String if the * {@link MetaModelTestServices#capitalizePackageNames} flag is set. * * @param string * The {@link String} to be lower cased. * @return The same {@link String} (probably with a lower cases). */ public static String probablyToLowerCase(String string) { if (string == null || string.length() == 0) return string; else if (capitalizePackageNames) return string.toLowerCase(); else return string; } /** * <p> * Converts a given qualified name into a {@link List} of {@link String}s * (representing the packages and the {@link Type}'s name. * </p> * * @param qualifiedName * The name which shall be converted. * @return The converted path. */ private static List<String> convertQualifiedNameToList(String qualifiedName) { List<String> result; result = new ArrayList<String>(); for (String aPackage : qualifiedName.split("::")) { if (capitalizePackageNames && !(aPackage.equals(ModelConstants.ROOT_PACKAGE_NAME) && result .size() == 0)) result.add(aPackage.substring(0, 1).toUpperCase() + aPackage.substring(1)); else result.add(aPackage); } return result; } /** * <p> * Returns the ID of the {@link IMetamodel} that is currently tested. * </p> * * @return The ID of the {@link IMetamodel} that is currently tested. */ public String getMetaModelUnderTestID() { return this.myMetaModelId; } /** * <p> * Returns the {@link IModel} which can be loaded by the current settings of * <code>MetaModelID</code>, <code>ModelBundleID</code>, and * <code>TestModelPath</code>. * </p> * * @return The current {@link IModel} or <code>null</code>. */ public IModel getModelUnderTest() { IModel result; File modelFile = null; /* Get the bundle location for the model files. */ Bundle bundle = Platform.getBundle(myTestModelBundleId); if (bundle != null) { try { URL url = bundle.getEntry(myTestModelPath); modelFile = new File(FileLocator.toFileURL(url).toURI()); } catch (MalformedURLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /* If started head less, try to find the bundle's location anyway. */ else { File testLocation = new File( System.getProperty("DRESDENOCL_LOCATION_TESTS") + myTestModelBundleId); File eclipseLocation = new File( System.getProperty("DRESDENOCL_LOCATION_ECLIPSE") + myTestModelBundleId); File bundleFile = null; if (testLocation != null && testLocation.exists() && testLocation.isDirectory()) { bundleFile = testLocation; } else if (eclipseLocation != null && eclipseLocation.exists() && eclipseLocation.isDirectory()) { bundleFile = eclipseLocation; } if (bundleFile != null) modelFile = new File(bundleFile + File.separator + myTestModelPath); else throw new RuntimeException("Bundle or directory '" + myTestModelBundleId + "' was not found."); } /* Check if the model has already been loaded. */ if (this.myCachedModels.containsKey(modelFile.toString())) { result = this.myCachedModels.get(modelFile.toString()); } /* Else check if the given file does not exist. */ else if (!modelFile.exists()) { throw new RuntimeException("The file " + modelFile + " does not exist."); } /* Else try to load the model. */ else { try { result = Ocl2ForEclipseFacade .getModel(modelFile, myMetaModelId); /* Cache the result. */ this.myCachedModels.put(modelFile.toString(), result); } catch (ModelAccessException e) { throw new RuntimeException(e.getMessage(), e); } } // end else. return result; } /** * <p> * Searches for a {@link Namespace} in the current {@link IModel} under * test. * </p> * * @param qualifiedName * The qualified name of the {@link Namespace} which shall be * returned. * @return The found {@link Namespace}. */ public Namespace getNamespaceUnderTest(String qualifiedName) { Namespace result; IModel model; /* Get the model. */ model = this.getModelUnderTest(); /* Get the type to test. */ try { result = model .findNamespace(convertQualifiedNameToList(qualifiedName)); } catch (ModelAccessException e) { throw new RuntimeException(e.getMessage()); } return result; } /** * <p> * Searches for a {@link Type} in the current {@link IModel} under test. * </p> * * @param qualifiedName * The qualified name of the {@link Type} which shall be * returned. * @return The found {@link Type}. */ public Type getTypeUnderTest(String qualifiedName) { Type result; IModel model; /* Get the model. */ model = this.getModelUnderTest(); if (capitalizePackageNames) { StringBuffer newQualifiedName = new StringBuffer(); for (String elem : qualifiedName.split("::")) { if (newQualifiedName.length() == 0 && elem.equals(ModelConstants.ROOT_PACKAGE_NAME)) newQualifiedName.append(elem); else { if (newQualifiedName.length() > 0) newQualifiedName.append("::"); // no else. newQualifiedName.append(elem.substring(0, 1).toUpperCase() + elem.substring(1, elem.length())); } } // end for. qualifiedName = newQualifiedName.toString(); } // no else. /* Get the type to test. */ try { result = model.findType(convertQualifiedNameToList(qualifiedName)); } catch (ModelAccessException e) { throw new RuntimeException(e.getMessage()); } return result; } /** * <p> * Sets the ID of the {@link IMetamodel} which shall be tested. * </p> * * @param metaModelID * The ID of the {@link IMetamodel} which shall be tested. */ public void setMetaModelID(String metaModelID) { this.myMetaModelId = metaModelID; } /** * <p> * Sets the ID of the {@link Bundle} providing the {@link IModel} which * shall be tested. * </p> * * @param testModelBundleID * The ID of the {@link Bundle} providing the {@link IModel} * which shall be tested. */ public void setTestModelBundleID(String testModelBundleID) { this.myTestModelBundleId = testModelBundleID; } /** * <p> * Sets the path of the {@link IModel} which shall be tested. * </p> * * @param testModelPath * The path of the {@link IModel} which shall be tested. */ public void setTestModelPath(String testModelPath) { this.myTestModelPath = testModelPath; } }