com.amazon.ion.IonSequence Maven / Gradle / Ivy
Show all versions of ion-java Show documentation
/*
* Copyright 2007-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file 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.
*/
package com.amazon.ion;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/**
* Common functionality of Ion list
and sexp
types.
*
* WARNING: This interface should not be implemented or extended by
* code outside of this library.
*
* Ion sequences implement the standard Java {@link List} interface, behaving
* generally as expected, with the following exceptions:
*
* -
* Due to the reference-equality-based semantics of Ion sequences, methods
* like {@link #remove(Object)} do not use {@link Object#equals} as
* specified by the contract of {@link java.util.Collection}.
* Instead they use reference equality ({@code ==} operator) to find the
* given instance.
*
* -
* Any given {@link IonValue} instance may be a child of at most one
* {@link IonContainer}. Instances may be children of any number of
* non-Ion {@link Collection}s.
*
* -
* The implementations of {@link List#equals(Object)}} and
* {@link List#hashCode()} does not conform to the specification of those
* methods in order to conform with Ion's definition of equality which
* takes into account the {@link IonSequence}'s {@link IonType} and its
* annotations in addition to the contents of the collection.
*
* -
* {@link List#equals(Object)} always returns
false
* for any non-{@link IonSequence} implementation of {@link List},
* including the sub-list returned from
* {@link IonSequence#subList(int, int)}.
*
* -
* {@link List#hashCode()} returns a different hash code than
* other {@link List#hashCode()} implementations. including the
* sub-list returned from {@link IonSequence#subList(int, int)}.
*
*
*
*
*/
public interface IonSequence
extends IonContainer, List
{
/**
* Returns the element at the specified position in this sequence.
*
* @param index identifies the element to return.
* @return the element at the given index; not null
.
* @throws NullValueException if {@link #isNullValue()}.
* @throws IndexOutOfBoundsException if the index is out of range
* (index < 0 || index >= size()
).
*/
public IonValue get(int index)
throws NullValueException, IndexOutOfBoundsException;
/**
* Appends a child value to the end of this sequence.
* If {@link #isNullValue()}, then it becomes a single-element
* sequence.
*
* @param child is the value to be appended to this sequence.
* @return {@code true} (as per the general contract of the
* {@link Collection#add} method).
*
* @throws NullPointerException
* if {@code child} is null
.
* @throws ContainedValueException
* if {@code child} is already part of a container.
* @throws IllegalArgumentException
* if {@code child} is an {@link IonDatagram}.
*/
public boolean add(IonValue child)
throws ContainedValueException, NullPointerException;
/**
* Provides a factory that when invoked constructs a new value and
* {@code add}s it to this sequence.
*
* These two lines are equivalent:
*
* seq.add().newInt(3);
* seq.add(seq.getSystem().newInt(3));
*
*/
public ValueFactory add();
/**
* Inserts a child value at the specified position in this sequence.
* If {@link #isNullValue()}, then it becomes a single-element
* sequence.
*
* @param child is the element to be appended to this sequence.
*
* @throws NullPointerException
* if {@code child} is null
.
* @throws ContainedValueException
* if {@code child} is already part of a container.
* @throws IllegalArgumentException
* if {@code child} is an {@link IonDatagram}.
* @throws IndexOutOfBoundsException if the index is out of range
* (index < 0 || index > size()).
*/
public void add(int index, IonValue child)
throws ContainedValueException, NullPointerException;
/**
* Provides a factory that when invoked constructs a new value and
* {@code add}s it to this sequence at the specified position.
*
* These two lines are equivalent:
*
* seq.add(12).newInt(3);
* seq.add(12, seq.getSystem().newInt(3));
*
*
* The given {@code index} is validated when the factory's creation method
* is invoked, not when this method is invoked.
*/
public ValueFactory add(int index);
/**
* Replaces the element at the specified position in this list with the
* specified element.
*
* @param index index of the element to replace.
* @param element element to be stored at the specified position.
* @return the element previously at the specified index.
*
* @throws UnsupportedOperationException
* if this is an {@link IonDatagram}.
* @throws NullPointerException
* if the specified element is {@code null}.
* @throws ContainedValueException
* if the specified element is already part of a container.
* @throws IllegalArgumentException
* if the specified element is an {@link IonDatagram}.
* @throws ReadOnlyValueException
* if this value or the specified element {@link #isReadOnly()}.
* @throws IndexOutOfBoundsException
* if the index is out of range ({@code index < 0 || index >= size()}).
*/
public IonValue set(int index, IonValue element);
/**
* Removes the element at the specified position.
* Shifts any subsequent elements to the left (subtracts one from their
* indices). Returns the element that was removed from the list.
*
* @param index the index of the element to be removed.
*
* @return the element previously at the specified position.
*
* @throws IndexOutOfBoundsException if the index is out of range
* (index < 0 || index >= size()).
*/
public IonValue remove(int index);
/**
* Removes a given {@link IonValue} from this sequence, if it is present.
*
* Due to the reference-equality-based semantics of Ion sequences,
* this method does not use {@link Object#equals} as specified by the
* contract of {@link java.util.Collection}. Instead it uses reference
* equality ({@code ==} operator) to find the given instance.
*
* @return {@code true} if this sequence changed as a result of the call.
*
* @throws NullPointerException if {@code o} is {@code null}.
* @throws ClassCastException if {@code o} is not an {@link IonValue}.
*/
public boolean remove(Object o);
/**
* Removes all elements from this sequence that are also contained in the
* specified collection. After this call returns, this sequence will
* contain no elements in common with the specified collection.
*
* Due to the reference-equality-based semantics of Ion sequences,
* this method does not use {@link Object#equals} as specified by the
* contract of {@link java.util.Collection}. Instead it uses reference
* equality ({@code ==} operator) to find the given instance.
*
* @return {@code true} if this sequence changed as a result of the call.
*
* @throws NullPointerException if {@code c} is {@code null}.
* @throws NullPointerException if {@code c} contains one or more
* {@code null} elements.
* @throws ClassCastException if {@code c} contains one or more elements
* that do not implement {@link IonValue}.
*/
public boolean removeAll(Collection> c);
/**
* Retains only the elements in this sequence that are also contained in
* the specified collection. In other words, removes from this sequence
* all of its elements that are not contained in the specified collection.
*
* Due to the reference-equality-based semantics of Ion sequences,
* this method does not use {@link Object#equals} as specified by the
* contract of {@link java.util.Collection}. Instead it uses reference
* equality ({@code ==} operator) to find the given instance.
*
* @return {@code true} if this sequence changed as a result of the call.
*
* @throws NullPointerException if {@code c} is {@code null}.
* @throws NullPointerException if {@code c} contains one or more
* {@code null} elements.
* @throws ClassCastException if {@code c} contains one or more elements
* that do not implement {@link IonValue}.
*/
public boolean retainAll(Collection> c);
/**
* Determines whether this sequence contains the given instance.
*
* Due to the reference-equality-based semantics of Ion sequences,
* this method does not use {@link Object#equals} as specified by the
* contract of {@link java.util.Collection}. Instead it uses reference
* equality ({@code ==} operator) to find the given instance.
*
* @return {@code true} if {@code o} is an element of this sequence.
*
* @throws NullPointerException if {@code o} is {@code null}.
* @throws ClassCastException if {@code o} is not an {@link IonValue}.
*/
public boolean contains(Object o);
/**
* Determines whether this sequence contains all of the given instances.
*
* Due to the reference-equality-based semantics of Ion sequences,
* this method does not use {@link Object#equals} as specified by the
* contract of {@link java.util.Collection}. Instead it uses reference
* equality ({@code ==} operator) to find the given instances.
*
* @return {@code true} if this sequence contains all of the elements of
* the given collection.
*
* @throws NullPointerException if {@code c} is {@code null}.
* @throws NullPointerException if {@code c} contains one or more
* {@code null} elements.
* @throws ClassCastException if {@code c} contains one or more elements
* that do not implement {@link IonValue}.
*/
public boolean containsAll(Collection> c);
/**
* Returns the index in the sequence of the specified element,
* or -1 if this sequence doesn't contain the element.
*
* Due to the reference-equality-based semantics of Ion sequences,
* this method does not use {@link Object#equals} as specified by the
* contract of {@link java.util.List}. Instead it uses reference
* equality ({@code ==} operator) to find the instance.
*
* @param o the element to search for.
* @return the index in this sequence of the element,
* or -1 if this sequence doesn't contain the element.
*/
public int indexOf(Object o);
/**
* Returns the index in the sequence of the specified element,
* or -1 if this sequence doesn't contain the element.
*
*
* Due to the reference-equality-based semantics of Ion sequences,
* this method does not use {@link Object#equals} as specified by the
* contract of {@link java.util.List}. Instead it uses reference
* equality ({@code ==} operator) to find the instance.
*
* And since IonSequences do not allow for duplicates this method behaves
* in the same way as {@link IonSequence#indexOf(Object)}
*
*
* @param o the element to search for.
* @return the index in this sequence of the element,
* or -1 if this sequence doesn't contain the element.
*/
public int lastIndexOf(Object o);
/**
* Appends all of the elements in the specified collection to the end of
* this sequence, in the order that they are returned by the collection's
* iterator.
* The behavior of this operation is unspecified if the specified
* collection is modified while the operation is in progress.
* (Note that this will occur if the specified collection is this sequence,
* and it's nonempty.)
*
* Since Ion values can only have a single parent, this method will fail if
* the given collection is a non-empty {@link IonContainer}.
*
* @param c
* elements to be appended to this sequence.
*
* @return {@code true} if this sequence changed as a result of the call.
*
* @throws UnsupportedOperationException
* if this is an {@link IonDatagram}.
* @throws ClassCastException
* if one of the elements of the collection is not an {@link IonValue}
* @throws NullPointerException
* if one of the elements of the collection is {@code null}.
* @throws ContainedValueException
* if one of the elements is already contained by an {@link IonContainer}.
*/
public boolean addAll(Collection extends IonValue> c);
/**
* Inserts all of the elements in the specified collection into this
* sequence at the specified position. Shifts the element currently at that
* position (if any) and any subsequent elements to the right (increases
* their indices). The new elements will appear in this sequence in the
* order that they are returned by the specified collection's iterator.
* The behavior of this operation is unspecified if the specified
* collection is modified while the operation is in progress.
* (Note that this will occur if the specified collection is this sequence,
* and it's nonempty.)
*
* Since Ion values can only have a single parent, this method will fail if
* the given collection is a non-empty {@link IonContainer}.
*
* @param index
* index at which to insert first element from the specified collection.
* @param c
* elements to be inserted into this sequence.
*
* @return {@code true} if this sequence changed as a result of the call.
*
* @throws UnsupportedOperationException
* if this is an {@link IonDatagram}.
* @throws ClassCastException
* if one of the elements of the collection is not an {@link IonValue}
* @throws NullPointerException
* if one of the elements of the collection is {@code null}.
* @throws ContainedValueException
* if one of the elements is already contained by an {@link IonContainer}.
* @throws IndexOutOfBoundsException
* if the index is out of range (index < 0 || index > size()).
*/
public boolean addAll(int index, Collection extends IonValue> c);
/**
* Returns a list iterator of the elements in this sequence (in proper
* order).
*
* The result does not support {@link ListIterator#add(Object)} or
* {@link ListIterator#set(Object)}.
* If this sequence {@link #isReadOnly()} then it also does not support
* {@link Iterator#remove()}.
*/
public ListIterator listIterator();
/**
* Returns a list iterator of the elements in this sequence (in proper
* order), starting at the specified position in this sequence.
*
* The result does not support {@link ListIterator#add(Object)} or
* {@link ListIterator#set(Object)}.
* If this sequence {@link #isReadOnly()} then it also does not support
* {@link Iterator#remove()}.
*
* @param index
* index of first element to be returned from the list iterator (by a call
* to the {@code next} method).
*
* @throws IndexOutOfBoundsException
* if the index is out of range ({@code index < 0 || index > size()}).
*/
public ListIterator listIterator(int index);
/**
*
* Returns a view of the portion of this list according to
* {@link List#subList(int, int)} contract.
*
*
*
* Sublist methods will throw a
* {@link java.util.ConcurrentModificationException} if its parent list,
* i.e. this list, had any changes that affect its size the after sublist
* was created.
*
*
* The implementation of {@link List} returned by this method
* implements {@link List#equals(Object)} and
* {@link List#equals(Object)} ()} per the specification of these methods.
* However, the existing implementation of {@link IonSequence} does not
* provide a specification compliant {@link List#equals} and
* {@link List#hashCode()}} which results to the following caveats:
*
* Given:
*
*
* int[] ints = new int[] {1, 2, 3, 4};
* IonList list = SYSTEM.newList(ints);
* IonSexp sexp = SYSTEM.newSexp(ints)
* IonSexp dgrm = SYSTEM.newDatagram(ints)
* List listSubList = list.subList(0, ints.size())
* List sexpSubList = sexp.subList(0, ints.size())
* List dgrmSubList = sexp.subList(0, ints.size())
* List arrayList = new ArrayList();
* for(int i : ints) { arrayList.add(SYSTEM.newInt(i)); }
*
*
* {@link IonSequence#equals(Object)} always returns false when presented
* with a non {@link IonSequence} instance of {@link List}.
* Hence, the following invocations of {@link Object#equals(Object)}
* return false even if the contained elements are equivalent. This
* means that {@link Object#equals(Object)} is not symmetric in these
* cases. The reason for the asymmetry is historical:
* {@link IonSequence} has long violated the contract outlined by the
* {@link List} documentation. For the current major version of this
* library we maintain backwards compatibility and support this behaviour
* as-is.
*
*
* list.equals(listSubList) // false
* list.equals(sexpSubList) // false
* list.equals(dgrm) // false
* list.equals(arrayList) // false
*
* sexp.equals(listSubList) // false
* sexp.equals(sexpSubList) // false
* sexp.equals(dgrm) // false
* sexp.equals(arrayList) // false
*
* dgrm.equals(listSubList) // false
* dgrm.equals(sexpSubList) // false
* dgrm.equals(dgrmSubList) // false
* dgrm.equals(arrayList) // false
*
*
* However, {@link IonSequence#subList(int, int)} was implemented much
* later and faithfully implements {@link List#equals(Object)} meaning
* the cases below all work as expected. While {@link IonSequence}
* does not comply with the specification for {@link List#equals(Object)}
* because it has to comply with Ion's rules for equality, the same is
* not true for sub-lists. Unlike {@link IonSequence}, sub-lists have
* no notion of an {@link IonType}, annotations or nullability which
* allows for compliance with the {@link List} specification.
*
*
* listSubList.equals(listSubList); // true
* listSubList.equals(sexpSubList); // true
* listSubList.equals(dgrmSubList); // true
* listSubList.equals(list); // true
* listSubList.equals(sexp); // true
* listSubList.equals(arrayList); // true
*
* sexpSubList.equals(listSubList); // true
* sexpSubList.equals(sexpSubList); // true
* sexpSubList.equals(dgrmSubList); // true
* sexpSubList.equals(list); // true
* sexpSubList.equals(sexp); // true
* sexpSubList.equals(arrayList); // true
*
* dgrmSubList.equals(listSubList); // true
* dgrmSubList.equals(sexpSubList); // true
* dgrmSubList.equals(dgrmSubList); // true
* dgrmSubList.equals(list); // true
* dgrmSubList.equals(sexp); // true
* dgrmSubList.equals(arrayList); // true
*
*
* @see List#subList(int, int)
*/
public List subList(int fromIndex, int toIndex);
/**
* Returns an array containing all of the elements in this sequence in
* proper order. Obeys the general contract of the
* {@link Collection#toArray()} method.
*
* If this sequence is an {@linkplain #isNullValue() Ion null value}, it
* will behave like an empty sequence.
*
* @return an array containing all of the elements in this sequence in
* proper order.
*/
public IonValue[] toArray();
/**
* Returns an array containing all of the elements in this sequence in
* proper order; the runtime type of the returned array is that of the
* specified array. Obeys the general contract of the
* {@link Collection#toArray()} method.
*
* If this sequence is an {@linkplain #isNullValue() Ion null value}, it
* will behave like an empty sequence.
*
* @param a the array into which the elements of this sequence are to be
* stored, if it is big enough; otherwise, a new array of the same
* runtime type is allocated for this purpose.
*
* @return an array containing all of the elements in this sequence in
* proper order.
*
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in this
* sequence.
* @throws NullPointerException if the specified array is null
.
*/
public T[] toArray(T[] a);
/**
* Removes all children of this sequence, returning them in an array.
* This is much more efficient than iterating the sequence and removing
* children one by one.
*
* @return a new array with all of the children of {@code s} in order, or
* {@code null} if {@link #isNullValue()}.
*
* @throws NullPointerException if {@code type} is {@code null}.
* @throws ClassCastException if any value in this sequence does not
* implement the given type.
*/
public T[] extract(Class type);
public IonSequence clone()
throws UnknownSymbolException;
}