
org.aksw.simba.lsq.spinx.model.BgpNode Maven / Gradle / Ivy
package org.aksw.simba.lsq.spinx.model;
import java.util.Arrays;
import java.util.Set;
import org.aksw.jena_sparql_api.rdf.collections.ResourceUtils;
import org.aksw.jenax.annotation.reprogen.HashId;
import org.aksw.jenax.annotation.reprogen.Inverse;
import org.aksw.jenax.annotation.reprogen.Iri;
import org.aksw.jenax.annotation.reprogen.ResourceView;
import org.aksw.jenax.reprogen.hashid.HashIdCxt;
import org.aksw.simba.lsq.model.LsqQuery;
import org.aksw.simba.lsq.model.util.SpinCoreUtils;
import org.aksw.simba.lsq.vocab.LSQ;
import org.apache.jena.graph.Node;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
import org.spinrdf.vocabulary.SP;
import com.google.common.collect.Iterables;
import com.google.common.hash.HashCode;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
@ResourceView
public interface BgpNode
extends Resource, Labeled
{
@Iri(LSQ.Terms.hasBgpNode)
@Inverse
@HashId
Bgp getBgp();
/**
* The set of RDFNodes mentioned in a BGP of a SPIN model that denote the same RDF term.
*
* Although all referenced nodes and resources must denote the same RDF term, references
* my refer to different IRIs or blank nodes in the case of variables.
*
*
* Possible solutions:
* (1) Mark an arbitrary member of the set as the 'primary' one: Bad because on which basis to assert that?
* (2) Ensure that for each RDF term there is a canonical resource in the RDF model that can be refered to.
* This would add another layer of indirection.
*
*
* @return
*/
// @HashId
// @Range({Literal.class, SpinVar.class})
// @PolymorphicOnly({Literal.class, Var.class})
@Iri(LSQ.Terms.proxyFor)
Set getProxyFor();
/**
* Custom hashId handler because the jsa mapper currently does not support a range that
* may be literals as well as subclasses of resource. Literals are literals (so there is no problem) but
* we currently cannot tell the mapper that in case of Resource it should try a specific set of classes
* (a SPIN Variable in this specific case) and use appropriate's class associated id generation mechanism.
*
* Once the @Range annotation is working, we can remove this custom handler
*
* @param cxt
* @return
*/
@HashId
default HashCode getHashId(HashIdCxt cxt) {
HashFunction hashFn = cxt.getHashFunction();
Set proxies = getProxyFor();
// The set of proxy nodes either contains:
// - a single literal
// - a single IRI
// - several resources which all have the same value for the sp:varName attribute
RDFNode literalOrIriOrSpinVar = Iterables.getFirst(proxies, null);
RDFNode literal;
if(literalOrIriOrSpinVar == null) {
literal = null;
} else if(literalOrIriOrSpinVar.isLiteral()) {
literal = literalOrIriOrSpinVar;
} else { // if(pick.isResource()) {
literal = ResourceUtils.getPropertyValue(literalOrIriOrSpinVar.asResource(), SP.varName);
if(literal == null) {
if(literalOrIriOrSpinVar.isURIResource()) {
Model model = getModel();
// 'iri:' prefix to reduce change of clash with an IRI in a literal such as "http://foo.bar"
literal = model.createLiteral("iri:" + literalOrIriOrSpinVar.asResource().getURI());
} else {
throw new IllegalStateException("Proxy reference for a BgpNode must be either a literal or a resource with a SP.varName attribute or an IRI; got: " + literalOrIriOrSpinVar);
}
}
}
HashCode nodeHash = literal == null
? hashFn.hashInt(0)
: cxt.getGlobalProcessor().apply(literal, cxt);
if(literalOrIriOrSpinVar.isResource() && cxt.getHashId(literalOrIriOrSpinVar) == null /* TODO maybe use !isProcessed? */) {
cxt.putHashId(literal, nodeHash);
// cxt.putString(actual, "var-" + actual.asLiteral().getString());
}
Bgp bgp = getBgp();
HashCode bgpHash = cxt.getHashId(bgp);
HashCode result = Hashing.combineUnordered(Arrays.asList(bgpHash, nodeHash));
return result;
}
// @StringId
// String getStringId(HashIdCxt cxt) {
// return "
// }
// TODO These two methods should by mapped by DirectedHyperEdge
@Iri(LSQ.Terms.in)
Set getInEdges();
@Iri(LSQ.Terms.out)
Set getOutEdges();
// @Iri(LSQ.Strs.hasJoinVarExec)
// Set getJoinRestrictedSelectivities();
@Iri(LSQ.Terms.hasExec)
Set getBgpNodeExecs();
/**
* A resource for the subset of bgp's triple patterns in which the the BGPNode occurs.
* The identity should be allocated based on the set of the involved triple patterns' identities.
*
* @return
*/
@Iri(LSQ.Terms.hasSubBgp)
Bgp getSubBgp();
BgpNode setSubBgp(Bgp subBgp);
/**
* The resource that corresponds to the query
* SELECT COUNT(DISTINCT joinVar) WHERE subBGP
*
* @return
*/
@Iri(LSQ.Terms.joinExtensionQuery)
LsqQuery getJoinExtensionQuery();
BgpNode setJoinExtensionQuery(Resource joinExtensionQuery);
public default Node toJenaNode() {
Set set = getProxyFor();
if(set.isEmpty()) {
throw new RuntimeException("toJenaNode() requires non-empty set of referenced RDF terms");
}
RDFNode node = set.iterator().next();
Node result = SpinCoreUtils.readNode(node);
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy