From 21ec7ddf7e9795f9f292faffe84148253aaad926 Mon Sep 17 00:00:00 2001 From: Max Hohenegger Date: Mon, 19 Dec 2011 17:03:15 +0100 Subject: [PATCH] wrapped delete-call on EObjects inside command, otherwise they are not deleted persistently --- .../test/server/ModelGeneratorTest.java | 15 +- .../META-INF/MANIFEST.MF | 25 +- .../common/ModelGeneratorUtil.java | 1349 +++++++++-------- 3 files changed, 697 insertions(+), 692 deletions(-) diff --git a/org.eclipse.emf.emfstore.client.test/src/org/eclipse/emf/emfstore/client/test/server/ModelGeneratorTest.java b/org.eclipse.emf.emfstore.client.test/src/org/eclipse/emf/emfstore/client/test/server/ModelGeneratorTest.java index 019c223..245a98d 100644 --- a/org.eclipse.emf.emfstore.client.test/src/org/eclipse/emf/emfstore/client/test/server/ModelGeneratorTest.java +++ b/org.eclipse.emf.emfstore.client.test/src/org/eclipse/emf/emfstore/client/test/server/ModelGeneratorTest.java @@ -12,13 +12,11 @@ import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EReference; -import org.eclipse.emf.ecore.resource.ResourceSet; -import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.emfstore.client.model.ProjectSpace; import org.eclipse.emf.emfstore.client.model.Usersession; +import org.eclipse.emf.emfstore.client.model.WorkspaceManager; import org.eclipse.emf.emfstore.client.test.SetupHelper; import org.eclipse.emf.emfstore.common.model.Project; -import org.eclipse.emf.emfstore.common.model.util.ModelUtil; import org.eclipse.emf.emfstore.modelgenerator.ModelGenerator; import org.eclipse.emf.emfstore.modelgenerator.common.ModelGeneratorConfiguration; import org.eclipse.emf.emfstore.modelgenerator.common.ModelGeneratorUtil; @@ -46,15 +44,8 @@ public class ModelGeneratorTest extends ServerTests { public void beforeTest() throws EmfStoreException { super.beforeTest(); - projectSpace = org.eclipse.emf.emfstore.client.model.ModelFactory.eINSTANCE.createProjectSpace(); - projectSpace.setProject(org.eclipse.emf.emfstore.common.model.ModelFactory.eINSTANCE.createProject()); - projectSpace.setProjectName(projectName); - projectSpace.setProjectDescription(projectDescription); - projectSpace.setLocalOperations(org.eclipse.emf.emfstore.client.model.ModelFactory.eINSTANCE - .createOperationComposite()); - ResourceSet resourceSet = new ResourceSetImpl(); - resourceSet.getLoadOptions().putAll(ModelUtil.getResourceLoadOptions()); - projectSpace.initResources(resourceSet); + projectSpace = WorkspaceManager.getInstance().getCurrentWorkspace() + .createLocalProject(projectName, projectDescription); Usersession session = org.eclipse.emf.emfstore.client.model.ModelFactory.eINSTANCE.createUsersession(); session.setServerInfo(SetupHelper.getServerInfo()); diff --git a/org.eclipse.emf.emfstore.modelgenerator.common/META-INF/MANIFEST.MF b/org.eclipse.emf.emfstore.modelgenerator.common/META-INF/MANIFEST.MF index f6d92c9..e6d1bb0 100644 --- a/org.eclipse.emf.emfstore.modelgenerator.common/META-INF/MANIFEST.MF +++ b/org.eclipse.emf.emfstore.modelgenerator.common/META-INF/MANIFEST.MF @@ -1,12 +1,13 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Modelgenerator Common -Bundle-SymbolicName: org.eclipse.emf.emfstore.modelgenerator.common -Bundle-Version: 0.8.9.M9 -Bundle-RequiredExecutionEnvironment: J2SE-1.5 -Export-Package: org.eclipse.emf.emfstore.modelgenerator.common, - org.eclipse.emf.emfstore.modelgenerator.common.attribute -Require-Bundle: org.eclipse.emf.ecore, - org.eclipse.emf.edit -Bundle-ActivationPolicy: lazy -Bundle-Vendor: Eclipse Modeling Project +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Modelgenerator Common +Bundle-SymbolicName: org.eclipse.emf.emfstore.modelgenerator.common +Bundle-Version: 0.8.9.M9 +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Export-Package: org.eclipse.emf.emfstore.modelgenerator.common, + org.eclipse.emf.emfstore.modelgenerator.common.attribute +Require-Bundle: org.eclipse.emf.ecore, + org.eclipse.emf.edit, + org.eclipse.emf.emfstore.client;bundle-version="0.8.9" +Bundle-ActivationPolicy: lazy +Bundle-Vendor: Eclipse Modeling Project diff --git a/org.eclipse.emf.emfstore.modelgenerator.common/src/org/eclipse/emf/emfstore/modelgenerator/common/ModelGeneratorUtil.java b/org.eclipse.emf.emfstore.modelgenerator.common/src/org/eclipse/emf/emfstore/modelgenerator/common/ModelGeneratorUtil.java index 8b072a0..2cd1559 100644 --- a/org.eclipse.emf.emfstore.modelgenerator.common/src/org/eclipse/emf/emfstore/modelgenerator/common/ModelGeneratorUtil.java +++ b/org.eclipse.emf.emfstore.modelgenerator.common/src/org/eclipse/emf/emfstore/modelgenerator/common/ModelGeneratorUtil.java @@ -1,668 +1,681 @@ -/** - * Copyright (c) 2008-2009 Jonas Helming, Maximilian Koegel. 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 - */ -package org.eclipse.emf.emfstore.modelgenerator.common; - -import java.util.Arrays; -import java.util.LinkedList; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.Map.Entry; - -import org.eclipse.emf.common.util.TreeIterator; -import org.eclipse.emf.ecore.EAttribute; -import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EClassifier; -import org.eclipse.emf.ecore.EEnum; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.EPackage; -import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.emf.ecore.EPackage.Registry; -import org.eclipse.emf.ecore.EReference; -import org.eclipse.emf.ecore.EcorePackage; -import org.eclipse.emf.ecore.util.EcoreUtil; -import org.eclipse.emf.edit.command.AddCommand; -import org.eclipse.emf.edit.command.RemoveCommand; -import org.eclipse.emf.edit.command.SetCommand; -import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; -import org.eclipse.emf.edit.domain.EditingDomain; -import org.eclipse.emf.emfstore.modelgenerator.common.attribute.AttributeHandler; -import org.eclipse.emf.emfstore.modelgenerator.common.attribute.IAttributeSetter; - -/** - * Utility class to generate and change Ecore models. - * All methods should be accessed in a static way, - * therefore the constructor is not visible. - */ -public final class ModelGeneratorUtil { - - /** - * Set of all EClasses that are contained in EPackages that are - * currently registered in the EPackage registry. - * - * @see #getAllEClasses() - */ - private static List allEClasses; - - /** - * Set of all EPackages that are currently registered in the - * EPackage registry and not contained in any other package. - * - * @see #getAllRootEPackages() - */ - private static Set rootModelPackages; - - /** - * Map that maps EPackages to a set of all their contained EClasses. - * - * @see #getAllEClasses(EPackage) - */ - private static Map> packageToModelElementEClasses = new LinkedHashMap>(); - - /** - * Map that maps EReferences to all possible EClasses that can be contained - * when using them. - * - * @see #getAllEContainments(EReference) - */ - private static Map> allEContainments = new LinkedHashMap>(); - - /** - * Map that maps EClasses to their subclasses. - * - * @see #getAllSubEClasses(EClass) - */ - private static Map> eClassToSubEClasses = new LinkedHashMap>(); - - /** - * Private constructor. - */ - private ModelGeneratorUtil() { - // all methods should be accessed in a static way - } - - /** - * Returns the EPackage to the specified nsURI. - * - * @param nsURI the NsUri of the EPackage to get - * @return the EPackage belonging to nsURI - * @see Registry#getEPackage(String) - */ - public static EPackage getEPackage(String nsURI) { - return EPackage.Registry.INSTANCE.getEPackage(nsURI); - } - - /** - * Returns all EPackages on the root level that are currently - * registered in the registry. - * - * @return a Set of all root EPackages - * @see Registry - */ - public static Set getAllRootEPackages() { - // were the root packages computed before? - if(rootModelPackages != null) { - return rootModelPackages; - } - rootModelPackages = new LinkedHashSet(); - Registry registry = EPackage.Registry.INSTANCE; - - for (Entry entry : registry.entrySet()) { - EPackage ePackage = registry.getEPackage(entry.getKey()); - // is the current EPackage a root package? - if (ePackage.getESuperPackage() == null){ - rootModelPackages.add(ePackage); - } - } - return rootModelPackages; - } - - /** - * Retrieve all EClasses that are contained in ePackage. - * - * @param ePackage the package to get contained EClasses from - * @return a set of EClasses contained in ePackage - */ - public static List getAllEClasses(EPackage ePackage) { - if(packageToModelElementEClasses.containsKey(ePackage)) { - return packageToModelElementEClasses.get(ePackage); - } - if(ePackage == null) { - packageToModelElementEClasses.put(ePackage, new LinkedList()); - return packageToModelElementEClasses.get(ePackage); - } - List result = new LinkedList(); - // obtain all EClasses from sub packages - for(EPackage subPackage : ePackage.getESubpackages()) { - result.addAll(getAllEClasses(subPackage)); - } - // obtain all EClasses that are direct contents of the EPackage - for(EClassifier classifier : ePackage.getEClassifiers()) { - if(classifier instanceof EClass) { - result.add((EClass) classifier); - } - } - // save the result for upcoming method calls - packageToModelElementEClasses.put(ePackage, result); - return result; - } - - /** - * Iterates over all registered EPackages in order to retrieve all available - * EClasses, excluding abstract classes and interfaces, and returns them as a Set. - * - * @return a set of all EClasses that are contained in registered EPackages - * @see Registry - */ - public static List getAllEClasses() { - // were all EClasses computed before? - if (allEClasses != null) { - return allEClasses; - } - allEClasses = new LinkedList(); - Registry registry = EPackage.Registry.INSTANCE; - // for all registered EPackages - for (Entry entry : registry.entrySet()) { - EPackage ePackage = registry.getEPackage(entry.getKey()); - for(EClass eClass : getAllEClasses(ePackage)) { - // no abstracts or interfaces - if(canHaveInstance(eClass)) { - allEClasses.add(eClass); - } - } - } - return allEClasses; - } - - /** - * Returns all possible EClasses, excluding abstract classes and interfaces, - * that can be contained when using reference. - * - * @param reference the EReference to get containable EClasses for - * @return a set of all EClasses that can be contained when using reference - */ - public static List getAllEContainments(EReference reference) { - if(allEContainments.containsKey(reference)) { - return allEContainments.get(reference); - } - if(reference == null) { - allEContainments.put(reference, new LinkedList()); - return allEContainments.get(reference); - } - List result = new LinkedList(); - EClass referenceType = reference.getEReferenceType(); - // no abstracts or interfaces - if(canHaveInstance(referenceType)) { - result.add(referenceType); - } - // 'referenceType: EObject' allows all kinds of EObjects - if(EcorePackage.eINSTANCE.getEObject().equals(referenceType)) { - return getAllEClasses(); - } - // all sub EClasses can be referenced as well - result.addAll(getAllSubEClasses(referenceType)); - // save the result for upcoming method calls - allEContainments.put(reference, result); - return result; - } - - /** - * Returns whether eClass can be instantiated or not. - * An EClass can be instantiated, if it is neither an interface nor abstract. - * - * @param eClass the EClass in question - * @return whether eClass can be instantiated or not. - */ - public static boolean canHaveInstance(EClass eClass) { - return !eClass.isInterface() && !eClass.isAbstract(); - } - - /** - * Returns all subclasses of an EClass, excluding abstract classes - * and interfaces. - * - * @param eClass the EClass to get subclasses for - * @return all subclasses of eClass - */ - public static List getAllSubEClasses(EClass eClass) { - if(eClassToSubEClasses.containsKey(eClass)) { - return eClassToSubEClasses.get(eClass); - } - if(eClass == null) { - eClassToSubEClasses.put(eClass, new LinkedList()); - return eClassToSubEClasses.get(eClass); - } - List allEClasses = getAllEClasses(); - List result = new LinkedList(); - for (EClass possibleSubClass : allEClasses) { - // is the EClass really a subClass, while not being abstract or an interface? - if (eClass.isSuperTypeOf(possibleSubClass) && canHaveInstance(possibleSubClass)) { - result.add(possibleSubClass); - } - } - // save the result for upcoming method calls - eClassToSubEClasses.put(eClass, result); - return result; - } - - /** - * Returns all containing references where parentClass is - * the container and childClass the containment. - * - * @param childClass the EClass which shall be contained - * @param parentClass the EClass to get containment references from - * @return all possible container-references as a set - */ - public static Set getAllPossibleContainingReferences(EClass childClass, EClass parentClass) { - List allReferences = parentClass.getEAllContainments(); - Set result = new LinkedHashSet(); - for(EReference reference : allReferences) { - EClass referenceType = reference.getEReferenceType(); - if(referenceType == null) { - continue; - } - // is the reference type a perfect match? - if(referenceType.equals(childClass)) { - result.add(reference); - // is the reference type either EObject or a super type? - } else if (referenceType.equals(EcorePackage.eINSTANCE.getEObject()) - || referenceType.isSuperTypeOf(childClass)) { - result.add(reference); - } - } - return result; - } - - /** - * Returns all direct and indirect contents of rootObject as a map. - * All EObjects that appear in these contents are mapped to their corresponding - * EClass. - * - * @param rootObject the EObject to get contents for - * @return all contents as a map from EClass to lists of EObjects - */ - public static Map> getAllClassesAndObjects(EObject rootObject) { - // initialize the computation process - Map> result = new LinkedHashMap>(); - TreeIterator allContents = rootObject.eAllContents(); - List newList = new LinkedList(); - newList.add(rootObject); - result.put(rootObject.eClass(), newList); - // iterate over all direct and indirect contents - while(allContents.hasNext()) { - EObject eObject = allContents.next(); - // did this EObject's EClass appear before? - if(result.containsKey(eObject.eClass())) { - result.get(eObject.eClass()).add(eObject); - } else { - newList = new LinkedList(); - newList.add(eObject); - result.put(eObject.eClass(), newList); - } - } - return result; - } - - /** - * Returns all valid references for an EObject. This excludes container/containment references. - * A reference is valid if it is neither derived nor volatile and if it is changeable and - * either many-valued or not already set. - * - * @param eObject the EObject to get references for - * @param exceptionLog the current log of exceptions - * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? - * @return all valid references as a list - */ - public static List getValidReferences(EObject eObject, - Set exceptionLog, boolean ignoreAndLog) { - List result = new LinkedList(); - for(EReference reference : eObject.eClass().getEAllReferences()) { - if(!reference.isContainer() && !reference.isContainment() && isValid(reference, eObject, exceptionLog, ignoreAndLog) - && (reference.isMany() || !eObject.eIsSet(reference))) { - result.add(reference); - } - } - return result; - } - - /** - * Returns whether an EStructuralFeature is valid for an EObject or not. - * A reference is valid, if it can be set or added to. - * - * @param feature the EStructuralFeature in question - * @param eObject the EObject to check the feature for - * @param exceptionLog the current log of exceptions - * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? - * @return if the feature can be set or added to - */ - public static boolean isValid(EStructuralFeature feature, EObject eObject, - Set exceptionLog, boolean ignoreAndLog) { - boolean result = false; - try { - if(feature.isMany()) { - // has the maximum amount of referenced objects been reached? - Collection referencedItems = (Collection) eObject.eGet(feature); - if(feature.getUpperBound() >= 0 && referencedItems.size() >= feature.getUpperBound()) { - return false; - } - } - // can the feature be changed reflectively? - result = feature.isChangeable() && !feature.isVolatile() && !feature.isDerived(); - } catch(RuntimeException e) { - handle(e, exceptionLog, ignoreAndLog); - } - return result; - } - - /** - * Handles exception, meaning it is thrown if ignoreAndLog - * is false. Otherwise exception is ignored and added to - * exceptionLog. - * - * @param exception the exception to handle - * @param exceptionLog the current log of exceptions - * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? - */ - private static void handle(RuntimeException exception, Set exceptionLog, - boolean ignoreAndLog) { - if(ignoreAndLog) { - exceptionLog.add(exception); - } else { - throw exception; - } - } - - /** - * Sets a feature between eObject and newValue - * using a SetCommand. Exceptions are caught if ignoreAndLog is - * true, otherwise a RuntimeException might be thrown if the command fails. - * - * @param eObject the EObject for which feature shall be set - * @param feature the EStructuralFeature that shall be set - * @param newValue the Object that shall be set as a feature in parentEObject - * @param exceptionLog the current log of exceptions - * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? - * @return newValue if the SetCommand was performed successful - * or null if it failed - * @see SetCommand - */ - public static EObject setPerCommand(EObject eObject, EStructuralFeature feature, Object newValue, - Set exceptionLog, boolean ignoreAndLog) { - EditingDomain domain = AdapterFactoryEditingDomain.getEditingDomainFor(eObject); - // no new value to set? -> unset the feature - if(newValue==null) { - newValue = SetCommand.UNSET_VALUE; - } - try { - new SetCommand(domain, eObject, feature, newValue).doExecute(); - if(newValue instanceof EObject) { - return (EObject) newValue; - } else { - return null; - } - } catch(RuntimeException e){ - handle(e, exceptionLog, ignoreAndLog); - return null; - } - } - - /** - * Adds newValue to the many-valued feature of - * eObject using an AddCommand. - * Exceptions are caught if ignoreAndLog is - * true, otherwise a RuntimeException might be thrown if the command fails. - * - * @param eObject the EObject to which newObject shall be added - * @param feature the EStructuralFeature that newObject shall be added to - * @param newValue the Object that shall be added to feature - * @param exceptionLog the current log of exceptions - * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? - * @return newValue if the AddCommand was performed successful - * or null if it failed - * @see AddCommand#AddCommand(EditingDomain, EObject, EStructuralFeature, Object) - */ - public static EObject addPerCommand(EObject eObject, EStructuralFeature feature, Object newValue, - Set exceptionLog, boolean ignoreAndLog) { - EditingDomain domain = AdapterFactoryEditingDomain.getEditingDomainFor(eObject); - try { - if(feature.isUnique() && ((Collection) eObject.eGet(feature)).contains(newValue)) { - // unique feature already contains object -> nothing to do - return null; - } - new AddCommand(domain, eObject, feature, newValue).doExecute(); - if(newValue instanceof EObject) { - return (EObject) newValue; - } else { - return null; - } - } catch(RuntimeException e){ - handle(e, exceptionLog, ignoreAndLog); - return null; - } - } - - /** - * Adds all objects to the many-valued feature of - * eObject using an AddCommand. - * Exceptions are caught if ignoreAndLog is - * true, otherwise a RuntimeException might be thrown if the command fails. - * - * @param eObject the EObject to which objects shall be added - * @param feature the EReference that objects shall be added to - * @param objects collection of objects that shall be added to feature - * @param exceptionLog the current log of exceptions - * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? - */ - public static void addPerCommand(EObject eObject, EStructuralFeature feature, Collection objects, - Set exceptionLog, boolean ignoreAndLog) { - EditingDomain domain = AdapterFactoryEditingDomain.getEditingDomainFor(eObject); - try { - for(Object object : objects) { - if(feature.isUnique() && ((Collection) eObject.eGet(feature)).contains(object)) { - // object already exists in unique feature, don't add it again - objects.remove(object); - } - } - // no objects to add left - if(objects.isEmpty()) { - return; - } - new AddCommand(domain, eObject, feature, objects).doExecute(); - } catch(RuntimeException e) { - handle(e, exceptionLog, ignoreAndLog); - } - } - - /** - * Removes objects from a feature of eObject - * using a RemoveCommand. Exceptions are caught if ignoreAndLog is - * true, otherwise a RuntimeException might be thrown if the command fails. - * - * @param eObject the EObject to remove objects from - * @param feature the EStructuralFeature objects shall be removed from - * @param objects collection of Objects that shall be removed - * @param exceptionLog the current log of exceptions - * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? - * @see RemoveCommand - */ - public static void removePerCommand(EObject eObject, EStructuralFeature feature, Collection objects, - Set exceptionLog, boolean ignoreAndLog) { - EditingDomain domain = AdapterFactoryEditingDomain.getEditingDomainFor(eObject); - try { - new RemoveCommand(domain, eObject, feature, objects).doExecute(); - } catch(RuntimeException e){ - handle(e, exceptionLog, ignoreAndLog); - } - } - - /** - * Retrieves all EClasses from allEClasses that can possibly be - * referenced by reference and returns them as a list. - * - * @param reference the EReference to get EClasses for - * @param allEClasses set of all possible EClasses - * @return list of all EClasses that can be referenced by reference - */ - public static Set getReferenceClasses(EReference reference, Set allEClasses) { - Set result = new LinkedHashSet(); - EClass referenceType = reference.getEReferenceType(); - // 'referenceType: EObject' allows all kinds of EObjects - if(referenceType.equals(EcorePackage.eINSTANCE.getEObject())) { - return allEClasses; - } - for(EClass eClass : allEClasses) { - // can eClass be referenced by reference - if(referenceType.equals(eClass) || referenceType.isSuperTypeOf(eClass)) { - result.add(eClass); - } - } - return result; - } - - /** - * Sets or adds to a reference for an EObject with any generated instance - * of referenceClass using SetCommand/AddCommand. If the reference is - * not required, random decides whether the reference is set or how - * many EObjects are added to it. - * - * @param eObject the EObject to set the reference for - * @param referenceClass the EClass all referenced EObject shall be instances of - * @param reference the reference to set - * @param random the Random-object that randomizes EObjects and their amount - * @param exceptionLog the current log of exceptions - * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? - * @param allEObjects all existing EObjects mapped to their EClass - * - * @see #addPerCommand(EObject, EStructuralFeature, Collection, Set, boolean) - * @see #addPerCommand(EObject, EStructuralFeature, Object, Set, boolean) - * @see #setPerCommand(EObject, EStructuralFeature, Object, Set, boolean) - */ - public static void setReference(EObject eObject, EClass referenceClass, EReference reference, - Random random, Set exceptionLog, boolean ignoreAndLog, Map> allEObjects) { - List possibleReferenceObjects = allEObjects.get(referenceClass); - Collections.shuffle(possibleReferenceObjects, random); - if(!possibleReferenceObjects.isEmpty()) { - int index = 0; - if(reference.isMany()) { - int numberOfReferences = computeFeatureAmount(reference, random); - for(int i = 0; i < numberOfReferences; i++) { - ModelGeneratorUtil.addPerCommand(eObject, reference, possibleReferenceObjects.get(index), - exceptionLog, ignoreAndLog); - // ensures every EObject is set at most once - if(++index==possibleReferenceObjects.size()) { - break; - } - } - //Change of referencing - // Delete reference.isRequired() in order to set 0..1 references - //} else if (reference.isRequired() || random.nextBoolean()){ - } else if (random.nextBoolean()) { - ModelGeneratorUtil.setPerCommand(eObject, reference, possibleReferenceObjects.get(index), - exceptionLog, ignoreAndLog); - } - } - } - - /** - * Sets all possible attributes of known types to random values using {@link IAttributeSetter} - * and SetCommands/AddCommands. - * - * @param eObject the EObject to set attributes for - * @param random the Random object used to determine the creation of attributes - * @param exceptionLog the current log of exceptions - * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? - * @see IAttributeSetter - * @see AttributeHandler - * @see #addPerCommand(EObject, EStructuralFeature, Collection, Set, boolean) - * @see #addPerCommand(EObject, EStructuralFeature, Object, Set, boolean) - * @see #setPerCommand(EObject, EStructuralFeature, Object, Set, boolean) - */ - public static void setEObjectAttributes(EObject eObject, Random random, - Set exceptionLog, boolean ignoreAndLog) { - Map> attributeSetters = AttributeHandler.getAttributeSetters(); - - for(EAttribute attribute : eObject.eClass().getEAllAttributes()) { - EClassifier attributeType = attribute.getEAttributeType(); - - if(!isValid(attribute, eObject, exceptionLog, ignoreAndLog)) { - continue; - } - - // the attribute setter used to create new attributes - IAttributeSetter attributeSetter = null; - - // is there a setter for this attribute? - if(attributeSetters.containsKey(attributeType)) { - attributeSetter = attributeSetters.get(attributeType); - } else if(isEnum(attributeType)) { - attributeSetter = AttributeHandler.getEEnumSetter((EEnum) attributeType); - } - - // was there a fitting attribute setter? - if(attributeSetter != null) { - if (attribute.isMany()) { - int numberOfAttributes = computeFeatureAmount(attribute, random); - addPerCommand(eObject, attribute, - attributeSetter.createNewAttributes(numberOfAttributes), exceptionLog, ignoreAndLog); - } else { - setPerCommand(eObject, attribute, - attributeSetter.createNewAttribute(), exceptionLog, ignoreAndLog); - } - } - } - } - - /** - * Returns whether attributeType is an instance of EEnum. - * - * @param attributeType the EClassifier in question - * @return is attributeType an instance of EEnum? - */ - private static boolean isEnum(EClassifier attributeType) { - return EcorePackage.eINSTANCE.getEEnum().isInstance(attributeType); - } - - /** - * Computes the random amount of objects to add to a feature. - * - * @param feature the feature to compute the amount of objects for - * @param random the Random object used to obtain random values - * @return 1 if the feature is single valued,
- * a random value from 0 to 10 if the feature is many-valued and has no upper bound,
- * a random value between the feature's lower and upper bound otherwise - */ - private static int computeFeatureAmount(EStructuralFeature feature, Random random) { - if(!feature.isMany()) { - return 1; - } - if(feature.getUpperBound() < feature.getLowerBound()) { - return random.nextInt(10); - } - return feature.getLowerBound() + random.nextInt(feature.getUpperBound() - feature.getLowerBound() + 1); - } - - /** - * Deletes an EObject, while exceptions are handled with the values specified. - * - * @param eObject the EObject to delete - * @param exceptionLog the current log of exceptions - * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? - * @see EcoreUtil#delete(EObject) - */ - public static void delete(EObject eObject, Set exceptionLog, boolean ignoreAndLog) { - try { - EcoreUtil.delete(eObject,true); - - } catch(RuntimeException e) { - handle(e, exceptionLog, ignoreAndLog); - } - } -} +/** + * Copyright (c) 2008-2009 Jonas Helming, Maximilian Koegel. 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 + */ +package org.eclipse.emf.emfstore.modelgenerator.common; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; +import java.util.Set; + +import org.eclipse.emf.common.command.AbstractCommand; +import org.eclipse.emf.common.util.TreeIterator; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EEnum; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EPackage.Registry; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.edit.command.AddCommand; +import org.eclipse.emf.edit.command.RemoveCommand; +import org.eclipse.emf.edit.command.SetCommand; +import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.emf.emfstore.client.model.Configuration; +import org.eclipse.emf.emfstore.modelgenerator.common.attribute.AttributeHandler; +import org.eclipse.emf.emfstore.modelgenerator.common.attribute.IAttributeSetter; + +/** + * Utility class to generate and change Ecore models. + * All methods should be accessed in a static way, + * therefore the constructor is not visible. + */ +public final class ModelGeneratorUtil { + + /** + * Set of all EClasses that are contained in EPackages that are + * currently registered in the EPackage registry. + * + * @see #getAllEClasses() + */ + private static List allEClasses; + + /** + * Set of all EPackages that are currently registered in the + * EPackage registry and not contained in any other package. + * + * @see #getAllRootEPackages() + */ + private static Set rootModelPackages; + + /** + * Map that maps EPackages to a set of all their contained EClasses. + * + * @see #getAllEClasses(EPackage) + */ + private static Map> packageToModelElementEClasses = new LinkedHashMap>(); + + /** + * Map that maps EReferences to all possible EClasses that can be contained + * when using them. + * + * @see #getAllEContainments(EReference) + */ + private static Map> allEContainments = new LinkedHashMap>(); + + /** + * Map that maps EClasses to their subclasses. + * + * @see #getAllSubEClasses(EClass) + */ + private static Map> eClassToSubEClasses = new LinkedHashMap>(); + + /** + * Private constructor. + */ + private ModelGeneratorUtil() { + // all methods should be accessed in a static way + } + + /** + * Returns the EPackage to the specified nsURI. + * + * @param nsURI the NsUri of the EPackage to get + * @return the EPackage belonging to nsURI + * @see Registry#getEPackage(String) + */ + public static EPackage getEPackage(String nsURI) { + return EPackage.Registry.INSTANCE.getEPackage(nsURI); + } + + /** + * Returns all EPackages on the root level that are currently + * registered in the registry. + * + * @return a Set of all root EPackages + * @see Registry + */ + public static Set getAllRootEPackages() { + // were the root packages computed before? + if(rootModelPackages != null) { + return rootModelPackages; + } + rootModelPackages = new LinkedHashSet(); + Registry registry = EPackage.Registry.INSTANCE; + + for (Entry entry : registry.entrySet()) { + EPackage ePackage = registry.getEPackage(entry.getKey()); + // is the current EPackage a root package? + if (ePackage.getESuperPackage() == null){ + rootModelPackages.add(ePackage); + } + } + return rootModelPackages; + } + + /** + * Retrieve all EClasses that are contained in ePackage. + * + * @param ePackage the package to get contained EClasses from + * @return a set of EClasses contained in ePackage + */ + public static List getAllEClasses(EPackage ePackage) { + if(packageToModelElementEClasses.containsKey(ePackage)) { + return packageToModelElementEClasses.get(ePackage); + } + if(ePackage == null) { + packageToModelElementEClasses.put(ePackage, new LinkedList()); + return packageToModelElementEClasses.get(ePackage); + } + List result = new LinkedList(); + // obtain all EClasses from sub packages + for(EPackage subPackage : ePackage.getESubpackages()) { + result.addAll(getAllEClasses(subPackage)); + } + // obtain all EClasses that are direct contents of the EPackage + for(EClassifier classifier : ePackage.getEClassifiers()) { + if(classifier instanceof EClass) { + result.add((EClass) classifier); + } + } + // save the result for upcoming method calls + packageToModelElementEClasses.put(ePackage, result); + return result; + } + + /** + * Iterates over all registered EPackages in order to retrieve all available + * EClasses, excluding abstract classes and interfaces, and returns them as a Set. + * + * @return a set of all EClasses that are contained in registered EPackages + * @see Registry + */ + public static List getAllEClasses() { + // were all EClasses computed before? + if (allEClasses != null) { + return allEClasses; + } + allEClasses = new LinkedList(); + Registry registry = EPackage.Registry.INSTANCE; + // for all registered EPackages + for (Entry entry : registry.entrySet()) { + EPackage ePackage = registry.getEPackage(entry.getKey()); + for(EClass eClass : getAllEClasses(ePackage)) { + // no abstracts or interfaces + if(canHaveInstance(eClass)) { + allEClasses.add(eClass); + } + } + } + return allEClasses; + } + + /** + * Returns all possible EClasses, excluding abstract classes and interfaces, + * that can be contained when using reference. + * + * @param reference the EReference to get containable EClasses for + * @return a set of all EClasses that can be contained when using reference + */ + public static List getAllEContainments(EReference reference) { + if(allEContainments.containsKey(reference)) { + return allEContainments.get(reference); + } + if(reference == null) { + allEContainments.put(reference, new LinkedList()); + return allEContainments.get(reference); + } + List result = new LinkedList(); + EClass referenceType = reference.getEReferenceType(); + // no abstracts or interfaces + if(canHaveInstance(referenceType)) { + result.add(referenceType); + } + // 'referenceType: EObject' allows all kinds of EObjects + if(EcorePackage.eINSTANCE.getEObject().equals(referenceType)) { + return getAllEClasses(); + } + // all sub EClasses can be referenced as well + result.addAll(getAllSubEClasses(referenceType)); + // save the result for upcoming method calls + allEContainments.put(reference, result); + return result; + } + + /** + * Returns whether eClass can be instantiated or not. + * An EClass can be instantiated, if it is neither an interface nor abstract. + * + * @param eClass the EClass in question + * @return whether eClass can be instantiated or not. + */ + public static boolean canHaveInstance(EClass eClass) { + return !eClass.isInterface() && !eClass.isAbstract(); + } + + /** + * Returns all subclasses of an EClass, excluding abstract classes + * and interfaces. + * + * @param eClass the EClass to get subclasses for + * @return all subclasses of eClass + */ + public static List getAllSubEClasses(EClass eClass) { + if(eClassToSubEClasses.containsKey(eClass)) { + return eClassToSubEClasses.get(eClass); + } + if(eClass == null) { + eClassToSubEClasses.put(eClass, new LinkedList()); + return eClassToSubEClasses.get(eClass); + } + List allEClasses = getAllEClasses(); + List result = new LinkedList(); + for (EClass possibleSubClass : allEClasses) { + // is the EClass really a subClass, while not being abstract or an interface? + if (eClass.isSuperTypeOf(possibleSubClass) && canHaveInstance(possibleSubClass)) { + result.add(possibleSubClass); + } + } + // save the result for upcoming method calls + eClassToSubEClasses.put(eClass, result); + return result; + } + + /** + * Returns all containing references where parentClass is + * the container and childClass the containment. + * + * @param childClass the EClass which shall be contained + * @param parentClass the EClass to get containment references from + * @return all possible container-references as a set + */ + public static Set getAllPossibleContainingReferences(EClass childClass, EClass parentClass) { + List allReferences = parentClass.getEAllContainments(); + Set result = new LinkedHashSet(); + for(EReference reference : allReferences) { + EClass referenceType = reference.getEReferenceType(); + if(referenceType == null) { + continue; + } + // is the reference type a perfect match? + if(referenceType.equals(childClass)) { + result.add(reference); + // is the reference type either EObject or a super type? + } else if (referenceType.equals(EcorePackage.eINSTANCE.getEObject()) + || referenceType.isSuperTypeOf(childClass)) { + result.add(reference); + } + } + return result; + } + + /** + * Returns all direct and indirect contents of rootObject as a map. + * All EObjects that appear in these contents are mapped to their corresponding + * EClass. + * + * @param rootObject the EObject to get contents for + * @return all contents as a map from EClass to lists of EObjects + */ + public static Map> getAllClassesAndObjects(EObject rootObject) { + // initialize the computation process + Map> result = new LinkedHashMap>(); + TreeIterator allContents = rootObject.eAllContents(); + List newList = new LinkedList(); + newList.add(rootObject); + result.put(rootObject.eClass(), newList); + // iterate over all direct and indirect contents + while(allContents.hasNext()) { + EObject eObject = allContents.next(); + // did this EObject's EClass appear before? + if(result.containsKey(eObject.eClass())) { + result.get(eObject.eClass()).add(eObject); + } else { + newList = new LinkedList(); + newList.add(eObject); + result.put(eObject.eClass(), newList); + } + } + return result; + } + + /** + * Returns all valid references for an EObject. This excludes container/containment references. + * A reference is valid if it is neither derived nor volatile and if it is changeable and + * either many-valued or not already set. + * + * @param eObject the EObject to get references for + * @param exceptionLog the current log of exceptions + * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? + * @return all valid references as a list + */ + public static List getValidReferences(EObject eObject, + Set exceptionLog, boolean ignoreAndLog) { + List result = new LinkedList(); + for(EReference reference : eObject.eClass().getEAllReferences()) { + if(!reference.isContainer() && !reference.isContainment() && isValid(reference, eObject, exceptionLog, ignoreAndLog) + && (reference.isMany() || !eObject.eIsSet(reference))) { + result.add(reference); + } + } + return result; + } + + /** + * Returns whether an EStructuralFeature is valid for an EObject or not. + * A reference is valid, if it can be set or added to. + * + * @param feature the EStructuralFeature in question + * @param eObject the EObject to check the feature for + * @param exceptionLog the current log of exceptions + * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? + * @return if the feature can be set or added to + */ + public static boolean isValid(EStructuralFeature feature, EObject eObject, + Set exceptionLog, boolean ignoreAndLog) { + boolean result = false; + try { + if(feature.isMany()) { + // has the maximum amount of referenced objects been reached? + Collection referencedItems = (Collection) eObject.eGet(feature); + if(feature.getUpperBound() >= 0 && referencedItems.size() >= feature.getUpperBound()) { + return false; + } + } + // can the feature be changed reflectively? + result = feature.isChangeable() && !feature.isVolatile() && !feature.isDerived(); + } catch(RuntimeException e) { + handle(e, exceptionLog, ignoreAndLog); + } + return result; + } + + /** + * Handles exception, meaning it is thrown if ignoreAndLog + * is false. Otherwise exception is ignored and added to + * exceptionLog. + * + * @param exception the exception to handle + * @param exceptionLog the current log of exceptions + * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? + */ + private static void handle(RuntimeException exception, Set exceptionLog, + boolean ignoreAndLog) { + if(ignoreAndLog) { + exceptionLog.add(exception); + } else { + throw exception; + } + } + + /** + * Sets a feature between eObject and newValue + * using a SetCommand. Exceptions are caught if ignoreAndLog is + * true, otherwise a RuntimeException might be thrown if the command fails. + * + * @param eObject the EObject for which feature shall be set + * @param feature the EStructuralFeature that shall be set + * @param newValue the Object that shall be set as a feature in parentEObject + * @param exceptionLog the current log of exceptions + * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? + * @return newValue if the SetCommand was performed successful + * or null if it failed + * @see SetCommand + */ + public static EObject setPerCommand(EObject eObject, EStructuralFeature feature, Object newValue, + Set exceptionLog, boolean ignoreAndLog) { + EditingDomain domain = AdapterFactoryEditingDomain.getEditingDomainFor(eObject); + // no new value to set? -> unset the feature + if(newValue==null) { + newValue = SetCommand.UNSET_VALUE; + } + try { + new SetCommand(domain, eObject, feature, newValue).doExecute(); + if(newValue instanceof EObject) { + return (EObject) newValue; + } else { + return null; + } + } catch(RuntimeException e){ + handle(e, exceptionLog, ignoreAndLog); + return null; + } + } + + /** + * Adds newValue to the many-valued feature of + * eObject using an AddCommand. + * Exceptions are caught if ignoreAndLog is + * true, otherwise a RuntimeException might be thrown if the command fails. + * + * @param eObject the EObject to which newObject shall be added + * @param feature the EStructuralFeature that newObject shall be added to + * @param newValue the Object that shall be added to feature + * @param exceptionLog the current log of exceptions + * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? + * @return newValue if the AddCommand was performed successful + * or null if it failed + * @see AddCommand#AddCommand(EditingDomain, EObject, EStructuralFeature, Object) + */ + public static EObject addPerCommand(EObject eObject, EStructuralFeature feature, Object newValue, + Set exceptionLog, boolean ignoreAndLog) { + EditingDomain domain = AdapterFactoryEditingDomain.getEditingDomainFor(eObject); + try { + if(feature.isUnique() && ((Collection) eObject.eGet(feature)).contains(newValue)) { + // unique feature already contains object -> nothing to do + return null; + } + new AddCommand(domain, eObject, feature, newValue).doExecute(); + if(newValue instanceof EObject) { + return (EObject) newValue; + } else { + return null; + } + } catch(RuntimeException e){ + handle(e, exceptionLog, ignoreAndLog); + return null; + } + } + + /** + * Adds all objects to the many-valued feature of + * eObject using an AddCommand. + * Exceptions are caught if ignoreAndLog is + * true, otherwise a RuntimeException might be thrown if the command fails. + * + * @param eObject the EObject to which objects shall be added + * @param feature the EReference that objects shall be added to + * @param objects collection of objects that shall be added to feature + * @param exceptionLog the current log of exceptions + * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? + */ + public static void addPerCommand(EObject eObject, EStructuralFeature feature, Collection objects, + Set exceptionLog, boolean ignoreAndLog) { + EditingDomain domain = AdapterFactoryEditingDomain.getEditingDomainFor(eObject); + try { + for(Object object : objects) { + if(feature.isUnique() && ((Collection) eObject.eGet(feature)).contains(object)) { + // object already exists in unique feature, don't add it again + objects.remove(object); + } + } + // no objects to add left + if(objects.isEmpty()) { + return; + } + new AddCommand(domain, eObject, feature, objects).doExecute(); + } catch(RuntimeException e) { + handle(e, exceptionLog, ignoreAndLog); + } + } + + /** + * Removes objects from a feature of eObject + * using a RemoveCommand. Exceptions are caught if ignoreAndLog is + * true, otherwise a RuntimeException might be thrown if the command fails. + * + * @param eObject the EObject to remove objects from + * @param feature the EStructuralFeature objects shall be removed from + * @param objects collection of Objects that shall be removed + * @param exceptionLog the current log of exceptions + * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? + * @see RemoveCommand + */ + public static void removePerCommand(EObject eObject, EStructuralFeature feature, Collection objects, + Set exceptionLog, boolean ignoreAndLog) { + EditingDomain domain = AdapterFactoryEditingDomain.getEditingDomainFor(eObject); + try { + new RemoveCommand(domain, eObject, feature, objects).doExecute(); + } catch(RuntimeException e){ + handle(e, exceptionLog, ignoreAndLog); + } + } + + /** + * Retrieves all EClasses from allEClasses that can possibly be + * referenced by reference and returns them as a list. + * + * @param reference the EReference to get EClasses for + * @param allEClasses set of all possible EClasses + * @return list of all EClasses that can be referenced by reference + */ + public static Set getReferenceClasses(EReference reference, Set allEClasses) { + Set result = new LinkedHashSet(); + EClass referenceType = reference.getEReferenceType(); + // 'referenceType: EObject' allows all kinds of EObjects + if(referenceType.equals(EcorePackage.eINSTANCE.getEObject())) { + return allEClasses; + } + for(EClass eClass : allEClasses) { + // can eClass be referenced by reference + if(referenceType.equals(eClass) || referenceType.isSuperTypeOf(eClass)) { + result.add(eClass); + } + } + return result; + } + + /** + * Sets or adds to a reference for an EObject with any generated instance + * of referenceClass using SetCommand/AddCommand. If the reference is + * not required, random decides whether the reference is set or how + * many EObjects are added to it. + * + * @param eObject the EObject to set the reference for + * @param referenceClass the EClass all referenced EObject shall be instances of + * @param reference the reference to set + * @param random the Random-object that randomizes EObjects and their amount + * @param exceptionLog the current log of exceptions + * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? + * @param allEObjects all existing EObjects mapped to their EClass + * + * @see #addPerCommand(EObject, EStructuralFeature, Collection, Set, boolean) + * @see #addPerCommand(EObject, EStructuralFeature, Object, Set, boolean) + * @see #setPerCommand(EObject, EStructuralFeature, Object, Set, boolean) + */ + public static void setReference(EObject eObject, EClass referenceClass, EReference reference, + Random random, Set exceptionLog, boolean ignoreAndLog, Map> allEObjects) { + List possibleReferenceObjects = allEObjects.get(referenceClass); + Collections.shuffle(possibleReferenceObjects, random); + if(!possibleReferenceObjects.isEmpty()) { + int index = 0; + if(reference.isMany()) { + int numberOfReferences = computeFeatureAmount(reference, random); + for(int i = 0; i < numberOfReferences; i++) { + ModelGeneratorUtil.addPerCommand(eObject, reference, possibleReferenceObjects.get(index), + exceptionLog, ignoreAndLog); + // ensures every EObject is set at most once + if(++index==possibleReferenceObjects.size()) { + break; + } + } + //Change of referencing + // Delete reference.isRequired() in order to set 0..1 references + //} else if (reference.isRequired() || random.nextBoolean()){ + } else if (random.nextBoolean()) { + ModelGeneratorUtil.setPerCommand(eObject, reference, possibleReferenceObjects.get(index), + exceptionLog, ignoreAndLog); + } + } + } + + /** + * Sets all possible attributes of known types to random values using {@link IAttributeSetter} + * and SetCommands/AddCommands. + * + * @param eObject the EObject to set attributes for + * @param random the Random object used to determine the creation of attributes + * @param exceptionLog the current log of exceptions + * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? + * @see IAttributeSetter + * @see AttributeHandler + * @see #addPerCommand(EObject, EStructuralFeature, Collection, Set, boolean) + * @see #addPerCommand(EObject, EStructuralFeature, Object, Set, boolean) + * @see #setPerCommand(EObject, EStructuralFeature, Object, Set, boolean) + */ + public static void setEObjectAttributes(EObject eObject, Random random, + Set exceptionLog, boolean ignoreAndLog) { + Map> attributeSetters = AttributeHandler.getAttributeSetters(); + + for(EAttribute attribute : eObject.eClass().getEAllAttributes()) { + EClassifier attributeType = attribute.getEAttributeType(); + + if(!isValid(attribute, eObject, exceptionLog, ignoreAndLog)) { + continue; + } + + // the attribute setter used to create new attributes + IAttributeSetter attributeSetter = null; + + // is there a setter for this attribute? + if(attributeSetters.containsKey(attributeType)) { + attributeSetter = attributeSetters.get(attributeType); + } else if(isEnum(attributeType)) { + attributeSetter = AttributeHandler.getEEnumSetter((EEnum) attributeType); + } + + // was there a fitting attribute setter? + if(attributeSetter != null) { + if (attribute.isMany()) { + int numberOfAttributes = computeFeatureAmount(attribute, random); + addPerCommand(eObject, attribute, + attributeSetter.createNewAttributes(numberOfAttributes), exceptionLog, ignoreAndLog); + } else { + setPerCommand(eObject, attribute, + attributeSetter.createNewAttribute(), exceptionLog, ignoreAndLog); + } + } + } + } + + /** + * Returns whether attributeType is an instance of EEnum. + * + * @param attributeType the EClassifier in question + * @return is attributeType an instance of EEnum? + */ + private static boolean isEnum(EClassifier attributeType) { + return EcorePackage.eINSTANCE.getEEnum().isInstance(attributeType); + } + + /** + * Computes the random amount of objects to add to a feature. + * + * @param feature the feature to compute the amount of objects for + * @param random the Random object used to obtain random values + * @return 1 if the feature is single valued,
+ * a random value from 0 to 10 if the feature is many-valued and has no upper bound,
+ * a random value between the feature's lower and upper bound otherwise + */ + private static int computeFeatureAmount(EStructuralFeature feature, Random random) { + if(!feature.isMany()) { + return 1; + } + if(feature.getUpperBound() < feature.getLowerBound()) { + return random.nextInt(10); + } + return feature.getLowerBound() + random.nextInt(feature.getUpperBound() - feature.getLowerBound() + 1); + } + + /** + * Deletes an EObject, while exceptions are handled with the values specified. + * + * @param eObject the EObject to delete + * @param exceptionLog the current log of exceptions + * @param ignoreAndLog should exceptions be ignored and added to exceptionLog? + * @see EcoreUtil#delete(EObject) + */ + public static void delete(final EObject eObject, Set exceptionLog, boolean ignoreAndLog) { + + Configuration.getEditingDomain().getCommandStack().execute(new AbstractCommand() { + + @Override + public void redo() { + // TODO Auto-generated method stub + } + + @Override + public void execute() { + EcoreUtil.delete(eObject, true); + } + + @Override + public boolean canExecute() { + return true; + } + }); + } +}