| /******************************************************************************* |
| * Copyright (c) 2011, 2016 Willink Transformations and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * E.D.Willink - Initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.ocl.pivot.internal.values; |
| |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.jdt.annotation.Nullable; |
| import org.eclipse.ocl.pivot.ids.CollectionTypeId; |
| import org.eclipse.ocl.pivot.ids.IdResolver; |
| import org.eclipse.ocl.pivot.ids.MapTypeId; |
| import org.eclipse.ocl.pivot.ids.TypeId; |
| import org.eclipse.ocl.pivot.messages.PivotMessages; |
| import org.eclipse.ocl.pivot.utilities.ClassUtil; |
| import org.eclipse.ocl.pivot.utilities.ValueUtil; |
| 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.MapEntry; |
| import org.eclipse.ocl.pivot.values.MapValue; |
| import org.eclipse.ocl.pivot.values.SetValue; |
| import org.eclipse.ocl.pivot.values.ValuesPackage; |
| |
| /** |
| * @generated NOT |
| */ |
| public class MapValueImpl extends ValueImpl implements MapValue //, Iterable<Object> |
| { |
| private <K,V> boolean checkElementsAreValues(Iterable<Map.Entry<K, V>> elements) { |
| for (Map.Entry<K, V> element : elements) { |
| assert ValueUtil.isBoxed(element.getKey()); |
| assert ValueUtil.isBoxed(element.getValue()); |
| // if (element instanceof Collection<?>) { |
| // assert isNormalized((Iterable<?>)element); |
| // assert checkElementsAreValues((Iterable<?>)element); |
| // } |
| } |
| return true; |
| } |
| |
| public static @NonNull MapValue createMapValueOfEach(@NonNull MapTypeId typeId, MapEntry[] mapEntries) { |
| Map<Object, Object> boxedValues = new HashMap<Object, Object>(); |
| if (mapEntries != null) { |
| for (MapEntry mapEntry : mapEntries) { |
| boxedValues.put(mapEntry.getKey(), mapEntry.getValue()); // FIXME boxed |
| } |
| } |
| return new MapValueImpl(typeId, boxedValues); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| protected EClass eStaticClass() { |
| return ValuesPackage.Literals.MAP_VALUE; |
| } |
| |
| protected @NonNull MapTypeId typeId; |
| protected @NonNull Map<Object, Object> boxedValues; |
| private int hashCode = 0; |
| |
| public MapValueImpl(@NonNull MapTypeId typeId, @NonNull Map<Object, Object> boxedValues) { |
| this.typeId = typeId; |
| this.boxedValues = boxedValues; |
| assert checkElementsAreValues(boxedValues.entrySet()); |
| } |
| |
| @Override |
| public @Nullable List<?> asEcoreObject(@NonNull IdResolver idResolver, @Nullable Class<?> instanceClass) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public @Nullable <T> List<T> asEcoreObjects(@NonNull IdResolver idResolver, @Nullable Class<T> instanceClass) { |
| // EMap<Object, Object> eMap = new BasicEMap<Object, Object>(); |
| // return eMap; |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public @NonNull Map<? extends Object, ? extends Object> asMap() { |
| return boxedValues; |
| } |
| |
| @Override |
| public @NonNull MapValue asMapValue() { |
| return this; |
| } |
| |
| @Override |
| public @NonNull Object asObject() { |
| return boxedValues; |
| } |
| |
| @Override |
| public Object at(Object value) { |
| if (value instanceof InvalidValueException) { |
| throw (InvalidValueException)value; |
| } |
| Object object = boxedValues.get(value); |
| if ((object == null) && !boxedValues.containsKey(value)) { |
| throw new InvalidValueException(PivotMessages.IndexNotInUse, value); |
| } |
| return object; |
| } |
| |
| @Override |
| public @NonNull Set<Map.Entry<Object, Object>> entrySet() { |
| return boxedValues.entrySet(); |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (!(obj instanceof MapValue)) { |
| return false; |
| } |
| MapValue that = (MapValue)obj; |
| int thisSize = this.intSize(); |
| int thatSize = that.intSize(); |
| if (thisSize != thatSize) { |
| return false; |
| } |
| Set<Object> theseKeys = this.keySet(); |
| Set<Object> thoseKeys = that.keySet(); |
| if (!theseKeys.equals(thoseKeys)) { |
| return false; |
| } |
| for (Object key : theseKeys){ |
| Object thisValue = this.at(key); |
| Object thatValue = that.at(key); |
| if (!ClassUtil.safeEquals(thisValue, thatValue)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean excludes(@Nullable Object key) { |
| if (key instanceof InvalidValueException) { |
| throw (InvalidValueException)key; |
| } |
| return boxedValues.containsKey(key) == false; // FIXME redundant test to suppress warning |
| } |
| |
| @Override |
| public @NonNull Boolean excludes(@Nullable Object key, @Nullable Object value) { |
| if (key instanceof InvalidValueException) { |
| throw (InvalidValueException)key; |
| } |
| if (value instanceof InvalidValueException) { |
| throw (InvalidValueException)value; |
| } |
| Object keyValue = boxedValues.get(key); |
| if (keyValue == null) { |
| if (!boxedValues.containsKey(value)) { |
| return true; |
| } |
| return value != null; |
| } |
| else { |
| return keyValue.equals(value) == false; |
| } |
| } |
| |
| @Override |
| public @NonNull Boolean excludesAll(@NonNull CollectionValue c) { |
| Set<Object> keySet = boxedValues.keySet(); |
| for (Object e1 : c.iterable()) { |
| if (e1 == null) { |
| for (Object e2 : keySet) { |
| if (e2 == null) { |
| return false; |
| } |
| } |
| } |
| else { |
| for (Object e2 : keySet) { |
| if (e1.equals(e2)) { |
| return false; |
| } |
| } |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean excludesMap(@NonNull MapValue m) { |
| Set<Object> keySet = boxedValues.keySet(); |
| for (Object e1 : m.getKeys()) { |
| if (e1 == null) { |
| for (Object e2 : keySet) { |
| if (e2 == null) { |
| Object thisValue = at(e2); |
| Object thatValue = m.at(e2); |
| if (ClassUtil.safeEquals(thisValue, thatValue)) { |
| return false; |
| } |
| } |
| } |
| } |
| else { |
| for (Object e2 : keySet) { |
| if (e1.equals(e2)) { |
| Object thisValue = at(e2); |
| Object thatValue = m.at(e2); |
| if (ClassUtil.safeEquals(thisValue, thatValue)) { |
| return false; |
| } |
| } |
| } |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean excludesValue(@Nullable Object thatValue) { |
| if (thatValue instanceof InvalidValueException) { |
| throw (InvalidValueException)thatValue; |
| } |
| for (Object thisValue : boxedValues.values()) { |
| if (ClassUtil.safeEquals(thisValue, thatValue)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull MapValue excluding(@Nullable Object key) { |
| if (key instanceof InvalidValueException) { |
| throw (InvalidValueException)key; |
| } |
| Map<Object, Object> newBoxedValues = new HashMap<Object, Object>(boxedValues); |
| newBoxedValues.remove(key); |
| return new MapValueImpl(typeId, newBoxedValues); |
| } |
| |
| @Override |
| public @NonNull MapValue excluding(@Nullable Object key, @Nullable Object value) { |
| if (key instanceof InvalidValueException) { |
| throw (InvalidValueException)key; |
| } |
| if (value instanceof InvalidValueException) { |
| throw (InvalidValueException)value; |
| } |
| Map<Object, Object> newBoxedValues = new HashMap<Object, Object>(boxedValues); |
| Object actualValue = newBoxedValues.get(key); |
| if (ClassUtil.safeEquals(actualValue, value)) { |
| newBoxedValues.remove(key); |
| } |
| return new MapValueImpl(typeId, newBoxedValues); |
| } |
| |
| @Override |
| public @NonNull MapValue excludingAll(@NonNull CollectionValue c) { |
| Map<Object, Object> newBoxedValues = new HashMap<Object, Object>(boxedValues); |
| for (Object key : c) { |
| newBoxedValues.remove(key); |
| } |
| return new MapValueImpl(typeId, newBoxedValues); |
| } |
| |
| @Override |
| public @NonNull MapValue excludingMap(@NonNull MapValue map) { |
| Map<Object, Object> newBoxedValues = new HashMap<Object, Object>(boxedValues); |
| for (Map.Entry<Object, Object> entry : map.entrySet()) { |
| Object key = entry.getKey(); |
| Object actualValue = newBoxedValues.get(key); |
| if (ClassUtil.safeEquals(actualValue, entry.getValue())) { |
| newBoxedValues.remove(key); |
| } |
| } |
| return new MapValueImpl(typeId, newBoxedValues); |
| } |
| |
| @Override |
| public @NonNull Set<Entry<Object, Object>> getElements() { |
| return boxedValues.entrySet(); |
| } |
| |
| @Override |
| public @NonNull SetValue getKeys() { |
| CollectionTypeId setId = TypeId.SET.getSpecializedId(typeId.getValueTypeId()); |
| return ValueUtil.createSetValue(setId, keySet()); |
| } |
| |
| @Override |
| public @NonNull MapTypeId getTypeId() { |
| return typeId; |
| } |
| |
| @Override |
| public @NonNull BagValue getValues() { |
| CollectionTypeId bagId = TypeId.BAG.getSpecializedId(typeId.getValueTypeId()); |
| return ValueUtil.createBagValue(bagId, new BagImpl<Object>(boxedValues.values())); |
| } |
| |
| @Override |
| public final int hashCode() { |
| if (hashCode == 0) { |
| synchronized (this) { |
| if (hashCode == 0) { |
| long hash = 0x3333333333333333L; |
| for (Map.Entry<Object,Object> entry : boxedValues.entrySet()) { |
| Object key = entry.getKey(); |
| if (key != null) { |
| hash += 3 * key.hashCode(); |
| } |
| Object value = entry.getValue(); |
| if (value != null) { |
| hash += 5 * value.hashCode(); |
| } |
| } |
| hashCode = (int) hash; |
| if (hashCode == 0) { |
| hashCode = (int) (hash >> 32); |
| if (hashCode == 0) { |
| hashCode = 0x87654321; |
| } |
| } |
| } |
| } |
| } |
| return hashCode; |
| } |
| |
| @Override |
| public @NonNull Boolean includes(@Nullable Object key) { |
| if (key instanceof InvalidValueException) { |
| throw (InvalidValueException)key; |
| } |
| return boxedValues.containsKey(key) != false; // FIXME redundant test to suppress warning |
| } |
| |
| @Override |
| public @NonNull Boolean includes(@Nullable Object key, @Nullable Object value) { |
| if (key instanceof InvalidValueException) { |
| throw (InvalidValueException)key; |
| } |
| if (value instanceof InvalidValueException) { |
| throw (InvalidValueException)value; |
| } |
| Object keyValue = boxedValues.get(key); |
| if (keyValue == null) { |
| if (!boxedValues.containsKey(value)) { |
| return false; |
| } |
| return value == null; |
| } |
| else { |
| return keyValue.equals(value) != false; |
| } |
| } |
| |
| @Override |
| public @NonNull Boolean includesAll(@NonNull CollectionValue c) { |
| Set<Object> keySet = boxedValues.keySet(); |
| for (Object e1 : c.iterable()) { |
| boolean gotIt = false; |
| if (e1 == null) { |
| for (Object e2 : keySet) { |
| if (e2 == null) { |
| gotIt = true; |
| break; |
| } |
| } |
| } |
| else { |
| for (Object e2 : keySet) { |
| if (e1.equals(e2)) { |
| gotIt = true; |
| break; |
| } |
| } |
| } |
| if (!gotIt) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean includesMap(@NonNull MapValue m) { |
| Set<Object> keySet = boxedValues.keySet(); |
| for (Object e1 : m.getKeys()) { |
| boolean gotIt = false; |
| if (e1 == null) { |
| for (Object e2 : keySet) { |
| if (e2 == null) { |
| Object thisValue = at(e2); |
| Object thatValue = m.at(e2); |
| if (ClassUtil.safeEquals(thisValue, thatValue)) { |
| gotIt = true; |
| break; |
| } |
| } |
| } |
| } |
| else { |
| for (Object e2 : keySet) { |
| if (e1.equals(e2)) { |
| Object thisValue = at(e2); |
| Object thatValue = m.at(e2); |
| if (ClassUtil.safeEquals(thisValue, thatValue)) { |
| gotIt = true; |
| break; |
| } |
| } |
| } |
| } |
| if (!gotIt) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public @NonNull Boolean includesValue(@Nullable Object thatValue) { |
| if (thatValue instanceof InvalidValueException) { |
| throw (InvalidValueException)thatValue; |
| } |
| for (Object thisValue : boxedValues.values()) { |
| if (ClassUtil.safeEquals(thisValue, thatValue)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public @NonNull MapValue including(@NonNull MapTypeId returnTypeId, @Nullable Object key, @Nullable Object value) { |
| if (key instanceof InvalidValueException) { |
| throw (InvalidValueException)key; |
| } |
| if (value instanceof InvalidValueException) { |
| throw (InvalidValueException)value; |
| } |
| Map<Object, Object> newBoxedValues = new HashMap<Object, Object>(boxedValues); |
| newBoxedValues.put(key, value); |
| return new MapValueImpl(returnTypeId, newBoxedValues); |
| } |
| |
| @Override |
| public @NonNull MapValue includingMap(@NonNull MapTypeId returnTypeId, @NonNull MapValue map) { |
| Map<Object, Object> newBoxedValues = new HashMap<Object, Object>(boxedValues); |
| for (Map.Entry<Object, Object> entry : map.entrySet()) { |
| newBoxedValues.put(entry.getKey(), entry.getValue()); |
| } |
| return new MapValueImpl(returnTypeId, newBoxedValues); |
| } |
| |
| @Override |
| public int intSize() { |
| return boxedValues.size(); |
| } |
| |
| @Override |
| public @NonNull Boolean isEmpty() { |
| return intSize() == 0; |
| } |
| |
| @Override |
| public @NonNull Set<Object> keySet() { |
| return boxedValues.keySet(); |
| } |
| |
| @Override |
| public @NonNull Boolean notEmpty() { |
| return intSize() != 0; |
| } |
| |
| @Override |
| @NonNull |
| public IntegerValue size() { |
| return ValueUtil.integerValueOf(intSize()); |
| } |
| |
| @Override |
| public String toString() { |
| StringBuilder s = new StringBuilder(); |
| toString(s, 100); |
| return s.toString(); |
| } |
| |
| @Override |
| public void toString(@NonNull StringBuilder s, int lengthLimit) { |
| s.append(TypeId.MAP_NAME); |
| s.append("{"); |
| boolean isFirst = true; |
| for (Map.Entry<Object, Object> entry : boxedValues.entrySet()) { |
| if (!isFirst) { |
| s.append(","); |
| } |
| if (s.length() < lengthLimit) { |
| ValueUtil.toString(entry.getKey(), s, lengthLimit-1); |
| s.append(" <- "); |
| ValueUtil.toString(entry.getValue(), s, lengthLimit-1); |
| } |
| else { |
| s.append("..."); |
| break; |
| } |
| isFirst = false; |
| } |
| s.append("}"); |
| } |
| } |