package org.basex.query.up;
import static org.basex.util.Token.*;
import java.util.Arrays;
import org.basex.query.item.ANode;
import org.basex.query.item.NodeType;
import org.basex.query.item.QNm;
import org.basex.query.item.Type;
import org.basex.util.Atts;
/**
* This class serves as a container for updated names.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class NamePool {
/** Names. */
private QNm[] names = new QNm[1];
/** Attribute/element flag. */
private boolean[] attr = new boolean[1];
/** Number of occurrences. */
private int[] occ = new int[1];
/** Number of entries. */
private int size;
/**
* Adds an entry to the pool and increases its number of occurrence.
* @param name name
* @param type node type
*/
public void add(final QNm name, final Type type) {
if(type != NodeType.ATT && type != NodeType.ELM) return;
final int i = index(name, type == NodeType.ATT);
occ[i]++;
}
/**
* Adds an entry to the pool and decreases its number of occurrence.
* @param node node
*/
public void remove(final ANode node) {
if(node.type != NodeType.ATT && node.type != NodeType.ELM) return;
final int i = index(node.qname(), node.type == NodeType.ATT);
occ[i]--;
}
/**
* Finds duplicate attributes.
* @return duplicate attribute, or {@code null}
*/
QNm duplicate() {
for(int i = 0; i < size; ++i) if(occ[i] > 1) return names[i];
return null;
}
/**
* Checks if no namespace conflicts occur.
* @return success flag
*/
boolean nsOK() {
final Atts at = new Atts();
for(int i = 0; i < size; ++i) {
if(occ[i] <= 0) continue;
final QNm nm = names[i];
final byte[] pref = nm.prefix();
final byte[] uri = nm.uri();
final byte[] u = at.string(pref);
if(u == null) at.add(pref, uri);
// check if only one uri is assigned to a prefix
else if(!eq(uri, u)) return false;
}
return true;
}
/**
* Returns an index to an existing entry.
* @param name name to be found
* @param at attribute/element flag
* @return index offset, or -1
*/
private int index(final QNm name, final boolean at) {
for(int i = 0; i < size; ++i) {
if(names[i].eq(name) && attr[i] == at) return i;
}
if(size == names.length) {
names = Arrays.copyOf(names, size << 1);
attr = Arrays.copyOf(attr, size << 1);
occ = Arrays.copyOf(occ, size << 1);
}
names[size] = name;
attr[size] = at;
return size++;
}
}