io.sirix.index.Indexes Maven / Gradle / Ivy
package io.sirix.index;
import io.brackit.query.atomic.QNm;
import io.brackit.query.jdm.DocumentException;
import io.brackit.query.jdm.Stream;
import io.brackit.query.jdm.Type;
import io.brackit.query.jdm.node.Node;
import io.brackit.query.node.parser.FragmentHelper;
import io.brackit.query.util.path.Path;
import io.brackit.query.util.path.PathException;
import org.checkerframework.checker.index.qual.NonNegative;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
/**
* @author Karsten Schmidt
* @author Sebastian Baechle
*/
public final class Indexes implements Materializable {
public static final QNm INDEXES_TAG = new QNm("indexes");
private final Set indexes;
public Indexes() {
indexes = new HashSet<>();
}
public synchronized Set getIndexDefs() {
return new HashSet<>(indexes);
}
public synchronized IndexDef getIndexDef(final @NonNegative int indexNo, final IndexType type) {
checkArgument(indexNo >= 0, "indexNo must be >= 0!");
for (final IndexDef sid : indexes) {
if (sid.getID() == indexNo && sid.getType() == type) {
return sid;
}
}
return null;
}
@Override
public synchronized void init(final Node> root) throws DocumentException {
final QNm name = root.getName();
if (!INDEXES_TAG.equals(name)) {
throw new DocumentException("Expected tag '%s' but found '%s'", INDEXES_TAG, name);
}
try (Stream extends Node>> children = root.getChildren()) {
Node> child;
while ((child = children.next()) != null) {
QNm childName = child.getName();
if (!childName.equals(IndexDef.INDEX_TAG)) {
throw new DocumentException("Expected tag '%s' but found '%s'", IndexDef.INDEX_TAG, childName);
}
final Node> dbTypeAttrNode = child.getAttribute(new QNm("dbType"));
final var dbType = IndexDef.DbType.ofString(dbTypeAttrNode.atomize().asStr().toString());
final IndexDef indexDefinition =
new IndexDef(dbType.orElseThrow(() -> new DocumentException("DB type not found.")));
indexDefinition.init(child);
indexes.add(indexDefinition);
}
}
}
@Override
public synchronized Node> materialize() throws DocumentException {
FragmentHelper helper = new FragmentHelper();
helper.openElement(INDEXES_TAG);
for (IndexDef idxDef : indexes) {
helper.insert(idxDef.materialize());
}
helper.closeElement();
return helper.getRoot();
}
public synchronized void add(IndexDef indexDefinition) {
indexes.add(indexDefinition);
}
public synchronized void removeIndex(final @NonNegative int indexID) {
checkArgument(indexID >= 0, "indexID must be >= 0!");
for (final IndexDef indexDef : indexes) {
if (indexDef.getID() == indexID) {
indexes.remove(indexDef);
return;
}
}
}
public Optional findPathIndex(final Path path) throws DocumentException {
requireNonNull(path);
try {
for (final IndexDef index : indexes) {
if (index.isPathIndex() && checkIfAPathMatches(path, index)) {
return Optional.of(index);
}
}
return Optional.empty();
} catch (PathException e) {
throw new DocumentException(e);
}
}
private boolean checkIfAPathMatches(Path path, IndexDef index) {
if (index.getPaths().isEmpty()) {
return true;
}
for (final Path indexedPath : index.getPaths()) {
if (indexedPath.matches(path)) {
return true;
}
}
return false;
}
public Optional findCASIndex(final Path path, final Type type) throws DocumentException {
requireNonNull(path);
try {
for (final IndexDef index : indexes) {
if (index.isCasIndex() && index.getContentType().equals(type) && checkIfAPathMatches(path, index)) {
return Optional.of(index);
}
}
return Optional.empty();
} catch (PathException e) {
throw new DocumentException(e);
}
}
public Optional findNameIndex(final QNm... names) throws DocumentException {
requireNonNull(names);
out:
for (final IndexDef index : indexes) {
if (index.isNameIndex()) {
final Set incl = index.getIncluded();
final Set excl = index.getExcluded();
if (names.length == 0 && incl.isEmpty() && excl.isEmpty()) {
// Require generic name index
return Optional.of(index);
}
for (final QNm name : names) {
if (!incl.isEmpty() && !incl.contains(name) || !excl.isEmpty() && excl.contains(name)) {
continue out;
}
}
return Optional.of(index);
}
}
return Optional.empty();
}
public int getNrOfIndexDefsWithType(final IndexType type) {
requireNonNull(type);
int nr = 0;
for (final IndexDef index : indexes) {
if (index.getType() == type) {
nr++;
}
}
return nr;
}
}