package org.basex.data;
import java.util.Arrays;
import org.basex.util.Array;
import org.basex.util.list.IntList;
/**
* This class provides a container for query full-text positions,
* which is evaluated by the visualizations.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
* @author Sebastian Gath
*/
public final class FTPosData {
/** Position references. */
private FTPos[] pos = new FTPos[1];
/** Data reference. */
private Data data;
/** Number of values. */
private int size;
/**
* Adds position data.
*
* @param d data reference
* @param pre pre value
* @param all full-text matches
*/
public void add(final Data d, final int pre, final FTMatches all) {
if(data == null) data = d;
else if(data != d) return;
final IntList ps = new IntList();
for(final FTMatch m : all) {
for(final FTStringMatch sm : m) {
for(int s = sm.s; s <= sm.e; ++s) ps.add(s);
}
}
int c = find(pre);
if(c < 0) {
c = -c - 1;
if(size == pos.length) pos = Arrays.copyOf(pos, size << 1);
Array.move(pos, c, 1, size++ - c);
pos[c] = new FTPos(pre, ps.toArray());
} else {
pos[c].union(ps.toArray());
}
}
/**
* Gets full-text data from the container.
* If no data is stored for a pre value, {@code null} is returned.
* int[0] : [pos0, ..., posn]
* int[1] : [poi0, ..., poin]
* @param d data reference
* @param p int pre value
* @return int[2][n] full-text data or {@code null}
*/
public FTPos get(final Data d, final int p) {
final int i = find(p);
return i < 0 || data != d ? null : pos[i];
}
/**
* Returns the number of entries.
* @return size
*/
public int size() {
int c = 0;
for(int i = 0; i < size; ++i) c += pos[i].size();
return c;
}
/**
* Compares full-text data for equality.
* @param ft reference to compare to
* @return boolean same()
*/
boolean sameAs(final FTPosData ft) {
if(size != ft.size) return false;
for(int i = 0; i < size; ++i) {
if(pos[i].pre != ft.pos[i].pre ||
!Arrays.equals(pos[i].pos, ft.pos[i].pos)) return false;
}
return true;
}
/**
* Returns the position of the specified pre value.
* @param p int pre value
* @return position or negative insertion value - 1
*/
private int find(final int p) {
// binary search
int l = 0, h = size - 1;
while(l <= h) {
final int m = l + h >>> 1;
final int c = pos[m].pre - p;
if(c == 0) return m;
if(c < 0) l = m + 1;
else h = m - 1;
}
return -l - 1;
}
}