/**
* Contains the Alteration class and its subclasses; Addition and Removal.
*/
package com.scottlogic.util;
/**
* Represents the alterations to the backingList of a {@code PatchWorkArray}.
* <p>
* These come in two flavors: {@code Addition}s and {@code Removal}. {@code Addition}s cover
* a single index and represents the fact that the containing PatchWorkArray has a sublist
* at that index in its backingList. {@code Removal}s cover a continuous block of indices in the
* {@code PatchWorkArray}'s backingList and represent that those indices do not contain valid
* elements.
*/
abstract class Alteration implements Comparable<Alteration> {
int index; //the index that this alteration occurs..
int indexDiff; //the difference that this alteration makes to the index..
Alteration(int index, int indexDiff){
this.index = index;
this.indexDiff = indexDiff;
}
//Compares elements on their index only..
@Override
public int compareTo(Alteration other) {
return index-other.index;
}
/**
* Returns the impact on performance which the existence of this
* Alteration will have on a containing {@code PatchWorkArray}.
* <p>
* Let <i>t</i> be the sum of the values returned by calling this method on all
* {@code Alteration}s in a {@code PatchWorkArray}, the time it takes to find an
* element in that list by index should be <i>O(log(t))</i>.
*
* @return an indication of the performance hit a {@code PatchWorkArray}
* would have if it included this {@code Alteration}.
*/
abstract int getPerformanceHit();
/**
* Returns whether or not this {@code Alteration} covers the given index
* in the {@code PatchWorkArray}'s backingList.
*
* @param index the index of thebackingList to check.
* @return <code>true</code> in the case that this {@code Alteration} covers the given
* index of the backingList.
*/
abstract boolean coversBackingListIndex(int index);
//Simply returns the index..
@Override
public int hashCode() {
return index;
}
/**
* Returns the number of elements that this alteration affects,
* which is calculated as being the absolute size of the {@code #indexDiff}.
*
* @return the absolute size of the {@code #indexDiff}.
*/
public int size(){
return Math.abs(indexDiff);
}
//Works solely on the index..
@Override
public boolean equals(Object obj) {
boolean same = false;
if(obj instanceof Alteration){
same = ((Alteration) obj).index == index;
}
return same;
}
@Override
public String toString(){
return "[" + index + "," + indexDiff + "]";
}
}
/**
* Represents an alteration to a patch work array, where elements have been
* added to the array at a specific index.
*/
class Addition extends Alteration {
Addition(int index){
super(index, -1);
}
void addElement(){
indexDiff -= 1;
}
void removeElement(){
indexDiff += 1;
}
//each element in an Addition slows the containing PatchWorkArray down..
int getPerformanceHit(){
return size();
}
boolean coversBackingListIndex(int index){
return this.index == index;
}
}
/**
* Represents a consecutive block of elements being removed from the list.
* <p>
* The index of the removal is the smallest index in the block of consecutive removals.
*/
class Removal extends Alteration {
/**
* Creates a new Removal of size 1 at the given index.
*
* @param index the index for this Removal.
*/
Removal(int index){
super(index, 1);
}
/**
* Creates a new Removal of the given size at the given index.
*
* @param index the index for this Removal.
* @param indexDiff the number of elements that have been removed that this Removal represents.
*/
Removal(int index, int indexDiff){
super(index, indexDiff);
}
/**
* This should only be called if the element to in position index-1 is a normal
* element that is due to be removed.
*/
void removeElementToLeft(){
index--; //move the index to the left..
indexDiff += 1;
}
void removeElementToRight(){
indexDiff += 1;
}
//the effect of this removal on the containing PatchWorkArray should be constant..
int getPerformanceHit(){
return 1;
}
boolean coversBackingListIndex(int index){
return this.index <= index && this.index + indexDiff > index;
}
}