Interface IPosition<T,P extends IPosition<T,P>>
-
- Type Parameters:
T
- type of element held in the list
- All Superinterfaces:
IPositionHolder<T,P>
,IPositionListener
- All Known Implementing Classes:
IPositionBase
,Position
public interface IPosition<T,P extends IPosition<T,P>> extends IPositionHolder<T,P>
Represents a position in the list at the given index and with a span of 0 or 1 elements.Add/remove operations affect the index and span of this position depending on the anchor type of the position.
Once the span becomes 0, no modifications to the list can change it to span 1 element.
PositionAnchor.CURRENT
- tracks a specific element at index when the position is instantiated. Adding elements before the position will shift the range down in the list. Removing elements before the position will shift the range up in the list. Removing elements which include the position's index will set its span to 0. The position is always available for adding/removing next/previous elements. The current element is only available when span is 1.PositionAnchor.PREVIOUS
- tracks the previous element to the position from which it was instantiated. The span will be 0 if no previous element existed when it was instantiated (ie. at position 0) or was removed later.The index of this position reflects the position in the list previous to the position from which it was instantiated and the index is valid if span is 1 or index is >0. Relative offset <0 will be increased by 1 if span is 0 to reflect removal of previous element.
This anchor position type is used for iterating positions in reverse since it ignores insertions into the list immediately before the current position.
PositionAnchor.NEXT
- tracks the next element to the position from which it was instantiated. The span will be 0 if no next element existed when it was instantiated (ie. at end of the list) or was removed later.The index of this position reflects the position in the list next to the position from which it was instantiated and the index is valid if span is 1 or index is <list.size(). Relative offset >0 will be reduced by 1 if span is 0 to reflect removal of next element.
This anchor position type is used for iterating positions since it ignores insertions into the list immediately after the current position.
All offset based operations on this position are operations on the list at index relative to this position's index and span, so offsets may be -ve or +ve as long as absolute index is >=0 and <list.size()
NOTE: Offsets are affected by span being 0 or 1 and type of anchor for the position: Offset of 0 refers to the element of this position and is only available if this position span is 1.
Offset <0 refer to the elements preceding the element at this position. For
PositionAnchor.PREVIOUS
If span is 0 then the offset is increased by 1 to reflect that there is no current element at this position.Offset >0 refer to the elements following the element at this position. If span is 0 then offset is reduced by 1 to reflect that there is no current element.
PositionList iterator will iterate over list elements while elements are added or removed from the list without affecting count of the iteration as long as elements are only added immediately before or after the current position.
This is not limited to adding 1 element. Each added element before or after the current position moves the previous/next element position in the list. The first addition is limited to relative offset of -1, 0 or 1 from current index if the addition is not to affect iteration.
The following operations can insert anywhere in the previously inserted range.
Deletions have no limitations. They can never cause new elements to be inserted after the next element position of the iterator so cannot cause iteration to continue on a newly added element.
All this makes list manipulation while traversing it easier to write, debug and understand because all operations are relative to current position instead of a numeric index. In the code you see -1, 0, +1, for previous, current and next element references taking removal and addition of elements into account.
PositionList adjusts all outstanding positions into its instance. Allowing getting multiple positions in the list before making modification, in order to track index of elements at those positions. If after modifications the position has 0 span, as reflected by its
IPositionHolder.isValidElement()
being false, then the element at that position was removed. Otherwise, getIndex() will return the current index of that element in the list. If there is no valid element will return the index of the position, which will be the next available element in the list.Index computations can be a real bug generator, throw inserting, deleting and traversing a list at the same time and you have a beast to debug and maintenance nightmare to look forward to. PositionList and Position instances make all that go away. That's why I wrote these classes so I don't have to write and debug the same error prone code for manipulating lists.
-
-
Method Summary
All Methods Instance Methods Abstract Methods Modifier and Type Method Description boolean
add(int offset, T element)
Add element at position given by relative offset to current position.boolean
add(T element)
boolean
addAll(int offset, java.util.Collection<T> elements)
boolean
addAll(java.util.Collection<T> elements)
boolean
append(T element)
T
get()
T
get(int offset)
Insert element at indexint
getIndex(int offset)
T
getOrNull()
T
getOrNull(int offset)
Insert element at index<S extends T>
SgetOrNull(int offset, java.lang.Class<S> elementClass)
Get the requested class or null if element at position cannot be cast to this class<S extends T>
SgetOrNull(java.lang.Class<S> elementClass)
Get the requested class or null if element at position cannot be cast to this classP
getPosition(int offset)
P
indexOf(int offset, java.util.function.Predicate<P> predicate)
P
indexOf(int offset, T o)
P
indexOf(java.util.function.Predicate<P> predicate)
P
indexOf(T o)
void
invalidate()
Mark position as not valid may be useful for something.boolean
isEmpty()
boolean
isValidIndex()
P
lastIndexOf(int offset, java.util.function.Predicate<P> predicate)
P
lastIndexOf(int offset, T o)
P
lastIndexOf(java.util.function.Predicate<P> predicate)
P
lastIndexOf(T o)
int
maxOffset()
int
minOffset()
T
remove()
T
remove(int offset)
void
remove(int startOffset, int endOffset)
T
set(int offset, T element)
Set element at given indexvoid
set(T element)
int
size()
-
Methods inherited from interface com.vladsch.flexmark.experimental.util.collection.iteration.IPositionHolder
backwards, detachListener, equals, forwards, getAnchor, getIndex, hashCode, hasNext, hasPrevious, isDetached, isValid, isValidElement, next, nextForwards, nextIndex, nextOrNull, previous, previousBackwards, previousIndex, previousOrNull, setDetached, unframed, withAnchor
-
Methods inherited from interface com.vladsch.flexmark.experimental.util.collection.iteration.IPositionListener
deleted, inserted
-
-
-
-
Method Detail
-
getIndex
int getIndex(int offset)
- Parameters:
offset
- offset to current positionFIX: allow getIndex(offset) to return -1
- Returns:
- absolute index in list, even if this position is not valid, it will always be [-1, list.size()]
-
getPosition
P getPosition(int offset)
- Parameters:
offset
- index relative to current position, <0 previous elements, 0 means current, >0 following elements- Returns:
- Position representing the index relative to current position,
throws
IllegalStateException
if current position is not valid and given index == 0 throwsIndexOutOfBoundsException
if requested index results in absolute index <0 or >size() of the listNOTE: to avoid exceptions test if position has a valid index with isValidIndex()
-
invalidate
void invalidate()
Mark position as not valid may be useful for something. Invalidates current element with all side-effects of this state
-
isValidIndex
boolean isValidIndex()
- Returns:
- true if index of this position is between 0 and size() of the list
-
get
T get()
- Returns:
- get element at this position, throws
IllegalStateException
if current position is not valid or after last element of list
-
get
T get(int offset)
Insert element at index- Parameters:
offset
- relative to this position, absolute index [0, size()], if absolute index == size() then element is added at the end of the list. The latter is also considered an insert at size() index.- Returns:
- element
-
getOrNull
T getOrNull()
- Returns:
- get element at this position or null if no such thing
-
getOrNull
@Nullable T getOrNull(int offset)
Insert element at index- Parameters:
offset
- relative to this position, absolute index [0, size()], if absolute index == size() then element is added at the end of the list. The latter is also considered an insert at size() index.- Returns:
- element or null if for some reason the index or position are not valid
-
getOrNull
@Nullable <S extends T> S getOrNull(java.lang.Class<S> elementClass)
Get the requested class or null if element at position cannot be cast to this class- Type Parameters:
S
- type of element- Parameters:
elementClass
- class of element desired- Returns:
- element of type or null
-
getOrNull
@Nullable <S extends T> S getOrNull(int offset, java.lang.Class<S> elementClass)
Get the requested class or null if element at position cannot be cast to this class- Type Parameters:
S
- type of element- Parameters:
offset
- relative to this position, absolute index [0, size()], if absolute index == size() then element is added at the end of the list. The latter is also considered an insert at size() index.elementClass
- class of element desired- Returns:
- element of type or null
-
set
void set(T element)
- Parameters:
element
- to which to set the current element in the list throws IllegalStateException if current index is not validIf the current index is after the last element this will add the value to the end of the list treating as an insert, with corresponding updates to any positions that this would affect.
-
set
T set(int offset, T element)
Set element at given index- Parameters:
offset
- relative to this position, absolute index [0, size()], if absolute index == size() then element is added at the end of the list. The latter is considered an insert at the index.element
- value to set at offset- Returns:
- element value at that position before. If adding at end of list then null is always returned.
-
add
boolean add(T element)
- Parameters:
element
- to insert after the current position in the list, not at the end of the list as a regular List does. throws IllegalStateException if current index is not valid- Returns:
- true
-
add
boolean add(int offset, T element)
Add element at position given by relative offset to current position.NOTE: The position of insert is changed, depending on what has happened to the elements around the current position since it was instantiated: if element at position was deleted then offset 0 and 1 have the same effect, insert element before next.
0 will always insert before the current position, so add(0, item1) will insert before current position, which advances the position to keep up with the current element. Next add(0, item2) will insert item2 after item1.
- Parameters:
offset
- offset, can be negative. 0 means insert before current, 1 means after current, -1 means before previouselement
- to insert- Returns:
- true
-
addAll
boolean addAll(@NotNull java.util.Collection<T> elements)
-
addAll
boolean addAll(int offset, @NotNull java.util.Collection<T> elements)
-
remove
T remove()
-
remove
T remove(int offset)
-
remove
void remove(int startOffset, int endOffset)
-
maxOffset
int maxOffset()
- Returns:
- max offset from current position
-
minOffset
int minOffset()
- Returns:
- min offset from current position to 0
-
size
int size()
-
isEmpty
boolean isEmpty()
-
append
boolean append(T element)
-
-