/*
* ImmutableFenwickTree.java
*
* Copyright (C) 2010 Leo Osvald <leo.osvald@gmail.com>
*
* This file is part of SGLJ.
*
* SGLJ is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SGLJ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sglj.util.struct;
import java.util.Collection;
/**
* A fenwick tree which does not use or require the
* {@link #inheritSubCodomain(Object, Object)} method to be implemented.
* However, this implementation imposes two new restrictions. First,
* the collection is no longer fully mutable.
* The {@link #set(int, Object)} method
* may only be called at most once, provided that the method
* {@link #lock()} has not been called. After the {@link #lock()} method
* has been called, it is guaranteed that no modifications are
* allowed and this static collection may then be considered "immutable".
* Constructors which take a collection or array creates a true
* immutable objects (the {@link #lock()} method is automatically called).
* Second, the {@link #retrieveQuery(int, int)} method is no longer
* a supported operation, since it cannot be calculated without
* the {@link #inheritSubCodomain(Object, Object)} method.
* <br>
*
* By not having to implement that method, the
* {@link #mergeCodomains(Object, Object)} method is made
* less-restrictive. For example, one might now implement fenwick tree
* to retrieve minimum element in range [0, index], which
* is impossible to work if the {@link #inheritSubCodomain(Object, Object)}
* has to be implemented. Here is the example code for a fenwick
* tree which computes the minimum element in range [0, index]:<br>
*
* <pre>
* class FTMin extends ImmutableFenwickTree<Integer, Integer> {
*
* public FTMin(Integer[] elements, boolean rightToLeft) {
* super(elements,
* false); // we want min[0, index], not min[index, indexCount()]
* }
*
* //@Override
* public Integer mergeCodomains(Integer a, Integer b) {
* return Math.min(a, b);
* }
*
* //@Override
* protected Integer createData(Integer element) {
* return element != null ? element
* : Integer.MAX_VALUE; // this is neutral for minimum
* }
* }
* </pre>
*
* @author Leo Osvald
*
* @param <E>
* @param <T>
*/
public abstract class ImmutableFenwickTree<E, T> extends FenwickTree<E, T> {
private boolean locked;
public ImmutableFenwickTree(int size, boolean rightToLeft) {
super(size, rightToLeft);
}
public ImmutableFenwickTree(E[] elements, boolean rightToLeft) {
super(elements, rightToLeft);
lock();
}
public ImmutableFenwickTree(StaticCollection<? extends E> c,
boolean rightToLeft) {
super(c, rightToLeft);
lock();
}
public ImmutableFenwickTree(Collection<? extends E> c,
boolean rightToLeft) {
super(c, rightToLeft);
lock();
}
@Override
public final T inheritSubCodomain(T domain, T subdomain) {
return domain;
}
@Override
public final T retrieveQuery(int fromIndex, int toIndex) {
throw new UnsupportedOperationException();
}
public void set(int index, E element) {
if (get(index) != null || locked)
throw new UnsupportedOperationException();
super.set(index, element);
}
public void lock() {
this.locked = true;
}
}