imported tip (bertails's updates 2010-11-26)
authorEric Prud'hommeaux <eric@w3.org>
Fri, 26 Nov 2010 13:12:43 -0500
changeset 277 d98482ca5bc3
parent 276 ee19c1656227 (current diff)
parent 274 ea4aabb5ebec (diff)
child 278 8626490ef8d1
imported tip (bertails's updates 2010-11-26)
.hgignore
--- a/.hgignore	Thu Nov 04 13:56:35 2010 -0400
+++ b/.hgignore	Fri Nov 26 13:12:43 2010 -0500
@@ -10,6 +10,7 @@
 *~
 *.class
 *.log
+*.orig
 \#*
 .\#*
 ^project/plugins/project/build\.properties$
--- a/directmapping/src/main/scala/DirectMapping.scala	Thu Nov 04 13:56:35 2010 -0400
+++ b/directmapping/src/main/scala/DirectMapping.scala	Fri Nov 26 13:12:43 2010 -0500
@@ -88,20 +88,20 @@
   }
 
   /** The NodeMap-generating functions: */
-  def relation2KeyMap (u:StemIRI, r:Relation) : KeyMap = {
+  def relation2KeyMap (r:Relation) : KeyMap = {
     val m = KeyMap(Map[CandidateKey, Map[List[CellValue], Node]]())
     r.body.foldLeft(m)((m, t) => {
-      val (pairs, node) = rdfNodeForTuple(u, t, r)
+      val (pairs, node) = rdfNodeForTuple(t, r)
       m ++ (pairs, node)
     })
   }
 
-  def rdfNodeForTuple (u:StemIRI, t:Tuple, r:Relation) : (List[(CandidateKey, List[CellValue])], Node) = {
+  def rdfNodeForTuple (t:Tuple, r:Relation) : (List[(CandidateKey, List[CellValue])], Node) = {
     val s:Node =
       if (r.pk.isDefined) {
 	/** Table has a primkary key. */
 	val vs = t.lexvaluesNoNulls(r.pk.get.attrs)
-	nodemap(u, r.name, r.pk.get.attrs, vs)
+	nodemap(r.name, r.pk.get.attrs, vs)
       } else
 	/** Table has no primkary key (but has some candidate keys). */
 	freshbnode()
@@ -112,20 +112,20 @@
   }
 
   /** The triples-generating functions start with databasemap: */
-  def directDB (u:StemIRI, db:Database) : Graph = {
+  def directDB (db:Database) : Graph = {
     val idxables = db.keySet.toSet filter { rn => !db(rn).candidates.isEmpty }
-    val nodeMap:NodeMap = idxables map {rn => rn -> relation2KeyMap(u, db(rn))}
-    db.keySet.toSet.flatMap((rn:RelName) => directR(u, db(rn), nodeMap, db))
+    val nodeMap:NodeMap = idxables map {rn => rn -> relation2KeyMap(db(rn))}
+    db.keySet.toSet.flatMap((rn:RelName) => directR(db(rn), nodeMap, db))
   }
 
-  def directR (u:StemIRI, r:Relation, nodes:NodeMap, db:Database) : Graph =
+  def directR (r:Relation, nodes:NodeMap, db:Database) : Graph =
     /* flatMap.toSet assumes that no two triples from directT would be the same.
      * We know this because relations with candidate keys are mapped to unique
      * subjects, and potentially redundant rows get unique blank node subjects.
      */
-    r.body.flatMap(t => directT(u, t, r, nodes, db)).toSet
+    r.body.flatMap(t => directT(t, r, nodes, db)).toSet
 
-  def directT (u:StemIRI, t:Tuple, r:Relation, nodes:NodeMap, db:Database) : Set[Triple] = {
+  def directT (t:Tuple, r:Relation, nodes:NodeMap, db:Database) : Set[Triple] = {
     val s:Node =
       if (r.candidates.size > 0) {
 	// Known to have at least one key, so take the first one.
@@ -135,12 +135,12 @@
       } else
 	/** Table has no candidate keys. */
 	freshbnode()
-    directS(u, s, t, r, nodes, db)
+    directS(s, t, r, nodes, db)
   }
 
-  def directS (u:StemIRI, s:Node, t:Tuple, r:Relation, nodes:NodeMap, db:Database) : Set[Triple] = {
-    references(t, r).map(as => directN(u, s, as, r, t, nodes)) ++
-    scalars(t, r).map(a => directL(u, r.name, s, a, r.header, t))
+  def directS (s:Node, t:Tuple, r:Relation, nodes:NodeMap, db:Database) : Set[Triple] = {
+    references(t, r).map(as => directN(s, as, r, t, nodes)) ++
+    scalars(t, r).map(a => directL(r.name, s, a, r.header, t))
   }
 
   var NextBNode = 97
@@ -150,14 +150,14 @@
     BNode(ret.toChar.toString)
   }
 
-  def directL (u:StemIRI, rn:RelName, s:Node, a:AttrName, h:Header, t:Tuple) : Triple = {
-    val p = predicatemap (u, rn, List(a))
+  def directL (rn:RelName, s:Node, a:AttrName, h:Header, t:Tuple) : Triple = {
+    val p = predicatemap (rn, List(a))
     val l = t.lexvalue(a).get
     val o = literalmap(l, h.sqlDatatype(a))
     Triple(s, p, o)
   }
-  def directN (u:StemIRI, s:Node, as:List[AttrName], r:Relation, t:Tuple, nodes:NodeMap) : Triple = {
-    val p = predicatemap (u, r.name, as)
+  def directN (s:Node, as:List[AttrName], r:Relation, t:Tuple, nodes:NodeMap) : Triple = {
+    val p = predicatemap (r.name, as)
     val ls:List[LexicalValue] = t.lexvaluesNoNulls(as)
     val target = r.fks(as)
     if (!nodes.contains(target.rel))
@@ -174,13 +174,13 @@
   implicit def relName2string (rn:RelName) = rn.n
   implicit def attrName2string (rn:AttrName) = rn.n
 
-  def nodemap (u:StemIRI, rn:RelName, as:List[AttrName], ls:List[LexicalValue]) : IRI = {
+  def nodemap (rn:RelName, as:List[AttrName], ls:List[LexicalValue]) : IRI = {
     val pairs:List[String] = as.zip(ls).map(x => UE(x._1) + "." + UE(x._2.s))
-    u + ("/" + UE(rn) + "/" + pairs.mkString("_") + "#_")
+    IRI(UE(rn) + "/" + pairs.mkString("_") + "#_")
   }
 
-  def predicatemap (u:StemIRI, rn:RelName, as:List[AttrName]) : IRI =
-    u + ("/" + UE(rn) + "#" + as.mkString("_"))
+  def predicatemap (rn:RelName, as:List[AttrName]) : IRI =
+    IRI(UE(rn) + "#" + as.mkString("_"))
 
   def XSD (d:Datatype) : IRI =
     d match {
--- a/directmapping/src/test/scala/DirectMappingTest.scala	Thu Nov 04 13:56:35 2010 -0400
+++ b/directmapping/src/test/scala/DirectMappingTest.scala	Fri Nov 26 13:12:43 2010 -0500
@@ -2,247 +2,35 @@
 
 import org.w3.sw.rdf._
 import org.w3.sw.rdb.RDB._
-import org.w3.sw.sql.SqlParser
+import org.w3.sw.sql
 import org.w3.sw.directmapping.DirectMapping._
 
 import org.scalatest.FunSuite
 
 class Test extends FunSuite {
 
+  import DirectMappingSpec._
+
   implicit def l2db (rs:List[Relation]):Map[RelName, Relation] =
     rs.map(r => (r.name -> r)).toMap
   implicit def string2relName (n:String) = RelName(n)
   implicit def string2attrName (n:String) = AttrName(n)
 
-  test("2 People 1 Addresses") {
-
-    val p = SqlParser()
-    val s = """
-CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
-INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
-CREATE TABLE People (ID INT PRIMARY KEY, fname STRING, addr INT, FOREIGN KEY (addr) REFERENCES Addresses(ID));
-INSERT INTO People (ID, fname, addr) VALUES (7, "Bob", 18);
-INSERT INTO People (ID, fname, addr) VALUES (8, "Sue", NULL);
-"""
-    val db = p.parseAll(p.ddl, s).get
-    val g = directDB(StemIRI("http://foo.example/DB"), db)
-
-    val expected:Graph =
-      Set(
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#ID"),TypedLiteral("7",IRI("http://www.w3.org/2001/XMLSchema#int"))),
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#fname"),TypedLiteral("Bob",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#addr"),IRI("http://foo.example/DB/Addresses/ID.18#_")),
-	Triple(IRI("http://foo.example/DB/People/ID.8#_"),IRI("http://foo.example/DB/People#ID"),TypedLiteral("8",IRI("http://www.w3.org/2001/XMLSchema#int"))),
-	Triple(IRI("http://foo.example/DB/People/ID.8#_"),IRI("http://foo.example/DB/People#fname"),TypedLiteral("Sue",IRI("http://www.w3.org/2001/XMLSchema#string"))), 
-
-	Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Addresses#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/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")))
-      )
-    assert (expected === g)
-  }
-
-
-  test("2 People 1 Addresses 1 Department") {
-
-    val p = SqlParser()
-    val s = """
-CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
-INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
-CREATE TABLE Department (ID INT PRIMARY KEY, name STRING, city STRING,
-                         manager INT, FOREIGN KEY (manager) REFERENCES People(ID), UNIQUE (name, city));
-INSERT INTO Department (ID, name, city, manager) VALUES (23, "accounting", "Cambridge", 8);
-CREATE TABLE People (ID INT PRIMARY KEY, fname STRING,
-                     addr INT, FOREIGN KEY (addr) REFERENCES Addresses(ID),
-                     deptName STRING, deptCity STRING, FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
-INSERT INTO People (ID, fname, addr, deptName, deptCity) VALUES (7, "Bob", 18, "accounting", "Cambridge");
-INSERT INTO People (ID, fname, addr, deptName, deptCity) VALUES (8, "Sue", NULL, NULL, NULL);
-"""
-    val db = p.parseAll(p.ddl, s).get
-    val g = directDB(StemIRI("http://foo.example/DB"), db)
-
-    val expected:Graph =
-      Set(
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#deptName"),TypedLiteral("accounting",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#deptCity"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#deptName_deptCity"),IRI("http://foo.example/DB/Department/ID.23#_")),
-
-	Triple(IRI("http://foo.example/DB/Department/ID.23#_"),IRI("http://foo.example/DB/Department#ID"),TypedLiteral("23",IRI("http://www.w3.org/2001/XMLSchema#int"))),
-	Triple(IRI("http://foo.example/DB/Department/ID.23#_"),IRI("http://foo.example/DB/Department#name"),TypedLiteral("accounting",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/Department/ID.23#_"),IRI("http://foo.example/DB/Department#city"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/Department/ID.23#_"),IRI("http://foo.example/DB/Department#manager"),IRI("http://foo.example/DB/People/ID.8#_")),
-
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#ID"),TypedLiteral("7",IRI("http://www.w3.org/2001/XMLSchema#int"))),
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#fname"),TypedLiteral("Bob",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#addr"),IRI("http://foo.example/DB/Addresses/ID.18#_")),
-	Triple(IRI("http://foo.example/DB/People/ID.8#_"),IRI("http://foo.example/DB/People#ID"),TypedLiteral("8",IRI("http://www.w3.org/2001/XMLSchema#int"))),
-	Triple(IRI("http://foo.example/DB/People/ID.8#_"),IRI("http://foo.example/DB/People#fname"),TypedLiteral("Sue",IRI("http://www.w3.org/2001/XMLSchema#string"))), 
-
-	Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Addresses#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/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")))
-      )
-    assert (expected === g)
-  }
-
-
-  test("2 People 1 Addresses 1 Department 2 Projects 1 Task") {
-
-    val p = SqlParser()
-    val s = """
-CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
-INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
-CREATE TABLE Department (ID INT PRIMARY KEY, name STRING, city STRING, manager INT,
-                         FOREIGN KEY (manager) REFERENCES People(ID),
-                         UNIQUE (name, city));
-INSERT INTO Department (ID, name, city, manager) VALUES (23, "accounting", "Cambridge", 8);
-CREATE TABLE People (ID INT PRIMARY KEY, fname STRING, addr INT,
-                     FOREIGN KEY (addr) REFERENCES Addresses(ID),
-                     deptName STRING, deptCity STRING,
-                     FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
-INSERT INTO People (ID, fname, addr, deptName, deptCity) VALUES (7, "Bob", 18, "accounting", "Cambridge");
-INSERT INTO People (ID, fname, addr, deptName, deptCity) VALUES (8, "Sue", NULL, NULL, NULL);
-CREATE TABLE Projects (lead INT,
-                       FOREIGN KEY (lead) REFERENCES People(ID),
-                       name STRING, UNIQUE (lead, name), 
-                       deptName STRING, deptCity STRING,
-                       UNIQUE (name, deptName, deptCity),
-                       FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
-INSERT INTO Projects (lead, name, deptName, deptCity) VALUES (8, "pencil survey", "accounting", "Cambridge");
-INSERT INTO Projects (lead, name, deptName, deptCity) VALUES (8, "eraser survey", "accounting", "Cambridge");
-CREATE TABLE TaskAssignments (worker INT,
-                              FOREIGN KEY (worker) REFERENCES People(ID),
-                              project STRING, PRIMARY KEY (worker, project), 
-                              deptName STRING, deptCity STRING,
-                              FOREIGN KEY (worker) REFERENCES People(ID),
-                              FOREIGN KEY (project, deptName, deptCity) REFERENCES Projects(name, deptName, deptCity),
-                              FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
-INSERT INTO TaskAssignments (worker, project, deptName, deptCity) VALUES (7, "pencil survey", "accounting", "Cambridge");
-"""
-    val db = p.parseAll(p.ddl, s).get
-    val g = directDB(StemIRI("http://foo.example/DB"), db)
+  def testDirectMapping(testName:String, db:Database, expectedGraph:Graph) =
+    test(testName) {
+      val computedGraph = directDB(db)
+      assert (expectedGraph === computedGraph)
+    }
 
-    val expected:Graph =
-      Set(
-	Triple(BNode("a"), IRI("http://foo.example/DB/Projects#lead"), IRI("http://foo.example/DB/People/ID.8#_")),
-	Triple(BNode("a"), IRI("http://foo.example/DB/Projects#name"), TypedLiteral("pencil survey", IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(BNode("a"), IRI("http://foo.example/DB/Projects#deptName"), TypedLiteral("accounting", IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(BNode("a"), IRI("http://foo.example/DB/Projects#deptCity"), TypedLiteral("Cambridge", IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(BNode("a"), IRI("http://foo.example/DB/Projects#deptName_deptCity"), IRI("http://foo.example/DB/Department/ID.23#_")),
-
-	Triple(BNode("b"), IRI("http://foo.example/DB/Projects#lead"), IRI("http://foo.example/DB/People/ID.8#_")),
-	Triple(BNode("b"), IRI("http://foo.example/DB/Projects#name"), TypedLiteral("eraser survey", IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(BNode("b"), IRI("http://foo.example/DB/Projects#deptName"), TypedLiteral("accounting", IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(BNode("b"), IRI("http://foo.example/DB/Projects#deptCity"), TypedLiteral("Cambridge", IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(BNode("b"), IRI("http://foo.example/DB/Projects#deptName_deptCity"), IRI("http://foo.example/DB/Department/ID.23#_")),
-
-	Triple(IRI("http://foo.example/DB/TaskAssignments/worker.7_project.pencil+survey#_"), IRI("http://foo.example/DB/TaskAssignments#worker"), IRI("http://foo.example/DB/People/ID.7#_")),
-	Triple(IRI("http://foo.example/DB/TaskAssignments/worker.7_project.pencil+survey#_"), IRI("http://foo.example/DB/TaskAssignments#project"), TypedLiteral("pencil survey", IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/TaskAssignments/worker.7_project.pencil+survey#_"), IRI("http://foo.example/DB/TaskAssignments#deptName"), TypedLiteral("accounting", IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/TaskAssignments/worker.7_project.pencil+survey#_"), IRI("http://foo.example/DB/TaskAssignments#deptCity"), TypedLiteral("Cambridge", IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/TaskAssignments/worker.7_project.pencil+survey#_"), IRI("http://foo.example/DB/TaskAssignments#deptName_deptCity"), IRI("http://foo.example/DB/Department/ID.23#_")),
-	Triple(IRI("http://foo.example/DB/TaskAssignments/worker.7_project.pencil+survey#_"), IRI("http://foo.example/DB/TaskAssignments#project_deptName_deptCity"), BNode("a")),
-
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#deptName"),TypedLiteral("accounting",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#deptCity"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#deptName_deptCity"),IRI("http://foo.example/DB/Department/ID.23#_")),
-
-	Triple(IRI("http://foo.example/DB/Department/ID.23#_"),IRI("http://foo.example/DB/Department#ID"),TypedLiteral("23",IRI("http://www.w3.org/2001/XMLSchema#int"))),
-	Triple(IRI("http://foo.example/DB/Department/ID.23#_"),IRI("http://foo.example/DB/Department#name"),TypedLiteral("accounting",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/Department/ID.23#_"),IRI("http://foo.example/DB/Department#city"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/Department/ID.23#_"),IRI("http://foo.example/DB/Department#manager"),IRI("http://foo.example/DB/People/ID.8#_")),
-
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#ID"),TypedLiteral("7",IRI("http://www.w3.org/2001/XMLSchema#int"))),
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#fname"),TypedLiteral("Bob",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#addr"),IRI("http://foo.example/DB/Addresses/ID.18#_")),
-	Triple(IRI("http://foo.example/DB/People/ID.8#_"),IRI("http://foo.example/DB/People#ID"),TypedLiteral("8",IRI("http://www.w3.org/2001/XMLSchema#int"))),
-	Triple(IRI("http://foo.example/DB/People/ID.8#_"),IRI("http://foo.example/DB/People#fname"),TypedLiteral("Sue",IRI("http://www.w3.org/2001/XMLSchema#string"))), 
-
-	Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Addresses#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/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")))
-      )
-    assert (expected === g)
-  }
-
-
-  test("1 People 1 Addresses 1 Offices") {
+  testDirectMapping("2 People 1 Addresses", db_emp_adder, directgraph_emp_adder)
 
-    val p = SqlParser()
-    val s = """
-CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
-INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
-CREATE TABLE People (ID INT PRIMARY KEY, fname STRING, addr INT,
-                     FOREIGN KEY (addr) REFERENCES Addresses(ID));
-INSERT INTO People (ID, fname, addr) VALUES (7, "Bob", 18);
-CREATE TABLE Offices (ID INT PRIMARY KEY,
-                      building INT, ofcNumber STRING,
-                      FOREIGN KEY (ID) REFERENCES Addresses(ID));
-INSERT INTO Offices (ID, building, ofcNumber) VALUES (18, 32, "G528");
-"""
-    val db = p.parseAll(p.ddl, s).get
-    val g = directDB(StemIRI("http://foo.example/DB"), db)
-
-    val expected:Graph =
-      Set(
-	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"))), 
-
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#ID"),TypedLiteral("7",IRI("http://www.w3.org/2001/XMLSchema#int"))),
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#fname"),TypedLiteral("Bob",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#addr"),IRI("http://foo.example/DB/Addresses/ID.18#_")),
-
-	Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Addresses#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/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")))
-      )
-    assert (expected === g)
-  }
-
-
-  test("1 People 1 Addresses 1 Offices 1 ExectutiveOffices") {
+  testDirectMapping("2 People 1 Addresses 1 Department", db_multi_key, directgraph_multi_key)
 
-    val p = SqlParser()
-    val s = """
-CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
-INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
-CREATE TABLE People (ID INT PRIMARY KEY, fname STRING, addr INT,
-                     FOREIGN KEY (addr) REFERENCES Addresses(ID));
-INSERT INTO People (ID, fname, addr) VALUES (7, "Bob", 18);
-CREATE TABLE Offices (ID INT PRIMARY KEY,
-                      building INT, ofcNumber STRING,
-                      FOREIGN KEY (ID) REFERENCES Addresses(ID));
-INSERT INTO Offices (ID, building, ofcNumber) VALUES (18, 32, "G528");
-CREATE TABLE ExecutiveOffices (ID INT PRIMARY KEY,
-                               desk STRING,
-                               FOREIGN KEY (ID) REFERENCES Offices(ID));
-INSERT INTO ExecutiveOffices (ID, desk) VALUES (18, "oak");
-"""
-
-    val db = p.parseAll(p.ddl, s).get
-    val g = directDB(StemIRI("http://foo.example/DB"), db)
+  testDirectMapping("2 People 1 Addresses 1 Department 2 Projects 1 Task", db_ref_no_pk, directmapping_ref_no_pk)
 
-    val expected:Graph =
-      Set(
-	Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/ExecutiveOffices#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/ExecutiveOffices#desk"),TypedLiteral("oak",IRI("http://www.w3.org/2001/XMLSchema#string"))), 
-
-	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"))), 
+  testDirectMapping("1 People 1 Addresses 1 Offices", db_hier_tabl_proto, directmapping_hier_tabl_proto)
 
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#ID"),TypedLiteral("7",IRI("http://www.w3.org/2001/XMLSchema#int"))),
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#fname"),TypedLiteral("Bob",IRI("http://www.w3.org/2001/XMLSchema#string"))),
-	Triple(IRI("http://foo.example/DB/People/ID.7#_"),IRI("http://foo.example/DB/People#addr"),IRI("http://foo.example/DB/Addresses/ID.18#_")),
-
-	Triple(IRI("http://foo.example/DB/Addresses/ID.18#_"),IRI("http://foo.example/DB/Addresses#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/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")))
-      )
-    assert (expected === g)
-  }
-
+  testDirectMapping("1 People 1 Addresses 1 Offices 1 ExectutiveOffices", db_hier_tabl, directgraph_hier_tabl)
 
   test("NodeMap") {
 
--- a/project/build/RDB2RDF.scala	Thu Nov 04 13:56:35 2010 -0400
+++ b/project/build/RDB2RDF.scala	Fri Nov 26 13:12:43 2010 -0500
@@ -15,7 +15,9 @@
   lazy val rdb = project("rdb", "rdb", new RDB(_))
   lazy val sql = project("sql", "sql", new SQL(_), rdb)
   lazy val rdf = project("rdf", "rdf", new RDF(_))
-  lazy val directmapping = project("directmapping", "directmapping", new DirectMapping(_), rdb, rdf, sql)
+  lazy val turtle = project("turtle", "turtle", new Turtle(_), rdf)
+  lazy val sharedtestdata = project("sharedtestdata", "sharedtestdata", new SharedTestData(_), rdb, rdf, sql)
+  lazy val directmapping = project("directmapping", "directmapping", new DirectMapping(_), rdb, rdf, sql, sharedtestdata)
   lazy val sparql = project("sparql", "sparql", new SPARQL(_), rdf)
   lazy val sparql2sql = project("sparql2sql", "sparql2sql", new SPARQL2SQL(_), sparql, sql)
   lazy val sparql2sparql = project("sparql2sparql", "sparql2sparql", new SPARQL2SPARQL(_), sparql)
@@ -29,6 +31,10 @@
 
   class RDF(info: ProjectInfo) extends DefaultProject(info) with Common
 
+  class Turtle(info: ProjectInfo) extends DefaultProject(info) with Common
+
+  class SharedTestData(info: ProjectInfo) extends DefaultProject(info) with Common
+
   class DirectMapping(info: ProjectInfo) extends DefaultProject(info) with Common
 
   class SPARQL(info: ProjectInfo) extends DefaultProject(info) with Common
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project/plugins/project/build.properties	Fri Nov 26 13:12:43 2010 -0500
@@ -0,0 +1,3 @@
+#Project properties
+#Fri Nov 26 10:16:06 EST 2010
+plugin.uptodate=true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sharedtestdata/src/main/scala/DirectMappingSpec.scala	Fri Nov 26 13:12:43 2010 -0500
@@ -0,0 +1,199 @@
+package org.w3.sw.directmapping
+
+import org.w3.sw.rdf._
+import org.w3.sw.rdb.RDB._
+import org.w3.sw.sql
+
+object DirectMappingSpec {
+
+  val SqlParser = sql.SqlParser()
+
+  val db_emp_adder = SqlParser.parseAll(SqlParser.ddl, """
+CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
+INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
+CREATE TABLE People (ID INT PRIMARY KEY, fname STRING, addr INT, FOREIGN KEY (addr) REFERENCES Addresses(ID));
+INSERT INTO People (ID, fname, addr) VALUES (7, "Bob", 18);
+INSERT INTO People (ID, fname, addr) VALUES (8, "Sue", NULL);
+""").get
+
+  val directgraph_emp_adder:Graph =
+    Set(
+      Triple(IRI("People/ID.7#_"),IRI("People#ID"),TypedLiteral("7",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("People/ID.7#_"),IRI("People#fname"),TypedLiteral("Bob",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("People/ID.7#_"),IRI("People#addr"),IRI("Addresses/ID.18#_")),
+      Triple(IRI("People/ID.8#_"),IRI("People#ID"),TypedLiteral("8",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("People/ID.8#_"),IRI("People#fname"),TypedLiteral("Sue",IRI("http://www.w3.org/2001/XMLSchema#string"))), 
+      
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#ID"),TypedLiteral("18",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#city"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#state"),TypedLiteral("MA",IRI("http://www.w3.org/2001/XMLSchema#string")))
+    )
+
+  val db_multi_key = SqlParser.parseAll(SqlParser.ddl, """
+CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
+INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
+CREATE TABLE Department (ID INT PRIMARY KEY, name STRING, city STRING,
+                         manager INT, FOREIGN KEY (manager) REFERENCES People(ID), UNIQUE (name, city));
+INSERT INTO Department (ID, name, city, manager) VALUES (23, "accounting", "Cambridge", 8);
+CREATE TABLE People (ID INT PRIMARY KEY, fname STRING,
+                     addr INT, FOREIGN KEY (addr) REFERENCES Addresses(ID),
+                     deptName STRING, deptCity STRING, FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
+INSERT INTO People (ID, fname, addr, deptName, deptCity) VALUES (7, "Bob", 18, "accounting", "Cambridge");
+INSERT INTO People (ID, fname, addr, deptName, deptCity) VALUES (8, "Sue", NULL, NULL, NULL);
+""").get
+
+  val directgraph_multi_key:Graph =
+    Set(
+      Triple(IRI("People/ID.7#_"),IRI("People#deptName"),TypedLiteral("accounting",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("People/ID.7#_"),IRI("People#deptCity"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("People/ID.7#_"),IRI("People#deptName_deptCity"),IRI("Department/ID.23#_")),
+
+      Triple(IRI("Department/ID.23#_"),IRI("Department#ID"),TypedLiteral("23",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("Department/ID.23#_"),IRI("Department#name"),TypedLiteral("accounting",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("Department/ID.23#_"),IRI("Department#city"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("Department/ID.23#_"),IRI("Department#manager"),IRI("People/ID.8#_")),
+
+      Triple(IRI("People/ID.7#_"),IRI("People#ID"),TypedLiteral("7",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("People/ID.7#_"),IRI("People#fname"),TypedLiteral("Bob",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("People/ID.7#_"),IRI("People#addr"),IRI("Addresses/ID.18#_")),
+      Triple(IRI("People/ID.8#_"),IRI("People#ID"),TypedLiteral("8",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("People/ID.8#_"),IRI("People#fname"),TypedLiteral("Sue",IRI("http://www.w3.org/2001/XMLSchema#string"))), 
+
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#ID"),TypedLiteral("18",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#city"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#state"),TypedLiteral("MA",IRI("http://www.w3.org/2001/XMLSchema#string"))))
+
+  val db_ref_no_pk = SqlParser.parseAll(SqlParser.ddl, """
+CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
+INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
+CREATE TABLE Department (ID INT PRIMARY KEY, name STRING, city STRING, manager INT,
+                         FOREIGN KEY (manager) REFERENCES People(ID),
+                         UNIQUE (name, city));
+INSERT INTO Department (ID, name, city, manager) VALUES (23, "accounting", "Cambridge", 8);
+CREATE TABLE People (ID INT PRIMARY KEY, fname STRING, addr INT,
+                     FOREIGN KEY (addr) REFERENCES Addresses(ID),
+                     deptName STRING, deptCity STRING,
+                     FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
+INSERT INTO People (ID, fname, addr, deptName, deptCity) VALUES (7, "Bob", 18, "accounting", "Cambridge");
+INSERT INTO People (ID, fname, addr, deptName, deptCity) VALUES (8, "Sue", NULL, NULL, NULL);
+CREATE TABLE Projects (lead INT,
+                       FOREIGN KEY (lead) REFERENCES People(ID),
+                       name STRING, UNIQUE (lead, name), 
+                       deptName STRING, deptCity STRING,
+                       UNIQUE (name, deptName, deptCity),
+                       FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
+INSERT INTO Projects (lead, name, deptName, deptCity) VALUES (8, "pencil survey", "accounting", "Cambridge");
+INSERT INTO Projects (lead, name, deptName, deptCity) VALUES (8, "eraser survey", "accounting", "Cambridge");
+CREATE TABLE TaskAssignments (worker INT,
+                              FOREIGN KEY (worker) REFERENCES People(ID),
+                              project STRING, PRIMARY KEY (worker, project), 
+                              deptName STRING, deptCity STRING,
+                              FOREIGN KEY (worker) REFERENCES People(ID),
+                              FOREIGN KEY (project, deptName, deptCity) REFERENCES Projects(name, deptName, deptCity),
+                              FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
+INSERT INTO TaskAssignments (worker, project, deptName, deptCity) VALUES (7, "pencil survey", "accounting", "Cambridge");
+""").get
+
+  val directmapping_ref_no_pk =
+    Set(
+      Triple(BNode("a"), IRI("Projects#lead"), IRI("People/ID.8#_")),
+      Triple(BNode("a"), IRI("Projects#name"), TypedLiteral("pencil survey", IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(BNode("a"), IRI("Projects#deptName"), TypedLiteral("accounting", IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(BNode("a"), IRI("Projects#deptCity"), TypedLiteral("Cambridge", IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(BNode("a"), IRI("Projects#deptName_deptCity"), IRI("Department/ID.23#_")),
+
+      Triple(BNode("b"), IRI("Projects#lead"), IRI("People/ID.8#_")),
+      Triple(BNode("b"), IRI("Projects#name"), TypedLiteral("eraser survey", IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(BNode("b"), IRI("Projects#deptName"), TypedLiteral("accounting", IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(BNode("b"), IRI("Projects#deptCity"), TypedLiteral("Cambridge", IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(BNode("b"), IRI("Projects#deptName_deptCity"), IRI("Department/ID.23#_")),
+
+      Triple(IRI("TaskAssignments/worker.7_project.pencil+survey#_"), IRI("TaskAssignments#worker"), IRI("People/ID.7#_")),
+      Triple(IRI("TaskAssignments/worker.7_project.pencil+survey#_"), IRI("TaskAssignments#project"), TypedLiteral("pencil survey", IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("TaskAssignments/worker.7_project.pencil+survey#_"), IRI("TaskAssignments#deptName"), TypedLiteral("accounting", IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("TaskAssignments/worker.7_project.pencil+survey#_"), IRI("TaskAssignments#deptCity"), TypedLiteral("Cambridge", IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("TaskAssignments/worker.7_project.pencil+survey#_"), IRI("TaskAssignments#deptName_deptCity"), IRI("Department/ID.23#_")),
+      Triple(IRI("TaskAssignments/worker.7_project.pencil+survey#_"), IRI("TaskAssignments#project_deptName_deptCity"), BNode("a")),
+
+      Triple(IRI("People/ID.7#_"),IRI("People#deptName"),TypedLiteral("accounting",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("People/ID.7#_"),IRI("People#deptCity"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("People/ID.7#_"),IRI("People#deptName_deptCity"),IRI("Department/ID.23#_")),
+
+      Triple(IRI("Department/ID.23#_"),IRI("Department#ID"),TypedLiteral("23",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("Department/ID.23#_"),IRI("Department#name"),TypedLiteral("accounting",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("Department/ID.23#_"),IRI("Department#city"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("Department/ID.23#_"),IRI("Department#manager"),IRI("People/ID.8#_")),
+
+      Triple(IRI("People/ID.7#_"),IRI("People#ID"),TypedLiteral("7",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("People/ID.7#_"),IRI("People#fname"),TypedLiteral("Bob",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("People/ID.7#_"),IRI("People#addr"),IRI("Addresses/ID.18#_")),
+      Triple(IRI("People/ID.8#_"),IRI("People#ID"),TypedLiteral("8",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("People/ID.8#_"),IRI("People#fname"),TypedLiteral("Sue",IRI("http://www.w3.org/2001/XMLSchema#string"))), 
+
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#ID"),TypedLiteral("18",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#city"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#state"),TypedLiteral("MA",IRI("http://www.w3.org/2001/XMLSchema#string")))
+    )
+
+  val db_hier_tabl_proto = SqlParser.parseAll(SqlParser.ddl, """
+CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
+INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
+CREATE TABLE People (ID INT PRIMARY KEY, fname STRING, addr INT,
+                     FOREIGN KEY (addr) REFERENCES Addresses(ID));
+INSERT INTO People (ID, fname, addr) VALUES (7, "Bob", 18);
+CREATE TABLE Offices (ID INT PRIMARY KEY,
+                      building INT, ofcNumber STRING,
+                      FOREIGN KEY (ID) REFERENCES Addresses(ID));
+INSERT INTO Offices (ID, building, ofcNumber) VALUES (18, 32, "G528");
+""").get
+
+  val directmapping_hier_tabl_proto:Graph =
+    Set(
+      Triple(IRI("Addresses/ID.18#_"),IRI("Offices#ID"),TypedLiteral("18",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("Offices#building"),TypedLiteral("32",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("Offices#ofcNumber"),TypedLiteral("G528",IRI("http://www.w3.org/2001/XMLSchema#string"))), 
+
+      Triple(IRI("People/ID.7#_"),IRI("People#ID"),TypedLiteral("7",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("People/ID.7#_"),IRI("People#fname"),TypedLiteral("Bob",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("People/ID.7#_"),IRI("People#addr"),IRI("Addresses/ID.18#_")),
+
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#ID"),TypedLiteral("18",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#city"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#state"),TypedLiteral("MA",IRI("http://www.w3.org/2001/XMLSchema#string")))
+    )
+
+  val db_hier_tabl = SqlParser.parseAll(SqlParser.ddl, """
+CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
+INSERT INTO Addresses (ID, city, state) VALUES (18, "Cambridge", "MA");
+CREATE TABLE People (ID INT PRIMARY KEY, fname STRING, addr INT,
+                     FOREIGN KEY (addr) REFERENCES Addresses(ID));
+INSERT INTO People (ID, fname, addr) VALUES (7, "Bob", 18);
+CREATE TABLE Offices (ID INT PRIMARY KEY,
+                      building INT, ofcNumber STRING,
+                      FOREIGN KEY (ID) REFERENCES Addresses(ID));
+INSERT INTO Offices (ID, building, ofcNumber) VALUES (18, 32, "G528");
+CREATE TABLE ExecutiveOffices (ID INT PRIMARY KEY,
+                               desk STRING,
+                               FOREIGN KEY (ID) REFERENCES Offices(ID));
+INSERT INTO ExecutiveOffices (ID, desk) VALUES (18, "oak");
+""").get
+					
+  val directgraph_hier_tabl:Graph =
+    Set(
+      Triple(IRI("Addresses/ID.18#_"),IRI("ExecutiveOffices#ID"),TypedLiteral("18",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("ExecutiveOffices#desk"),TypedLiteral("oak",IRI("http://www.w3.org/2001/XMLSchema#string"))), 
+
+      Triple(IRI("Addresses/ID.18#_"),IRI("Offices#ID"),TypedLiteral("18",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("Offices#building"),TypedLiteral("32",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("Offices#ofcNumber"),TypedLiteral("G528",IRI("http://www.w3.org/2001/XMLSchema#string"))), 
+
+      Triple(IRI("People/ID.7#_"),IRI("People#ID"),TypedLiteral("7",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("People/ID.7#_"),IRI("People#fname"),TypedLiteral("Bob",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("People/ID.7#_"),IRI("People#addr"),IRI("Addresses/ID.18#_")),
+
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#ID"),TypedLiteral("18",IRI("http://www.w3.org/2001/XMLSchema#int"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#city"),TypedLiteral("Cambridge",IRI("http://www.w3.org/2001/XMLSchema#string"))),
+      Triple(IRI("Addresses/ID.18#_"),IRI("Addresses#state"),TypedLiteral("MA",IRI("http://www.w3.org/2001/XMLSchema#string")))
+    )
+
+}
--- a/sparql2sqlendpoint/src/main/resources/default-config.json	Thu Nov 04 13:56:35 2010 -0400
+++ b/sparql2sqlendpoint/src/main/resources/default-config.json	Fri Nov 26 13:12:43 2010 -0500
@@ -20,8 +20,7 @@
 "
   },
   // the ddl used for the direct mapping (default one)
-  "default": {
-    "ddl": "
+  "ddl": "
 CREATE TABLE Addresses (ID INT PRIMARY KEY, city STRING, state STRING);
 INSERT INTO Addresses (ID, city, state) VALUES (18, 'Cambridge', 'MA');
 CREATE TABLE Department (ID INT PRIMARY KEY, name STRING, city STRING, manager INT,
@@ -51,5 +50,4 @@
                               FOREIGN KEY (deptName, deptCity) REFERENCES Department(name, city));
 INSERT INTO TaskAssignments (worker, project, deptName, deptCity) VALUES (7, 'pencil survey', 'accounting', 'Cambridge');
 "
-  }
 }
--- a/sparql2sqlendpoint/src/main/scala/Configuration.scala	Thu Nov 04 13:56:35 2010 -0400
+++ b/sparql2sqlendpoint/src/main/scala/Configuration.scala	Fri Nov 26 13:12:43 2010 -0500
@@ -7,7 +7,7 @@
 
 // adapted from http://github.com/codahale/fig
 
-object Configuration {
+object JsonBasedConfiguration {
   /**
    * returns the content of a file, if accessible from the classpath
    */
@@ -42,7 +42,7 @@
  *
  * @author coda
  */
-class Configuration(filename: String) {
+class JsonBasedConfiguration(filename: String) {
   case class Value(path: String, value: JsonAST.JValue) {
     /**
      * Returns the value as an instance of type A.
@@ -93,11 +93,27 @@
   }
 
   private val json = {
-    val content = Configuration.option(Source.fromFile(new File(filename)).mkString) getOrElse Configuration.fromFileInClasspath(filename)
+    val content = JsonBasedConfiguration.option(Source.fromFile(new File(filename)).mkString) getOrElse JsonBasedConfiguration.fromFileInClasspath(filename)
     JsonParser.parse(content.replaceAll("""(^//.*|[\s]+//.*)""", ""))
   }
 
   /**
+   * returns all the available keys from the configuration file
+   */
+  val availableKeys:List[String] = {
+    def getKeys(json:JsonAST.JValue):List[String] = {
+      json match {
+        case JsonAST.JField(name, value) if value.children.size == 0 =>
+          List(name)
+        case JsonAST.JField(name, value) =>
+          value.children flatMap { getKeys(_) } map { name + "." + _ }
+        case _ => List()
+      }
+    }
+    json.children flatMap { getKeys(_) }
+  }
+  
+  /**
    * Given a dot-notation JSON path (e.g., "parent.child.fieldname"), returns
    * a Value which can be converted into a specific type or Option thereof.
    */
--- a/sparql2sqlendpoint/src/main/scala/Servlet.scala	Thu Nov 04 13:56:35 2010 -0400
+++ b/sparql2sqlendpoint/src/main/scala/Servlet.scala	Fri Nov 26 13:12:43 2010 -0500
@@ -99,51 +99,39 @@
 
 import org.w3.util.fig._
 
-trait Config {
+trait Configuration {
+  def getConfigurationValue(key:String):String
+  def availableKeys:List[String]
+}
 
-  val config = new Configuration("default-config.json")
-  Class.forName(config("db.driver").as[String]).newInstance
+trait DefaultJsonConfiguration extends Configuration {
+
+  val config = new JsonBasedConfiguration("default-config.json")
+
+  def getConfigurationValue(key:String) = config(key).as[String]
+
+  val availableKeys = config.availableKeys
+
+  Class.forName(getConfigurationValue("db.driver")).newInstance
 
   def getConnection():Connection =
-    DriverManager.getConnection(config("db.url").as[String],
-                                config("db.user").as[String],
-                                config("db.password").as[String])
+    DriverManager.getConnection(getConfigurationValue("db.url"),
+                                getConfigurationValue("db.user"),
+                                getConfigurationValue("db.password"))
   
-  val defaultStemURI:String = config("ui.stemuri").as[String]
+  val defaultStemURI:String = getConfigurationValue("ui.stemuri")
 
-  val defaultSparqlQuery:String = config("ui.sparql-query").as[String]
+  val defaultSparqlQuery:String = getConfigurationValue("ui.sparql-query")
 
   val db:org.w3.sw.rdb.RDB.Database = {
     val DDLParser = new org.w3.sw.sql.SqlParser()
-    val ddl = config("default.ddl").as[String]
-    println(ddl)
+    val ddl = getConfigurationValue("ddl")
     DDLParser.parseAll(DDLParser.ddl, ddl).get
   }
 
 }
 
-object SPARQL2SQLEndpoint {
-
-  import org.eclipse.jetty.server.Server
-  import org.eclipse.jetty.servlet.{ServletContextHandler, ServletHolder}
-
-  /* see http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty */
-  def main(args: Array[String]) {
-
-    val server:Server = new Server(8080)
-    val context:ServletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS)
-    context.setContextPath("/")
-    server.setHandler(context)
-  
-    context.addServlet(new ServletHolder(new SPARQL2SQLEndpoint()),"/*");
-    server.start
-    server.join
-
-  }
-
-}
-
-class SPARQL2SQLEndpoint extends HttpServlet with Config {
+class SPARQL2SQLEndpoint extends HttpServlet with DefaultJsonConfiguration {
 
   val encoding = "utf-8"
 
@@ -213,3 +201,74 @@
   }
 
 }
+
+object SPARQL2SQLEndpoint {
+
+  import org.eclipse.jetty.server.Server
+  import org.eclipse.jetty.servlet.{ServletContextHandler, ServletHolder}
+
+  /**
+   * returns the value associated to a key
+   * example: javar -jar mybundle.jar -db.user root
+   */
+  def getElementAfter(args: List[String], key:String):Option[String] = {
+    args match {
+      case head :: tail if head == key => tail.headOption
+      case head :: tail => getElementAfter(tail, key)
+      case Nil => None
+    }
+  }
+
+  def main(args: Array[String]) {
+
+    def createStatements(connection: => Connection) = {
+      import Control._
+
+      val tables = queryEach(connection, "SHOW TABLES;") { row => row.getNString(1) }
+
+      val create = tables flatMap { tableName =>
+        val showCreateTable = "SHOW CREATE TABLE " + tableName + ";"
+        queryEach(connection, showCreateTable) { row => row.getString(2) }
+      }
+
+      /* remove the stuff the SQL parser does not understand yet */
+      val createStatements = create map { _.replaceAll("\\).*?$", ")")
+                                           .replaceAll(" KEY", "")
+                                           .replaceAll("`", "")
+                                           .replaceAll(" DEFAULT .*?,", ",")
+                                           .replaceAll("`", "")
+                                           .replaceAll(" NOT NULL", "") } mkString "\n"
+      createStatements
+    }
+
+    val endpoint = new SPARQL2SQLEndpoint() {
+      override def getConfigurationValue(key:String) = {
+        val value = getElementAfter(args.toList, "-"+key)
+        if (key == "ddl" && value == Some("auto")) {
+          val statements = createStatements(getConnection)
+          println("Found schema:\n" + statements)
+          statements
+        } else {
+          value getOrElse super.getConfigurationValue(key)
+        }
+      }
+    }
+
+    val message = endpoint.availableKeys map { key => "* " + key } mkString(start="You can override the following parameters by adding -<parameter> <value> on the command line:\n",
+                                                                            sep="\n",
+                                                                            end="")
+    println(message)
+
+    /* see http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty */
+    val server:Server = new Server(8080)
+    val context:ServletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS)
+    context.setContextPath("/")
+    server.setHandler(context)
+    
+    context.addServlet(new ServletHolder(endpoint),"/*");
+    server.start
+    server.join
+
+  }
+
+}