/*
Copyright (C) 2009 by Claas Wilke (info@claaswilke.de)
This file is part of the Generic Model Instance Type Test Suite 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.modelinstancetype.test;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.dresdenocl.testsuite._abstract.AbstractDresdenOclTest;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;
import org.dresdenocl.essentialocl.EssentialOclPlugin;
import org.dresdenocl.facade.Ocl2ForEclipseFacade;
import org.dresdenocl.metamodels.uml2.UML2MetamodelPlugin;
import org.dresdenocl.model.IModel;
import org.dresdenocl.model.ModelAccessException;
import org.dresdenocl.model.metamodel.IMetamodel;
import org.dresdenocl.modelbus.ModelBusPlugin;
import org.dresdenocl.modelinstance.IModelInstance;
import org.dresdenocl.modelinstance.IModelInstanceProvider;
import org.dresdenocl.modelinstance.IModelInstanceType;
import org.dresdenocl.modelinstancetype.test.msg.ModelInstanceTypeTestSuiteMessages;
import org.dresdenocl.modelinstancetype.test.testmodel.TestModelTypesNames;
import org.dresdenocl.modelinstancetype.types.IModelInstanceObject;
import org.dresdenocl.pivotmodel.PivotModelFactory;
import org.dresdenocl.pivotmodel.Property;
import org.dresdenocl.pivotmodel.Type;
/**
* <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 ModelInstanceTypeTestServices {
/** The ID of the {@link IMetamodel} which shall be tested. */
private static final String META_MODEL_ID = UML2MetamodelPlugin.ID;
/**
* The ID of the {@link Bundle} providing the {@link IModel} which shall be
* used for testing.
*/
private static final String MODEL_BUNDLE_ID = ModelInstanceTypeTestPlugin.PLUGIN_ID;
/**
* The path of the {@link IModel} which shall be used for testing.
*/
private static final String MODEL_PATH = "resources/testmodel.uml";
/** The only instance of {@link ModelInstanceTypeTestServices}. */
private static ModelInstanceTypeTestServices myInstance;
/**
* Contains the already loaded {@link IModelInstance}s identified by their
* {@link File} represented as a {@link String}.
*/
private Map<String, IModelInstance> myCachedModelInstances = new HashMap<String, IModelInstance>();
/**
* The {@link IModel}s used during testing;
*/
protected IModel myModel;
/**
* The ID of the {@link Bundle} providing the {@link IModelInstance} which
* shall be tested.
*/
private String myModelInstanceBundleId;
/** The path of the {@link IModelInstance} which shall be tested. */
private String myModelInstancePath;
/** The ID of the {@link IModelInstanceType} which shall be tested. */
private String myModelInstanceTypeId;
/**
* Indicates, how many boolean {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
*/
private int myBooleanPropertyCounter = 1;
/**
* Indicates, how many integer {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
*/
private int myIntegerPropertyCounter = 1;
/**
* Indicates, how many integer {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
*/
private int myRealPropertyCounter = 1;
/**
* Indicates, how many integer {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
*/
private int myStringPropertyCounter = 1;
/**
* Indicates, how many bag {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
*/
private int myBagPropertyCounter = 1;
/**
* Indicates, how many OrderedSet {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
*/
private int myOrderedSetPropertyCounter = 1;
/**
* Indicates, how many Sequence {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
*/
private int mySequencePropertyCounter = 1;
/**
* Indicates, how many Set {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
*/
private int mySetPropertyCounter = 1;
/**
* <p>
* The private constructor.
* </p>
*/
private ModelInstanceTypeTestServices() {
}
public static ModelInstanceTypeTestServices getInstance() {
/* Probably create the instance. */
if (myInstance == null) {
myInstance = new ModelInstanceTypeTestServices();
}
// no else.
return myInstance;
}
/**
* <p>
* Indicates, how many bag {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
* </p>
*
* @return How many bag {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
*/
public int getBagPropertyCounter() {
return myBagPropertyCounter;
}
/**
* <p>
* Indicates, how many boolean {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
* </p>
*
* @return Indicates, how many boolean {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
*/
public int getBooleanPropertyCounter() {
return this.myBooleanPropertyCounter;
}
/**
* <p>
* Returns an empty {@link IModelInstance} of the current
* {@link IModelInstanceType} under test.
* </p>
*
* @return An empty {@link IModelInstance}.
*/
public IModelInstance getEmptyModelInstance() {
IModelInstance result;
/* Load the IModel first. */
if (this.myModel == null) {
this.loadModel();
}
// no else.
/* Check if the model has been loaded. */
if (this.myModel != null) {
try {
result = Ocl2ForEclipseFacade.getEmptyModelInstance(
this.myModel, this.myModelInstanceTypeId);
}
// end try.
catch (IllegalArgumentException e) {
throw new RuntimeException(e.getMessage(), e);
}
catch (ModelAccessException e) {
throw new RuntimeException(e.getMessage(), e);
}
// end catch.
}
else {
String msg;
msg = ModelInstanceTypeTestSuiteMessages.ModelInstanceTypeTestSuite_Services_ModelWasNull;
throw new RuntimeException(msg);
}
return result;
}
/**
* <p>
* Indicates, how many integer {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
* </p>
*
* @return Indicates, how many integer {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
*/
public int getIntegerPropertyCounter() {
return this.myIntegerPropertyCounter;
}
/**
* <p>
* Returns all {@link IModelInstanceObject}s of a given {@link Type} that
* are part of the current {@link IModelInstance} under test.
* </p>
*
* @param type
* The {@link Type} whose {@link IModelInstanceObject}s shall be
* returned.
* @return All {@link IModelInstanceObject}s of the given {@link Type}, if
* any.
*/
public Set<IModelInstanceObject> getModelInstanceObjectsOfType(Type type) {
return this.getModelInstance().getAllInstances(type);
}
/**
* <p>
* Returns the {@link IModelInstance} which can be loaded by the current
* settings of {@link ModelInstanceTypeTestServices#myModelInstanceTypeId},
* {@link ModelInstanceTypeTestServices#myModelInstanceBundleId}, and
* {@link ModelInstanceTypeTestServices#myModelInstancePath}.
* </p>
*
* @return The current {@link IModelInstance} or <code>null</code>.
*/
public IModelInstance getModelInstance() {
IModelInstance result;
/* Load the IModel first. */
if (this.myModel == null) {
this.loadModel();
}
// no else.
File modelInstanceFile;
try {
modelInstanceFile = AbstractDresdenOclTest.getFile(
this.myModelInstancePath, this.myModelInstanceBundleId);
} catch (IOException e1) {
throw new RuntimeException(e1.getMessage(), e1);
}
/* Check if the model instance has already been loaded. */
if (this.myCachedModelInstances.containsKey(modelInstanceFile
.toString())) {
result = this.myCachedModelInstances.get(modelInstanceFile
.toString());
}
/* Else check if the given file does not exist. */
else if (!modelInstanceFile.exists()) {
String msg;
msg = ModelInstanceTypeTestSuiteMessages.ModelInstanceTypeTestSuite_Services_ModelInstanceFileNotFound;
msg = NLS.bind(msg, this.myModelInstancePath,
this.myModelInstanceBundleId);
throw new RuntimeException(msg);
}
/* Else try to load the model instance. */
else {
try {
/* Check if the model has been loaded. */
if (this.myModel != null) {
result = Ocl2ForEclipseFacade.getModelInstance(
modelInstanceFile, this.myModel,
this.myModelInstanceTypeId);
/* Cache the result. */
this.myCachedModelInstances.put(
modelInstanceFile.toString(), result);
}
else {
String msg;
msg = ModelInstanceTypeTestSuiteMessages.ModelInstanceTypeTestSuite_Services_ModelWasNull;
throw new RuntimeException(msg);
}
}
catch (ModelAccessException e) {
throw new RuntimeException(e.getMessage());
}
}
// end else.
return result;
}
/**
* <p>
* Returns the {@link IModelInstanceProvider} of the current
* {@link IModelInstanceType} under test.
* </p>
*
* @return The {@link IModelInstanceProvider} of the current
* {@link IModelInstanceType} under test.
*/
public IModelInstanceProvider getModelInstanceProvider() {
return ModelBusPlugin.getModelInstanceTypeRegistry()
.getModelInstanceType(this.myModelInstanceTypeId)
.getModelInstanceProvider();
}
/**
* <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 getModelType(String qualifiedName) {
Type result;
/* Probably load the model. */
if (this.myModel == null) {
this.loadModel();
}
// no else.
/* Get the type to test. */
try {
result = this.myModel
.findType(convertQualifiedNameToQualifiedNameList(qualifiedName));
}
catch (ModelAccessException e) {
throw new RuntimeException(e.getMessage());
}
return result;
}
/**
* <p>
* Returns the {@link IModel} used for testing.
* </p>
*
* @return The {@link IModel} used for testing.
*/
public IModel getModelUnderTest() {
return this.myModel;
}
/**
* <p>
* Indicates, how many OrderedSet {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
* </p>
*
* @return How many OrderedSet {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
*/
public int getOrderedSetPropertyCounter() {
return myOrderedSetPropertyCounter;
}
/**
* <p>
* Indicates, how many real {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
* </p>
*
* @return Indicates, how many real {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
*/
public int getRealPropertyCounter() {
return this.myRealPropertyCounter;
}
/**
* <p>
* Indicates, how many Sequence {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
* </p>
*
* @return How many Sequence {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
*/
public int getSequencePropertyCounter() {
return mySequencePropertyCounter;
}
/**
* <p>
* Indicates, how many Set {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
* </p>
*
* @return How many Set {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
*/
public int getSetPropertyCounter() {
return mySetPropertyCounter;
}
/**
* <p>
* Indicates, how many string {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
* </p>
*
* @return Indicates, how many string {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
*/
public int getStringPropertyCounter() {
return this.myStringPropertyCounter;
}
/**
* <p>
* Sets how many Bag {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
* </p>
*
* @param bagPropertyCounter
* How many bag {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
*/
public void setBagPropertyCounter(int bagPropertyCounter) {
this.myBagPropertyCounter = bagPropertyCounter;
}
/**
* <p>
* Sets how many boolean {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
* </p>
*
* @param booleanPropertyCounter
* The count how many boolean {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
*/
public void setBooleanPropertyCounter(int booleanPropertyCounter) {
this.myBooleanPropertyCounter = booleanPropertyCounter;
}
/**
* <p>
* Sets how many OrderedSet {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
* </p>
*
* @param orderedSetPropertyCounter
* How many OrderedSet {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
*/
public void setOrderedSetPropertyCounter(int orderedSetPropertyCounter) {
this.myOrderedSetPropertyCounter = orderedSetPropertyCounter;
}
/**
* <p>
* Sets how many Integer {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
* </p>
*
* @param integerPropertyCounter
* The count how many Integer {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
*/
public void setIntegerPropertyCounter(int integerPropertyCounter) {
this.myIntegerPropertyCounter = integerPropertyCounter;
}
/**
* <p>
* Sets how many Real {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
* </p>
*
* @param realPropertyCounter
* The count how many Real {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
*/
public void setRealPropertyCounter(int realPropertyCounter) {
this.myRealPropertyCounter = realPropertyCounter;
}
/**
* <p>
* Sets how many Sequence {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
* </p>
*
* @param sequencePropertyCounter
* How many Sequence {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
*/
public void setSequencePropertyCounter(int sequencePropertyCounter) {
this.mySequencePropertyCounter = sequencePropertyCounter;
}
/**
* <p>
* Sets how many Set {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
* </p>
*
* @param setPropertyCounter
* How many Set {@link Property}s the
* <code>CollectionTypeProviderClass</code> has.
*/
public void setSetPropertyCounter(int setPropertyCounter) {
this.mySetPropertyCounter = setPropertyCounter;
}
/**
* <p>
* Sets how many String {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
* </p>
*
* @param stringPropertyCounter
* The count how many String {@link Property}s the
* <code>PrimitiveTypeProviderClass</code> has.
*/
public void setStringPropertyCounter(int stringPropertyCounter) {
this.myStringPropertyCounter = stringPropertyCounter;
}
/**
* <p>
* Sets the ID of the {@link Bundle} providing the {@link IModelInstance}
* which shall be tested.
* </p>
*
* @param testModelBundleID
* The ID of the {@link Bundle} providing the
* {@link IModelInstance} which shall be tested.
*/
public void setTestModelInstanceBundleID(String testModelBundleID) {
this.myModelInstanceBundleId = testModelBundleID;
}
/**
* <p>
* Sets the path of the {@link IModelInstance} which shall be tested.
* </p>
*
* @param testModelPath
* The path of the {@link IModelInstance} which shall be tested.
*/
public void setTestModelInstancePath(String testModelPath) {
this.myModelInstancePath = testModelPath;
}
/**
* <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 setModelInstanceTypeID(String modelInstanceTypeId) {
this.myModelInstanceTypeId = modelInstanceTypeId;
}
/**
* <p>
* A helper method that probably adds some additional {@link Property}s to
* {@link Type}s in the {@link IModel}. E.g., to provide more than one
* boolean {@link Property} to test different adaptations.
* </p>
*/
private void addPropertiesToTestModel() {
Type primitiveTypeProviderClass;
Type collectionTypeProviderClass;
primitiveTypeProviderClass = this
.getModelType(TestModelTypesNames.TYPE_NAME_PRIMITIVE_TYPE_PROVIDER_CLASS);
collectionTypeProviderClass = this
.getModelType(TestModelTypesNames.TYPE_NAME_COLLECTION_TYPE_PROVIDER_CLASS);
if (primitiveTypeProviderClass != null) {
/* Probably add additional boolean properties to the model. */
for (int index = 2; index <= getBooleanPropertyCounter(); index++) {
Property aProperty;
aProperty = PivotModelFactory.eINSTANCE.createProperty();
aProperty.setName("booleanProperty" + index);
aProperty.setType(EssentialOclPlugin.getOclLibraryProvider()
.getOclLibrary().getOclBoolean());
primitiveTypeProviderClass.addProperty(aProperty);
}
/* Probably add additional integer properties to the model. */
for (int index = 2; index <= getIntegerPropertyCounter(); index++) {
Property aProperty;
aProperty = PivotModelFactory.eINSTANCE.createProperty();
aProperty.setName("integerProperty" + index);
aProperty.setType(EssentialOclPlugin.getOclLibraryProvider()
.getOclLibrary().getOclInteger());
primitiveTypeProviderClass.addProperty(aProperty);
}
/* Probably add additional real properties to the model. */
for (int index = 2; index <= getRealPropertyCounter(); index++) {
Property aProperty;
aProperty = PivotModelFactory.eINSTANCE.createProperty();
aProperty.setName("realProperty" + index);
aProperty.setType(EssentialOclPlugin.getOclLibraryProvider()
.getOclLibrary().getOclReal());
primitiveTypeProviderClass.addProperty(aProperty);
}
/* Probably add additional string properties to the model. */
for (int index = 2; index <= getStringPropertyCounter(); index++) {
Property aProperty;
aProperty = PivotModelFactory.eINSTANCE.createProperty();
aProperty.setName("stringProperty" + index);
aProperty.setType(EssentialOclPlugin.getOclLibraryProvider()
.getOclLibrary().getOclString());
primitiveTypeProviderClass.addProperty(aProperty);
}
}
// no else.
if (collectionTypeProviderClass != null) {
/* Probably add additional bag properties to the model. */
for (int index = 2; index <= getBagPropertyCounter(); index++) {
Property aProperty;
aProperty = PivotModelFactory.eINSTANCE.createProperty();
aProperty.setName("bagProperty" + index);
aProperty.setType(EssentialOclPlugin
.getOclLibraryProvider()
.getOclLibrary()
.getBagType(
EssentialOclPlugin.getOclLibraryProvider()
.getOclLibrary().getOclAny()));
collectionTypeProviderClass.addProperty(aProperty);
}
/* Probably add additional ordered set properties to the model. */
for (int index = 2; index <= getOrderedSetPropertyCounter(); index++) {
Property aProperty;
aProperty = PivotModelFactory.eINSTANCE.createProperty();
aProperty.setName("orderedSetProperty" + index);
aProperty.setType(EssentialOclPlugin
.getOclLibraryProvider()
.getOclLibrary()
.getOrderedSetType(
EssentialOclPlugin.getOclLibraryProvider()
.getOclLibrary().getOclAny()));
collectionTypeProviderClass.addProperty(aProperty);
}
/* Probably add additional sequence properties to the model. */
for (int index = 2; index <= getSequencePropertyCounter(); index++) {
Property aProperty;
aProperty = PivotModelFactory.eINSTANCE.createProperty();
aProperty.setName("sequenceProperty" + index);
aProperty.setType(EssentialOclPlugin
.getOclLibraryProvider()
.getOclLibrary()
.getSequenceType(
EssentialOclPlugin.getOclLibraryProvider()
.getOclLibrary().getOclAny()));
collectionTypeProviderClass.addProperty(aProperty);
}
/* Probably add additional set properties to the model. */
for (int index = 2; index <= getBagPropertyCounter(); index++) {
Property aProperty;
aProperty = PivotModelFactory.eINSTANCE.createProperty();
aProperty.setName("setProperty" + index);
aProperty.setType(EssentialOclPlugin
.getOclLibraryProvider()
.getOclLibrary()
.getSetType(
EssentialOclPlugin.getOclLibraryProvider()
.getOclLibrary().getOclAny()));
collectionTypeProviderClass.addProperty(aProperty);
}
}
// no else.
}
/**
* <p>
* Converts a given qualified name into a {@link List} describing its
* qualified name in the {@link IModel}.
*
* @param qualifiedName
* The qualifiedName name that shall be converted.
* @return The converted qualified name.
*/
private List<String> convertQualifiedNameToQualifiedNameList(
String qualifiedName) {
List<String> result;
result = new ArrayList<String>();
for (String aPackagesName : qualifiedName.split("::")) {
result.add(aPackagesName);
}
return result;
}
/**
* <p>
* A helper method that loads the {@link IModel} required for testing.
* </p>
*/
private void loadModel() {
/* Check if the model has already been loaded. */
if (this.myModel == null) {
try {
File modelFile = AbstractDresdenOclTest.getFile(MODEL_PATH,
MODEL_BUNDLE_ID);
this.myModel = Ocl2ForEclipseFacade.getModel(modelFile,
META_MODEL_ID);
this.addPropertiesToTestModel();
}
catch (ModelAccessException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
// no else. Model has already been loaded.
}
}