SingletonBindingSet.java
/*******************************************************************************
* Copyright (c) 2021 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.sail.shacl.ast.planNodes;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.query.Binding;
import org.eclipse.rdf4j.query.BindingSet;
import org.eclipse.rdf4j.query.impl.SimpleBinding;
/**
* A simple binding set tuned for the use case that the ShaclSail has.
*/
public class SingletonBindingSet implements BindingSet {
private static final long serialVersionUID = 6083219124988052038L;
private final String name;
private final Value value;
private Binding cachedBinding;
private int cachedHashCode = 0;
public SingletonBindingSet(String bindingName, Value value) {
this.name = bindingName;
this.value = value;
}
@Override
public Iterator<Binding> iterator() {
if (cachedBinding == null) {
cachedBinding = new SimpleBinding(name, value);
}
return new SingleIterator(cachedBinding);
}
private static class SingleIterator implements Iterator<Binding> {
private Binding next;
public SingleIterator(Binding next) {
this.next = next;
}
@Override
public boolean hasNext() {
return next != null;
}
@Override
public Binding next() {
Binding temp = next;
next = null;
return temp;
}
}
@Override
public Set<String> getBindingNames() {
return Set.of(name);
}
@Override
public Binding getBinding(String bindingName) {
if (this.name.equals(bindingName)) {
if (cachedBinding == null) {
cachedBinding = new SimpleBinding(name, value);
}
return cachedBinding;
}
return null;
}
@Override
public boolean hasBinding(String bindingName) {
return name.equals(bindingName);
}
@Override
public Value getValue(String bindingName) {
if (name.equals(bindingName)) {
return value;
}
return null;
}
@Override
public int size() {
return 1;
}
@Override
public int hashCode() {
if (cachedHashCode == 0) {
cachedHashCode = (name.hashCode() ^ value.hashCode());
}
return cachedHashCode;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof BindingSet)) {
return false;
}
BindingSet that = (BindingSet) other;
if (this.size() != that.size()) {
return false;
}
if (this.size() == 1) {
Binding binding = iterator().next();
Binding thatBinding = that.iterator().next();
return binding.getName().equals(thatBinding.getName()) && binding.getValue().equals(thatBinding.getValue());
}
// Compare other's bindings to own
for (Binding binding : that) {
Value ownValue = getValue(binding.getName());
if (!binding.getValue().equals(ownValue)) {
// Unequal bindings for this name
return false;
}
}
return true;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(32 * size());
sb.append('[');
Iterator<Binding> iter = iterator();
while (iter.hasNext()) {
sb.append(iter.next().toString());
if (iter.hasNext()) {
sb.append(';');
}
}
sb.append(']');
return sb.toString();
}
@Override
public boolean isEmpty() {
return false;
}
}