Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.basex.gui.view.table;
import static org.basex.util.Token.*;
import org.basex.core.*;
import org.basex.core.cmd.*;
import org.basex.data.*;
import org.basex.gui.*;
import org.basex.index.name.*;
import org.basex.index.stats.*;
import org.basex.util.*;
import org.basex.util.list.*;
/**
* This is a container for the table data.
*
* @author BaseX Team 2005-22, BSD License
* @author Christian Gruen
*/
final class TableData {
/** Number of rows which is parsed for a new document. */
private static final int MAXROWS = 1000;
/** Maximum token for sorting data. */
private static final byte[] MAXTOK = { -1 };
/** Maximum number for sorting data. */
private static final byte[] MAXNUM = token(Double.MAX_VALUE);
/** Database context. */
final Context ctx;
/** Root nodes. */
TokenList roots;
/** Rows of the main table. */
IntList rootRows;
/** Pre values of the rows. */
IntList rows;
/** Columns. */
TableCol[] cols;
/** Row height. */
int rowH;
/** Currently sorted column. */
int sortCol = -1;
/** Sort order (ascending/descending). */
boolean asc;
/** Mouse X position. */
int mouseX;
/** Mouse Y position. */
int mouseY;
/** ID of the table root element. */
int root;
/** GUI options. */
private final GUIOptions gopts;
/** Last query. */
private String last = "";
/** Table Column. */
static final class TableCol {
/** Element/attribute name. */
byte[] name;
/** Column IDs. */
int id;
/** Element/attribute flag. */
boolean elem;
/** Column width. */
double width;
/** Hidden Column width. */
double hwidth;
/** Column filter. */
String filter = "";
}
/**
* Initializes the table data.
* @param ctx database context
* @param gopts gui options
*/
TableData(final Context ctx, final GUIOptions gopts) {
this.ctx = ctx;
this.gopts = gopts;
}
/**
* Initializes the table data.
* @param data data reference
*/
void init(final Data data) {
roots = new TokenList();
// sort keys by occurrence
for(final byte[] k : data.paths.desc(EMPTY, true, true)) {
int c = 0;
for(final byte[] kk : data.paths.desc(k, true, false)) {
final Names names = startsWith(kk, '@') ? data.attrNames : data.elemNames;
if(names.stats(names.id(delete(kk, '@'))).isLeaf()) ++c;
}
// add keys with a minimum of three columns
if(c > 2) roots.add(k);
}
init(data, -1);
}
/**
* Initializes the table data.
* @param rt optional root node (ignored if -1)
* @param dt data reference
*/
void init(final Data dt, final int rt) {
cols = new TableCol[0];
root = rt;
sortCol = -1;
last = "";
rowH = 1;
if(rt == -1 && roots.isEmpty()) return;
if(root == -1) root = dt.elemNames.id(roots.get(0));
for(final byte[] k : dt.paths.desc(dt.elemNames.key(root), true, true)) {
final boolean elem = !startsWith(k, '@');
final byte[] key = delete(k, '@');
final Names names = elem ? dt.elemNames : dt.attrNames;
if(names.stats(names.id(key)).isLeaf()) addCol(key, elem);
}
context(true);
}
/**
* Initializes the table data.
* @param create flag for creating new rows
*/
void context(final boolean create) {
if(cols.length == 0) return;
final boolean rt = ctx.root();
if(!create && rt && rootRows != null) {
rows = rootRows;
sortCol = -1;
} else {
createRows();
if(rt) rootRows = rows;
}
if(cols[0].width == 0 && cols[0].hwidth == 0) calcWidths();
}
/**
* Adds the specified element or attribute as column if it exists in the data.
* @param name element/attribute name to be added
* @param elem element flag
*/
private void addCol(final byte[] name, final boolean elem) {
final Data data = ctx.data();
final int id = (elem ? data.elemNames : data.attrNames).id(name);
if(id == 0) return;
final TableCol col = new TableCol();
col.id = id;
col.elem = elem;
col.name = name;
cols = Array.add(cols, col);
}
/**
* Creates the row list for the specified nodes.
*/
private void createRows() {
final Data data = ctx.data();
rows = new IntList();
for(int pre : ctx.current().pres()) {
if(pre >= data.meta.size) break;
final int s = pre + data.size(pre, data.kind(pre));
// find first root element name
do {
if(data.kind(pre) == Data.ELEM && data.nameId(pre) == root) break;
} while(++pre < s);
// parse whole document and collect root element names
while(pre < s) {
final int k = data.kind(pre);
if(k == Data.ELEM && data.nameId(pre) == root) rows.add(pre);
pre += data.attSize(pre, k);
}
}
sort();
}
/**
* Calculates the column widths, based on the contents.
*/
private void calcWidths() {
if(cols.length == 0) return;
final Data data = ctx.data();
final int cs = cols.length;
// scan first MAXROWS root elements
final int nRows = rows.size();
final TableIterator ti = new TableIterator(data, this);
final int ll = Math.min(nRows, MAXROWS);
for(int l = 0; l < ll; ++l) {
// find all row contents and add string lengths
ti.init(rows.get(l));
while(ti.more()) cols[ti.col].width += data.textLen(ti.pre, ti.text);
}
// sort columns by string lengths
final double[] widths = new double[cs];
for(int c = 0; c < cs; ++c) widths[c] = cols[c].width;
final int[] il = Array.createOrder(widths, false);
final TableCol[] cl = new TableCol[cs];
for(int c = 0; c < cs; ++c) cl[c] = cols[il[c]];
cols = cl;
setWidths(false);
}
/**
* Sets the column widths, based on the contents.
* @param enforce enforce zero widths
*/
void setWidths(final boolean enforce) {
// calculate width of each column
double sum = 0;
for(final TableCol col : cols) sum += col.width;
// avoid too small columns
final double min = enforce ? 0.0 : 0.5;
final int cs = cols.length;
for(final TableCol col : cols) col.width = Math.max(min / cs, col.width / sum);
// recalculate column widths
sum = 0;
for(final TableCol col : cols) sum += col.width;
// normalize widths
for(final TableCol col : cols) col.width /= sum;
}
/**
* Sorts column entries.
*/
void sort() {
if(sortCol == -1) return;
final int c = cols[sortCol].id;
final boolean e = cols[sortCol].elem;
final Data data = ctx.data();
final Names index = e ? data.elemNames : data.attrNames;
final boolean num = StatsType.isNumeric(index.stats(c).type);
final byte[][] tokens = new byte[rows.size()][];
final int rs = rows.size();
for(int r = 0; r < rs; ++r) {
int p = rows.get(r);
final int s = p + data.size(p, data.kind(p));
while(p != s) {
final int k = data.kind(p);
if((e ? k == Data.ELEM : k == Data.ATTR) && data.nameId(p) == c) {
tokens[r] = data.atom(p);
break;
}
p += e ? data.attSize(p, k) : 1;
}
if(tokens[r] == null || tokens[r].length == 0) {
tokens[r] = num ? MAXNUM : MAXTOK;
}
}
rows.sort(tokens, asc, num);
}
/**
* Returns pre value of possible root element.
* @param data data reference
* @param pre pre value to start with
* @return pre value of root element
*/
int getRoot(final Data data, final int pre) {
if(pre == -1) return -1;
int p = pre;
int k = data.kind(p);
while(p != -1 && (k != Data.ELEM || data.nameId(p) != root)) {
p = data.parent(p, k);
k = p == -1 ? 0 : data.kind(p);
}
return p;
}
/**
* Returns the column at the specified horizontal position.
* @param w panel width
* @param mx mouse position
* @return column
*/
int column(final int w, final int mx) {
double cs = 0;
final int cl = cols.length;
for(int c = 0; c < cl; c++) {
final double cw = w * cols[c].width, ce = cs + cw;
if(mx > cs && mx < ce) return c;
cs = ce;
}
return -1;
}
/**
* Resets the filter entries.
*/
void resetFilter() {
for(final TableCol col : cols) col.filter = "";
}
/**
* Builds and returns an XQuery for the filtered terms.
* @return query, or {@code null} if the query is identical to the last one
*/
String find() {
final Data data = ctx.data();
final StringList filters = new StringList();
final TokenList names = new TokenList();
final BoolList elems = new BoolList();
for(final TableCol col : cols) {
filters.add(col.filter);
names.add(col.name);
elems.add(col.elem);
}
final String query = Find.tableQuery(filters, names, elems, string(data.elemNames.key(root)),
gopts.get(GUIOptions.FILTERRT) || rows == rootRows);
if(query.equals(last)) return null;
last = query;
return query;
}
/**
* Sets and returns the row height for the given factor.
* @param f factor (1 = maximum/default)
* @return row height
*/
int rowH(final double f) {
rowH = Math.max(1, (int) (f * GUIConstants.fontSize * 7 / 4));
return rowH;
}
}