~ a tuple knows the relation it belongs to no-hierarchy
authorAlexandre Bertails <bertails@gmail.com>
Sun, 13 Feb 2011 23:02:26 -0500
branchno-hierarchy
changeset 343 b4679fb25560
parent 342 05d5a585b109
child 344 e4918c0a0e71
~ a tuple knows the relation it belongs to
directmapping/src/main/scala/DirectMapping.scala
rdb/src/main/scala/RDB.scala
--- a/directmapping/src/main/scala/DirectMapping.scala	Sun Feb 13 18:09:52 2011 -0500
+++ b/directmapping/src/main/scala/DirectMapping.scala	Sun Feb 13 23:02:26 2011 -0500
@@ -75,7 +75,7 @@
         } }  
       }
       val m = Map[CandidateKey, Map[List[CellValue], Node]]()
-      val tuples = r.body map { t => tupleToNode(t, r) }
+      val tuples = r.body map { t => tupleToNode(t) }
       tuples.foldLeft(m){ case (m, (pairs, node)) => ++(m, pairs, node) }
     }
     
@@ -85,12 +85,13 @@
      * * if there is a primary key: the constant IRI based on the actual values from the pk
      * * if no primary key: a fresh bnode
      */
-    def tupleToNode (t:Tuple, r:Relation) : (List[(CandidateKey, List[CellValue])], Node) = {
+    def tupleToNode (t:Tuple) : (List[(CandidateKey, List[CellValue])], Node) = {
+      val r:Relation = t.r
       val s:Node =
         r.pk match {
           case Some(pk) =>
             /** Table has a primkary key. */
-            NodeIRI(tupleToIRI(r, pk, t.lexvalues(pk)))
+            NodeIRI(tupleToIRI(t, pk))
           case None =>
             /** Table has no primkary key (but has some candidate keys). */
             NodeBNode(freshbnode())
@@ -112,9 +113,10 @@
        * We know this because relations with candidate keys are mapped to unique
        * subjects, and potentially redundant rows get unique blank node subjects.
        */
-      Graph(r.body flatMap { t => tupleSemantics(nodemap, r, t) })
+      Graph(r.body flatMap { t => tupleSemantics(nodemap, t) })
   
-    def tupleSemantics (nodemap:NodeMap, r:Relation, t:Tuple):Set[Triple] = {
+    def tupleSemantics (nodemap:NodeMap, t:Tuple):Set[Triple] = {
+      val r:Relation = t.r
       val s:SubjectNode =
 	// look for the first candidate key if available
         r.candidates.headOption match {
@@ -131,8 +133,8 @@
 	    SubjectNode(freshnode)
 	  }
         }
-      val fromFKs = t.references(r) map { fk => referenceSemantics(r, nodemap, t, fk) }
-      val fromLexicalValues = t.scalars(r) flatMap { a => lexicalValueSemantics(r, t, a) }
+      val fromFKs = t.references(r) map { fk => referenceSemantics(nodemap, t, fk) }
+      val fromLexicalValues = t.scalars(r) flatMap { a => lexicalValueSemantics(t, a) }
       // the relation provenance is mapped to an RDF type information, computed from the relation itself
       val fromRelation = (PredicateIRI(IRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")),
 			  ObjectNode(NodeIRI(IRI(UE(r)))))
@@ -142,7 +144,8 @@
     /**
      * a foreign key contribute to generating triples
      */
-    def referenceSemantics (r:Relation, nodes:NodeMap, t:Tuple, fk:ForeignKey):(Predicate, Object) = {
+    def referenceSemantics (nodes:NodeMap, t:Tuple, fk:ForeignKey):(Predicate, Object) = {
+      val r:Relation = t.r
       val p = referencePredicateSemantics(r, fk)
       val cellvalues:List[CellValue] = t.cellvalues(fk)
       val ForeignKey(as, target@Target(_, key)) = fk
@@ -160,7 +163,8 @@
     /**
      * a lexical value contribute to generating triples (only if it is not null)
      */
-    def lexicalValueSemantics(r:Relation, t:Tuple, a:AttrName):Option[(Predicate, Object)] = {
+    def lexicalValueSemantics(t:Tuple, a:AttrName):Option[(Predicate, Object)] = {
+      val r:Relation = t.r
       // a is implicitly promoted to an AttrList
       val p = lexicalValuePredicateSemantics(r, a)
       val cellValue = t(a)
@@ -199,9 +203,11 @@
      * - the lexicalvalues are generated from pk
      * hence, the zip operation is safe as both list have the same size
      */
-    def tupleToIRI(rn:Relation, as:AttrList, ls:List[LexicalValue]):IRI = {
-      val pairs:List[String] = as.attrs zip ls map { case (attrName, lexicalValue) => UE(attrName) + "." + UE(lexicalValue.s) }
-      IRI(UE(rn) + "/" + pairs.mkString("_") + "#_")
+    def tupleToIRI(t:Tuple, pk:AttrList):IRI = {
+      val r:Relation = t.r
+      val ls:List[LexicalValue] = t.lexvalues(pk)
+      val pairs:List[String] = pk.attrs zip ls map { case (attrName, lexicalValue) => UE(attrName) + "." + UE(lexicalValue.s) }
+      IRI(UE(r) + "/" + pairs.mkString("_") + "#_")
     }  
 
     // TODO: aren't they already part of the RDF model?
--- a/rdb/src/main/scala/RDB.scala	Sun Feb 13 18:09:52 2011 -0500
+++ b/rdb/src/main/scala/RDB.scala	Sun Feb 13 23:02:26 2011 -0500
@@ -43,6 +43,12 @@
 		      pk:Option[CandidateKey],
 		      fks:ForeignKeys) {
 
+    for {
+      t <- body
+    } {
+      t.relation = Some(this)
+    }
+
     /** adds a tuple in the body of the relation */
     def +(t:Tuple):Relation = this.copy(body = body :+ t)
     /** a relation is indexable if it has at least one candidate key */
@@ -74,6 +80,11 @@
    * especially, the order of the attribute names is not known within the tuple
    */
   case class Tuple (private val m:Map[AttrName, CellValue]) extends PartialFunction[AttrName, CellValue] {
+
+    // hack for the tuple to know the relation it belongs to
+    var relation:Option[Relation] = None
+    lazy val r:Relation = relation.get
+
     def apply (a:AttrName) = m(a)
 
     def isDefinedAt(a:AttrName) = m isDefinedAt a