~ NodeMap is a real partial function no-hierarchy
authorAlexandre Bertails <bertails@gmail.com>
Sat, 12 Feb 2011 15:34:32 -0500
branchno-hierarchy
changeset 330 7f4830491c64
parent 329 d23caa599848
child 331 b13a84b588cf
~ NodeMap is a real partial function
directmapping/src/main/scala/DirectMapping.scala
--- a/directmapping/src/main/scala/DirectMapping.scala	Sat Feb 12 13:19:54 2011 -0500
+++ b/directmapping/src/main/scala/DirectMapping.scala	Sat Feb 12 15:34:32 2011 -0500
@@ -10,10 +10,12 @@
 
   trait DirectMapping {
 
-    /** A KeyMap associates the candidate key and key values with the
-     * node for any tuple in a unique relation. */
-    case class KeyMap(m:Map[CandidateKey,  Map[List[CellValue], Node]]) {
-      //def KeyMap() : KeyMap = KeyMap(Map[CandidateKey,  Map[List[CellValue], Node]]())
+    /**
+     * A KeyMap associates the candidate key and key values with the
+     * node for any tuple in a unique relation.
+     * CandidateKey -> List[CellValue] -> Node
+     */
+    case class KeyMap(private val m:Map[CandidateKey,  Map[List[CellValue], Node]]) extends PartialFunction[CandidateKey, PartialFunction[List[CellValue], Node]] {
       def apply(i:CandidateKey) : Map[List[CellValue], Node] = m(i)
       def ++(pairs:List[(CandidateKey, List[CellValue])], n:Node):KeyMap = {
         val m2:Map[CandidateKey,  Map[List[CellValue], Node]] =
@@ -29,18 +31,15 @@
           } }
         KeyMap(m2)
       }
-      def contains(ck:CandidateKey) = m contains ck
+      def isDefinedAt(ck:CandidateKey) = m isDefinedAt ck
     }
-    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 a rearrangement of the pk, per issue fk-pk-order?
-        m(rn)(k)(vs)  
-      }
-      def contains(rn:RelName) = m.contains(rn)
+
+    type NodeMap = PartialFunction[RelName, KeyMap]
+
+    def NodeMap(db:Database):NodeMap = {
+      val idxables = db.keySet filter { rn => db(rn).candidates nonEmpty }
+      idxables map { rn:RelName => rn -> relation2KeyMap(db(rn)) } toMap
     }
-    implicit def list2map (l:Set[(RelName, KeyMap)]):Map[RelName,KeyMap] = l.toMap
-    implicit def list2Nmap (l:Set[(RelName, KeyMap)]):NodeMap = NodeMap(l)
   
     /** The direct mapping requires one parameter: the StemIRI */
     case class StemIRI(stem:String) {
@@ -87,8 +86,7 @@
   
     /** The triples-generating functions start with databasemap: */
     def directDB (db:Database) : Graph = {
-      val idxables = db.keySet filter { rn => db(rn).candidates nonEmpty }
-      val nodeMap:NodeMap = idxables map { rn => rn -> relation2KeyMap(db(rn)) }
+      val nodeMap = NodeMap(db)
       Graph(db.keySet flatMap  { (rn:RelName) => directR(db(rn), nodeMap, db) })
     }
   
@@ -105,7 +103,7 @@
           // Known to have at least one key, so take the first one.
           case Some(firstKey) => {
             val vs = t.notNullLexvalues(firstKey)
-            nodes.ultimateReferent(r.name, firstKey, vs, db)
+            nodes(r.name)(firstKey)(vs)
           }
           /** Table has no candidate keys. */
           case None =>
@@ -147,9 +145,9 @@
       val p = predicatemap (r.name, fk)
       val ls:List[LexicalValue] = t.notNullLexvalues(fk)
       val ForeignKey(as, Target(rel, key)) = fk
-      if (!nodes.contains(rel))
+      if (!(nodes isDefinedAt rel))
         error("No referent relation \"" + rel + "\" to match " + r.name + t)
-      if (!nodes(rel).contains(key))
+      if (!(nodes(rel) isDefinedAt key))
         error("Relation " + rel + " has no attributes (" + key + ") to match " + r.name + t)
       if (!nodes(rel)(key).contains(ls))
         error("Relation " + rel + "(" + key + ") has no values " + ls + " to match " + r.name + t)