blob: 4fbcab08a32a3d25fa97cad58c1af06bba94657f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _DECAF_UTIL_ABSTRACTSEQUENTIALLIST_H_
#define _DECAF_UTIL_ABSTRACTSEQUENTIALLIST_H_
#include <decaf/util/Config.h>
#include <decaf/lang/exceptions/UnsupportedOperationException.h>
#include <decaf/lang/exceptions/NullPointerException.h>
#include <decaf/lang/exceptions/IllegalArgumentException.h>
#include <decaf/lang/Iterable.h>
#include <decaf/util/Iterator.h>
#include <decaf/util/AbstractList.h>
#include <memory>
namespace decaf {
namespace util {
/**
* This class provides a skeletal implementation of the List interface to minimize
* the effort required to implement this interface backed by a "sequential access"
* data store (such as a linked list). For random access data (such as an array),
* AbstractList should be used in preference to this class.
*
* This class is the opposite of the AbstractList class in the sense that it implements
* the "random access" methods (get(int index), set(int index, E element), add(int index,
* E element) and remove(int index)) on top of the list's list iterator, instead of the
* other way around.
*
* To implement a list the programmer needs only to extend this class and provide
* implementations for the listIterator and size methods. For an unmodifiable list, the
* programmer need only implement the list iterator's hasNext, next, hasPrevious,
* previous and index methods.
*
* For a modifiable list the programmer should additionally implement the list iterator's
* set method. For a variable-size list the programmer should additionally implement the
* list iterator's remove and add methods.
*
* The programmer should generally provide a void (no argument) and collection constructor,
* as per the recommendation in the Collection interface specification.
*
* @since 1.0
*/
template< typename E >
class AbstractSequentialList : public decaf::util::AbstractList<E> {
public:
using AbstractList<E>::add;
using AbstractList<E>::addAll;
public:
virtual ~AbstractSequentialList() {}
virtual Iterator<E>* iterator() {
return this->listIterator( 0 );
}
virtual Iterator<E>* iterator() const {
return this->listIterator( 0 );
}
virtual ListIterator<E>* listIterator() {
return this->listIterator( 0 );
}
virtual ListIterator<E>* listIterator() const {
return this->listIterator( 0 );
}
virtual ListIterator<E>* listIterator(int index DECAF_UNUSED) {
throw decaf::lang::exceptions::UnsupportedOperationException(
__FILE__, __LINE__, "Abstract sequential list does not implement the listIterator.");
}
virtual ListIterator<E>* listIterator(int index DECAF_UNUSED) const {
throw decaf::lang::exceptions::UnsupportedOperationException(
__FILE__, __LINE__, "Abstract sequential list does not implement the listIterator.");
}
/**
* {@inheritDoc}
*
* This implementation first gets a list iterator pointing to the indexed
* element (with listIterator(index)). Then, it gets the element using
* ListIterator.next and returns it.
*/
virtual E get(int index) const {
try {
std::auto_ptr<ListIterator<E> > iter(this->listIterator(index));
return iter->next();
} catch (decaf::util::NoSuchElementException& ex) {
throw decaf::lang::exceptions::IndexOutOfBoundsException(
__FILE__, __LINE__, "get called with invalid index.");
}
}
/**
* {@inheritDoc}
*
* This implementation first gets a list iterator pointing to the indexed element
* (with listIterator(index)). Then, it gets the current element using
* ListIterator.next and replaces it with ListIterator.set.
*/
virtual E set(int index, const E& element) {
try {
std::auto_ptr<ListIterator<E> > iter(this->listIterator(index));
E result = iter->next();
iter->set(element);
return result;
} catch (decaf::util::NoSuchElementException& ex) {
throw decaf::lang::exceptions::IndexOutOfBoundsException(
__FILE__, __LINE__, "set called with invalid index.");
}
}
/**
* {@inheritDoc}
*
* This implementation first gets a list iterator pointing to the indexed element
* (with listIterator(index)). Then, it inserts the specified element with
* ListIterator.add.
*/
virtual void add(int index, const E& element) {
try {
std::auto_ptr<ListIterator<E> > iter(this->listIterator(index));
iter->add(element);
} catch (decaf::util::NoSuchElementException& ex) {
throw decaf::lang::exceptions::IndexOutOfBoundsException(
__FILE__, __LINE__, "add called with invalid index.");
}
}
/**
* {@inheritDoc}
*
* This implementation gets an iterator over the specified collection and a list
* iterator over this list pointing to the indexed element (with listIterator(index)).
* Then, it iterates over the specified collection, inserting the elements obtained
* from the iterator into this list, one at a time, using ListIterator.add
* (to skip over the added element).
*/
virtual bool addAll(int index, const Collection<E>& source) {
std::auto_ptr<ListIterator<E> > iter(this->listIterator(index));
std::auto_ptr<Iterator<E> > srcIter(source.iterator());
int next = iter->nextIndex();
while (srcIter->hasNext()) {
iter->add(srcIter->next());
}
return next != iter->nextIndex();
}
/**
* {@inheritDoc}
*
* This implementation first gets a list iterator pointing to the indexed element
* (with listIterator(index)). Then, it removes the element with ListIterator.remove.
*/
virtual E removeAt(int index) {
try {
std::auto_ptr<ListIterator<E> > iter(this->listIterator(index));
E result = iter->next();
iter->remove();
return result;
} catch (decaf::util::NoSuchElementException& ex) {
throw decaf::lang::exceptions::IndexOutOfBoundsException(
__FILE__, __LINE__, "set called with invalid index.");
}
}
};
}}
#endif /* _DECAF_UTIL_ABSTRACTSEQUENTIALLIST_H_ */