Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
edelta.refactorings.lib.EdeltaRefactorings Maven / Gradle / Ivy
package edelta.refactorings.lib;
import com.google.common.collect.Iterables;
import edelta.lib.EdeltaDefaultRuntime;
import edelta.lib.EdeltaEcoreUtil;
import edelta.lib.EdeltaModelMigrator;
import edelta.lib.EdeltaRuntime;
import edelta.lib.EdeltaUtils;
import edelta.refactorings.lib.helper.EdeltaFeatureDifferenceFinder;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.ETypedElement;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.ListExtensions;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
import org.eclipse.xtext.xbase.lib.StringExtensions;
@SuppressWarnings("all")
public class EdeltaRefactorings extends EdeltaDefaultRuntime {
public EdeltaRefactorings(final EdeltaRuntime other) {
super(other);
}
public EAttribute addMandatoryAttribute(final EClass eClass, final String attributeName, final EDataType dataType) {
final Consumer _function = (EAttribute it) -> {
EdeltaUtils.makeSingleRequired(it);
};
return this.stdLib.addNewEAttribute(eClass, attributeName, dataType, _function);
}
public EReference addMandatoryReference(final EClass eClass, final String referenceName, final EClass type) {
final Consumer _function = (EReference it) -> {
EdeltaUtils.makeSingleRequired(it);
};
return this.stdLib.addNewEReference(eClass, referenceName, type, _function);
}
/**
* Changes this feature to single (upper = 1); concerning model migration,
* it takes the first element of the previous model object's collection
* for this feature.
*
* @param feature
*/
public void changeToSingle(final EStructuralFeature feature) {
this.changeUpperBound(feature, 1);
}
/**
* Changes this feature to multiple (upper = -1); concerning model migration,
* it makes sure that a collection is created if the previous model object's value was set.
*
* @param feature
*/
public void changeToMultiple(final EStructuralFeature feature) {
this.changeUpperBound(feature, (-1));
}
/**
* Changes this feature to multiple with the given upper bound; concerning model migration,
* it makes sure that a collection is created with at most the specified upper bound
* if the previous model object's value was set, discarding possible additional values in
* the original collection.
*
* @param feature
* @param upperBound
*/
public void changeUpperBound(final EStructuralFeature feature, final int upperBound) {
feature.setUpperBound(upperBound);
final Consumer _function = (EdeltaModelMigrator it) -> {
it.copyRule(
it.isRelatedTo(feature),
it.multiplicityAwareCopy(feature));
};
this.modelMigration(_function);
}
/**
* Merges the given attributes into a single new attribute in the containing class.
* The attributes must be compatible (same containing class, same type, same cardinality, etc).
*
* @param newAttributeName
* @param attributes
* @param valueMerger is used to merge the values of the original
* features in the new model
* @return the new attribute added to the containing class of the attributes
*/
public EAttribute mergeAttributes(final String newAttributeName, final Collection attributes, final Function, Object> valueMerger) {
return this.mergeFeatures(newAttributeName, attributes, valueMerger, null);
}
/**
* Merges the given references into a single new reference in the containing class.
* The references must be compatible (same containing class, same type, same cardinality, etc).
*
* @param newReferenceName
* @param references
* @param valueMerger is used to merge the values of the original
* features in the new model
* @param postCopy executed after the model migrations
* @return the new reference added to the containing class of the references
*/
public EReference mergeReferences(final String newReferenceName, final Collection references, final Function, EObject> valueMerger, final Runnable postCopy) {
return this.mergeFeatures(newReferenceName, references, valueMerger, postCopy);
}
/**
* Merges the given features into a single new feature in the containing class.
* The features must be compatible (same containing class, same type, same cardinality, etc).
*
* @param meant for both {@link EAttribute} and {@link EReference}
* @param the type for the function (either {@link Object} or {@link EObject})
* @param newFeatureName
* @param features
* @param valueMerger is used to merge the values of the original
* features in the new model
* @param postCopy if not null, it is executed after the model migrations
* @return the new feature added to the containing class of the features
*/
public T mergeFeatures(final String newFeatureName, final Collection features, final Function, V> valueMerger, final Runnable postCopy) {
this.checkNoDifferences(features,
new EdeltaFeatureDifferenceFinder().ignoringName(),
"The two features cannot be merged");
final T firstFeature = IterableExtensions.head(features);
final EClass owner = firstFeature.getEContainingClass();
final T mergedFeature = this.stdLib.copyToAs(firstFeature, owner, newFeatureName);
EdeltaUtils.removeAllElements(features);
final Consumer _function = (EdeltaModelMigrator it) -> {
final EdeltaModelMigrator.CopyProcedure _function_1 = (EStructuralFeature __, EObject oldObj, EObject newObj) -> {
final Function _function_2 = (T a) -> {
return it.getOriginal(a);
};
Stream originalFeatures = features.stream().map(_function_2);
final Function _function_3 = (T f) -> {
return oldObj.eGet(f);
};
List oldValues = originalFeatures.map(_function_3).collect(Collectors.toList());
Collection _migrated = it.getMigrated(oldValues);
V merged = valueMerger.apply(((Collection) _migrated));
newObj.eSet(mergedFeature, merged);
};
it.copyRule(
it.wasRelatedTo(firstFeature), _function_1, postCopy);
};
this.modelMigration(_function);
return mergedFeature;
}
/**
* Merges the given features into a single new feature in the containing class.
* The features must be compatible (same containing class, same type, same cardinality, etc).
*
* TODO: this has to be removed once all the examples and tests have been ported
* to model migration as well.
*
* @param
* @param newFeatureName
* @param features
* @return the new feature added to the containing class of the features
*/
public T mergeFeatures(final String newFeatureName, final Collection features) {
this.checkNoDifferences(features,
new EdeltaFeatureDifferenceFinder().ignoringName(),
"The two features cannot be merged");
final T feature = IterableExtensions.head(features);
final EClass owner = feature.getEContainingClass();
final T copy = this.stdLib.copyToAs(feature, owner, newFeatureName);
EdeltaUtils.removeAllElements(features);
return copy;
}
/**
* Merges the given features into the single given existing feature in the containing class.
* The features must be compatible (same containing class, same type, same cardinality, etc)
* and their types must be subtypes of the specified feature.
*
* @param feature the features will be merged into this feature
* @param features
*/
public EStructuralFeature mergeFeatures(final EStructuralFeature feature, final Collection features) {
this.checkCompliant(feature, features);
Iterable _plus = Iterables.concat(Collections.unmodifiableList(CollectionLiterals.newArrayList(feature)), features);
this.checkNoDifferences(_plus,
new EdeltaFeatureDifferenceFinder().ignoringName().ignoringType(),
"The two features cannot be merged");
EdeltaUtils.removeAllElements(features);
return feature;
}
/**
* Merges the given features into a single new feature, with the given type, in the containing class.
* The features must be compatible (same containing class, same type, same cardinality, etc)
* and their types must be subtypes of the specified type.
*
* @param newFeatureName
* @param type
* @param features
*/
public EStructuralFeature mergeFeatures(final String newFeatureName, final EClassifier type, final Collection features) {
final EStructuralFeature feature = IterableExtensions.head(features);
final EClass owner = feature.getEContainingClass();
final EStructuralFeature copy = this.stdLib.copyToAs(feature, owner, newFeatureName, type);
this.mergeFeatures(copy, features);
return copy;
}
/**
* Split the given attribute into several attributes with the same type
* as the original one, using the specified names. The original attribute
* will be removed. The passed valueSplitter is used to migrate the
* original object into the corresponding split ones.
*
* @param attribute
* @param newNames
* @param valueSplitter
* @return the collection of features
*/
public Collection splitAttribute(final EAttribute attribute, final Collection newNames, final Function> valueSplitter) {
final Collection splitAttributes = this.splitFeature(attribute, newNames);
final Consumer _function = (EdeltaModelMigrator it) -> {
final EdeltaModelMigrator.CopyProcedure _function_1 = (EStructuralFeature feature, EObject oldObj, EObject newObj) -> {
Object oldValue = oldObj.eGet(feature);
Iterator> splittedValues = valueSplitter.apply(oldValue).iterator();
for (final EAttribute splitFeature : splitAttributes) {
{
boolean _hasNext = splittedValues.hasNext();
boolean _not = (!_hasNext);
if (_not) {
return;
}
newObj.eSet(splitFeature, splittedValues.next());
}
}
};
it.copyRule(
it.wasRelatedTo(attribute), _function_1);
};
this.modelMigration(_function);
return splitAttributes;
}
/**
* Split the given reference into several references with the same type
* as the original one, using the specified names. The original reference
* will be removed. The passed valueSplitter is used to migrate the
* original object into the corresponding split ones.
*
* @param reference
* @param newNames
* @param valueSplitter
* @param postCopy executed after the model migrations
* @return the collection of features
*/
public Collection splitReference(final EReference reference, final Collection newNames, final Function> valueSplitter, final Runnable postCopy) {
final Collection splitReferences = this.splitFeature(reference, newNames);
final Consumer _function = (EdeltaModelMigrator it) -> {
final EdeltaModelMigrator.CopyProcedure _function_1 = (EStructuralFeature feature, EObject oldObj, EObject newObj) -> {
EObject oldValue = it.getMigrated(
EdeltaEcoreUtil.getValueAsEObject(oldObj, feature));
Iterator splittedValues = valueSplitter.apply(oldValue).iterator();
for (final EReference splitFeature : splitReferences) {
{
boolean _hasNext = splittedValues.hasNext();
boolean _not = (!_hasNext);
if (_not) {
return;
}
newObj.eSet(splitFeature, splittedValues.next());
}
}
};
it.copyRule(
it.wasRelatedTo(reference), _function_1, postCopy);
};
this.modelMigration(_function);
return splitReferences;
}
/**
* Split the given feature into several features with the same type
* as the original one, using the specified names. The original feature
* will be removed.
*
* @param
* @param featureToSplit
* @param newFeatureNames
* @return the collection of features
*/
public Collection splitFeature(final T featureToSplit, final Collection newFeatureNames) {
this.checkNotMany(featureToSplit,
"Cannot split \'many\' feature");
this.checkNoBidirectionalReferences(Collections.unmodifiableList(CollectionLiterals.newArrayList(featureToSplit)),
"Cannot split a bidirectional reference");
final EClass owner = featureToSplit.getEContainingClass();
final Function _function = (String newName) -> {
return this.stdLib.copyToAs(featureToSplit, owner, newName);
};
List splitFeatures = newFeatureNames.stream().map(_function).collect(Collectors.toList());
EdeltaUtils.removeElement(featureToSplit);
return splitFeatures;
}
/**
* Given an EAttribute, expected to have an EEnum type, creates a subclass of
* the containing class for each value of the referred EEnum
* (each subclass is given a name corresponding to the the EEnumLiteral,
* all lowercase but the first letter, for example, given the literal
* "LITERAL1", the subclass is given the name "Literal1").
* The attribute will then be removed and so will the EEnum.
* The original containing EClass is made abstract.
*
* @param attr
* @return the collection of created subclasses
*/
public Collection enumToSubclasses(final EAttribute attr) {
final EDataType type = attr.getEAttributeType();
if ((type instanceof EEnum)) {
final EClass owner = attr.getEContainingClass();
final Function1 _function = (EEnumLiteral it) -> {
return StringExtensions.toFirstUpper(it.toString().toLowerCase());
};
final EdeltaModelMigrator.EObjectFunction _function_1 = (EObject oldObj) -> {
final String literalValue = EdeltaEcoreUtil.getValueFromFeatureName(oldObj, attr.getName()).toString();
final EClass correspondingSubclass = EdeltaUtils.findSiblingByName(owner, StringExtensions.toFirstUpper(literalValue.toLowerCase()));
return EdeltaEcoreUtil.createInstance(correspondingSubclass);
};
final Collection createdSubclasses = this.introduceSubclasses(owner,
IterableExtensions.toList(ListExtensions.map(((EEnum)type).getELiterals(), _function)), _function_1);
EdeltaUtils.removeElement(type);
return createdSubclasses;
} else {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(type);
String _plus = ("Not an EEnum: " + _eObjectRepr);
this.showError(attr, _plus);
return null;
}
}
/**
* Creates the classes with the given names as subclasses of the passed
* superClass, which will then be made abstract; the objectMigrator is applied
* for migrating objects that were originally instances of the superClass.
*
* @param superClass
* @param name
* @param objectMigration
*/
public Collection introduceSubclasses(final EClass superClass, final Collection names, final EdeltaModelMigrator.EObjectFunction objectMigrator) {
EdeltaUtils.makeAbstract(superClass);
final Function1 _function = (String name) -> {
return this.stdLib.addNewSubclass(superClass, name);
};
final List subclasses = IterableExtensions.toList(IterableExtensions.map(names, _function));
final Consumer _function_1 = (EdeltaModelMigrator it) -> {
it.createInstanceRule(
it.isRelatedTo(superClass), objectMigrator);
};
this.modelMigration(_function_1);
return subclasses;
}
/**
* Given a collection of subclasses, which are expected to be direct subclasses of
* an EClass, say superclass, generates an EEnum (in the superclass' package)
* with the specified name, representing the inheritance relation,
* with an EEnumLiteral for each subclass (the name is the name
* of the subclass in uppercase); the subclasses are removed, and
* an attributed is added to the superclass with the created EEnum as type
* (the name is the name of the EEnum, first letter lowercase).
*
* For example, given the name "BaseType" and the collection of classes
* {"Derived1", "Derived2"} subclasses of the superclass "Base",
* it creates the EEnum "BaseType" with literals "DERIVED1", "DERIVED2",
* (the values will be incremental numbers starting from 0,
* according to the order of the subclasses in the collection)
* it adds to "Base" the EAttribute "baseType" of type "BaseType".
* The EClasses "Derived1" and "Derived2" are removed from the package.
*
* @param name the name for the created EEnum
* @param subclasses
* @return the created EAttribute
*/
public EAttribute subclassesToEnum(final String name, final Collection subclasses) {
this.checkNoFeatures(subclasses);
final EClass superclass = this.getSingleDirectSuperclass(subclasses);
final Consumer _function = (EEnum it) -> {
final Procedure2 _function_1 = (EClass subClass, Integer index) -> {
final String enumLiteralName = subClass.getName().toUpperCase();
EEnumLiteral _addNewEEnumLiteral = this.stdLib.addNewEEnumLiteral(it, enumLiteralName);
final Procedure1 _function_2 = (EEnumLiteral it_1) -> {
it_1.setValue((index).intValue());
};
ObjectExtensions.operator_doubleArrow(_addNewEEnumLiteral, _function_2);
};
IterableExtensions.forEach(subclasses, _function_1);
};
final EEnum enum_ = this.stdLib.addNewEEnumAsSibling(superclass, name, _function);
final EAttribute attribute = this.stdLib.addNewEAttribute(superclass, this.fromTypeToFeatureName(enum_), enum_);
EdeltaUtils.makeConcrete(superclass);
EdeltaUtils.removeAllElements(subclasses);
final Consumer _function_1 = (EdeltaModelMigrator it) -> {
final EdeltaModelMigrator.EObjectFunction _function_2 = (EObject oldObj) -> {
final EEnumLiteral enumLiteralName = enum_.getEEnumLiteral(
oldObj.eClass().getName().toUpperCase());
final Consumer _function_3 = (EObject newObj) -> {
newObj.eSet(attribute, enumLiteralName);
};
return EdeltaEcoreUtil.createInstance(superclass, _function_3);
};
it.createInstanceRule(
it.wasRelatedToAtLeastOneOf(subclasses), _function_2);
};
this.modelMigration(_function_1);
return attribute;
}
/**
* Extracts the specified features into a new class with the given name.
* The features must belong to the same class.
* In the containing class a containment required reference to
* the extracted class will be created (its name will be the name
* of the extracted class with the first letter lowercase).
*
* @param name the name for the extracted class
* @param features the features to extract
* @return the added EReference to the extracted metaclass
*/
public EReference extractClass(final String name, final Collection features) {
boolean _isEmpty = features.isEmpty();
if (_isEmpty) {
return null;
}
this.checkNoBidirectionalReferences(features,
"Cannot extract bidirectional references");
final EClass owner = this.findSingleOwner(features);
final EClass extracted = this.stdLib.addNewEClassAsSibling(owner, name);
final EReference reference = this.addMandatoryReference(owner, StringExtensions.toFirstLower(name), extracted);
this.makeContainmentBidirectional(reference);
this.stdLib.moveAllTo(features, extracted);
final Consumer _function = (EdeltaModelMigrator it) -> {
final EdeltaModelMigrator.CopyProcedure _function_1 = (EStructuralFeature origFeature, EObject origObj, EObject migratedObj) -> {
final Supplier _function_2 = () -> {
return EdeltaEcoreUtil.createInstance(extracted);
};
EObject extractedObj = EdeltaEcoreUtil.getOrSetEObject(migratedObj, reference, _function_2);
extractedObj.eSet(
it.getMigrated(origFeature),
it.getMigrated(origObj.eGet(origFeature)));
};
it.copyRule(
it.wasRelatedToAtLeastOneOf(features), _function_1);
};
this.modelMigration(_function);
return reference;
}
/**
* Inlines the features of the specified class into the single class
* that has a containment reference to the specified class.
* The specified class will then be removed.
*
* @param cl
* @return the features of the original class
*/
public List inlineClass(final EClass cl) {
return this.inlineClass(cl, "");
}
/**
* Inlines the features of the specified class into the single class
* that has a containment reference to the specified class.
* The specified class will then be removed.
*
* @param cl
* @param prefix the prefix for the names of the inlined features
* @return the features of the original class
*/
public List inlineClass(final EClass cl, final String prefix) {
final EReference reference = this.findSingleContainmentReferenceToThisClass(cl);
this.checkNotMany(reference,
"Cannot inline in a \'many\' reference");
final Function1 _function = (EStructuralFeature it) -> {
EReference _eOpposite = reference.getEOpposite();
return Boolean.valueOf((it != _eOpposite));
};
final List featuresToInline = IterableExtensions.toList(IterableExtensions.filter(cl.getEStructuralFeatures(), _function));
final Consumer _function_1 = (EStructuralFeature it) -> {
String _name = it.getName();
String _plus = (prefix + _name);
it.setName(_plus);
};
featuresToInline.forEach(_function_1);
this.stdLib.moveAllTo(featuresToInline, reference.getEContainingClass());
EdeltaUtils.removeElement(cl);
final Consumer _function_2 = (EdeltaModelMigrator it) -> {
final EdeltaModelMigrator.CopyProcedure _function_3 = (EStructuralFeature origFeature, EObject origObj, EObject migratedObj) -> {
final EObject origReferredObj = EdeltaEcoreUtil.getValueAsEObject(origObj, origFeature);
for (final EStructuralFeature feature : featuresToInline) {
migratedObj.eSet(feature,
it.getMigrated(origReferredObj.eGet(it.getOriginal(feature))));
}
};
it.copyRule(
it.wasRelatedTo(reference), _function_3);
};
this.modelMigration(_function_2);
return featuresToInline;
}
/**
* Makes the EReference, which is assumed to be already part of an EClass,
* a single required containment reference, adds to the referred
* type, which is assumed to be set, an opposite required single reference.
* @param reference
*/
public EReference makeContainmentBidirectional(final EReference reference) {
EReference _xblockexpression = null;
{
EdeltaUtils.makeContainment(reference);
final EClass owner = reference.getEContainingClass();
final EClass referredType = reference.getEReferenceType();
EReference _addMandatoryReference = this.addMandatoryReference(referredType, this.fromTypeToFeatureName(owner), owner);
final Procedure1 _function = (EReference it) -> {
EdeltaUtils.makeBidirectional(it, reference);
};
_xblockexpression = ObjectExtensions.operator_doubleArrow(_addMandatoryReference, _function);
}
return _xblockexpression;
}
/**
* Replaces an EReference with an EClass (with the given name, the same package
* as the package of the reference's containing class),
* updating possible opposite reference,
* so that a relation can be extended with additional features.
* The original reference will be made a containment reference,
* (its other properties will not be changed)
* to the added EClass (and made bidirectional).
*
* For example, given
*
* b2 b1
* A <-------> C
*
*
* (where the opposite "b2" might not be present)
* if we pass "b1" and the name "B", then the result will be
*
*
* a b1 b2 c
* A <-------> B <------> C
*
*
* where "b1" will be a containment reference.
* Note the names inferred for the new additional opposite references.
*
* @param name the name for the extracted class
* @param reference the reference to turn into a reference to the extracted class
* @return the extracted class
*/
public EClass referenceToClass(final String name, final EReference reference) {
this.checkNotContainment(reference,
"Cannot apply referenceToClass on containment reference");
final EPackage ePackage = reference.getEContainingClass().getEPackage();
final EClass extracted = this.stdLib.addNewEClass(ePackage, name);
final EReference extractedRef = this.addMandatoryReference(extracted,
this.fromTypeToFeatureName(reference.getEType()), reference.getEReferenceType());
final EReference eOpposite = reference.getEOpposite();
if ((eOpposite != null)) {
EdeltaUtils.makeBidirectional(eOpposite, extractedRef);
}
reference.setEType(extracted);
this.makeContainmentBidirectional(reference);
final Consumer _function = (EdeltaModelMigrator it) -> {
final Predicate _function_1 = (EStructuralFeature feature) -> {
return (it.isRelatedTo(feature, reference) ||
it.isRelatedTo(feature, eOpposite));
};
final EdeltaModelMigrator.CopyProcedure _function_2 = (EStructuralFeature feature, EObject oldObj, EObject newObj) -> {
boolean _isRelatedTo = it.isRelatedTo(feature, eOpposite);
if (_isRelatedTo) {
return;
}
Collection oldValueOrValues = EdeltaEcoreUtil.getValueForFeature(oldObj, feature,
reference.getUpperBound());
final Function _function_3 = (Object oldValue) -> {
final EObject copy = it.getMigrated(((EObject) oldValue));
final Consumer _function_4 = (EObject o) -> {
o.eSet(extractedRef, copy);
};
return EdeltaEcoreUtil.createInstance(extracted, _function_4);
};
List copies = oldValueOrValues.stream().map(_function_3).collect(Collectors.toList());
EdeltaEcoreUtil.setValueForFeature(newObj, reference, copies);
};
it.copyRule(_function_1, _function_2);
};
this.modelMigration(_function);
return extracted;
}
/**
* Given an EClass, which is meant to represent a relation,
* removes such a class, transforming the relation into an EReference.
*
* For example, given
*
* a b1 b2 c
* A <-------> B <------> C
*
*
* (where the opposites "a" and "b2" might not be present)
* if we pass "B", then the result will be
*
* b2 b1
* A <-------> C
*
*
* @param cl
* @return the EReference that now represents the relation, that is,
* the EReference originally of type cl ("b1" above)
*/
public EReference classToReference(final EClass cl) {
final EReference reference = this.findSingleContainmentAmongReferencesToThisClass(cl);
final EClass owner = reference.getEContainingClass();
final EReference referenceToTarget = this.findSingleReferenceNotOfType(cl, owner);
reference.setEType(referenceToTarget.getEType());
EdeltaUtils.dropContainment(reference);
final EReference opposite = referenceToTarget.getEOpposite();
if ((opposite != null)) {
EdeltaUtils.makeBidirectional(reference, opposite);
}
EdeltaUtils.removeElement(cl);
return reference;
}
/**
* Given a non empty list of {@link EStructuralFeature}, which are known to
* appear in several classes as duplicates, extracts a new common superclass,
* with the duplicate feature,
* adds the extracted class as the superclass of the classes with the duplicate
* feature and removes the duplicate feature from such each class.
*
* The name of the extracted class is the name of the feature, with the first
* letter capitalized and the "Element" suffix (example, if the feature is
* "name" the extracted class will be called "NameElement").
* An additional number can be
* added as a suffix to avoid name clashes with existing classes.
*
* @param duplicates
*/
public EClass extractSuperclass(final List duplicates) {
final EStructuralFeature feature = IterableExtensions.head(duplicates);
String _firstUpper = StringExtensions.toFirstUpper(feature.getName());
String _plus = (_firstUpper + "Element");
final String superClassName = this.ensureEClassifierNameIsUnique(feature, _plus);
return this.extractSuperclass(superClassName, duplicates);
}
/**
* Given a non empty list of {@link EStructuralFeature}, which are known to
* appear in several classes as duplicates, extracts a new common superclass,
* with the given name, with the duplicate feature,
* adds the extracted class as the superclass of the classes with the duplicate
* feature and removes the duplicate feature from such each class.
*
* @param name
* @param duplicates
*/
public EClass extractSuperclass(final String name, final List duplicates) {
final EStructuralFeature feature = IterableExtensions.head(duplicates);
final Consumer _function = (EClass it) -> {
EdeltaUtils.makeAbstract(it);
final Function1 _function_1 = (EStructuralFeature it_1) -> {
return it_1.getEContainingClass();
};
final Consumer _function_2 = (EClass c) -> {
this.stdLib.addESuperType(c, it);
};
ListExtensions.map(duplicates, _function_1).forEach(_function_2);
this.pullUpFeatures(it, duplicates);
};
return this.stdLib.addNewEClassAsSibling(feature.getEContainingClass(), name, _function);
}
/**
* Given a non empty list of {@link EStructuralFeature}, which are known to
* appear in several subclasses as duplicates, pulls them up in
* the given common superclass
* (and removes the duplicate feature from each subclass).
*
* @param dest
* @param duplicates
*/
public EStructuralFeature pullUpFeatures(final EClass dest, final Collection duplicates) {
this.checkNoDifferences(duplicates,
new EdeltaFeatureDifferenceFinder().ignoringContainingClass(),
"The two features are not equal");
final Function1 _function = (EStructuralFeature it) -> {
return it.getEContainingClass();
};
this.checkAllDirectSubclasses(dest, IterableExtensions.toList(IterableExtensions.map(duplicates, _function)));
final EStructuralFeature pulledUp = this.stdLib.copyTo(IterableExtensions.head(duplicates), dest);
EdeltaUtils.removeAllElements(duplicates);
final Consumer _function_1 = (EdeltaModelMigrator it) -> {
it.mapFeaturesRule(duplicates, pulledUp);
};
this.modelMigration(_function_1);
return pulledUp;
}
/**
* Given a feature and a non empty list of {@link EClass}, which are known to
* be direct subclasses of the containing class of the feature, pushes the feature down in
* the given common subclasses
* (and removes the feature from the original containing class).
*
* @param featureToPush
* @param subClasses
*/
public Collection pushDownFeature(final EStructuralFeature featureToPush, final List subClasses) {
this.checkAllDirectSubclasses(featureToPush.getEContainingClass(), subClasses);
final HashMap pushedDownFeatures = new HashMap();
for (final EClass subClass : subClasses) {
{
EStructuralFeature pushedDown = EcoreUtil.copy(featureToPush);
pushedDownFeatures.put(subClass, pushedDown);
subClass.getEStructuralFeatures().add(0, pushedDown);
}
}
EdeltaUtils.removeElement(featureToPush);
final Consumer _function = (EdeltaModelMigrator it) -> {
final EdeltaModelMigrator.FeatureMigrator _function_1 = (EStructuralFeature feature, EObject oldObj, EObject newObj) -> {
return pushedDownFeatures.get(newObj.eClass());
};
it.featureMigratorRule(
it.wasRelatedTo(featureToPush), _function_1);
};
this.modelMigration(_function);
return pushedDownFeatures.values();
}
/**
* Create a new target class with the given name that merges all
* the passed classes.
*
* The classes are expected to have the same single direct superclass
* and to define the same features.
*
* @param mergedClassName
* @param toMerge
*/
public EClass mergeClasses(final String mergedClassName, final Collection toMerge) {
final EClass superClass = this.getSingleDirectSuperclass(toMerge);
this.checkSameFeatures(toMerge);
final Function1> _function = (EClass it) -> {
return it.getEStructuralFeatures();
};
this.checkNoBidirectionalReferences(IterableExtensions.toList(Iterables.concat(IterableExtensions.>map(toMerge, _function))),
"Cannot merge in the presence of bidirectional references");
final EClass merged = this.stdLib.copyToAs(IterableExtensions.head(toMerge), superClass.getEPackage(), mergedClassName);
EdeltaUtils.removeAllElements(toMerge);
final Consumer _function_1 = (EdeltaModelMigrator it) -> {
final EdeltaModelMigrator.EObjectFunction _function_2 = (EObject origObj) -> {
EObject _xblockexpression = null;
{
final EList origFeatures = origObj.eClass().getEAllStructuralFeatures();
final Consumer _function_3 = (EObject newObj) -> {
for (final EStructuralFeature origFeature : origFeatures) {
it.copyFrom(newObj, merged.getEStructuralFeature(origFeature.getName()), origObj, origFeature);
}
};
_xblockexpression = EdeltaEcoreUtil.createInstance(merged, _function_3);
}
return _xblockexpression;
};
it.createInstanceRule(
it.wasRelatedToAtLeastOneOf(toMerge), _function_2);
};
this.modelMigration(_function_1);
return merged;
}
/**
* Splits the passed class into several classes with the given names;
* all classes will be copies of the original class (which will be removed).
* Concerning model migration, it creates an object of the first split class.
*
* @param toSplit
* @param names
*/
public Collection splitClass(final EClass toSplit, final Collection names) {
final EPackage containingPackage = toSplit.getEPackage();
final EdeltaModelMigrator.EObjectFunction _function = (EObject origObj) -> {
return EdeltaEcoreUtil.createInstance(this.getEClass(containingPackage, IterableExtensions.head(names)));
};
return this.splitClass(toSplit, names, _function);
}
/**
* Splits the passed class into several classes with the given names;
* all classes will be copies of the original class (which will be removed).
* The objectMigrator is used when migrating the model objects of the original class:
* it is used to create an instance of the proper class and then all the features
* of the original object are copied into the created instance automatically
*
* @param toSplit
* @param names
* @param objectMigration
*/
public Collection splitClass(final EClass toSplit, final Collection names, final EdeltaModelMigrator.EObjectFunction objectMigrator) {
final Consumer _function = (EdeltaModelMigrator it) -> {
final EdeltaModelMigrator.EObjectFunction _function_1 = (EObject origObj) -> {
final EList origFeatures = origObj.eClass().getEAllStructuralFeatures();
final EObject newObj = objectMigrator.apply(origObj);
final EClass newClass = newObj.eClass();
for (final EStructuralFeature origFeature : origFeatures) {
it.copyFrom(newObj, newClass.getEStructuralFeature(origFeature.getName()), origObj, origFeature);
}
return newObj;
};
it.createInstanceRule(
it.wasRelatedTo(toSplit), _function_1);
};
return this.splitClass(toSplit, names, _function);
}
/**
* Splits the passed class into several classes with the given names;
* all classes will be copies of the original class (which will be removed).
* The migratorConsumer is used when migrating the model and the developer ahs
* the full control on such a migration by using the migratorConsumer appropriately
* to define migration rules.
*
* @param toSplit
* @param names
* @param objectMigration
*/
public Collection splitClass(final EClass toSplit, final Collection names, final Consumer migratorConsumer) {
final EPackage containingPackage = toSplit.getEPackage();
final Function1 _function = (String n) -> {
return this.stdLib.copyToAs(toSplit, containingPackage, n);
};
final List split = IterableExtensions.toList(IterableExtensions.map(names, _function));
EdeltaUtils.removeElement(toSplit);
this.modelMigration(migratorConsumer);
return split;
}
/**
* Ensures that the proposed classifier name is unique within the containing package of
* the passed context; if not, it appends an incremental index until the name
* is actually unique
*/
public String ensureEClassifierNameIsUnique(final ENamedElement context, final String proposedName) {
String className = proposedName;
EPackage ePackage = EdeltaUtils.getEContainingPackage(context);
final Function1 _function = (EClassifier it) -> {
return it.getName();
};
final List currentEClassifiersNames = IterableExtensions.sort(ListExtensions.map(ePackage.getEClassifiers(), _function));
int counter = 1;
while (currentEClassifiersNames.contains(className)) {
String _className = className;
int _plusPlus = counter++;
className = (_className + Integer.valueOf(_plusPlus));
}
return className;
}
public String fromTypeToFeatureName(final EClassifier type) {
return StringExtensions.toFirstLower(type.getName());
}
/**
* Makes sure that this is not a containment reference,
* otherwise it shows an error message
* and throws an IllegalArgumentException.
*
* @param reference the reference that must not be a containment reference
* @param errorMessage the message to show in case the reference
* is a containment reference
*/
public void checkNotContainment(final EReference reference, final String errorMessage) {
boolean _isContainment = reference.isContainment();
if (_isContainment) {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(reference);
final String message = ((errorMessage + ": ") + _eObjectRepr);
this.showError(reference, message);
throw new IllegalArgumentException(message);
}
}
/**
* Makes sure that this is not a multi element (upperBound > 1),
* otherwise it shows an error message
* and throws an IllegalArgumentException.
*
* @param element the element that must not be multi
* @param errorMessage the message to show in case the check fails
*/
public void checkNotMany(final ETypedElement element, final String errorMessage) {
boolean _isMany = element.isMany();
if (_isMany) {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(element);
final String message = ((errorMessage + ": ") + _eObjectRepr);
this.showError(element, message);
throw new IllegalArgumentException(message);
}
}
/**
* Makes sure that the passed collection does not have EReferences
* with an EOpposite. Otherwise shows an error (using
* also the passed errorMessage) with the details of the bidirectional references and
* throws an IllegalArgumentException
*/
public void checkNoBidirectionalReferences(final Collection features, final String errorMessage) {
final Function1 _function = (EReference it) -> {
EReference _eOpposite = it.getEOpposite();
return Boolean.valueOf((_eOpposite != null));
};
final Iterable bidirectionalReferences = IterableExtensions.filter(Iterables.filter(features, EReference.class), _function);
boolean _isEmpty = IterableExtensions.isEmpty(bidirectionalReferences);
boolean _not = (!_isEmpty);
if (_not) {
final Function1 _function_1 = (EReference it) -> {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(it);
return (" " + _eObjectRepr);
};
String _join = IterableExtensions.join(IterableExtensions.map(bidirectionalReferences, _function_1), "\n");
final String message = ((errorMessage + ":\n") + _join);
this.showError(IterableExtensions.head(bidirectionalReferences), message);
throw new IllegalArgumentException(message);
}
}
/**
* Makes sure that there are no differences in the passed features,
* using the specified differenceFinder, otherwise it shows an error message
* with the details of the differences and throws an IllegalArgumentException.
*
* @param features
* @param differenceFinder
* @param errorMessage
* @return true if there are no differences
*/
public void checkNoDifferences(final Iterable extends EStructuralFeature> features, final EdeltaFeatureDifferenceFinder differenceFinder, final String errorMessage) {
final EStructuralFeature feature = IterableExtensions.head(features);
final Function1 _function = (EStructuralFeature it) -> {
return Boolean.valueOf(((feature != it) && (!differenceFinder.equals(feature, it))));
};
final EStructuralFeature different = IterableExtensions.findFirst(features, _function);
if ((different != null)) {
String _differenceDetails = differenceFinder.getDifferenceDetails();
final String message = ((errorMessage + ":\n") + _differenceDetails);
this.showError(different, message);
throw new IllegalArgumentException(message);
}
}
/**
* Makes sure that all the passed classes are direct subclasses of
* the passed class.
*
* @param superClass
* @param classes
*/
public void checkAllDirectSubclasses(final EClass superClass, final Collection classes) {
final Function1 _function = (EClass it) -> {
boolean _contains = it.getESuperTypes().contains(superClass);
return Boolean.valueOf((!_contains));
};
final Iterable nonDirectSubclasses = IterableExtensions.filter(classes, _function);
boolean _isEmpty = IterableExtensions.isEmpty(nonDirectSubclasses);
boolean _not = (!_isEmpty);
if (_not) {
final Consumer _function_1 = (EClass it) -> {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(superClass);
String _plus = ("Not a direct subclass of: " + _eObjectRepr);
this.showError(it, _plus);
};
nonDirectSubclasses.forEach(_function_1);
throw new IllegalArgumentException("Not all direct subclasses");
}
}
/**
* Makes sure that the features have types that are subtypes of the
* specified feature, if not, shows
* error information and throws an IllegalArgumentException.
*
* @param feature
* @param features
*/
public void checkCompliant(final EStructuralFeature feature, final Collection extends EStructuralFeature> features) {
Predicate _xifexpression = null;
if ((feature instanceof EReference)) {
final Predicate _function = (EStructuralFeature other) -> {
boolean _xifexpression_1 = false;
if ((other instanceof EReference)) {
_xifexpression_1 = ((EReference)feature).getEReferenceType().isSuperTypeOf(((EReference)other).getEReferenceType());
} else {
_xifexpression_1 = false;
}
return _xifexpression_1;
};
_xifexpression = _function;
} else {
final Predicate _function_1 = (EStructuralFeature other) -> {
EClassifier _eType = feature.getEType();
EClassifier _eType_1 = other.getEType();
return (_eType == _eType_1);
};
_xifexpression = _function_1;
}
final Predicate compliance = _xifexpression;
final Function1 _function_2 = (EStructuralFeature it) -> {
boolean _test = compliance.test(it);
return Boolean.valueOf((!_test));
};
final Iterable extends EStructuralFeature> nonCompliant = IterableExtensions.filter(features, _function_2);
boolean _isEmpty = IterableExtensions.isEmpty(nonCompliant);
boolean _not = (!_isEmpty);
if (_not) {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(feature.getEType());
String _plus = ("features not compliant with type " + _eObjectRepr);
String _plus_1 = (_plus + ":\n");
final Function1 _function_3 = (EStructuralFeature it) -> {
String _eObjectRepr_1 = EdeltaUtils.getEObjectRepr(it);
String _plus_2 = (" " + _eObjectRepr_1);
String _plus_3 = (_plus_2 + ": ");
String _eObjectRepr_2 = EdeltaUtils.getEObjectRepr(it.getEType());
return (_plus_3 + _eObjectRepr_2);
};
String _join = IterableExtensions.join(IterableExtensions.map(nonCompliant, _function_3), "\n");
final String message = (_plus_1 + _join);
this.showError(feature, message);
throw new IllegalArgumentException(message);
}
}
public void checkType(final EStructuralFeature feature, final EClassifier expectedType) {
String _fullyQualifiedName = EdeltaUtils.getFullyQualifiedName(feature.getEType());
String _fullyQualifiedName_1 = EdeltaUtils.getFullyQualifiedName(expectedType);
boolean _notEquals = (!Objects.equals(_fullyQualifiedName, _fullyQualifiedName_1));
if (_notEquals) {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(expectedType);
String _plus = ("expecting " + _eObjectRepr);
String _plus_1 = (_plus + " but was ");
String _eObjectRepr_1 = EdeltaUtils.getEObjectRepr(feature.getEType());
final String message = (_plus_1 + _eObjectRepr_1);
this.showError(feature, message);
throw new IllegalArgumentException(message);
}
}
/**
* Makes sure the passed EClasses have no features, if not, shows
* error information and throws an IllegalArgumentException.
*
* @param classes
*/
public void checkNoFeatures(final Collection classes) {
final Function1 _function = (EClass c) -> {
final EList features = c.getEStructuralFeatures();
final boolean empty = features.isEmpty();
if ((!empty)) {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(c);
String _plus = ("Not an empty class: " + _eObjectRepr);
String _plus_1 = (_plus + ":\n");
final Function1 _function_1 = (EStructuralFeature it) -> {
String _eObjectRepr_1 = EdeltaUtils.getEObjectRepr(it);
return (" " + _eObjectRepr_1);
};
String _join = IterableExtensions.join(ListExtensions.map(features, _function_1), "\n");
String _plus_2 = (_plus_1 + _join);
this.showError(c, _plus_2);
}
return Boolean.valueOf((!empty));
};
final List classesWithFeatures = IterableExtensions.toList(IterableExtensions.filter(classes, _function));
boolean _isEmpty = classesWithFeatures.isEmpty();
boolean _not = (!_isEmpty);
if (_not) {
throw new IllegalArgumentException("Classes not empty");
}
}
/**
* Makes sure the passed EClasses have the same features,
* independently from the order, if not, shows
* error information and throws an IllegalArgumentException.
*
* @param classes
*/
public void checkSameFeatures(final Collection classes) {
final EClass firstClass = IterableExtensions.head(classes);
final Function1 _function = (EStructuralFeature it) -> {
return it.getName();
};
final List features = IterableExtensions.sortBy(firstClass.getEStructuralFeatures(), _function);
final Iterable otherClasses = IterableExtensions.tail(classes);
for (final EClass otherClass : otherClasses) {
{
final Function1 _function_1 = (EStructuralFeature it) -> {
return it.getName();
};
final List otherFeatures = IterableExtensions.sortBy(otherClass.getEStructuralFeatures(), _function_1);
final int expectedSize = features.size();
final int actualSize = otherFeatures.size();
if ((expectedSize != actualSize)) {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(firstClass);
String _plus = (((((("Different features size: expected " + Integer.valueOf(expectedSize)) + " but was ") + Integer.valueOf(actualSize)) + "\n ") +
"in classes ") + _eObjectRepr);
String _plus_1 = (_plus + ", ");
String _eObjectRepr_1 = EdeltaUtils.getEObjectRepr(otherClass);
String _plus_2 = (_plus_1 + _eObjectRepr_1);
this.showError(otherClass, _plus_2);
throw new IllegalArgumentException("Features don\'t match in size");
} else {
final EdeltaFeatureDifferenceFinder finder = new EdeltaFeatureDifferenceFinder().ignoringContainingClass();
final Iterator otherIt = otherFeatures.iterator();
for (final EStructuralFeature f : features) {
{
final EStructuralFeature other = otherIt.next();
boolean _equals = finder.equals(f, other);
boolean _not = (!_equals);
if (_not) {
final String message = finder.getDifferenceDetails();
this.showError(otherClass, message);
throw new IllegalArgumentException(message);
}
}
}
}
}
}
}
/**
* Finds, among all references to the given EClass, the single containment reference in the
* EClass' package's resource set, performing validation (that is,
* no reference is found, or more than one containment reference is found) checks and in case
* show errors and throws an IllegalArgumentException.
*
* Note that several references to the class are allowed: the important thing
* is that exactly one is a containment reference.
*
* @param cl
*/
public EReference findSingleContainmentAmongReferencesToThisClass(final EClass cl) {
final Iterable references = this.findReferencesToThisClass(cl);
final Function1 _function = (EReference it) -> {
return Boolean.valueOf(it.isContainment());
};
int _size = IterableExtensions.size(IterableExtensions.filter(references, _function));
boolean _greaterThan = (_size > 1);
if (_greaterThan) {
final Function1 _function_1 = (EReference it) -> {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(it);
return (" " + _eObjectRepr);
};
String _join = IterableExtensions.join(IterableExtensions.map(references, _function_1), "\n");
final String message = ("The EClass is referred by more than one container:\n" + _join);
this.showError(cl, message);
throw new IllegalArgumentException(message);
}
return IterableExtensions.head(references);
}
/**
* Finds all the EReferences to the given EClass in the
* EClass' package's resource set. If no such references are
* found it throws an IllegalArgumentException.
*
* @param cl
*/
public Iterable findReferencesToThisClass(final EClass cl) {
final Iterable references = this.allReferencesToThisClass(cl);
boolean _isEmpty = IterableExtensions.isEmpty(references);
if (_isEmpty) {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(cl);
final String message = ("The EClass is not referred: " + _eObjectRepr);
this.showError(cl, message);
throw new IllegalArgumentException(message);
}
return references;
}
/**
* Returns all the EReferences to the given EClass in the
* EClass' package's resource set.
*
* @param cl
*/
public Iterable allReferencesToThisClass(final EClass cl) {
final Function1 _function = (EStructuralFeature.Setting it) -> {
return it.getEObject();
};
return Iterables.filter(ListExtensions.map(this.allUsagesOfThisClass(cl), _function), EReference.class);
}
/**
* Finds the single usage of this class and it must be a
* containment reference. Otherwise it show errors and throws an IllegalArgumentException.
*
* Note that several references to the class are allowed: the important thing
* is that exactly one is a containment reference.
*
* @param cl
*/
public EReference findSingleContainmentReferenceToThisClass(final EClass cl) {
return this.getAsContainmentReference(this.findSingleUsageOfThisClass(cl));
}
/**
* Finds the single usage the given EClass in the
* EClass' package's resource set, performing validation (that is,
* no usage is found, or more than one) checks and in case
* show errors and throws an IllegalArgumentException.
*
* @param cl
*/
public EObject findSingleUsageOfThisClass(final EClass cl) {
final List usages = this.allUsagesOfThisClass(cl);
boolean _isEmpty = usages.isEmpty();
if (_isEmpty) {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(cl);
final String message = ("The EClass is not used: " + _eObjectRepr);
this.showError(cl, message);
throw new IllegalArgumentException(message);
}
int _size = usages.size();
boolean _greaterThan = (_size > 1);
if (_greaterThan) {
final Function1 _function = (EStructuralFeature.Setting it) -> {
String _eObjectRepr_1 = EdeltaUtils.getEObjectRepr(it.getEObject());
String _plus = (" " + _eObjectRepr_1);
String _plus_1 = (_plus + "\n");
String _plus_2 = (_plus_1 +
" ");
String _eObjectRepr_2 = EdeltaUtils.getEObjectRepr(it.getEStructuralFeature());
return (_plus_2 + _eObjectRepr_2);
};
String _join = IterableExtensions.join(ListExtensions.map(usages, _function), "\n");
final String message_1 = ("The EClass is used by more than one element:\n" + _join);
this.showError(cl, message_1);
throw new IllegalArgumentException(message_1);
}
return IterableExtensions.head(usages).getEObject();
}
/**
* Makes sure that the passed EObject represent a containment EReference
* otherwise shows an error and throws an IllegalArgumentException
*
* @param o
* @return the containment EReference if it is a containment reference
*/
public EReference getAsContainmentReference(final EObject o) {
if ((o instanceof EReference)) {
boolean _isContainment = ((EReference)o).isContainment();
boolean _not = (!_isContainment);
if (_not) {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(o);
final String message = ("Not a containment reference: " + _eObjectRepr);
this.showError(((ENamedElement)o), message);
throw new IllegalArgumentException(message);
}
return ((EReference)o);
}
String _eObjectRepr_1 = EdeltaUtils.getEObjectRepr(o);
final String message_1 = ("Not a reference: " + _eObjectRepr_1);
this.showError(((ENamedElement) o), message_1);
throw new IllegalArgumentException(message_1);
}
/**
* Returns all the usages of the given EClass in the
* EClass' package's resource set.
*
* @param cl
*/
public List allUsagesOfThisClass(final EClass cl) {
final Function1 _function = (EStructuralFeature.Setting it) -> {
EObject _eObject = it.getEObject();
return Boolean.valueOf((_eObject instanceof ENamedElement));
};
final Function1 _function_1 = (EStructuralFeature.Setting it) -> {
boolean _isDerived = it.getEStructuralFeature().isDerived();
return Boolean.valueOf((!_isDerived));
};
return IterableExtensions.toList(IterableExtensions.filter(IterableExtensions.filter(EcoreUtil.UsageCrossReferencer.find(cl, EdeltaUtils.packagesToInspect(cl)), _function), _function_1));
}
/**
* Finds the single EReference, in the EReferences of the given EClass,
* with a type different from the given type, performing validation (that is,
* no reference is found, or more than one) checks and in case
* show errors and throws an IllegalArgumentException
*
* @param cl
* @param target
*/
public EReference findSingleReferenceNotOfType(final EClass cl, final EClass type) {
final Function1 _function = (EReference it) -> {
EClassifier _eType = it.getEType();
return Boolean.valueOf((_eType != type));
};
final List otherReferences = IterableExtensions.toList(IterableExtensions.filter(cl.getEReferences(), _function));
boolean _isEmpty = otherReferences.isEmpty();
if (_isEmpty) {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(type);
final String message = ("No references not of type " + _eObjectRepr);
this.showError(cl, message);
throw new IllegalArgumentException(message);
}
int _size = otherReferences.size();
boolean _greaterThan = (_size > 1);
if (_greaterThan) {
String _eObjectRepr_1 = EdeltaUtils.getEObjectRepr(type);
String _plus = ("Too many references not of type " + _eObjectRepr_1);
String _plus_1 = (_plus +
":\n");
final Function1 _function_1 = (EReference it) -> {
String _eObjectRepr_2 = EdeltaUtils.getEObjectRepr(it);
return (" " + _eObjectRepr_2);
};
String _join = IterableExtensions.join(ListExtensions.map(otherReferences, _function_1), "\n");
final String message_1 = (_plus_1 + _join);
this.showError(cl, message_1);
throw new IllegalArgumentException(message_1);
}
return IterableExtensions.head(otherReferences);
}
/**
* Finds and returns the single containing class of the passed features.
* If there's more than one containing class throws an IllegalArgumentException.
*/
public EClass findSingleOwner(final Collection features) {
final Function1 _function = (EStructuralFeature it) -> {
return it.getEContainingClass();
};
final Map> owners = IterableExtensions.groupBy(features, _function);
int _size = owners.size();
boolean _greaterThan = (_size > 1);
if (_greaterThan) {
final Function1>, String> _function_1 = (Map.Entry> it) -> {
final String reprForClass = EdeltaUtils.getEObjectRepr(it.getKey());
this.showError(it.getKey(),
("Extracted features must belong to the same class: " + reprForClass));
final Function1 _function_2 = (EStructuralFeature it_1) -> {
String _eObjectRepr = EdeltaUtils.getEObjectRepr(it_1);
return (" " + _eObjectRepr);
};
String _join = IterableExtensions.join(ListExtensions.map(it.getValue(), _function_2), "\n");
return (((" " + reprForClass) + ":\n") + _join);
};
String _join = IterableExtensions.join(IterableExtensions.>, String>map(owners.entrySet(), _function_1), "\n");
final String message = ("Multiple containing classes:\n" + _join);
throw new IllegalArgumentException(message);
}
return IterableExtensions.head(features).getEContainingClass();
}
/**
* Checks that the passed subclasses have all exactly one superclass
* and that it is the same and returns that as a result. It also checks
* that such a common superclass has no further subclasses.
*
* In case of failure, besides reporting errors, it throws an
* IllegalArgumentException.
*/
public EClass getSingleDirectSuperclass(final Collection subclasses) {
final Function1 _function = (EClass it) -> {
int _size = it.getESuperTypes().size();
return Boolean.valueOf((_size != 1));
};
final Iterable invalid = IterableExtensions.filter(subclasses, _function);
boolean _isEmpty = IterableExtensions.isEmpty(invalid);
boolean _not = (!_isEmpty);
if (_not) {
final Consumer