blob: 0a0fb5c9193955b6394622ecfe13f37a2f64b162 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2019 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* E.D.Willink - Initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.pivot.internal.library.executor;
import java.lang.ref.WeakReference;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.WeakHashMap;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.common.util.Enumerator;
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.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.EcoreEList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.EcoreUtil.ExternalCrossReferencer;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.CompleteEnvironment;
import org.eclipse.ocl.pivot.CompleteInheritance;
import org.eclipse.ocl.pivot.CompletePackage;
import org.eclipse.ocl.pivot.Element;
import org.eclipse.ocl.pivot.Enumeration;
import org.eclipse.ocl.pivot.EnumerationLiteral;
import org.eclipse.ocl.pivot.Model;
import org.eclipse.ocl.pivot.Operation;
import org.eclipse.ocl.pivot.Property;
import org.eclipse.ocl.pivot.StandardLibrary;
import org.eclipse.ocl.pivot.TemplateParameter;
import org.eclipse.ocl.pivot.TemplateParameterSubstitution;
import org.eclipse.ocl.pivot.TemplateableElement;
import org.eclipse.ocl.pivot.TupleType;
import org.eclipse.ocl.pivot.Type;
import org.eclipse.ocl.pivot.TypedElement;
import org.eclipse.ocl.pivot.ids.ClassId;
import org.eclipse.ocl.pivot.ids.CollectionTypeId;
import org.eclipse.ocl.pivot.ids.DataTypeId;
import org.eclipse.ocl.pivot.ids.EnumerationId;
import org.eclipse.ocl.pivot.ids.EnumerationLiteralId;
import org.eclipse.ocl.pivot.ids.IdManager;
import org.eclipse.ocl.pivot.ids.IdResolver;
import org.eclipse.ocl.pivot.ids.IdVisitor;
import org.eclipse.ocl.pivot.ids.LambdaTypeId;
import org.eclipse.ocl.pivot.ids.MapTypeId;
import org.eclipse.ocl.pivot.ids.NestedPackageId;
import org.eclipse.ocl.pivot.ids.NsURIPackageId;
import org.eclipse.ocl.pivot.ids.OclInvalidTypeId;
import org.eclipse.ocl.pivot.ids.OclVoidTypeId;
import org.eclipse.ocl.pivot.ids.OperationId;
import org.eclipse.ocl.pivot.ids.PackageId;
import org.eclipse.ocl.pivot.ids.PrimitiveTypeId;
import org.eclipse.ocl.pivot.ids.PropertyId;
import org.eclipse.ocl.pivot.ids.RootPackageId;
import org.eclipse.ocl.pivot.ids.TemplateBinding;
import org.eclipse.ocl.pivot.ids.TemplateParameterId;
import org.eclipse.ocl.pivot.ids.TemplateableTypeId;
import org.eclipse.ocl.pivot.ids.TuplePartId;
import org.eclipse.ocl.pivot.ids.TupleTypeId;
import org.eclipse.ocl.pivot.ids.TypeId;
import org.eclipse.ocl.pivot.ids.UnspecifiedId;
import org.eclipse.ocl.pivot.internal.executor.ExecutorTuplePart;
import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal;
import org.eclipse.ocl.pivot.internal.values.BagImpl;
import org.eclipse.ocl.pivot.internal.values.OrderedSetImpl;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ocl.pivot.utilities.PivotConstants;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.ocl.pivot.utilities.ValueUtil;
import org.eclipse.ocl.pivot.values.Bag;
import org.eclipse.ocl.pivot.values.BagValue;
import org.eclipse.ocl.pivot.values.CollectionValue;
import org.eclipse.ocl.pivot.values.IntegerValue;
import org.eclipse.ocl.pivot.values.InvalidValueException;
import org.eclipse.ocl.pivot.values.MapValue;
import org.eclipse.ocl.pivot.values.OCLValue;
import org.eclipse.ocl.pivot.values.OrderedSet;
import org.eclipse.ocl.pivot.values.OrderedSetValue;
import org.eclipse.ocl.pivot.values.SequenceValue;
import org.eclipse.ocl.pivot.values.SetValue;
import org.eclipse.ocl.pivot.values.Unlimited;
import org.eclipse.ocl.pivot.values.UnlimitedNaturalValue;
import org.eclipse.ocl.pivot.values.Value;
import com.google.common.collect.Iterables;
public abstract class AbstractIdResolver implements IdResolver.IdResolverExtension
{
public static final class Id2InstanceVisitor implements IdVisitor<Object>
{
protected final @NonNull String stringValue;
private Id2InstanceVisitor(@NonNull String stringValue) {
this.stringValue = stringValue;
}
@Override
public @Nullable Object visitClassId(@NonNull ClassId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitCollectionTypeId(@NonNull CollectionTypeId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitDataTypeId(@NonNull DataTypeId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitEnumerationId(@NonNull EnumerationId id) {
return id.getEnumerationLiteralId(stringValue);
}
@Override
public @Nullable Object visitEnumerationLiteralId(@NonNull EnumerationLiteralId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitInvalidId(@NonNull OclInvalidTypeId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitLambdaTypeId(@NonNull LambdaTypeId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitMapTypeId(@NonNull MapTypeId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitNestedPackageId(@NonNull NestedPackageId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitNsURIPackageId(@NonNull NsURIPackageId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitNullId(@NonNull OclVoidTypeId id) {
return null;
}
@Override
public @Nullable Object visitOperationId(@NonNull OperationId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitPrimitiveTypeId(@NonNull PrimitiveTypeId id) {
if (id == TypeId.BOOLEAN) {
return Boolean.valueOf(stringValue);
}
else if (id == TypeId.STRING) {
return stringValue;
}
else if (id == TypeId.INTEGER) {
return ValueUtil.integerValueOf(stringValue);
}
else if (id == TypeId.REAL) {
return ValueUtil.realValueOf(stringValue);
}
else if (id == TypeId.UNLIMITED_NATURAL) {
return ValueUtil.integerValueOf(stringValue);
}
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitPropertyId(@NonNull PropertyId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitRootPackageId(@NonNull RootPackageId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitTemplateBinding(@NonNull TemplateBinding id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitTemplateParameterId(@NonNull TemplateParameterId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitTemplateableTypeId(@NonNull TemplateableTypeId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitTuplePartId(@NonNull TuplePartId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitTupleTypeId(@NonNull TupleTypeId id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Object visitUnspecifiedId(@NonNull UnspecifiedId id) {
throw new UnsupportedOperationException();
}
}
@SuppressWarnings("serial")
private static class MyList extends ArrayList<Object> {} // Private list to ensure that My List is never confused with a user List
protected final @NonNull CompleteEnvironment environment;
protected final @NonNull StandardLibrary standardLibrary;
private final @NonNull Set<@NonNull EObject> directRoots = new HashSet<>();
private boolean directRootsProcessed = false;
private boolean crossReferencedRootsProcessed = false;
/**
* @since 1.1
*/
protected final @NonNull Map<@NonNull Object, @NonNull Type> key2type = new HashMap<>(); // Concurrent puts are duplicates
private /*@LazyNonNull*/ Map<@NonNull EnumerationLiteralId, @NonNull Enumerator> enumerationLiteral2enumerator = null; // Concurrent puts are duplicates
private /*@LazyNonNull*/ Map<@NonNull Enumerator, @NonNull EnumerationLiteralId> enumerator2enumerationLiteralId = null; // Concurrent puts are duplicates
/**
* Mapping from name to list of correspondingly named types for definition of tuple parts. This cache is used to provide the
* required part definitions to construct a tuple type in the lightweight execution environment. This cache may remain
* unused when using the full pivot environment.
*/
private Map<@NonNull String, @NonNull Map<@NonNull Type, @NonNull WeakReference<@NonNull TypedElement>>> tupleParts = null; // Lazily created
/**
* Mapping from package URI to corresponding Pivot Package. (used to resolve NsURIPackageId).
*/
protected final @NonNull Map<@Nullable String, org.eclipse.ocl.pivot.@NonNull Package> nsURI2package = new HashMap<>();
/**
* Mapping from root package name to corresponding Pivot Package. (used to resolve RootPackageId).
*/
protected final @NonNull Map<@NonNull String, org.eclipse.ocl.pivot.@NonNull Package> roots2package = new HashMap<>();
/**
* Push-down stack of static types that may be used to resolve TemplateParameterIds.
*
* @since 1.7
*/
protected final @NonNull Stack<@Nullable Type> staticTypeStack = new Stack<>();
public AbstractIdResolver(@NonNull CompleteEnvironment environment) {
this.environment = environment;
this.standardLibrary = environment.getOwnedStandardLibrary();
}
protected abstract org.eclipse.ocl.pivot.@NonNull Package addEPackage(@NonNull EPackage ePackage);
private void addPackage(org.eclipse.ocl.pivot.@NonNull Package userPackage) {
String nsURI = userPackage.getURI();
if (nsURI != null) {
nsURI2package.put(nsURI, userPackage);
EPackage ePackage = userPackage.getEPackage();
if (ePackage != null) {
if (ClassUtil.basicGetMetamodelAnnotation(ePackage) != null) {
if (roots2package.get(PivotConstants.METAMODEL_NAME) == null) {
roots2package.put(PivotConstants.METAMODEL_NAME, userPackage);
}
}
}
else {
for (org.eclipse.ocl.pivot.Class asType : userPackage.getOwnedClasses()) {
if ("Boolean".equals(asType.getName())) { // FIXME Check PrimitiveType //$NON-NLS-1$
if (roots2package.get(PivotConstants.METAMODEL_NAME) == null) {
roots2package.put(PivotConstants.METAMODEL_NAME, userPackage);
}
break;
}
}
}
}
else {
String name = userPackage.getName();
if (name != null) {
roots2package.put(name, userPackage);
}
}
addPackages(userPackage.getOwnedPackages());
}
private void addPackages(/*@NonNull*/ Iterable<? extends org.eclipse.ocl.pivot.Package> userPackages) {
for (org.eclipse.ocl.pivot.Package userPackage : userPackages) {
assert userPackage != null;
addPackage(userPackage);
}
}
@Override
public void addRoot(@NonNull EObject eObject) {
directRoots.add(eObject);
}
/**
* @since 1.1
*/
@Override
public org.eclipse.ocl.pivot.@Nullable Package basicGetPackage(@NonNull PackageId packageId) {
Element element = packageId.accept(this);
if (element instanceof org.eclipse.ocl.pivot.Package) {
return (org.eclipse.ocl.pivot.Package) element;
}
return null;
}
@Override
public @Nullable Object boxedValueOf(@Nullable Object unboxedValue) {
if (unboxedValue == null) {
return unboxedValue;
}
else if (unboxedValue instanceof Value) {
return unboxedValue;
}
else if (unboxedValue instanceof Boolean) {
return unboxedValue;
}
else if (unboxedValue instanceof String) {
return unboxedValue;
}
else if (unboxedValue instanceof Number) {
if ((unboxedValue instanceof Integer) || (unboxedValue instanceof Long) || (unboxedValue instanceof Short) || (unboxedValue instanceof Byte)) {
return ValueUtil.integerValueOf(((Number) unboxedValue).longValue());
}
if ((unboxedValue instanceof Float) || (unboxedValue instanceof Double)) {
return ValueUtil.realValueOf(((Number) unboxedValue).doubleValue());
}
if (unboxedValue instanceof BigDecimal) {
return ValueUtil.realValueOf((BigDecimal) unboxedValue);
}
if (unboxedValue instanceof BigInteger) {
return ValueUtil.integerValueOf((BigInteger) unboxedValue);
}
if (unboxedValue instanceof Unlimited) {
return unboxedValue;
}
}
else if (unboxedValue instanceof Character) {
return ValueUtil.integerValueOf(((Character) unboxedValue).charValue());
}
else if (unboxedValue.getClass().isArray()) {
try {
@Nullable Object @NonNull [] unboxedValues = (@Nullable Object @NonNull [])unboxedValue;
Type dynamicType = getDynamicTypeOf(unboxedValues);
if (dynamicType == null) {
dynamicType = standardLibrary.getOclInvalidType();
}
TypeId elementTypeId = dynamicType.getTypeId();
CollectionTypeId collectedTypeId = TypeId.SEQUENCE.getSpecializedId(elementTypeId);
return createSequenceOfEach(collectedTypeId, (@Nullable Object @NonNull [])unboxedValue);
}
catch (IllegalArgumentException e) {}
}
else if (unboxedValue instanceof Iterable<?>) {
Iterable<?> unboxedValues = (Iterable<?>)unboxedValue;
Type dynamicType = getDynamicTypeOf(unboxedValues);
if (dynamicType == null) {
dynamicType = standardLibrary.getOclInvalidType();
}
TypeId elementTypeId = dynamicType.getTypeId();
if ((unboxedValue instanceof LinkedHashSet) || (unboxedValue instanceof OrderedSet)) {
CollectionTypeId collectedTypeId = TypeId.ORDERED_SET.getSpecializedId(elementTypeId);
return createOrderedSetOfAll(collectedTypeId, unboxedValues);
}
else if (unboxedValue instanceof Bag) {
CollectionTypeId collectedTypeId = TypeId.BAG.getSpecializedId(elementTypeId);
return createBagOfAll(collectedTypeId, unboxedValues);
}
else if (unboxedValue instanceof Set) {
CollectionTypeId collectedTypeId = TypeId.SET.getSpecializedId(elementTypeId);
return createSetOfAll(collectedTypeId, unboxedValues);
}
else {
CollectionTypeId collectedTypeId = TypeId.SEQUENCE.getSpecializedId(elementTypeId);
return createSequenceOfAll(collectedTypeId, unboxedValues);
}
}
/* else if (unboxedValue instanceof EEnumLiteral) {
return ValuesUtil.createEnumerationLiteralValue((EEnumLiteral)unboxedValue);
} */
else if (unboxedValue instanceof Type) {
return unboxedValue;
}
else if (unboxedValue instanceof EnumerationLiteral) {
return ((EnumerationLiteral) unboxedValue).getEnumerationLiteralId();
}
else if (unboxedValue instanceof EEnumLiteral) {
return getEnumerationLiteralId((EEnumLiteral) unboxedValue);
}
else if (unboxedValue instanceof EObject) {
return unboxedValue;
}
else if (unboxedValue instanceof Element) {
return unboxedValue;
}
else if (unboxedValue instanceof EnumerationLiteralId) { // ?? shouldn't happen
return unboxedValue;
}
else if (unboxedValue instanceof Enumerator) {
return boxedValueOfEnumerator((Enumerator) unboxedValue);
}
return unboxedValue;
}
@Override
public @Nullable Object boxedValueOf(@NonNull Object unboxedValue, @Nullable EClassifier eClassifier) {
if (unboxedValue instanceof Value) {
return unboxedValue;
}
else if (eClassifier instanceof EEnum) {
EnumerationId enumId = getEnumerationId((EEnum)eClassifier);
String name = ClassUtil.nonNullModel(((Enumerator)unboxedValue).getName());
return enumId.getEnumerationLiteralId(name);
}
else {
return boxedValueOf(unboxedValue);
}
}
@Override
public @Nullable Object boxedValueOf(@NonNull Object unboxedValue, @NonNull ETypedElement eFeature, @Nullable TypeId typeId) {
EClassifier eClassifier = eFeature.getEType();
if (typeId instanceof CollectionTypeId) {
Collection<?> unboxedValues = (Collection<?>) unboxedValue;
if (eClassifier instanceof EDataType) {
ArrayList<Object> values = new ArrayList<>(unboxedValues.size());
for (Object eVal : unboxedValues) {
if (eVal != null) {
values.add(boxedValueOf(eVal, eClassifier));
}
}
unboxedValues = values;
}
return createCollectionOfAll((CollectionTypeId)typeId, unboxedValues);
}
else if (typeId instanceof MapTypeId) {
MapTypeId mapTypeId = (MapTypeId)typeId;
@NonNull Map<?,?> unboxedMap;
if (unboxedValue instanceof EMap) {
@SuppressWarnings("null")
@NonNull Map<?, ?> map = ((@NonNull EMap<?,?>)unboxedValue).map();
unboxedMap = map;
}
else {
unboxedMap = (Map<?,?>)unboxedValue;
}
return createMapOfAll(mapTypeId.getKeyTypeId(), mapTypeId.getValueTypeId(), unboxedMap);
}
else {
return boxedValueOf(unboxedValue, eClassifier);
}
}
public @Nullable Object boxedValueOfEnumerator(@NonNull Enumerator unboxedValue) {
Map<@NonNull Enumerator, @NonNull EnumerationLiteralId> enumerator2enumerationLiteralId2 = enumerator2enumerationLiteralId;
if (enumerator2enumerationLiteralId2 == null) {
synchronized (this) {
enumerator2enumerationLiteralId2 = enumerator2enumerationLiteralId;
if (enumerator2enumerationLiteralId2 == null) {
enumerator2enumerationLiteralId = enumerator2enumerationLiteralId2 = new HashMap<>();
for (@NonNull CompletePackage dPackage : standardLibrary.getAllCompletePackages()) {
for (org.eclipse.ocl.pivot.Class dType : dPackage.getAllClasses()) {
if (dType instanceof Enumeration) {
for (EnumerationLiteral dEnumerationLiteral : ((Enumeration) dType).getOwnedLiterals()) {
Enumerator enumerator = dEnumerationLiteral.getEnumerator();
EnumerationLiteralId enumerationLiteralId = dEnumerationLiteral.getEnumerationLiteralId();
enumerator2enumerationLiteralId.put(enumerator, enumerationLiteralId);
}
}
}
}
}
}
}
EnumerationLiteralId enumerationLiteralId = enumerator2enumerationLiteralId2.get(unboxedValue);
if (enumerationLiteralId == null) {
throw new InvalidValueException("Unknown enumeration " + unboxedValue.getName()); //$NON-NLS-1$
}
return enumerationLiteralId;
}
@Override
public @NonNull BagValue createBagOfAll(@NonNull CollectionTypeId typeId, @NonNull Iterable<? extends Object> unboxedValues) {
Bag<Object> boxedValues = new BagImpl<>();
for (Object unboxedValue : unboxedValues) {
boxedValues.add(boxedValueOf(unboxedValue));
}
return ValueUtil.createBagValue(typeId, boxedValues);
}
@Override
public @NonNull BagValue createBagOfEach(@NonNull CollectionTypeId typeId, @Nullable Object @NonNull ... unboxedValues) {
Bag<Object> boxedValues = new BagImpl<>();
for (Object unboxedValue : unboxedValues) {
boxedValues.add(boxedValueOf(unboxedValue));
}
return ValueUtil.createBagValue(typeId, boxedValues);
}
/**
* Creates a new OCL <tt>Collection</tt> of the specified ordering and uniqueness.
*
* @param isOrdered the required collection ordering
* @param isUnique the required collection uniqueness
* @param unboxedValues the required collection contents
* @return the new collection
*/
@Override
public @NonNull CollectionValue createCollectionOfAll(boolean isOrdered, boolean isUnique, @NonNull TypeId elementTypeId, @NonNull Iterable<? extends Object> unboxedValues) {
if (isOrdered) {
if (isUnique) {
return createOrderedSetOfAll(TypeId.ORDERED_SET.getSpecializedId(elementTypeId), unboxedValues);
}
else {
return createSequenceOfAll(TypeId.SEQUENCE.getSpecializedId(elementTypeId), unboxedValues);
}
}
else {
if (isUnique) {
return createSetOfAll(TypeId.SET.getSpecializedId(elementTypeId), unboxedValues);
}
else {
return createBagOfAll(TypeId.BAG.getSpecializedId(elementTypeId), unboxedValues);
}
}
}
@Override
public @NonNull CollectionValue createCollectionOfAll(@NonNull CollectionTypeId collectedId, @NonNull Iterable<?> unboxedValues) {
CollectionTypeId collectionId = collectedId.getGeneralizedId();
if (collectionId == TypeId.BAG) {
return createBagOfAll(collectedId, unboxedValues);
}
else if (collectionId == TypeId.ORDERED_SET) {
return createOrderedSetOfAll(collectedId, unboxedValues);
}
else if (collectionId == TypeId.SEQUENCE) {
return createSequenceOfAll(collectedId, unboxedValues);
}
else if (collectionId == TypeId.SET) {
return createSetOfAll(collectedId, unboxedValues);
}
else /*if (collectionId == TypeId.COLLECTION)*/ {
if (unboxedValues instanceof LinkedHashSet<?>) {
return createOrderedSetOfAll(collectedId, unboxedValues);
}
else if (unboxedValues instanceof Set<?>) {
return createSetOfAll(collectedId, unboxedValues);
}
else if (unboxedValues instanceof Bag<?>) {
return createBagOfAll(collectedId, unboxedValues);
}
else /*if (unboxedValues instanceof List<?>)*/ {
return createSequenceOfAll(collectedId, unboxedValues);
}
}
}
@Override
public @Nullable Object createInstance(@NonNull TypeId typeId, @NonNull String stringValue) {
Id2InstanceVisitor visitor = new Id2InstanceVisitor(stringValue);
return typeId.accept(visitor);
}
@Override
public @NonNull MapValue createMapOfAll(@NonNull TypeId keyTypeId, @NonNull TypeId valueTypeId, @NonNull Map<?, ?> unboxedValues) {
Map<Object, Object> boxedValues = new HashMap<>();
for (Map.Entry<?, ?> unboxedValue : unboxedValues.entrySet()) {
boxedValues.put(boxedValueOf(unboxedValue.getKey()), boxedValueOf(unboxedValue.getValue()));
}
return ValueUtil.createMapValue(keyTypeId, valueTypeId, boxedValues);
}
@Override
public @NonNull OrderedSetValue createOrderedSetOfAll(@NonNull CollectionTypeId typeId, @NonNull Iterable<? extends Object> unboxedValues) {
OrderedSet<Object> boxedValues = new OrderedSetImpl<>();
for (Object unboxedValue : unboxedValues) {
boxedValues.add(boxedValueOf(unboxedValue));
}
return ValueUtil.createOrderedSetValue(typeId, boxedValues);
}
@Override
public @NonNull OrderedSetValue createOrderedSetOfEach(@NonNull CollectionTypeId typeId, @Nullable Object @NonNull ... unboxedValues) {
OrderedSet<Object> boxedValues = new OrderedSetImpl<>();
for (Object unboxedValue : unboxedValues) {
boxedValues.add(boxedValueOf(unboxedValue));
}
return ValueUtil.createOrderedSetValue(typeId, boxedValues);
}
@Override
public @NonNull SequenceValue createSequenceOfAll(@NonNull CollectionTypeId typeId, @NonNull Iterable<? extends Object> unboxedValues) {
List<Object> boxedValues = new ArrayList<>();
for (Object unboxedValue : unboxedValues) {
boxedValues.add(boxedValueOf(unboxedValue));
}
return ValueUtil.createSequenceValue(typeId, boxedValues);
}
@Override
public @NonNull SequenceValue createSequenceOfEach(@NonNull CollectionTypeId typeId, @Nullable Object @NonNull ... unboxedValues) {
List<Object> boxedValues = new ArrayList<>();
for (Object unboxedValue : unboxedValues) {
boxedValues.add(boxedValueOf(unboxedValue));
}
return ValueUtil.createSequenceValue(typeId, boxedValues);
}
@Override
public @NonNull SetValue createSetOfAll(@NonNull CollectionTypeId typeId, @NonNull Iterable<? extends Object> unboxedValues) {
Set<Object> boxedValues = new HashSet<>();
for (Object unboxedValue : unboxedValues) {
boxedValues.add(boxedValueOf(unboxedValue));
}
return ValueUtil.createSetValue(typeId, boxedValues);
}
@Override
public @NonNull SetValue createSetOfEach(@NonNull CollectionTypeId typeId, @Nullable Object @NonNull ... unboxedValues) {
Set<Object> boxedValues = new HashSet<>();
for (Object unboxedValue : unboxedValues) {
boxedValues.add(boxedValueOf(unboxedValue));
}
return ValueUtil.createSetValue(typeId, boxedValues);
}
@Override
public void dispose() {
tupleParts = null;
key2type.clear();
enumerationLiteral2enumerator = null;
enumerator2enumerationLiteralId = null;
}
@Override
public @Nullable Object ecoreValueOf(@Nullable Class<?> instanceClass, @Nullable Object value) {
if (value instanceof Value) {
return ((Value)value).asEcoreObject(this, instanceClass);
}
else if (value instanceof Number) {
Number number = (Number)value;
if ((instanceClass == Double.class) || (instanceClass == double.class)) {
return number.doubleValue();
}
else if ((instanceClass == Float.class) || (instanceClass == float.class)) {
return number.floatValue();
}
else if ((instanceClass == Short.class) || (instanceClass == short.class)) {
return number.shortValue();
}
else if ((instanceClass == Integer.class) || (instanceClass == int.class)) {
return number.intValue();
}
else if ((instanceClass == Long.class) || (instanceClass == long.class)) {
return number.longValue();
}
else if (instanceClass == BigDecimal.class) {
return BigDecimal.valueOf(number.doubleValue());
}
else if (instanceClass == BigInteger.class) {
return BigInteger.valueOf(number.longValue());
}
else { // instanceClass is null, make a best guess
if ((number instanceof BigDecimal) || (number instanceof Double) || (number instanceof Float)) {
return number.doubleValue();
}
else {
return number.intValue();
}
}
}
else if (value instanceof EnumerationLiteralId) {
return unboxedValueOf((EnumerationLiteralId)value);
}
else if (value instanceof EEnumLiteral) {
return ((EEnumLiteral)value).getInstance();
}
else if (value instanceof Iterable<?>) {
if (value instanceof EcoreEList.UnmodifiableEList<?>) {
return value;
}
else {
@SuppressWarnings("unchecked") Iterable<Object> values = (Iterable<Object>)value;
return ecoreValuesOfAll(instanceClass, values);
}
}
else {
return value;
}
}
/**
* @since 1.1
*/
@Override
public @NonNull <T> EList<T> ecoreValueOfAll(@Nullable Class<T> instanceClass, @NonNull Iterable<? extends Object> values) {
Object[] ecoreValues = new Object[Iterables.size(values)];
int i= 0;
for (Object value : values) {
ecoreValues[i++] = ecoreValueOf(instanceClass, value);
}
return new EcoreEList.UnmodifiableEList<>(null, null, ecoreValues.length, ecoreValues);
}
/** @deprecated no longer used */
@Deprecated
@Override
public @NonNull EList<Object> ecoreValuesOfAll(@Nullable Class<?> instanceClass, @NonNull Iterable<Object> values) {
Object[] ecoreValues = new Object[Iterables.size(values)];
int i= 0;
for (Object value : values) {
ecoreValues[i++] = ecoreValueOf(instanceClass, value);
}
return new EcoreEList.UnmodifiableEList<>(null, null, ecoreValues.length, ecoreValues);
}
/** @deprecated no longer used */
@Deprecated
@Override
public @NonNull EList<Object> ecoreValuesOfEach(@Nullable Class<?> instanceClass, @NonNull Object @NonNull ... values) {
Object[] ecoreValues = new Object[values.length];
int i= 0;
for (Object value : values) {
ecoreValues[i++] = ecoreValueOf(instanceClass, value);
}
return new EcoreEList.UnmodifiableEList<>(null, null, ecoreValues.length, ecoreValues);
}
@Override
public org.eclipse.ocl.pivot.@NonNull Class getClass(@NonNull TypeId typeId, @Nullable Object context) {
Element type = typeId.accept(this);
assert type != null;
return (org.eclipse.ocl.pivot.Class)type;
}
@Override
public org.eclipse.ocl.pivot.@NonNull Class getCollectionType(@NonNull CollectionTypeId typeId) {
return getCollectionType(typeId, false, null, null);
}
public org.eclipse.ocl.pivot.@NonNull Class getCollectionType(@NonNull CollectionTypeId typeId, boolean isNullFree, @Nullable IntegerValue lower, @Nullable UnlimitedNaturalValue upper) {
CollectionTypeId generalizedId = typeId.getGeneralizedId();
if ((typeId == generalizedId) && !isNullFree && (lower == null) && (upper == null)) {
if (generalizedId == TypeId.BAG) {
return standardLibrary.getBagType();
}
else if (generalizedId == TypeId.COLLECTION) {
return standardLibrary.getCollectionType();
}
else if (generalizedId == TypeId.ORDERED_SET) {
return standardLibrary.getOrderedSetType();
}
else if (generalizedId == TypeId.SEQUENCE) {
return standardLibrary.getSequenceType();
}
else if (generalizedId == TypeId.SET) {
return standardLibrary.getSetType();
}
else if (generalizedId == TypeId.UNIQUE_COLLECTION) {
return standardLibrary.getUniqueCollectionType();
}
else {
throw new UnsupportedOperationException();
}
}
else {
TypeId elementTypeId = typeId.getElementTypeId();
Type elementType = getType(elementTypeId, null);
if (generalizedId == TypeId.BAG) {
return environment.getBagType(elementType, isNullFree, lower, upper);
}
else if (generalizedId == TypeId.COLLECTION) {
return environment.getCollectionType(standardLibrary.getCollectionType(), elementType, isNullFree, lower, upper);
}
else if (generalizedId == TypeId.ORDERED_SET) {
return environment.getOrderedSetType(elementType, isNullFree, lower, upper);
}
else if (generalizedId == TypeId.SEQUENCE) {
return environment.getSequenceType(elementType, isNullFree, lower, upper);
}
else if (generalizedId == TypeId.SET) {
return environment.getSetType(elementType, isNullFree, lower, upper);
}
else {
throw new UnsupportedOperationException();
}
}
}
@Override
public org.eclipse.ocl.pivot.@NonNull Class getDynamicTypeOf(@Nullable Object value) {
if (value instanceof CollectionValue) {
CollectionValue collectionValue = (CollectionValue) value;
CollectionTypeId collectionTypeId = collectionValue.getTypeId();
Type elementType = getDynamicTypeOf(collectionValue.iterable());
if (elementType == null) {
elementType = getType(collectionTypeId.getElementTypeId(), null);
}
CollectionTypeId collectedId = collectionTypeId;
CollectionTypeId collectionId = collectedId.getGeneralizedId();
TypeId elementTypeId = elementType.getTypeId();
collectedId = collectionId.getSpecializedId(elementTypeId);
final IntegerValue size = collectionValue.size();
return getCollectionType(collectedId, false, size, size.asUnlimitedNaturalValue()); // FIXME dynamic isNullFree
}
else {
return getStaticTypeOf(value);
}
}
@Override
public @Nullable Type getDynamicTypeOf(@Nullable Object @NonNull ... values) {
Type elementType = null;
for (Object value : values) {
org.eclipse.ocl.pivot.Class valueType = getDynamicTypeOf(value);
if (elementType == null) {
elementType = valueType;
}
else {
elementType = elementType.getCommonType(this, valueType);
}
}
if (elementType == null) {
elementType = standardLibrary.getOclInvalidType();
}
return elementType;
}
@Override
public @Nullable Type getDynamicTypeOf(@NonNull Iterable<?> values) {
Type elementType = null;
for (Object value : values) {
org.eclipse.ocl.pivot.Class valueType = getDynamicTypeOf(value);
if (elementType == null) {
elementType = valueType;
}
else {
elementType = elementType.getCommonType(this, valueType);
}
}
return elementType;
}
/**
* @since 1.4
*/
protected @NonNull EnumerationId getEnumerationId(@NonNull EEnum eEnum) {
String name = eEnum.getName();
assert name != null;
EPackage parentPackage = eEnum.getEPackage();
assert parentPackage != null;
return getPackageId(parentPackage).getEnumerationId(name);
}
/**
* @since 1.4
*/
protected @NonNull EnumerationLiteralId getEnumerationLiteralId(@NonNull EEnumLiteral eEnumLiteral) {
EEnum eEnum = ClassUtil.nonNullModel(eEnumLiteral.getEEnum());
String name = ClassUtil.nonNullModel(eEnumLiteral.getName());
EnumerationId enumerationId = getEnumerationId(eEnum);
return enumerationId.getEnumerationLiteralId(name);
}
@Override
public @NonNull CompleteEnvironment getEnvironment() {
return environment;
}
@Override
public synchronized org.eclipse.ocl.pivot.@NonNull Class getJavaType(@NonNull Class<?> javaClass) {
Type type = key2type.get(javaClass);
if (type instanceof JavaType) {
return (JavaType)type;
}
/* if (javaClass == Boolean.class) {
type = standardLibrary.getBooleanType();
}
else if (javaClass == String.class) {
type = standardLibrary.getStringType();
}
else { */
JavaType javaType = new JavaType(javaClass);
// }
key2type.put(javaClass, javaType);
return javaType;
}
@Override
public org.eclipse.ocl.pivot.@NonNull Class getMapType(@NonNull MapTypeId typeId) {
return getMapType(typeId, true, true);
}
/**
* @since 1.6
*/
public org.eclipse.ocl.pivot.@NonNull Class getMapType(@NonNull MapTypeId typeId, boolean keysAreNullFree, boolean valuesAreNullFree) {
MapTypeId generalizedId = typeId.getGeneralizedId();
if (typeId == generalizedId) {
if (generalizedId == TypeId.MAP) {
return standardLibrary.getMapType();
}
else {
throw new UnsupportedOperationException();
}
}
else {
TypeId keyTypeId = typeId.getKeyTypeId();
TypeId valueTypeId = typeId.getValueTypeId();
Type keyType = getType(keyTypeId, null);
Type valueType = getType(valueTypeId, null);
if (generalizedId == TypeId.MAP) {
return environment.getMapType(standardLibrary.getMapType(), keyType, keysAreNullFree, valueType, valuesAreNullFree);
}
else {
throw new UnsupportedOperationException();
}
}
}
/**
* @since 1.1
*/
@Override
public @Nullable Iterable<org.eclipse.ocl.pivot.@NonNull Class> getModelClassesOf(@NonNull Object value) {
return null;
}
@Override
public @NonNull Operation getOperation(@NonNull OperationId operationId) {
Element element = operationId.accept(this);
if (element instanceof Operation) {
return (Operation) element;
}
throw new IllegalStateException("No " + operationId); //$NON-NLS-1$
}
@Override
public org.eclipse.ocl.pivot.@NonNull Package getPackage(@NonNull PackageId packageId) {
Element element = packageId.accept(this);
if (element instanceof org.eclipse.ocl.pivot.Package) {
return (org.eclipse.ocl.pivot.Package) element;
}
throw new IllegalStateException("No " + packageId); //$NON-NLS-1$
}
/**
* @since 1.4
*/
protected @NonNull PackageId getPackageId(@NonNull EPackage ePackage) { // UML overrides to resolve EPackages that are applied Profiles
return IdManager.getPackageId(ePackage);
}
@Override
public @NonNull Property getProperty(@NonNull PropertyId propertyId) {
Element element = propertyId.accept(this);
if (element instanceof Property) {
return (Property) element;
}
throw new IllegalStateException("No " + propertyId); //$NON-NLS-1$
}
@Override
public @NonNull StandardLibrary getStandardLibrary() {
return standardLibrary;
}
@Override
@Deprecated /* @deprecated getStaticTypeOfValue to enable TemplateParameters to be resolved */
public org.eclipse.ocl.pivot.@NonNull Class getStaticTypeOf(@Nullable Object value) {
Type staticType = getStaticTypeOfValue(null, value);
org.eclipse.ocl.pivot.Class asClass = staticType.isClass();
if (asClass != null) {
return asClass;
}
TemplateParameter templateParameter = staticType.isTemplateParameter();
if (templateParameter != null) {
return PivotUtil.getLowerBound(templateParameter, standardLibrary.getOclAnyType());
}
throw new UnsupportedOperationException();
}
@Override
public org.eclipse.ocl.pivot.@NonNull Class getStaticTypeOf(@Nullable Object value, @Nullable Object @NonNull ... values) {
Object bestTypeId = getTypeKeyOf(value);
Type bestType = key2type.get(bestTypeId);
assert bestType != null;
Collection<Object> assessedTypeKeys = null;
int count = 0;
for (Object anotherValue : values) {
Object anotherTypeId = getTypeKeyOf(anotherValue);
if ((assessedTypeKeys == null) ? (anotherTypeId != bestTypeId) : !assessedTypeKeys.contains(anotherTypeId)) {
Type anotherType = key2type.get(anotherTypeId);
assert anotherType != null;
Type commonType = bestType.getCommonType(this, anotherType);
if ((commonType != bestType) && (commonType instanceof org.eclipse.ocl.pivot.Class)) {
if (assessedTypeKeys == null) {
assessedTypeKeys = new ArrayList<>();
assessedTypeKeys.add(bestTypeId);
}
else if (count++ == 4) {
assessedTypeKeys = new HashSet<>(assessedTypeKeys);
}
assessedTypeKeys.add(anotherTypeId);
bestType = commonType;
bestTypeId = anotherTypeId;
}
}
}
return (org.eclipse.ocl.pivot.Class)bestType;
}
@Override
public org.eclipse.ocl.pivot.@NonNull Class getStaticTypeOf(@Nullable Object value, @NonNull Iterable<?> values) {
Object bestTypeKey = getTypeKeyOf(value);
Type bestType = key2type.get(bestTypeKey);
assert bestType != null;
Collection<Object> assessedTypeKeys = null;
int count = 0;
for (Object anotherValue : values) {
assert anotherValue != null;
Object anotherTypeKey = getTypeKeyOf(anotherValue);
if ((assessedTypeKeys == null) ? (anotherTypeKey != bestTypeKey) : !assessedTypeKeys.contains(anotherTypeKey)) {
Type anotherType = key2type.get(anotherTypeKey);
assert anotherType != null;
Type commonType = bestType.getCommonType(this, anotherType);
if (commonType != bestType) {
if (assessedTypeKeys == null) {
assessedTypeKeys = new ArrayList<>();
assessedTypeKeys.add(bestTypeKey);
}
else if (count++ == 4) {
assessedTypeKeys = new HashSet<>(assessedTypeKeys);
}
assessedTypeKeys.add(anotherTypeKey);
}
}
}
return (org.eclipse.ocl.pivot.Class)bestType;
}
@Override
public org.eclipse.ocl.pivot.@NonNull Class getStaticTypeOfValue(@Nullable Type staticType, @Nullable Object value) {
if (value instanceof EObject) {
EClass eClass = ((EObject)value).eClass();
assert eClass != null;
Type type = key2type.get(eClass);
if (type == null) {
type = getInheritance(eClass).getPivotClass();
assert type != null;
key2type.put(eClass, type);
}
return PivotUtil.getClass(type, standardLibrary);
}
else if (value instanceof Value) {
TypeId typeId = ((Value)value).getTypeId();
Type type = key2type.get(typeId);
if (type == null) {
boolean isTemplated = typeId.isTemplated();
if (isTemplated) {
staticTypeStack.push(staticType);
try {
type = (Type)typeId.accept(this);
}
finally {
staticTypeStack.pop();
}
}
else {
type = (Type)typeId.accept(this);
}
if (type == null) {
type = standardLibrary.getOclAnyType();
}
key2type.put(typeId, type);
}
return PivotUtil.getClass(type, standardLibrary);
}
else if (value == null) {
return standardLibrary.getOclVoidType();
}
if (value instanceof Boolean) {
return standardLibrary.getBooleanType();
}
else if (value instanceof String) {
return standardLibrary.getStringType();
}
else if (value instanceof Number) {
if ((value instanceof BigDecimal) || (value instanceof Double) || (value instanceof Float)) {
return standardLibrary.getRealType();
}
if ((value instanceof BigInteger) || (value instanceof Byte) || (value instanceof Integer) || (value instanceof Long) || (value instanceof Short)) {
return standardLibrary.getIntegerType();
}
}
else if (value instanceof EnumerationLiteralId) {
EnumerationLiteral enumLiteral = (EnumerationLiteral) ((EnumerationLiteralId)value).accept(this);
assert enumLiteral != null;
Enumeration enumeration = enumLiteral.getOwningEnumeration();
assert enumeration != null;
return enumeration;
}
Class<?> jClass = value.getClass();
assert jClass != null;
return getJavaType(jClass);
}
@Override
public @NonNull TypedElement getTuplePart(@NonNull String name, @NonNull TypeId typeId) {
return getTuplePart(name, getType(typeId, null));
}
public synchronized @NonNull TypedElement getTuplePart(@NonNull String name, @NonNull Type type) {
if (tupleParts == null) {
tupleParts = new WeakHashMap<>();
}
Map<@NonNull Type, @NonNull WeakReference<@NonNull TypedElement>> typeMap = tupleParts.get(name);
if (typeMap == null) {
typeMap = new WeakHashMap<>();
tupleParts.put(name, typeMap);
}
TypedElement tupleProperty = weakGet(typeMap, type);
if (tupleProperty == null) {
tupleProperty = new ExecutorTuplePart(type, name);
typeMap.put(type, new WeakReference<>(tupleProperty));
}
return tupleProperty;
}
@Override
public abstract @NonNull TupleType getTupleType(@NonNull TupleTypeId typeId);
@Override
public @NonNull Type getType(@NonNull TypeId typeId, @Nullable Object context) {
Element type = typeId.accept(this);
assert type != null;
return (Type)type;
}
private @NonNull Object getTypeKeyOf(@Nullable Object value) {
/*if (value instanceof DomainType) {
DomainType type = (DomainType) id2element.get(value);
if (type == null) {
type = standardLibrary.getMetaclass((DomainType) value);
assert type != null;
id2element.put(value, type);
}
return value;
}
else*/ if (value instanceof EObject) {
EClass typeKey = ((EObject)value).eClass();
assert typeKey != null;
Type type = key2type.get(typeKey);
if (type == null) {
type = getInheritance(typeKey).getPivotClass();
assert type != null;
key2type.put(typeKey, type);
}
return typeKey;
}
else if (value instanceof Value) {
TypeId typeKey = ((Value)value).getTypeId();
Type type = key2type.get(typeKey);
if (type == null) {
type = (org.eclipse.ocl.pivot.Class) typeKey.accept(this);
assert type != null;
key2type.put(typeKey, type);
}
return typeKey;
}
else if (value instanceof EnumerationLiteralId) {
TypeId typeKey = ((EnumerationLiteralId)value).getParentId();
Type type = key2type.get(typeKey);
if (type == null) {
type = (org.eclipse.ocl.pivot.Class) typeKey.accept(this);
assert type != null;
key2type.put(typeKey, type);
}
return typeKey;
}
else if (value == null) {
TypeId typeKey = TypeId.OCL_VOID;
key2type.put(typeKey, standardLibrary.getOclVoidType());
return typeKey;
}
else {
Class<?> typeKey = value.getClass();
assert typeKey != null;
Type type = key2type.get(typeKey);
if (type != null) {
return typeKey;
}
if (value instanceof Boolean) {
type = standardLibrary.getBooleanType();
}
else if (value instanceof String) {
type = standardLibrary.getStringType();
}
if (type != null) {
key2type.put(typeKey, type);
return typeKey;
}
}
throw new UnsupportedOperationException();
}
/**
* @since 1.1
*/
public boolean isOrdered(@NonNull Object aCollection) {
if (aCollection instanceof CollectionValue) {
return ((CollectionValue)aCollection).isOrdered();
}
else if (aCollection instanceof EcoreEList<?>) {
EStructuralFeature eStructuralFeature = ((EcoreEList<?>)aCollection).getEStructuralFeature();
if (eStructuralFeature != null) {
return eStructuralFeature.isOrdered();
}
}
else if (aCollection instanceof List<?>) {
return true;
}
else if (aCollection instanceof LinkedHashSet<?>) {
return true;
}
return false;
}
/**
* @since 1.1
*/
public boolean isUnique(@NonNull Object aCollection) {
if (aCollection instanceof CollectionValue) {
return ((CollectionValue)aCollection).isUnique();
}
else if (aCollection instanceof EcoreEList<?>) {
EStructuralFeature eStructuralFeature = ((EcoreEList<?>)aCollection).getEStructuralFeature();
if (eStructuralFeature != null) {
return eStructuralFeature.isUnique();
}
}
else if (aCollection instanceof Set<?>) {
return true;
}
return false;
}
// @Override
/* public boolean oclEquals2(@Nullable Object thisValue, @Nullable Object thatValue) {
if (thisValue == thatValue) {
return true;
}
else if (thisValue instanceof OCLValue) {
if (thatValue instanceof OCLValue) {
return ((OCLValue)thisValue).oclEquals((OCLValue)thatValue);
}
else {
thatValue = boxedValueOf(thatValue);
if (thatValue instanceof OCLValue) {
return ((OCLValue)thisValue).oclEquals((OCLValue)thatValue);
}
else {
return false;
}
}
}
else if (thatValue instanceof OCLValue) {
thisValue = boxedValueOf(thisValue);
if (thisValue instanceof OCLValue) {
return ((OCLValue)thisValue).oclEquals((OCLValue)thatValue);
}
else {
return false;
}
}
else if (thisValue != null) {
if (thatValue != null) {
return thisValue.equals(thatValue);
}
else {
return false;
}
}
else {
return thatValue == null;
}
} */
/**
* Return true if this Value is equal to thatValue regardless of the prevailing ecore/boxed/unboxed
* representation of each input.
*/
@Override
public boolean oclEquals(@Nullable Object thisObject, @Nullable Object thatObject) {
if (thisObject == thatObject) {
return true;
}
if ((thisObject == null) || (thatObject == null)) {
return false;
}
boolean thisIsValue = thisObject instanceof Value;
boolean thatIsValue = thatObject instanceof Value;
if (thisIsValue && thatIsValue) {
return ((Value)thisObject).equals(thatObject);
}
boolean thisIsOCLValue = thisObject instanceof OCLValue;
boolean thatIsOCLValue = thatObject instanceof OCLValue;
if (thisIsOCLValue || thatIsOCLValue) {
OCLValue thisOCLValue = (OCLValue)(thisIsOCLValue ? thisObject : boxedValueOf(thisObject));
OCLValue thatOCLValue = (OCLValue)(thatIsOCLValue ? thatObject : boxedValueOf(thatObject));
assert thisOCLValue != null;
assert thatOCLValue != null;
return thisOCLValue.oclEquals(thatOCLValue);
}
boolean thisIsCollection = thisObject instanceof Collection<?>;
boolean thatIsCollection = thatObject instanceof Collection<?>;
boolean thisIsCollectionValue = thisObject instanceof CollectionValue;
boolean thatIsCollectionValue = thatObject instanceof CollectionValue;
boolean thisIsCollecting = thisIsCollection || thisIsCollectionValue;
boolean thatIsCollecting = thatIsCollection || thatIsCollectionValue;
if (thisIsCollecting || thatIsCollecting) {
if (!thisIsCollecting || !thatIsCollecting) {
return false;
}
boolean thisIsUnique = isUnique(thisObject);
boolean thatIsUnique = isUnique(thatObject);
if (thisIsUnique != thatIsUnique) {
return false;
}
boolean thisIsOrdered = isOrdered(thisObject);
boolean thatIsOrdered = isOrdered(thatObject);
if (thisIsOrdered != thatIsOrdered) {
return false;
}
int thisSize = thisIsCollection ? ((Collection<?>)thisObject).size() : ((CollectionValue)thisObject).intSize();
int thatSize = thatIsCollection ? ((Collection<?>)thatObject).size() : ((CollectionValue)thatObject).intSize();
if (thisSize != thatSize) {
return false;
}
Iterator<?> thisIterator = ((Iterable<?>)thisObject).iterator();
Iterator<?> thatIterator = ((Iterable<?>)thatObject).iterator();
if (thisIsOrdered) {
while (thisIterator.hasNext() && thatIterator.hasNext()) {
Object thisElement = thisIterator.next();
Object thatElement = thatIterator.next();
if (!oclEquals(thisElement, thatElement)) {
return false;
}
}
return !thisIterator.hasNext() && !thatIterator.hasNext();
}
else {
if (thisSize < thatSize) {
return oclEqualsUnordered(thisIterator, thatIterator);
}
else {
return oclEqualsUnordered(thatIterator, thisIterator);
}
}
}
boolean thisIsNumber = thisObject instanceof Number;
boolean thatIsNumber = thatObject instanceof Number;
if (thisIsNumber || thatIsNumber) {
Value thisValue;
if (thisIsNumber) {
thisValue = ValueUtil.numberValueOf((Number)thisObject);
}
else if (thisObject instanceof Value) {
thisValue = (Value)thisObject;
}
else {
return false;
}
Value thatValue;
if (thatIsNumber) {
thatValue = ValueUtil.numberValueOf((Number)thatObject);
}
else if (thatObject instanceof Value) {
thatValue = (Value)thatObject;
}
else {
return false;
}
return thisValue.equals(thatValue);
}
return thisObject.equals(thatObject);
}
private boolean oclEqualsUnordered(/*@NonNull*/ Iterator<?> smallerIterator, /*@NonNull*/ Iterator<?> largerIterator) {
//
// Build a hash to element map from all the smallerIterator elements.
//
Map<Integer, Object> map = new HashMap<>();
while (smallerIterator.hasNext()) {
Object smallerElement = smallerIterator.next();
Integer hashCode = oclHashCode(smallerElement);
Object zeroOrMoreElements = map.get(hashCode);
if ((zeroOrMoreElements == null) && !map.containsKey(hashCode)) {
map.put(hashCode, smallerElement);
}
else if (zeroOrMoreElements instanceof MyList) {
((MyList)zeroOrMoreElements).add(smallerElement);
}
else {
MyList twoOrMoreElements = new MyList();
twoOrMoreElements.add(zeroOrMoreElements);
twoOrMoreElements.add(smallerElement);
map.put(hashCode, twoOrMoreElements);
}
}
//
// Remove a hash to element map entry for each of the largerIterator elements exiting non equal prematurely for a failure.
//
while (largerIterator.hasNext()) {
Object largerElement = largerIterator.next();
Integer hashCode = oclHashCode(largerElement);
Object zeroOrMoreElements = map.get(hashCode);
if ((zeroOrMoreElements == null) && !map.containsKey(hashCode)) {
return false;
}
else if (zeroOrMoreElements instanceof MyList) {
boolean gotIt = false;
MyList largerElements = (MyList)zeroOrMoreElements;
for (Object smallerElement : largerElements) {
if (oclEquals(smallerElement, largerElement)) {
largerElements.remove(smallerElement);
if (largerElements.size() <= 0) {
map.remove(hashCode);
}
gotIt = true;
}
}
if (!gotIt) {
return false;
}
}
else if (zeroOrMoreElements == largerElement) {
if (!oclEquals(zeroOrMoreElements, largerElement)) {
return false;
}
map.remove(hashCode);
}
}
return map.size() == 0;
}
/**
* Return the hashCode of the boxed value of anObject, thereby ensuring that the same hashCode
* is used for ecore, boxed and unboxed representations.
* @since 1.1
*/
@Override
public int oclHashCode(@Nullable Object anObject) {
if (anObject == null) {
return 0;
}
if (anObject instanceof OCLValue) {
return ((OCLValue)anObject).oclHashCode();
}
if (anObject instanceof Value) {
return ((Value)anObject).hashCode();
}
if (anObject instanceof Collection<?>) {
return ValueUtil.computeCollectionHashCode(isOrdered(anObject), isUnique(anObject), (Iterable<?>)anObject);
}
else if (anObject instanceof Number) {
if ((anObject instanceof BigDecimal) || (anObject instanceof Double) || (anObject instanceof Float) || (anObject instanceof BigInteger) || (anObject instanceof Long)) {
Object boxedValue = boxedValueOf(anObject);
assert boxedValue != null;
return boxedValue.hashCode();
}
return ((Number)anObject).intValue();
}
// else if (anObject instanceof String) {
// return ((String)anObject).hashCode();
// }
// else if (anObject instanceof Character) {
// return ((Character)anObject).charValue();
// }
else {
return anObject.hashCode();
// return System.identityHashCode(anObject);
}
}
protected synchronized void processCrossReferencedRoots() {
if (crossReferencedRootsProcessed ) {
return;
}
crossReferencedRootsProcessed = true;
new ExternalCrossReferencer(directRoots)
{
private static final long serialVersionUID = 1L;
private Set<EObject> moreRoots = new HashSet<>();
{ findExternalCrossReferences(); }
@Override
protected boolean crossReference(EObject eObject, EReference eReference, EObject crossReferencedEObject) {
EObject root = EcoreUtil.getRootContainer(crossReferencedEObject);
if (moreRoots.add(root) && !directRoots.contains(root)) {
if (root instanceof Model) {
addPackages(((Model)root).getOwnedPackages());
}
else if (root instanceof org.eclipse.ocl.pivot.Package) { // Perhaps this is only needed for a lazy JUnit test
addPackage((org.eclipse.ocl.pivot.Package)root);
}
}
return false;
}
};
}
protected synchronized void processDirectRoots() {
if (directRootsProcessed) {
return;
}
directRootsProcessed = true;
Set<EPackage> ePackages = new HashSet<>();
for (EObject eObject : directRoots) {
if (eObject instanceof Model) {
addPackages(((Model)eObject).getOwnedPackages());
}
// else if (eObject instanceof org.eclipse.ocl.pivot.Package) { // Perhaps this is only needed for a lazy JUnit test
// addPackage((org.eclipse.ocl.pivot.Package)eObject);
// }
else {
ePackages.add(eObject.eClass().getEPackage());
}
}
for (@SuppressWarnings("null")@NonNull EPackage ePackage : ePackages) {
addEPackage(ePackage);
}
}
@Override
public @Nullable Object unboxedValueOf(@Nullable Object boxedValue) {
if (boxedValue instanceof Value) {
return ((Value)boxedValue).asUnboxedObject(this);
}
else if (boxedValue instanceof EnumerationLiteralId) {
return unboxedValueOf((EnumerationLiteralId)boxedValue);
}
else {
return boxedValue;
}
}
@Override
public @NonNull Enumerator unboxedValueOf(@NonNull EnumerationLiteralId enumerationLiteralId) {
if (enumerationLiteral2enumerator == null) {
synchronized (this) {
if (enumerationLiteral2enumerator == null) {
enumerationLiteral2enumerator = new HashMap<>();
}
}
}
Enumerator enumerator = enumerationLiteral2enumerator.get(enumerationLiteralId);
if (enumerator == null) {
synchronized (enumerationLiteral2enumerator) {
enumerator = enumerationLiteral2enumerator.get(enumerationLiteralId);
if (enumerator == null) {
EnumerationLiteral enumerationLiteral = (EnumerationLiteral) enumerationLiteralId.accept(this);
if (enumerationLiteral != null) {
enumerator = enumerationLiteral.getEnumerator();
enumerationLiteral2enumerator.put(enumerationLiteralId, enumerator);
}
if (enumerator == null) {
throw new UnsupportedOperationException(); // FIXME
}
}
}
}
return enumerator;
}
@Override
public @NonNull EList<Object> unboxedValuesOfAll(@NonNull Collection<? extends Object> boxedValues) {
Object[] unboxedValues = new Object[boxedValues.size()];
int i= 0;
for (Object boxedValue : boxedValues) {
unboxedValues[i++] = unboxedValueOf(boxedValue);
}
return new EcoreEList.UnmodifiableEList<>(null, null, i, unboxedValues);
}
@Override
public @NonNull EList<Object> unboxedValuesOfEach(@Nullable Object @NonNull ... boxedValues) {
Object[] unboxedValues = new Object[boxedValues.length];
int i= 0;
for (Object boxedValue : boxedValues) {
unboxedValues[i++] = unboxedValueOf(boxedValue);
}
return new EcoreEList.UnmodifiableEList<>(null, null, boxedValues.length, unboxedValues);
}
@Override
public @NonNull Type visitClassId(@NonNull ClassId id) {
org.eclipse.ocl.pivot.Package parentPackage = (org.eclipse.ocl.pivot.Package) id.getParent().accept(this);
assert parentPackage != null;
Type nestedType = environment.getNestedType(parentPackage, id.getName());
if (nestedType == null) {
nestedType = environment.getNestedType(parentPackage, id.getName());
throw new UnsupportedOperationException();
}
return nestedType;
}
public @NonNull Type visitCollectedId(@NonNull CollectionTypeId id) {
Type elementType = (Type) id.getElementTypeId().accept(this);
if (elementType == null) {
throw new UnsupportedOperationException();
}
CollectionTypeId collectionTypeId = id.getGeneralizedId();
org.eclipse.ocl.pivot.Class collectionType = getCollectionType(collectionTypeId);
return environment.getCollectionType(collectionType, elementType, false, null, null);
}
@Override
public @NonNull Type visitCollectionTypeId(@NonNull CollectionTypeId id) {
return getCollectionType(id);
}
@Override
public @NonNull Type visitDataTypeId(@NonNull DataTypeId id) {
org.eclipse.ocl.pivot.Package parentPackage = (org.eclipse.ocl.pivot.Package) id.getParent().accept(this);
assert parentPackage != null;
Type nestedType = environment.getNestedType(parentPackage, id.getName());
if (nestedType == null) {
nestedType = environment.getNestedType(parentPackage, id.getName());
if (nestedType == null) {
throw new UnsupportedOperationException();
}
}
return nestedType;
}
@Override
public @NonNull Enumeration visitEnumerationId(@NonNull EnumerationId id) {
org.eclipse.ocl.pivot.Package parentPackage = (org.eclipse.ocl.pivot.Package) id.getParent().accept(this);
assert parentPackage != null;
Type nestedType = environment.getNestedType(parentPackage, id.getName());
if (nestedType == null) {
nestedType = environment.getNestedType(parentPackage, id.getName());
throw new UnsupportedOperationException();
}
if (!(nestedType instanceof Enumeration)) {
throw new UnsupportedOperationException();
}
return (Enumeration) nestedType;
}
@Override
public @NonNull EnumerationLiteral visitEnumerationLiteralId(@NonNull EnumerationLiteralId id) {
Element parent = id.getParentId().accept(this);
if (!(parent instanceof Enumeration)) {
throw new UnsupportedOperationException();
}
EnumerationLiteral enumerationLiteral = ((Enumeration)parent).getEnumerationLiteral(id.getName());
if (enumerationLiteral == null) {
throw new UnsupportedOperationException();
}
return enumerationLiteral;
}
@Override
public @NonNull Type visitInvalidId(@NonNull OclInvalidTypeId id) {
return standardLibrary.getOclInvalidType();
}
@Override
public @NonNull Type visitLambdaTypeId(@NonNull LambdaTypeId id) {
throw new UnsupportedOperationException();
}
@Override
public @NonNull Type visitMapTypeId(@NonNull MapTypeId id) {
return getMapType(id);
}
@Override
public org.eclipse.ocl.pivot.@NonNull Package visitNestedPackageId(@NonNull NestedPackageId packageId) {
org.eclipse.ocl.pivot.Package parentPackage = (org.eclipse.ocl.pivot.Package) packageId.getParent().accept(this);
assert parentPackage != null;
org.eclipse.ocl.pivot.Package nestedPackage = environment.getNestedPackage(parentPackage, packageId.getName());
if (nestedPackage == null) {
throw new UnsupportedOperationException();
}
return nestedPackage;
}
/* @Override
public org.eclipse.ocl.pivot.@NonNull Package visitNsURIPackageId(@NonNull NsURIPackageId id) {
org.eclipse.ocl.pivot.Package nsURIPackage = standardLibrary.getNsURIPackage(id.getNsURI());
if (nsURIPackage == null) {
throw new UnsupportedOperationException();
}
return nsURIPackage;
} */
@Override
public synchronized org.eclipse.ocl.pivot.@NonNull Package visitNsURIPackageId(@NonNull NsURIPackageId id) {
String nsURI = id.getNsURI();
org.eclipse.ocl.pivot.Package knownPackage = nsURI2package.get(nsURI);
if (knownPackage != null) {
return knownPackage;
}
org.eclipse.ocl.pivot.Package libraryPackage = standardLibrary.getNsURIPackage(nsURI);
if (libraryPackage != null) {
nsURI2package.put(nsURI, libraryPackage);
return libraryPackage;
}
if (!directRootsProcessed) {
processDirectRoots();
knownPackage = nsURI2package.get(nsURI);
if (knownPackage != null) {
return knownPackage;
}
}
if (!crossReferencedRootsProcessed) {
processCrossReferencedRoots();
knownPackage = nsURI2package.get(nsURI);
if (knownPackage != null) {
return knownPackage;
}
}
EPackage ePackage = id.getEPackage();
if (ePackage != null) {
org.eclipse.ocl.pivot.Package asPackage = addEPackage(ePackage);
/* EcoreReflectivePackage ecoreExecutorPackage = new EcoreReflectivePackage(ePackage, this, id);
// EList<EClassifier> eClassifiers = ePackage.getEClassifiers();
// EcoreReflectiveType[] types = new EcoreReflectiveType[eClassifiers.size()];
// for (int i = 0; i < types.length; i++) {
// types[i] = new EcoreReflectiveType(eClassifiers.get(i), ecoreExecutorPackage, 0);
// }
// ecoreExecutorPackage.init((ExecutorStandardLibrary) standardLibrary, types);
nsURI2package.put(nsURI, ecoreExecutorPackage); */
return asPackage;
}
throw new UnsupportedOperationException();
}
@Override
public @NonNull Type visitNullId(@NonNull OclVoidTypeId id) {
return standardLibrary.getOclVoidType();
}
@Override
public @NonNull Operation visitOperationId(@NonNull OperationId id) {
org.eclipse.ocl.pivot.Class domainType = (org.eclipse.ocl.pivot.Class) id.getParent().accept(this);
if (domainType == null) {
throw new UnsupportedOperationException();
}
CompleteInheritance inheritance = standardLibrary.getInheritance(domainType);
Operation memberOperation = inheritance.getMemberOperation(id);
if (memberOperation == null) {
throw new UnsupportedOperationException();
}
return memberOperation;
}
@Override
public @NonNull Type visitPrimitiveTypeId(@NonNull PrimitiveTypeId id) {
Type primitiveType = standardLibrary.getPrimitiveType(id);
if (primitiveType == null) {
throw new UnsupportedOperationException();
}
return primitiveType;
}
@Override
public @NonNull Property visitPropertyId(@NonNull PropertyId id) {
org.eclipse.ocl.pivot.Class domainType = (org.eclipse.ocl.pivot.Class) id.getParent().accept(this);
if (domainType == null) {
throw new UnsupportedOperationException();
}
CompleteInheritance inheritance = standardLibrary.getInheritance(domainType);
Property memberProperty = inheritance.getMemberProperty(id.getName());
if (memberProperty == null) {
throw new UnsupportedOperationException();
}
return memberProperty;
}
/* @Override
public org.eclipse.ocl.pivot.@NonNull Package visitRootPackageId(@NonNull RootPackageId id) {
String completeURIorName = id.getName();
org.eclipse.ocl.pivot.Package rootPackage = standardLibrary.getRootPackage(completeURIorName);
if (rootPackage == null) {
throw new UnsupportedOperationException();
}
return rootPackage;
} */
@Override
public org.eclipse.ocl.pivot.@Nullable Package visitRootPackageId(@NonNull RootPackageId id) {
if (id == IdManager.METAMODEL) {
return ClassUtil.nonNullState(getStandardLibrary().getPackage());
}
String name = id.getName();
org.eclipse.ocl.pivot.Package knownPackage = roots2package.get(name);
if (knownPackage != null) {
return knownPackage;
}
// org.eclipse.ocl.pivot.Package libraryPackage = standardLibrary.getNsURIPackage(nsURI);
// if (libraryPackage != null) {
// nsURI2package.put(nsURI, libraryPackage);
// return libraryPackage;
// }
if (!directRootsProcessed) {
processDirectRoots();
knownPackage = roots2package.get(name);
if (knownPackage != null) {
return knownPackage;
}
}
if (!crossReferencedRootsProcessed) {
processCrossReferencedRoots();
knownPackage = roots2package.get(name);
if (knownPackage != null) {
return knownPackage;
}
}
throw new UnsupportedOperationException();
}
@Override
public @NonNull Element visitTemplateBinding(@NonNull TemplateBinding id) {
return id.getTemplateParameter();
}
@Override
public @NonNull Element visitTemplateParameterId(@NonNull TemplateParameterId id) {
if (!staticTypeStack.isEmpty()) {
Type staticType = staticTypeStack.peek();
if (staticType != null) {
int globalIndex = id.getIndex();
List<@NonNull Iterable<org.eclipse.ocl.pivot.@NonNull TemplateBinding>> templateBindingsList = new ArrayList<>();
for (EObject eObject = staticType; eObject != null; eObject = eObject.eContainer()) {
if (eObject instanceof TemplateableElement) {
templateBindingsList.add(0, PivotUtil.getOwnedBindings((TemplateableElement) eObject));
}
int firstIndex = 0;
for (@NonNull Iterable<org.eclipse.ocl.pivot.@NonNull TemplateBinding> templateBindings : templateBindingsList) {
for (org.eclipse.ocl.pivot.@NonNull TemplateBinding templateBinding : templateBindings) {
List<@NonNull TemplateParameterSubstitution> ownedSubstitutions = PivotUtilInternal.getOwnedSubstitutionsList(templateBinding);
int localIndexes = ownedSubstitutions.size();
int localIndex = globalIndex - firstIndex;
if (localIndex < localIndexes) {
TemplateParameterSubstitution templateParameterSubstitution = ownedSubstitutions.get(localIndex);
assert templateParameterSubstitution != null;
return PivotUtil.getActual(templateParameterSubstitution);
}
firstIndex += localIndexes;
}
}
}
}
}
throw new UnsupportedOperationException();
}
@Override
public @NonNull Type visitTemplateableTypeId(@NonNull TemplateableTypeId id) {
return getType(id, null);
}
@Override
public @NonNull TypedElement visitTuplePartId(@NonNull TuplePartId id) {
throw new UnsupportedOperationException();
}
@Override
public @NonNull Type visitTupleTypeId(@NonNull TupleTypeId id) {
return getTupleType(id);
}
@Override
public @NonNull Type visitUnspecifiedId(@NonNull UnspecifiedId id) {
return (Type) id.getSpecifier();
}
/**
* Return the map.get(key).get() entry if there is one or null if not, removing any stale
* entry that may be encountered.
*/
protected <K, V> @Nullable V weakGet(@NonNull Map<K, WeakReference<V>> map, @NonNull K key) {
WeakReference<V> ref = map.get(key);
if (ref == null) {
return null;
}
@Nullable V value = ref.get();
if (value == null) {
map.remove(key);
}
return value;
}
}