--- a/src/main/scala/SparqlToSparql.scala Mon Feb 08 12:52:08 2010 -0500
+++ b/src/main/scala/SparqlToSparql.scala Mon Feb 08 15:19:02 2010 -0500
@@ -59,6 +59,13 @@
}
}
case class Bindings (b:Map[sparql.Construct, List[Map[sparql.Var, sparql.Term]]]) {
+ def countEditions () = {
+ var count = 0
+ b.map((constructlist) =>
+ constructlist._2.map((_) =>
+ count = count + 1))
+ count
+ }
def toGraphPattern ():sparql.GraphPattern = {
var conjNo = 0
val conjuncts = b.foldLeft(List[sparql.GraphPattern]())((conj, constructlist) => {
@@ -89,40 +96,58 @@
if (b.contains(construct)) this
else Bindings(b + (construct -> List[Map[sparql.Var, sparql.Term]]()))
}
- // val varsS:Option[Bindings] = vars.maybeRebind(construct, v, to)
- def maybeBind (construct:sparql.Construct, v:sparql.Term, to:sparql.Term):Option[Bindings] = {
- v match {
- case v:sparql.TermVar =>
- if (b(construct).size > 0 && b(construct)(0).contains(v.v)) {
- println(v.v + ":" + b(construct)(0)(v.v) + " == " + to + " => " + (to == b(construct)(0)(v.v)))
- if (to == b(construct)(0)(v.v)) Some(this) // !!! iterate on 0
- else None
+ // val varsS:Option[Bindings] = vars.maybeRebind(construct, v, tos)
+ // b:Map[sparql.Construct, List[Map[sparql.Var, sparql.Term]]]
+ def mustBind (construct:sparql.Construct, vs:sparql.Term, tos:sparql.Term, vo:sparql.Term, too:sparql.Term):Bindings = {
+ /* rediculous traversal for the first viably matching rule edition. */
+ var matched = false
+ val existing:List[Map[sparql.Var, sparql.Term]] = b(construct).map((map) => {
+ def _matches (l:sparql.Term, r:sparql.Term):Boolean = {
+ l match {
+ case v:sparql.TermVar =>
+ if (map.contains(v.v)) {
+ if (r == map(v.v)) true
+ else false
+ } else {
+ true
+ }
+ case u:sparql.TermUri =>
+ if (r == u.u) true
+ else false
+ case l:sparql.TermLit =>
+ if (r == l.lit) true
+ else false
+ }
+ }
+ val sMatches = _matches(vs, tos)
+ val oMatches = _matches(vo, too)
+
+ if (sMatches & oMatches) {
+ matched = true
+ map + (vs.asInstanceOf[sparql.TermVar].v -> tos) + (vo.asInstanceOf[sparql.TermVar].v -> too)
+ } else
+ map
+ })
+ if (matched)
+ Bindings(b + (construct -> existing))
+ else {
+ Bindings(b.map((constructlist) => {
+ val (oldConstr, l) = constructlist
+ if (oldConstr == construct) {
+ val ent = Map[sparql.Var, sparql.Term](vs.asInstanceOf[sparql.TermVar].v -> tos,
+ vo.asInstanceOf[sparql.TermVar].v -> too)
+ val list = l ++ List(ent)
+ (construct -> list)
} else {
- val old = if (b(construct).size > 0) b(construct)(0)
- else Map[sparql.Var, sparql.Term]()
- println(v.v + " unbound in " + old)
- val m:Map[sparql.Var, sparql.Term] = old ++ Map(v.v -> to)
- Some(Bindings(b + (construct -> List(m))))
+ (oldConstr -> l)
}
- case u:sparql.TermUri =>
- if (to == u.u) Some(this)
- else None
- case l:sparql.TermLit =>
- if (to == l.lit) Some(this)
- else None
+ }))
}
}
}
def createEmptyBindings () = Bindings(Map[sparql.Construct, List[Map[sparql.Var, sparql.Term]]]())
case class RuleMap (rules:Map[sparql.Uri, List[HornRule]]) {
- override def toString = "RuleMap(Map(" + rules.map((ent) => {
- val (u, l) = ent
- "\"" + _shorten(u.toString) + "\" -> List(" + l.map((hr) => {
- _shorten(hr.toString).replace("\n", "\n ")
- }).mkString("\n ", ",\n ", "") + ")"
- }).mkString("\n ", ",\n ", "") + "))"
-
def transform (prove:List[sparql.TriplePattern], used:Set[sparql.TriplePattern], varsP:Bindings):Bindings = {
val _pad = used.foldLeft("")((s, x) => s + " ")
def _deepPrint (s:String):Unit = { println(used.size + ":" + _pad + s.replace("\n", "\n" + _pad)) }
@@ -134,7 +159,7 @@
val car = prove(0)
val cdr = prove.filterNot (_ == car)
_deepPrint("RuleMap.transform(" + _shorten(car.toString) + ", " + varsP.toString + ")")
- val ret = car.p match {
+ val xform = car.p match {
case sparql.TermUri(u) =>
// for each rule that supplies predicate u
var _ruleNo = 0;
@@ -144,28 +169,35 @@
_deepPrint1(_prefix, "trying " + _shorten(hornRule.trigger.toString))
val vars = varsP.ensureGraphPattern(hornRule.construct)
// try matching the subject
- val varsS:Option[Bindings] = vars.maybeBind(hornRule.construct, hornRule.trigger.s, car.s)
- val ret:Bindings = if (varsS.isDefined) {
- // try matching the object
- val varsO:Option[Bindings] = varsS.get.maybeBind(hornRule.construct, hornRule.trigger.o, car.o)
- if (varsO.isDefined) {
- if (cdr.size > 0) {
- transform(cdr, used + car, varsO.get)
- } else {
- _deepPrint1("match!", _shorten(hornRule.trigger.toString) + "(" + _shorten(car.toString) + ") matches with " + _shorten(varsO.get.toString))
- varsO.get
- }
- } else createEmptyBindings
- } else createEmptyBindings
+ val varss:Bindings = vars.mustBind(hornRule.construct, hornRule.trigger.s, car.s, hornRule.trigger.o, car.o)
+ val ret =
+ if (cdr.size > 0) {
+ transform(cdr, used + car, varss)
+ } else {
+ _deepPrint1("match!", _shorten(hornRule.trigger.toString) + "(" + _shorten(car.toString) + ") matches with " + _shorten(varss.toString))
+ varss
+ }
_deepPrint1(_prefix, _shorten(hornRule.trigger.toString) + "(" + _shorten(car.toString) + ") matches ..." + bindings.toString + ret.toString)
- if (ret.b.size > bindings.b.size) ret
+
+ /* Magic Huristics */
+ if (bindings.countEditions == 0) ret
+ else if (ret.countEditions == 0) bindings
+ else if (ret.countEditions < bindings.countEditions) ret
else bindings
})
case _ => error("not implemented: " + car.p)
}
- _deepPrint("RuleMap.transform(" + _shorten(car.toString) + ") => " + _shorten(ret.toString))
- ret
+ _deepPrint("RuleMap.transform(" + _shorten(car.toString) + ") => " + _shorten(xform.toString))
+ xform
}
+
+ override def toString = "RuleMap(Map(" + rules.map((ent) => {
+ val (u, l) = ent
+ "\"" + _shorten(u.toString) + "\" -> List(" + l.map((hr) => {
+ _shorten(hr.toString).replace("\n", "\n ")
+ }).mkString("\n ", ",\n ", "") + ")"
+ }).mkString("\n ", ",\n ", "") + "))"
+
}
def mapGraphPattern (gp:sparql.GraphPattern, ruleMap:RuleMap):sparql.GraphPattern = {
--- a/src/test/scala/SparqlToSparqlTest.scala Mon Feb 08 12:52:08 2010 -0500
+++ b/src/test/scala/SparqlToSparqlTest.scala Mon Feb 08 15:19:02 2010 -0500
@@ -129,50 +129,53 @@
assert(transformed === expected)
}
-// test("trans head") {
-// val sparqlParser = Sparql()
-// val query = sparqlParser.parseAll(sparqlParser.select, """
-// PREFIX foaf : <http://xmlns.com/foaf/0.1/>
-// PREFIX xsd : <http://www.w3.org/2001/XMLSchema#>
-// SELECT ?lname {
-// ?who foaf:last_name ?lname .
-// ?who foaf:knows ?whom .
-// ?whom foaf:knows ?whom2 .
-// ?whom2 foaf:last_name "Smith"^^xsd:string }
-// """).get
-// val rule1 = sparqlParser.parseAll(sparqlParser.construct, """
-// PREFIX foaf : <http://xmlns.com/foaf/0.1/>
-// PREFIX empP : <http://hr.example/DB/Employee#>
-// PREFIX task : <http://hr.example/DB/Task#>
-// CONSTRUCT { ?emp foaf:last_name ?wname .
-// ?emp foaf:knows ?man .
-// ?man foaf:last_name ?mname }
-// WHERE { ?emp empP:lastName ?wname .
-// ?pair task:drone ?emp .
-// ?pair task:manager ?man .
-// ?man empP:lastName ?mname }
-// """).get
-// SparqlToSparql.Abbreviations.update("<http://xmlns.com/foaf/0.1/last_name>", "foaf:last_name")
-// SparqlToSparql.Abbreviations.update("<http://xmlns.com/foaf/0.1/knows>", "foaf:knows")
-// SparqlToSparql.Abbreviations.update("<http://hr.example/DB/Employee#lastName>", "Employee:lastName")
-// SparqlToSparql.Abbreviations.update("<http://hr.example/DB/Task#drone>", "Task:drone")
-// SparqlToSparql.Abbreviations.update("<http://hr.example/DB/Task#manager>", "Task:manager")
-// SparqlToSparql.Abbreviations.update("^^http://www.w3.org/2001/XMLSchema#string", "")
+ test("trans head") {
+ val sparqlParser = Sparql()
+ val query = sparqlParser.parseAll(sparqlParser.select, """
+PREFIX foaf : <http://xmlns.com/foaf/0.1/>
+PREFIX xsd : <http://www.w3.org/2001/XMLSchema#>
+SELECT ?lname {
+ ?who foaf:last_name ?lname .
+ ?who foaf:knows ?whom .
+ ?whom foaf:knows ?whom2 .
+ ?whom2 foaf:last_name "Smith"^^xsd:string }
+""").get
+ val rule1 = sparqlParser.parseAll(sparqlParser.construct, """
+PREFIX foaf : <http://xmlns.com/foaf/0.1/>
+PREFIX empP : <http://hr.example/DB/Employee#>
+PREFIX task : <http://hr.example/DB/Task#>
+CONSTRUCT { ?emp foaf:last_name ?wname .
+ ?emp foaf:knows ?man .
+ ?man foaf:last_name ?mname }
+ WHERE { ?emp empP:lastName ?wname .
+ ?pair task:drone ?emp .
+ ?pair task:manager ?man .
+ ?man empP:lastName ?mname }
+""").get
+ SparqlToSparql.Abbreviations.update("<http://xmlns.com/foaf/0.1/last_name>", "foaf:last_name")
+ SparqlToSparql.Abbreviations.update("<http://xmlns.com/foaf/0.1/knows>", "foaf:knows")
+ SparqlToSparql.Abbreviations.update("<http://hr.example/DB/Employee#lastName>", "Employee:lastName")
+ SparqlToSparql.Abbreviations.update("<http://hr.example/DB/Task#drone>", "Task:drone")
+ SparqlToSparql.Abbreviations.update("<http://hr.example/DB/Task#manager>", "Task:manager")
+ SparqlToSparql.Abbreviations.update("^^http://www.w3.org/2001/XMLSchema#string", "")
-// val transformed = SparqlToSparql(query, List(rule1))
-// val expected = sparqlParser.parseAll(sparqlParser.select, """
-// PREFIX empP : <http://hr.example/DB/Employee#>
-// PREFIX task : <http://hr.example/DB/Task#>
-// PREFIX xsd : <http://www.w3.org/2001/XMLSchema#>
-// SELECT ?lname
-// { ?who empP:lastName ?lname .
-// ?pair task:drone ?who .
-// ?pair task:manager ?whom .
-// ?pair2 task:drone ?whom .
-// ?pair2 task:manager ?whom2 .
-// ?whom2 empP:lastName "Smith"^^xsd:string }
-// """).get
-// assert(transformed === expected)
-// }
+ val transformed = SparqlToSparql(query, List(rule1))
+ val expected = sparqlParser.parseAll(sparqlParser.select, """
+PREFIX empP : <http://hr.example/DB/Employee#>
+PREFIX task : <http://hr.example/DB/Task#>
+PREFIX xsd : <http://www.w3.org/2001/XMLSchema#>
+SELECT ?lname
+ {{?who empP:lastName ?lname .
+ ?_0_pair task:drone ?who .
+ ?_0_pair task:manager ?whom .
+ ?whom empP:lastName ?_0_mname }
+ {?whom empP:lastName ?_1_wname .
+ ?_1_pair task:drone ?whom .
+ ?_1_pair task:manager ?whom2 .
+ ?whom2 empP:lastName "Smith"^^xsd:string }
+ }
+""").get
+ assert(transformed === expected)
+ }
}