/******************************************************************************* * Copyright (c) 2010, 2014 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.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; 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.TypeId; import org.eclipse.ocl.pivot.messages.PivotMessages; import org.eclipse.ocl.pivot.utilities.ValueUtil; 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.NullValue; import org.eclipse.ocl.pivot.values.OrderedCollectionValue; import org.eclipse.ocl.pivot.values.OrderedSet; import org.eclipse.ocl.pivot.values.OrderedSetValue; import org.eclipse.ocl.pivot.values.UniqueCollectionValue; import org.eclipse.ocl.pivot.values.ValuesPackage; /** * @generated NOT */ public abstract class OrderedSetValueImpl extends CollectionValueImpl implements OrderedSetValue { /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ @Override protected EClass eStaticClass() { return ValuesPackage.Literals.ORDERED_SET_VALUE; } public OrderedSetValueImpl(@NonNull CollectionTypeId typeId, @NonNull Collection<? extends Object> elements) { super(typeId, elements); assert checkElementsAreUnique(this.elements); } @Override public @NonNull OrderedSetValue appendAll(@NonNull OrderedCollectionValue objects) { OrderedSet<Object> result = new OrderedSetImpl<Object>(elements); Collection<? extends Object> thoseElements = objects.getElements(); result.removeAll(thoseElements); // appended objects must be last result.addAll(thoseElements); return new SparseOrderedSetValueImpl(getTypeId(), result); } @Override public @NonNull OrderedCollectionValue asOrderedCollectionValue() { return this; } @Override public @NonNull OrderedSetValueImpl asOrderedSetValue() { return this; } @Override public @NonNull LinkedHashSet<Object> asUnboxedObject(@NonNull IdResolver idResolver) { LinkedHashSet<Object> unboxedValues = new LinkedHashSet<Object>(); for (Object boxedValue : elements) { unboxedValues.add(idResolver.unboxedValueOf(boxedValue)); } return unboxedValues; } @Override public @NonNull UniqueCollectionValue asUniqueCollectionValue() { return this; } @Override public @Nullable Object at(int index) { index = index - 1; if (index < 0 || index >= elements.size()) { throw new InvalidValueException(PivotMessages.IndexOutOfRange, index + 1, size()); } int curr = 0; for (Iterator<? extends Object> it = iterator(); it.hasNext();) { Object object = it.next(); if (curr++ == index) { return object; } } throw new InvalidValueException("Null collection content"); } @Override public boolean equals(Object obj) { if (!(obj instanceof OrderedSetValue) || (obj instanceof NullValue)) { return false; } // This is probably a bug fix on LinkedHashSet that should consider ordering for equals Iterator<? extends Object> theseElements = iterator(); Iterator<? extends Object> thoseElements = ((OrderedSetValue)obj).iterator(); while (theseElements.hasNext() && thoseElements.hasNext()) { Object thisElement = theseElements.next(); Object thatElement = thoseElements.next(); if (thisElement == null) { if (thatElement != null) { return false; } } else { if (!thisElement.equals(thatElement)) { return false; } } } return !theseElements.hasNext() && !thoseElements.hasNext(); } @Override public @NonNull OrderedSetValue excluding(@Nullable Object value) { OrderedSet<Object> result = new OrderedSetImpl<Object>(); if (value == null) { for (Object element : elements) { if (element != null) { result.add(element); } } } else { for (Object element : elements) { if (!value.equals(element)) { result.add(element); } } } if (result.size() < elements.size()) { return new SparseOrderedSetValueImpl(getTypeId(), result); } else { return this; } } @Override public @NonNull OrderedSetValue excludingAll(@NonNull CollectionValue values) { OrderedSet<Object> result = new OrderedSetImpl<Object>(); for (Object element : elements) { boolean reject = false; if (element == null) { for (Object value : values) { if (value == null) { reject = true; break; } } } else { for (Object value : values) { if ((value != null) && value.equals(element)) { reject = true; break; } } } if (!reject) { result.add(element); } } if (result.size() < elements.size()) { return new SparseOrderedSetValueImpl(getTypeId(), result); } else { return this; } } // @Override // public @NonNull CollectionTypeId getCollectionTypeId() { // return TypeId.ORDERED_SET; // } @Override public @NonNull String getKind() { return TypeId.ORDERED_SET_NAME; } @Override public @NonNull OrderedSetValue includingAll(@NonNull CollectionValue values) { OrderedSet<Object> result = new OrderedSetImpl<Object>(elements); for (Object value : values) { result.add(value); } return new SparseOrderedSetValueImpl(getTypeId(), result); } @Override public @NonNull IntegerValue indexOf(@Nullable Object object) { int index = 1; if (object == null) { for (Object next : elements) { if (next == null) { return ValueUtil.integerValueOf(index); } index++; } } else { for (Object next : elements) { if (object.equals(next)) { return ValueUtil.integerValueOf(index); } index++; } } throw new InvalidValueException(PivotMessages.MissingValue, "indexOf"); } @Override public @NonNull OrderedSetValue insertAt(int index, @Nullable Object object) { if (object instanceof InvalidValueException) { throw new InvalidValueException(PivotMessages.InvalidSource, "insertAt"); } index = index - 1; boolean isContained = elements.contains(object); int effectiveSize = elements.size() - (isContained ? 1 : 0); if ((index < 0) || (effectiveSize < index)) { throw new InvalidValueException(PivotMessages.IndexOutOfRange, index + 1, size()); } OrderedSet<Object> result = new OrderedSetImpl<Object>(); int curr = 0; if (object == null) { for (Iterator<? extends Object> it = iterator(); it.hasNext();) { if (curr == index) { result.add(object); } Object next = it.next(); if (next != null) { result.add(next); curr++; } } } else { for (Iterator<? extends Object> it = iterator(); it.hasNext();) { if (curr == index) { result.add(object); } Object next = it.next(); if (!object.equals(next)) { result.add(next); curr++; } } } if (index == effectiveSize) { // the loop finished before we could add the object result.add(object); } return new SparseOrderedSetValueImpl(getTypeId(), result); } @Override public boolean isOrdered() { return true; } @Override public boolean isUnique() { return true; } @Override public @NonNull OrderedSetValue minus(@NonNull UniqueCollectionValue set) { OrderedSet<Object> result = new OrderedSetImpl<Object>(elements); result.removeAll(set.asCollection()); return new SparseOrderedSetValueImpl(getTypeId(), result); } @Override public @NonNull OrderedSetValue prependAll(@NonNull OrderedCollectionValue objects) { OrderedSet<Object> result = new OrderedSetImpl<Object>(objects.getElements()); result.addAll(elements); return new SparseOrderedSetValueImpl(getTypeId(), result); } @Override public @NonNull OrderedSetValue reverse() { List<? extends Object> elements = asList(); Collections.reverse(elements); return new SparseOrderedSetValueImpl(getTypeId(), elements); } @Override public @NonNull OrderedSetValue sort(@NonNull Comparator<Object> comparator) { List<Object> values = new ArrayList<Object>(elements); Collections.sort(values, comparator); return new SparseOrderedSetValueImpl(getTypeId(), values); } @Override public @NonNull OrderedSetValue subOrderedSet(int lower, int upper) { lower = lower - 1; upper = upper - 1; if (lower < 0) { throw new InvalidValueException(new IndexOutOfBoundsException("lower: " + (lower + 1))); //$NON-NLS-1$ } else if (upper >= elements.size()) { throw new InvalidValueException(new IndexOutOfBoundsException( "upper: " + (upper + 1) + ", size: " //$NON-NLS-1$ //$NON-NLS-2$ + size())); } else if (upper < lower) { throw new InvalidValueException(new IllegalArgumentException( "lower: " + (lower + 1) + ", upper: " //$NON-NLS-1$ //$NON-NLS-2$ + (upper + 1))); } OrderedSet<Object> result = new OrderedSetImpl<Object>(); int curr = 0; for (Iterator<? extends Object> it = elements.iterator(); it.hasNext();) { Object object = it.next(); if (curr >= lower && curr <= upper) { result.add(object); } curr++; } return new SparseOrderedSetValueImpl(getTypeId(), result); } // public @NonNull SequenceValue subSequence(int lower, int upper) { // return subOrderedSet(lower, upper); // } @Override public @NonNull OrderedSetValue symmetricDifference(@NonNull UniqueCollectionValue set) { OrderedSet<Object> result = new OrderedSetImpl<Object>(elements); for (Object e : set.iterable()) { if (result.contains(e)) { result.remove(e); } else { result.add(e); } } return new SparseOrderedSetValueImpl(getTypeId(), result); } // public SequenceValue toSequenceValue() { // return this; // } }