package org.basex.data;
import java.util.*;
import org.basex.util.*;
import org.basex.util.list.*;
/**
* This class organizes namespace scopes.
*
* @author BaseX Team 2005-17, BSD License
* @author Christian Gruen
*/
final class NSScope {
/** Data reference. */
private final Data data;
/** Namespaces. */
private final Namespaces nspaces;
/** Stack with pre values. */
private final IntList preStack = new IntList();
/** Root namespace. */
private final NSNode root;
/** Tracks existing nodes. */
private final ArrayList<NSNode> cache;
/**
* Default constructor.
* @param pre pre value
* @param data data reference
*/
NSScope(final int pre, final Data data) {
this.data = data;
nspaces = data.nspaces;
root = nspaces.cursor();
cache = nspaces.cache(pre);
}
/**
* Refreshes the namespace structure.
* @param nsPre pre value with namespaces
* @param c insertion counter
*/
void loop(final int nsPre, final int c) {
if(c == 0) nspaces.root(nsPre, data);
while(!preStack.isEmpty() && preStack.peek() > nsPre) nspaces.close(preStack.pop());
}
/**
* Opens a new level.
* @param pre pre value
*/
void open(final int pre) {
nspaces.open();
preStack.push(pre);
}
/**
* Parses the specified namespaces and returns all namespaces that are not declared yet.
* @param pre pre value
* @param nsp source namespaces
* @return {@code true} if new namespaces were added
*/
boolean open(final int pre, final Atts nsp) {
// collect new namespaces
final Atts ns = new Atts();
final int as = nsp.size();
for(int a = 0; a < as; a++) {
final byte[] prefix = nsp.name(a), uri = nsp.value(a);
final int uriId = nspaces.uriIdForPrefix(prefix, true);
if(uriId == 0 || uriId != nspaces.uriId(uri)) ns.add(prefix, uri);
}
nspaces.open(pre, ns);
preStack.push(pre);
return !ns.isEmpty();
}
/**
* Shifts cached namespaces by the specified value.
* @param diff shift
*/
void shift(final int diff) {
for(final NSNode node : cache) node.incrementPre(diff);
}
/**
* Closes the namespace scope.
*/
void close() {
while(!preStack.isEmpty()) nspaces.close(preStack.pop());
nspaces.cursor(root);
}
}