
com.signalcollect.triplerush.JenaGraphAdapter.scala Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) 2015 Cotiviti Labs ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.signalcollect.triplerush
import org.apache.jena.graph.{ Capabilities, GraphEvents, GraphStatisticsHandler, Node, Node_ANY, Node_Blank, Node_Variable, Triple }
import org.apache.jena.graph.impl.GraphBase
import org.apache.jena.query.ARQ
import org.apache.jena.rdf.model.ModelFactory
import org.apache.jena.sparql.engine.main.StageGenerator
import org.apache.jena.util.iterator.{ ExtendedIterator, WrappedIterator }
import com.signalcollect.triplerush.sparql.NodeConversion
import com.signalcollect.triplerush.sparql.TripleRushIterator
import com.signalcollect.triplerush.sparql.TripleRushStageGenerator
import collection.JavaConversions._
/**
* A TripleRush implementation of the Jena Graph interface.
*/
trait JenaGraphAdapter extends GraphBase with GraphStatisticsHandler {
this: TripleRush =>
def getModel = ModelFactory.createModelForGraph(this)
// Set TripleRushStageGenerator as default for all queries.
val tripleRushStageGen = ARQ.getContext.get(ARQ.stageGenerator) match {
case g: TripleRushStageGenerator =>
new TripleRushStageGenerator(g.other)
case otherGraph: StageGenerator =>
new TripleRushStageGenerator(otherGraph)
case _: Any => throw new Exception("No valid stage generator found.")
}
ARQ.getContext.set(ARQ.stageGenerator, tripleRushStageGen)
def getStatistic(s: Node, p: Node, o: Node): Long = {
val q = Seq(arqNodesToPattern(s, p, o))
count(q)
}
override def createStatisticsHandler = this
/**
* Meaning of prefixes in the encoded string:
* - Everything that starts with a letter is interpreted as an IRI,
* because their schema has to start with a letter.
* - If a string starts with a digit or a hyphen, then it is interpreted as an integer literal.
* - If a string starts with `"` or "<", then it is interpreted as a general literal.
*/
override def performAdd(triple: Triple): Unit = {
addTriple(triple)
}
override def clear: Unit = {
getEventManager.notifyEvent(this, GraphEvents.removeAll)
throw new UnsupportedOperationException("TripleRush implementation does not support the `clear` operation.")
}
override def close: Unit = {
super.close
}
def graphBaseFind(triplePattern: Triple): ExtendedIterator[Triple] = {
val s = triplePattern.getSubject
val p = triplePattern.getPredicate
val o = triplePattern.getObject
val pattern = arqNodesToPattern(s, p, o)
val resultIterator = resultIteratorForQuery(Seq(pattern))
val concreteS = if (s.isConcrete) Some(NodeConversion.nodeToString(s)) else None
val concreteP = if (p.isConcrete) Some(NodeConversion.nodeToString(p)) else None
val concreteO = if (o.isConcrete) Some(NodeConversion.nodeToString(o)) else None
val convertedIterator = TripleRushIterator.convert(concreteS, concreteP, concreteO, dictionary, resultIterator)
WrappedIterator.createNoRemove(convertedIterator)
}
override def graphBaseContains(t: Triple): Boolean = {
getStatistic(t.getSubject, t.getPredicate, t.getObject) >= 1
}
override def graphBaseSize: Int = {
val wildcard = Node.ANY
val sizeAsLong = getStatistic(wildcard, wildcard, wildcard)
if (sizeAsLong <= Int.MaxValue) {
sizeAsLong.toInt
} else {
Int.MaxValue // Better than crashing?
}
}
// TODO: Make more efficient by unrolling everything.
// TODO: Does not support using the same variable/blank node multiple times. Test if this case needs to be supported.
private[this] def arqNodesToPattern(s: Node, p: Node, o: Node): TriplePattern = {
var nextVariableId = -1
@inline def nodeToId(n: Node): Int = {
n match {
case variable: Node_ANY =>
val id = nextVariableId
nextVariableId -= 1
id
case variable: Node_Variable =>
throw new UnsupportedOperationException("Variables not supported.")
case blank: Node_Blank =>
val blankNodeString = NodeConversion.nodeToString(blank)
dictionary(blankNodeString)
case other @ _ =>
val otherNodeString = NodeConversion.nodeToString(other)
dictionary(otherNodeString)
}
}
val sId = nodeToId(s)
val pId = nodeToId(p)
val oId = nodeToId(o)
TriplePattern(sId, pId, oId)
}
override val getCapabilities = new Capabilities {
val sizeAccurate = true
val addAllowed = true
def addAllowed(everyTriple: Boolean) = true
val deleteAllowed = false
def deleteAllowed(everyTriple: Boolean) = false
val iteratorRemoveAllowed = false
val canBeEmpty = true
val findContractSafe = true
val handlesLiteralTyping = false
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy