| /* |
| * 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_ */ |