/*
Copyright (C) 2008-2009 by Claas Wilke (claaswilke@gmx.net)
This file is part of the OCL 2 Java Code Generator of Dresden OCL2 for Eclipse.
Dresden OCL2 for Eclipse is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your option)
any later version.
Dresden OCL2 for Eclipse is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
for more details.
You should have received a copy of the GNU Lesser General Public License along
with Dresden OCL2 for Eclipse. If not, see <http://www.gnu.org/licenses/>.
*/
package org.dresdenocl.ocl2java.types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* <p>
* An {@link OclSequence} is a collection where the elements are ordered. An
* element may be part of an {@link OclSequence} more than once.
* </p>
*
* @param <T>
* The type of the elements contained in this {@link OclSequence}.
*
* @author Claas Wilke
*/
public class OclSequence<T> extends OclCollection<T> {
/**
* <p>
* Creates a new {@link OclSet}.
* </p>
*/
public OclSequence() {
this.myCollection = new ArrayList<T>();
}
/**
* @param anObject
* The Object which shall be appended.
* @return The {@link OclSequence} of elements, consisting of all elements
* of this {@link OclSequence}, followed by the given object.
*/
public OclSequence<T> append(T anObject) {
OclSequence<T> result;
result = new OclSequence<T>();
result.addAll(this.myCollection);
result.add(anObject);
return result;
}
/**
* @return An {@link OclBag} containing all the elements from this
* {@link OclSequence}, in undefined order.
*/
public OclBag<T> asBag() {
OclBag<T> result;
result = new OclBag<T>();
result.addAll(this.myCollection);
return result;
}
/**
* @return The {@link OclOrderedSet} containing all the elements from this
* {@link OclSequence}, in the same order, with duplicates removed.
*/
public OclOrderedSet<T> asOrderedSet() {
OclOrderedSet<T> result;
result = new OclOrderedSet<T>();
for (T anElement : this.myCollection) {
/* Check if the element has already been added. */
if (!result.contains(anElement)) {
result.add(anElement);
}
// no else.
}
return result;
}
/**
* @return A {@link OclSequence} identical to this {@link OclSequence}. This
* operation exists for convenience reasons.
*/
public OclSequence<T> asSequence() {
OclSequence<T> result;
result = new OclSequence<T>();
result.addAll(this.myCollection);
return result;
}
/**
* @return The {@link OclSet} containing all the elements from this
* {@link OclSequence}, with duplicates removed.
*/
public OclSet<T> asSet() {
OclSet<T> result;
result = new OclSet<T>();
for (T anElement : this.myCollection) {
/* Check if the element has already been added. */
if (!result.contains(anElement)) {
result.add(anElement);
}
// no else.
}
return result;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@SuppressWarnings("unchecked")
public boolean equals(Object anObject) {
boolean result;
try {
OclSequence<T> aSequence = (OclSequence<T>) anObject;
result = this.equals(aSequence);
}
catch (ClassCastException e) {
result = false;
}
return result;
}
/**
* @param aSequence
* The {@link OclSequence} this {@link OclSequence} shall be compared with.
* @return True if this {@link OclSequence} and the given {@link OclSequence} contain
* the same elements, the same number of times.
*/
public boolean equals(OclSequence<T> aSequence) {
boolean result;
int index;
result = (this.size() == aSequence.size());
if (result) {
index = 1;
for (T anElement : aSequence) {
result &= this.get(index).equals(anElement);
if (!result) {
break;
}
// no else.
index++;
}
}
// no else.
return result;
}
/**
* @param anObject
* The object which shall not be part of the result.
* @return The {@link OclSequence} containing all elements of this
* {@link OclSequence} except all occurrences of the given Object.
*/
public OclSequence<T> excluding(T anObject) {
OclSequence<T> result;
result = new OclSequence<T>();
for (T anElement : this.myCollection) {
if (!anElement.equals(anObject)) {
result.add(anElement);
}
// no else.
}
return result;
}
/**
* @return The first element of this {@link OclSequence}.
*/
public T first() {
T result;
result = null;
if (this.size() > 0) {
result = this.get(1);
}
// no else.
return result;
}
/**
* <p>
* If the element type of this {@link OclSequence} is not a
* {@link Collection} type, this results in the same {@link OclSequence}. If
* the element type is a {@link Collection} type, the result is the
* {@link OclSequence} containing all the elements of all the elements of
* the contained {@link Collection}.
* </p>
*/
@SuppressWarnings("unchecked")
public OclSequence<?> flatten() {
OclSequence result;
result = new OclSequence();
for (T anElement : this.myCollection) {
/* The element is a collection, add all its elements. */
if (anElement instanceof Collection) {
Collection aCollection;
aCollection = (Collection) anElement;
result.addAll(aCollection);
}
/* Else add the element itself. */
else {
result.add(anElement);
}
}
return result;
}
/**
* @param index
* The index of the element which shall be returned.
* <strong>Please pay attention that indexes in OCL starts with
* 1.</strong>
* @return The i-th element of this {@link OclSequence}.
*/
public T get(int index) {
T result;
result = ((List<T>) this.myCollection).get(index - 1);
return result;
}
/**
* @param anObject
* The object which shall be included to this {@link OclBag}.
* @return The {@link OclSequence} containing all elements of this
* {@link OclSequence} plus anObject added as the last element.
*/
public OclSequence<T> including(T anObject) {
OclSequence<T> result;
result = new OclSequence<T>();
result.addAll(this.myCollection);
result.add(anObject);
return result;
}
/**
* @param anObject
* The {@link Object} which index shall be returned.
* @return The index of object anObject in this {@link OclSequence}.
* <strong>Please pay attention that indexes in OCL starts with
* 1.</strong>
*/
public int indexOf(T anObject) {
int result;
result = ((List<T>) this.myCollection).indexOf(anObject) + 1;
return result;
}
/**
* @param index
* The index where anObject shall be inserted. <strong>Please pay
* attention that indexes in OCL starts with 1.</strong>
* @param anObject
* The {@link Object} which shall be inserted.
* @return The {@link OclSequence} consisting of this {@link OclSequence}
* with anObject inserted at position index.
*/
public OclSequence<T> insertAt(int index, T anObject) {
OclSequence<T> result;
List<T> resultSequence;
result = new OclSequence<T>();
resultSequence = new ArrayList<T>();
resultSequence.addAll(this.myCollection);
/* Set does not contain duplicates. */
if (!resultSequence.contains(anObject)) {
resultSequence.add(index - 1, anObject);
}
// no else.
result.addAll(resultSequence);
return result;
}
/**
* @return The last element of this {@link OclSequence}.
*/
public T last() {
T result;
result = null;
if (this.size() > 0) {
result = this.get(this.size());
}
// no else.
return result;
}
/**
* @param anObject
* The Object which shall be prepended.
* @return The {@link OclSequence} consisting of anObject, followed by all
* elements of this {@link OclSequence}.
*/
public OclSequence<T> prepend(T anObject) {
OclSequence<T> result;
result = new OclSequence<T>();
result.add(anObject);
result.addAll(this.myCollection);
return result;
}
/**
* @param lower
* The index of the first element included in the result.
* <strong>Please pay attention that indexes in OCL starts with
* 1.</strong>
* @param upper
* The index of the last element included in the result.
* <strong>Please pay attention that indexes in OCL starts with
* 1.</strong>
* @return The sub-set of this {@link OclSequence} starting at number lower,
* up to and including element number upper.
*/
public OclSequence<T> subSequence(int lower, int upper) {
OclSequence<T> result;
/* Check the indexes. */
if (lower < 1 || lower > this.size() || upper < 1
|| upper > this.size() || lower > upper) {
String msg;
msg = "Wrong indexes for subOrderedSet. Lower was " + lower;
msg += " and upper was " + upper;
msg += " but the size of this OclOrderedSet was " + this.size();
msg += ".";
throw new IndexOutOfBoundsException(msg);
}
// no else.
result = new OclSequence<T>();
/* Indexes in OCL starts with 1. */
for (int index = lower - 1; index < upper; index++) {
result.add(((List<T>) this.myCollection).get(index));
}
return result;
}
/**
* @param aSequence
* The {@link OclSequence} this {@link OclSequence} shall be
* united with.
* @return The {@link OclSequence} consisting of all elements of this
* {@link OclSequence}, followed by all elements in aSequence.
*/
public OclSequence<T> union(OclSequence<T> aSequence) {
OclSequence<T> result;
result = new OclSequence<T>();
result.addAll(this.myCollection);
result.addAll(aSequence);
return result;
}
}