~ pass 1 gen hierarchical tables test
authorEric Prud'hommeaux <eric@w3.org>
Tue, 28 Sep 2010 22:54:18 -0400
changeset 27 594065eeeedc
parent 26 7429859b958b
child 28 4e6c7a41fac0
~ pass 1 gen hierarchical tables test
src/main/scala/Main.scala
src/test/scala/Test.scala
--- a/src/main/scala/Main.scala	Tue Sep 28 18:23:51 2010 -0400
+++ b/src/main/scala/Main.scala	Tue Sep 28 22:54:18 2010 -0400
@@ -122,7 +122,18 @@
       KeyMap(m2)
     }
   }
-  type NodeMap = Map[RelName, KeyMap]
+  case class NodeMap(m:Map[RelName, KeyMap]) {
+    def apply(rn:RelName) = m(rn)
+    def ultimateReferent (rn:RelName, k:CandidateKey, vs:List[LexicalValue], db:Database) : Node = {
+      // Issue: what if fk is to a rearrangement of the pk?
+      if (db.m(rn).pk.isDefined && db.m(rn).fks.contains(db.m(rn).pk.get)) {
+	/** Table's primary key is a foreign key. */
+	val target = db.m(rn).fks(db.m(rn).pk.get)
+	ultimateReferent(target.rel, target.attrs, vs, db)
+      } else
+	m(rn)(k)(vs)
+    }
+  }
 
   // Transformation argument:
   case class StemIRI(stem:String) {
@@ -131,7 +142,7 @@
 
   // Mapping functions:
   def databasemap (u:StemIRI, db:Database) : RDFGraph = {
-    val nodes:NodeMap = db.idxables.map(rn => rn -> relation2subject(u, rn, db.m(rn))).toMap
+    val nodes = NodeMap(db.idxables.map(rn => rn -> relation2subject(u, rn, db.m(rn))).toMap)
     db.m.keySet.flatMap(rn => relationmap(u, rn, db.m(rn), nodes, db))
   }
 
@@ -147,10 +158,12 @@
     val h = header(r)
     val s:Node =
       if (r.pk.isDefined) {
+	/** Table has a primkary key. */
 	// Assume: no NULLs in primary key
 	val vs = r.pk.get.map(k => lexvalue(h, t, k).get)
 	nodemap(u, rn, r.pk.get, vs)
       } else
+	/** Table has no primkary key (but has some candidate keys). */
 	freshbnode()
     (r.candidates.map(k => {
       val values:List[CellValue] = k.map(a => t(a))
@@ -163,14 +176,21 @@
 
   def tuplemap (u:StemIRI, rn:RelName, t:Tuple, r:Relation, nodes:NodeMap, db:Database) : Set[Triple] = {
     val h = header(r)
+    val hierarchicalKey:List[AttrName] =
+      if (r.pk.isDefined && r.fks.contains(r.pk.get))
+	r.fks(r.pk.get).attrs
+      else
+	List()
+
     val s:Node =
       if (r.candidates.size > 0) { // which implies !nodes.get(rn).isDefined
 	// Known to have at least one key, so take the first one.
 	val k = r.candidates(0)
 	// Assume: no NULLs in candidate key
 	val vs = k.map(a => lexvalue(h, t, a).get)
-	nodes(rn)(k)(vs)
+	nodes.ultimateReferent(rn, k, vs, db)
       } else
+	/** Table has no candidate keys. */
 	freshbnode()
 
     val allAttrs:Set[AttrName] = h.keySet
@@ -183,11 +203,11 @@
       val int:Set[AttrName] = nulllist & a.toSet
       if (int.toList.length == 0) None else List(a)
     })
-    val scalarlist = allAttrs -- unaryFKs -- nulllist /* -- h.pk */
-    val referencelist = r.fks.keySet -- nullFKs
+    val scalarlist = allAttrs -- unaryFKs -- nulllist ++ hierarchicalKey
+    val referencelist = r.fks.keySet -- nullFKs - hierarchicalKey
 
     scalarlist.map(a => scalartriples(u, rn, s, a, h, t)) ++
-    referencelist.map(as => referencetriples(u, rn, s, as, r, t, nodes, db))
+    referencelist.map(as => referencetriples(u, rn, s, as, r, t, nodes))
 
   }
 
@@ -204,15 +224,11 @@
     val o = literalmap(l, sqlDatatype(h, a))
     Triple(s, p, o)
   }
-  def referencetriples (u:StemIRI, rn:RelName, s:Node, as:List[AttrName], r:Relation, t:Tuple, nodes:NodeMap, db:Database) : Triple = {
+  def referencetriples (u:StemIRI, rn:RelName, s:Node, as:List[AttrName], r:Relation, t:Tuple, nodes:NodeMap) : Triple = {
     val p = predicatemap (u, rn, as)
     val ls:List[LexicalValue] = as.map(a =>t(a).asInstanceOf[LexicalValue])
     val target = r.fks(as)
-    val o999 = nodemap(u, target.rel, target.attrs, ls)
     val o:Object = nodes(target.rel)(target.attrs)(ls)
-    // if (db.m(target.rel).fks.contains(target.attrs))
-    //   error("need to follow " + target.rel + target.attrs + "->" + db.m(target.rel).fks(target.attrs))
-    // println("need to follow " + target.rel + target.attrs)
     Triple(s, p, o)
   }
 
--- a/src/test/scala/Test.scala	Tue Sep 28 18:23:51 2010 -0400
+++ b/src/test/scala/Test.scala	Tue Sep 28 22:54:18 2010 -0400
@@ -294,7 +294,7 @@
 
     val expected:RDFGraph =
       Set(
-	Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Offices#ID"),TypedLiteral("8",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+	Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Offices#ID"),TypedLiteral("18",IRI("http://www.w3.org/2001/XMLSchema#int"))),
 	Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Offices#building"),TypedLiteral("32",IRI("http://www.w3.org/2001/XMLSchema#int"))),
 	Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Offices#ofcNumber"),TypedLiteral("G528",IRI("http://www.w3.org/2001/XMLSchema#string"))), 
 
@@ -306,8 +306,6 @@
 	Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Addresses#city"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
 	Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Addresses#state"),TypedLiteral("MA",IRI("http://www.w3.org/2001/XMLSchema#string")))
       )
-    println("exp:\n  " + expected.mkString("\n  "))
-    println("got:\n  " + g.mkString("\n  "))
     assert (expected === g)
   }