package org.basex.core.cmd;
import static org.basex.core.Text.*;
import static org.basex.data.DataText.*;
import static org.basex.util.Token.*;
import java.io.IOException;
import org.basex.core.CommandBuilder;
import org.basex.core.User;
import org.basex.core.Commands.Cmd;
import org.basex.core.Commands.CmdInfo;
import org.basex.data.Data;
import org.basex.data.Nodes;
import org.basex.util.Table;
import org.basex.util.TokenBuilder;
import org.basex.util.list.TokenList;
/**
* Evaluates the 'info storage' command and returns the table representation
* of the currently opened database.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class InfoStorage extends AQuery {
/**
* Default constructor.
* @param arg optional arguments
*/
public InfoStorage(final String... arg) {
super(DATAREF | User.READ, arg);
}
@Override
protected boolean run() throws IOException {
// get arguments
final String start = args.length > 0 ? args[0] : null;
final String end = args.length > 1 ? args[1] : null;
// evaluate input as number range or xquery
if(start != null && toInt(start) == Integer.MIN_VALUE) {
queryNodes();
if(result == null) return false;
}
final Data data = context.data();
if(result != null) {
final Table table = th();
for(final int n : ((Nodes) result).list) table(table, data, n);
out.print(table.finish());
result = null;
} else {
int ps = 0;
int pe = 1000;
if(start != null) {
if(end != null) {
ps = toInt(start);
pe = toInt(end) + 1;
} else {
ps = toInt(start);
pe = ps + 1;
}
}
out.print(table(data, ps, pe));
}
return true;
}
/**
* Prints the specified range of the table.
* @param data data reference
* @param s first node to be printed
* @param e last node to be printed
* @return table
*/
public static byte[] table(final Data data, final int s, final int e) {
final TokenBuilder tb = new TokenBuilder();
final int ps = Math.max(0, s);
final int pe = Math.min(data.meta.size, e);
final Table table = th();
for(int p = ps; p < pe; ++p) table(table, data, p);
tb.add(table.finish());
final byte[] ns = data.nspaces.table(ps, pe);
if(ns.length != 0)
tb.add(NL).add(ns).add(data.nspaces.toString(ps, pe)).add(NL);
return tb.finish();
}
/**
* Writes the header for the 'table' command.
* @return table
*/
private static Table th() {
final Table t = new Table();
t.header.add(TABLEPRE);
t.header.add(TABLEDIST);
t.header.add(TABLESIZE);
t.header.add(TABLEATS);
t.header.add(TABLENS);
t.header.add(TABLEKND);
t.header.add(TABLECON);
for(int i = 0; i < 6; ++i) t.align.add(true);
return t;
}
/**
* Writes the entry for the specified pre value to the table.
* @param t table reference
* @param data data reference
* @param p node to be printed
*/
private static void table(final Table t, final Data data, final int p) {
final int k = data.kind(p);
final TokenList tl = new TokenList();
tl.add(p);
tl.add(p - data.parent(p, k));
tl.add(data.size(p, k));
tl.add(data.attSize(p, k));
final int u = data.uri(p, k);
if(data.nsFlag(p)) tl.add("+" + u);
else tl.add(u);
tl.add(TABLEKINDS[k]);
final byte[] cont;
if(k == Data.ELEM) {
cont = data.name(p, k);
} else if(k == Data.ATTR) {
cont = new TokenBuilder(data.name(p, k)).add(ATT1).add(
data.text(p, false)).add(ATT2).finish();
} else {
cont = data.text(p, true);
}
tl.add(replace(chop(cont, 64), '\n', ' '));
t.contents.add(tl);
}
@Override
public void build(final CommandBuilder cb) {
cb.init(Cmd.INFO + " " + CmdInfo.STORAGE);
if(args.length > 0 && args[0] != null && toInt(args[0]) ==
Integer.MIN_VALUE) {
cb.xquery(0);
} else {
cb.arg(0).arg(1);
}
}
}