merged with Alexandre Bertails branch. Apart from adding initial WebID code, a few small changes such as a method for translating mime type objects into their Jena equivalent.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/Filesystem.scala	Wed Oct 12 15:26:31 2011 +0200
@@ -0,0 +1,68 @@
+package org.w3.readwriteweb
+
+import org.w3.readwriteweb.util._
+
+import java.io._
+import java.net.URL
+import org.slf4j.{Logger, LoggerFactory}
+import com.hp.hpl.jena.rdf.model._
+import com.hp.hpl.jena.shared.JenaException
+import sys.error
+import scalaz._
+import Scalaz._
+
+class Filesystem(
+  baseDirectory: File,
+  val basePath: String,
+  val lang: String = "RDF/XML-ABBREV")(mode: RWWMode) extends ResourceManager {
+  
+  val logger:Logger = LoggerFactory.getLogger(this.getClass)
+
+  def sanityCheck():Boolean = baseDirectory.exists
+
+  def resource(url:URL):Resource = new Resource {
+    val relativePath:String = url.getPath.replaceAll("^"+basePath.toString+"/?", "")
+    val fileOnDisk = new File(baseDirectory, relativePath)
+
+    private def createFileOnDisk():Unit = {
+      // create parent directory if needed
+      val parent = fileOnDisk.getParentFile
+      if (! parent.exists) println(parent.mkdirs)
+      val r = fileOnDisk.createNewFile()
+      logger.debug("Create file %s with success: %s" format (fileOnDisk.getAbsolutePath, r.toString))
+    }
+
+    def get(): Validation[Throwable, Model] = {
+      val model = ModelFactory.createDefaultModel()
+      if (fileOnDisk.exists()) {
+        val fis = new FileInputStream(fileOnDisk)
+        try {
+          val reader = model.getReader(lang)
+          reader.read(model, fis, url.toString)
+        } catch {
+          case je:JenaException => error("@@@")
+        }
+        fis.close()
+        model.success
+      } else {
+        mode match {
+          case AllResourcesAlreadyExist => model.success
+          case ResourcesDontExistByDefault => new FileNotFoundException().fail
+        }
+      }
+    }
+
+    def save(model:Model):Validation[Throwable, Unit] =
+      try {
+        createFileOnDisk()
+        val fos = new FileOutputStream(fileOnDisk)
+        val writer = model.getWriter(lang)
+        writer.write(model, fos, url.toString)
+        fos.close().success
+      } catch {
+        case t => t.fail
+      }
+
+  }
+  
+}
--- a/src/main/scala/Post.scala	Wed Oct 12 14:19:47 2011 +0200
+++ b/src/main/scala/Post.scala	Wed Oct 12 15:26:31 2011 +0200
@@ -1,54 +1,61 @@
 package org.w3.readwriteweb
 
-import java.io._
+import org.w3.readwriteweb.util.modelFromString
+
+import java.io.{InputStream, StringReader}
 import scala.io.Source
-
 import org.slf4j.{Logger, LoggerFactory}
-
 import com.hp.hpl.jena.rdf.model._
 import com.hp.hpl.jena.query._
 import com.hp.hpl.jena.update._
 import com.hp.hpl.jena.shared.JenaException
 
-import org.w3.readwriteweb.util._
-
 sealed trait Post
-case class PostUpdate(update:UpdateRequest) extends Post
-case class PostRDF(model:Model) extends Post
-case class PostQuery(query:Query) extends Post
+
+case class PostUpdate(update: UpdateRequest) extends Post
+
+case class PostRDF(model: Model) extends Post
+
+case class PostQuery(query: Query) extends Post
+
 case object PostUnknown extends Post
 
+
 import scalaz._
 import Scalaz._
 
 object Post {
   
-  val logger:Logger = LoggerFactory.getLogger(this.getClass)
+  val logger: Logger = LoggerFactory.getLogger(this.getClass)
 
-  def parse(is:InputStream, baseURI:String):Post = {
+  def parse(is: InputStream, baseURI:String): Post = {
     val source = Source.fromInputStream(is, "UTF-8")
     val s = source.getLines.mkString("\n")
     parse(s, baseURI)
   }
   
-  def parse(s:String, baseURI:String):Post = {
+  def parse(s: String, baseURI: String): Post = {
     val reader = new StringReader(s)
+    
     def postUpdate =
       try {
-        val update:UpdateRequest = UpdateFactory.create(s, baseURI)
+        val update: UpdateRequest = UpdateFactory.create(s, baseURI)
         PostUpdate(update).success
       } catch {
-        case qpe:QueryParseException => qpe.fail
+        case qpe: QueryParseException => qpe.fail
       }
+      
     def postRDF =
       modelFromString(s, baseURI) flatMap { model => PostRDF(model).success }
+    
     def postQuery =
       try {
         val query = QueryFactory.create(s)
         PostQuery(query).success
       } catch {
-        case qe:QueryException => qe.fail
+        case qe: QueryException => qe.fail
       }
+    
     postUpdate | (postRDF | (postQuery | PostUnknown))
   }
   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/ReadWriteWebMain.scala	Wed Oct 12 15:26:31 2011 +0200
@@ -0,0 +1,106 @@
+package org.w3.readwriteweb
+
+import org.w3.readwriteweb.util._
+
+import javax.servlet._
+import javax.servlet.http._
+import unfiltered.jetty._
+import java.io.File
+import Console.err
+import org.slf4j.{Logger, LoggerFactory}
+
+import org.clapper.argot._
+import ArgotConverters._
+
+object ReadWriteWebMain {
+
+  val logger:Logger = LoggerFactory.getLogger(this.getClass)
+
+  val postUsageMsg= Some("""
+  |PROPERTIES
+  |
+  | * Keystore properties that need to be set if https is started
+  |  -Djetty.ssl.keyStoreType=type : the type of the keystore, JKS by default usually
+  |  -Djetty.ssl.keyStore=path : specify path to key store (for https server certificate)
+  |  -Djetty.ssl.keyStorePassword=password : specify password for keystore store (optional)
+  |
+  |NOTES
+  |
+  |  - Trust stores are not needed because we use the WebID protocol, and client certs are nearly never signed by CAs
+  |  - one of --http or --https must be selected
+     """.stripMargin);
+
+  val parser = new ArgotParser("read-write-web",postUsage=postUsageMsg)
+
+  val mode = parser.option[RWWMode](List("mode"), "m", "wiki mode: wiki or strict") {
+      (sValue, opt) =>
+        sValue match {
+          case "wiki" => AllResourcesAlreadyExist
+          case "strict" => ResourcesDontExistByDefault
+          case _ => throw new ArgotConversionException("Option %s: must be either wiki or strict" format (opt.name, sValue))
+        }
+      }
+
+    val rdfLanguage = parser.option[String](List("language"), "l", "RDF language: n3, turtle, or rdfxml") {
+      (sValue, opt) =>
+        sValue match {
+          case "n3" => "N3"
+          case "turtle" => "N3"
+          case "rdfxml" => "RDF/XML-ABBREV"
+          case _ => throw new ArgotConversionException("Option %s: must be either n3, turtle or rdfxml" format (opt.name, sValue))
+      }
+  }
+
+    val httpPort = parser.option[Int]("http", "Port","start the http server on port")
+    val httpsPort = parser.option[Int]("https","port","start the https server on port")
+
+    val rootDirectory = parser.parameter[File]("rootDirectory", "root directory", false) {
+      (sValue, opt) => {
+        val file = new File(sValue)
+        if (! file.exists)
+          throw new ArgotConversionException("Option %s: %s must be a valid path" format (opt.name, sValue))
+        else
+          file
+    }
+    }
+
+   implicit val webCache = new WebCache()
+
+
+   val baseURL = parser.parameter[String]("baseURL", "base URL", false)
+
+  // regular Java main
+  def main(args: Array[String]) {
+
+    try {
+       parser.parse(args)
+     } catch {
+      case e: ArgotUsageException => err.println(e.message); sys.exit(1)
+    }
+
+    val filesystem =
+        new Filesystem(
+          rootDirectory.value.get,
+          baseURL.value.get,
+          lang=rdfLanguage.value getOrElse "N3")(mode.value getOrElse ResourcesDontExistByDefault)
+
+    val app = new ReadWriteWeb(filesystem)
+
+    //this is incomplete: we should be able to start both ports.... not sure how to do this yet.
+    val service = httpsPort.value match {
+      case Some(port) => HttpsTrustAll(port,"0.0.0.0")
+      case None => Http(httpPort.value.get)
+    }
+
+    // configures and launches a Jetty server
+    service.filter(new FilterLogger(logger)).
+      filter(new webid.AuthFilter).
+      context("/public"){ ctx:ContextBuilder =>
+      ctx.resources(ClasspathUtils.fromClasspath("public/").toURI.toURL)
+    }.filter(app.plan).run()
+
+  }
+
+}
+
+
--- a/src/main/scala/Resource.scala	Wed Oct 12 14:19:47 2011 +0200
+++ b/src/main/scala/Resource.scala	Wed Oct 12 15:26:31 2011 +0200
@@ -1,84 +1,20 @@
 package org.w3.readwriteweb
 
-import java.io._
-import java.net.URL
-
-import org.slf4j.{Logger, LoggerFactory}
-
-import com.hp.hpl.jena.rdf.model._
-import com.hp.hpl.jena.shared.JenaException
-
 import org.w3.readwriteweb.util._
 
+import java.net.URL
+import com.hp.hpl.jena.rdf.model._
 import scalaz._
 import Scalaz._
 
-import _root_.scala.sys.error
-
 trait ResourceManager {
-  def basePath:String
-  def sanityCheck():Boolean
-  def resource(url:URL):Resource
+  def basePath: String
+  def sanityCheck(): Boolean
+  def resource(url: URL): Resource
 }
 
 trait Resource {
-  def get():Validation[Throwable, Model]
-  def save(model:Model):Validation[Throwable, Unit]
+  def get(): Validation[Throwable, Model]
+  def save(model: Model): Validation[Throwable, Unit]
 }
 
-class Filesystem(
-  baseDirectory: File,
-  val basePath: String,
-  val lang: String = "RDF/XML-ABBREV")(mode: RWWMode) extends ResourceManager {
-  
-  val logger:Logger = LoggerFactory.getLogger(this.getClass)
-  
-  def sanityCheck():Boolean = baseDirectory.exists
-  
-  def resource(url:URL):Resource = new Resource {
-    val relativePath:String = url.getPath.replaceAll("^"+basePath.toString+"/?", "")
-    val fileOnDisk = new File(baseDirectory, relativePath)
-    
-    private def createFileOnDisk():Unit = {
-      // create parent directory if needed
-      val parent = fileOnDisk.getParentFile
-      if (! parent.exists) println(parent.mkdirs)
-      val r = fileOnDisk.createNewFile()
-      logger.debug("Create file %s with success: %s" format (fileOnDisk.getAbsolutePath, r.toString))
-    }
-    
-    def get(): Validation[Throwable, Model] = {
-      val model = ModelFactory.createDefaultModel()
-      if (fileOnDisk.exists()) {
-        val fis = new FileInputStream(fileOnDisk)
-        try {
-          val reader = model.getReader(lang)
-          reader.read(model, fis, url.toString)
-        } catch {
-          case je:JenaException => error("@@@")
-        }
-        fis.close()
-        model.success
-      } else {
-        mode match {
-          case AllResourcesAlreadyExist => model.success
-          case ResourcesDontExistByDefault => new FileNotFoundException().fail
-        }
-      }
-    }
-    
-    def save(model:Model):Validation[Throwable, Unit] =
-      try {
-        createFileOnDisk()
-        val fos = new FileOutputStream(fileOnDisk)
-        val writer = model.getWriter(lang)
-        writer.write(model, fos, url.toString)
-        fos.close().success
-      } catch {
-        case t => t.fail
-      }
-
-  }
-  
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/plan.scala	Wed Oct 12 15:26:31 2011 +0200
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2011 Henry Story (bblfish.net)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Henry Story.  The name of bblfish.net may not be used to endorse
+ * or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+package org.w3.readwriteweb
+
+import org.w3.readwriteweb.util._
+
+import unfiltered.request._
+import unfiltered.response._
+
+import scala.io.Source
+import java.net.URL
+
+import org.slf4j.{Logger, LoggerFactory}
+
+import com.hp.hpl.jena.rdf.model.Model
+import com.hp.hpl.jena.query.{Query, QueryExecution, QueryExecutionFactory}
+import com.hp.hpl.jena.update.UpdateAction
+import Query.{QueryTypeSelect => SELECT,
+              QueryTypeAsk => ASK,
+              QueryTypeConstruct => CONSTRUCT,
+              QueryTypeDescribe => DESCRIBE}
+
+import scalaz._
+import Scalaz._
+
+class ReadWriteWeb(rm: ResourceManager) {
+  
+  val logger: Logger = LoggerFactory.getLogger(this.getClass)
+
+  def isHTML(accepts: List[String]): Boolean = {
+    val accept = accepts.headOption
+    accept == Some("text/html") || accept == Some("application/xhtml+xml")
+  }
+  
+  /** I believe some documentation is needed here, as many different tricks
+   *  are used to make this code easy to read and still type-safe
+   *  
+   *  Planify.apply takes an Intent, which is defined in Cycle by
+   *  type Intent [-A, -B] = PartialFunction[HttpRequest[A], ResponseFunction[B]]
+   *  the corresponding syntax is: case ... => ...
+   *  
+   *  this code makes use of ScalaZ Validation. For example of how to use it, see
+   *  http://scalaz.googlecode.com/svn/continuous/latest/browse.sxr/scalaz/example/ExampleValidation.scala.html
+   *  
+   *  the Resource abstraction returns Validation[Throwable, ?something]
+   *  we use the for monadic constructs (although it's *not* a monad).
+   *  Everything construct are mapped to Validation[ResponseFunction, ResponseFuntion],
+   *  the left value always denoting the failure. Hence, the rest of the for-construct
+   *  is not evaluated, but let the reader of the code understand clearly what's happening.
+   *  
+   *  This mapping is made possible with the failMap method. I couldn't find an equivalent
+   *  in the ScalaZ API so I made my own through an implicit.
+   *  
+   *  At last, Validation[ResponseFunction, ResponseFuntion] is exposed as a ResponseFunction
+   *  through another implicit conversion. It saves us the call to the Validation.lift() method
+   */
+  val plan = unfiltered.filter.Planify {
+    case req @ Path(path) if path startsWith rm.basePath => {
+      val baseURI = req.underlying.getRequestURL.toString
+      val r: Resource = rm.resource(new URL(baseURI))
+      req match {
+        case GET(_) & Accept(accepts) if isHTML(accepts) => {
+          val source = Source.fromFile("src/main/resources/skin.html")("UTF-8")
+          val body = source.getLines.mkString("\n")
+          Ok ~> ViaSPARQL ~> ContentType("text/html") ~> ResponseString(body)
+        }
+        case GET(_) | HEAD(_) =>
+          for {
+            model <- r.get() failMap { x => NotFound }
+            encoding = RDFEncoding(req)
+          } yield {
+            req match {
+              case GET(_) => Ok ~> ViaSPARQL ~> ContentType(encoding.toContentType) ~> ResponseModel(model, baseURI, encoding)
+              case HEAD(_) => Ok ~> ViaSPARQL ~> ContentType(encoding.toContentType)
+            }
+          }
+        case PUT(_) =>
+          for {
+            bodyModel <- modelFromInputStream(Body.stream(req), baseURI) failMap { t => BadRequest ~> ResponseString(t.getStackTraceString) }
+            _ <- r.save(bodyModel) failMap { t => InternalServerError ~> ResponseString(t.getStackTraceString) }
+          } yield Created
+        case POST(_) => {
+          Post.parse(Body.stream(req), baseURI) match {
+            case PostUnknown => {
+              logger.info("Couldn't parse the request")
+              BadRequest ~> ResponseString("You MUST provide valid content for either: SPARQL UPDATE, SPARQL Query, RDF/XML, TURTLE")
+            }
+            case PostUpdate(update) => {
+              logger.info("SPARQL UPDATE:\n" + update.toString())
+              for {
+                model <- r.get() failMap { t => NotFound }
+                // TODO: we should handle an error here
+                _ = UpdateAction.execute(update, model)
+                _ <- r.save(model) failMap { t =>  InternalServerError ~> ResponseString(t.getStackTraceString)}
+              } yield Ok
+            }
+            case PostRDF(diffModel) => {
+              logger.info("RDF content:\n" + diffModel.toString())
+              for {
+                model <- r.get() failMap { t => NotFound }
+                // TODO: we should handle an error here
+                _ = model.add(diffModel)
+                _ <- r.save(model) failMap { t =>  InternalServerError ~> ResponseString(t.getStackTraceString)}
+              } yield Ok
+            }
+            case PostQuery(query) => {
+              logger.info("SPARQL Query:\n" + query.toString())
+              lazy val encoding = RDFEncoding(req)
+              for {
+                model <- r.get() failMap { t => NotFound }
+              } yield {
+                val qe: QueryExecution = QueryExecutionFactory.create(query, model)
+                query.getQueryType match {
+                  case SELECT =>
+                    Ok ~> ContentType("application/sparql-results+xml") ~> ResponseResultSet(qe.execSelect())
+                  case ASK =>
+                    Ok ~> ContentType("application/sparql-results+xml") ~> ResponseResultSet(qe.execAsk())
+                  case CONSTRUCT => {
+                    val result: Model = qe.execConstruct()
+                    Ok ~> ContentType(encoding.toContentType) ~> ResponseModel(model, baseURI, encoding)
+                  }
+                  case DESCRIBE => {
+                    val result: Model = qe.execDescribe()
+                    Ok ~> ContentType(encoding.toContentType) ~> ResponseModel(model, baseURI, encoding)
+                  }
+                }
+              }
+            }
+          }
+        }
+        case _ => MethodNotAllowed ~> Allow("GET", "PUT", "POST")
+      }
+    }
+
+  }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/rdfLanguage.scala	Wed Oct 12 15:26:31 2011 +0200
@@ -0,0 +1,37 @@
+package org.w3.readwriteweb
+
+import unfiltered.request._
+
+sealed trait RDFEncoding {
+  def toContentType:String
+}
+
+case object RDFXML extends RDFEncoding {
+  def toContentType = "application/rdf+xml"
+}
+
+case object TURTLE extends RDFEncoding {
+  def toContentType = "text/turtle"
+}
+
+object RDFEncoding {
+  
+  def apply(contentType:String):RDFEncoding =
+    contentType match {
+      case "text/turtle" => TURTLE
+      case "application/rdf+xml" => RDFXML
+      case _ => RDFXML
+    }
+
+  def jena(encoding: RDFEncoding) = encoding match {
+     case RDFXML => "RDF/XML-ABBREV"
+     case TURTLE => "TURTLE"
+     case _      => "RDF/XML-ABBREV" //don't like this default
+   }
+
+  def apply(req:HttpRequest[_]):RDFEncoding = {
+    val contentType = Accept(req).headOption
+    contentType map { RDFEncoding(_) } getOrElse RDFXML
+  }
+  
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/util/ClasspathUtils.scala	Wed Oct 12 15:26:31 2011 +0200
@@ -0,0 +1,69 @@
+package org.w3.readwriteweb.util
+
+import java.io.{File, FileWriter}
+import java.util.jar._
+import scala.collection.JavaConversions._
+import scala.io.Source
+import java.net.{URL, URLDecoder}
+import org.slf4j.{Logger, LoggerFactory}
+
+/** useful stuff to read resources from the classpath */
+object ClasspathUtils {
+  
+  val logger: Logger = LoggerFactory.getLogger(this.getClass)
+
+  val clazz: Class[_] = this.getClass
+  val classloader = this.getClass.getClassLoader
+  
+  /** http://www.uofr.net/~greg/java/get-resource-listing.html
+   */
+  def getResourceListing(path: String): List[String] = {
+    var dirURL: URL = classloader.getResource(path)
+    if (dirURL != null && dirURL.getProtocol == "file") {
+      /* A file path: easy enough */
+      new File(dirURL.toURI).list.toList
+    } else {
+      if (dirURL == null) {
+        val me = clazz.getName().replace(".", "/")+".class"
+        dirURL = classloader.getResource(me)
+      }
+      if (dirURL.getProtocol == "jar") {
+        val jarPath = dirURL.getPath.substring(5, dirURL.getPath().indexOf("!"))
+        val jar: JarFile = new JarFile(URLDecoder.decode(jarPath, "UTF-8"))
+        val entries = jar.entries filter { _.getName startsWith path } map { e => {
+          var entry = e.getName substring path.length
+          val checkSubdir = entry indexOf "/"
+          if (checkSubdir >= 0) entry = entry.substring(0, checkSubdir)
+          entry
+        } }
+        entries filterNot { _.isEmpty } toList
+      } else
+        sys.error("Cannot list files for URL "+dirURL);
+    }
+  }
+  
+  /** extract a path found in the classpath
+   * 
+   *  @return the file on disk
+   */
+  def fromClasspath(path: String, base: File = new File("src/main/resources")): File = {
+    val workingPath = new File(base, path)
+    if (workingPath isDirectory) {
+      workingPath
+    } else {
+      val dir = new File(System.getProperty("java.io.tmpdir"),
+                         "virtual-trainer-" + scala.util.Random.nextInt(10000).toString)
+      if (! dir.mkdir()) logger.error("Couldn't extract %s from jar to %s" format (path, dir.getAbsolutePath))
+      val entries = getResourceListing(path) foreach { entry => {
+        val url = classloader.getResource(path + entry)
+        val content = Source.fromURL(url, "UTF-8").getLines.mkString("\n")
+        val writer = new FileWriter(new File(dir, entry))
+        writer.write(content)
+        writer.close()
+      }
+    }
+    dir
+    }
+  }
+  
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/util/FilterLogger.scala	Wed Oct 12 15:26:31 2011 +0200
@@ -0,0 +1,28 @@
+package org.w3.readwriteweb
+
+import javax.servlet._
+import javax.servlet.http._
+import unfiltered.jetty._
+import java.io.File
+import org.slf4j.{Logger, LoggerFactory}
+
+/** a simple JEE Servlet filter that logs HTTP requests
+ */
+class FilterLogger(logger: Logger) extends Filter {
+
+  def destroy(): Unit = ()
+
+  def doFilter(
+    request: ServletRequest,
+    response: ServletResponse,
+    chain: FilterChain): Unit = {
+    val r: HttpServletRequest = request.asInstanceOf[HttpServletRequest]
+    val method = r.getMethod
+    val uri = r.getRequestURI 
+    logger.info("%s %s" format (method, uri))
+    chain.doFilter(request, response)
+  }
+
+  def init(filterConfig: FilterConfig): Unit = ()
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/util/ValidationW.scala	Wed Oct 12 15:26:31 2011 +0200
@@ -0,0 +1,13 @@
+package org.w3.readwriteweb.util
+
+import scalaz._
+import Scalaz._
+
+trait ValidationW[E, S] {
+
+  val validation: Validation[E, S]
+ 
+  def failMap[EE](f: E => EE): Validation[EE, S] =
+    validation.fail map f validation
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/util/mode.scala	Wed Oct 12 15:26:31 2011 +0200
@@ -0,0 +1,7 @@
+package org.w3.readwriteweb
+
+sealed trait RWWMode
+
+case object AllResourcesAlreadyExist extends RWWMode
+
+case object ResourcesDontExistByDefault extends RWWMode
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/util/package.scala	Wed Oct 12 15:26:31 2011 +0200
@@ -0,0 +1,75 @@
+package org.w3.readwriteweb
+
+import java.io._
+import com.hp.hpl.jena.rdf.model._
+import com.hp.hpl.jena.query._
+import unfiltered.response._
+import scalaz._
+import Scalaz._
+
+package object util {
+  
+  val defaultLang = "RDF/XML-ABBREV"
+
+  class MSAuthorVia(value: String) extends ResponseHeader("MS-Author-Via", List(value))
+  
+  object ViaSPARQL extends MSAuthorVia("SPARQL")
+  
+  object ResponseModel {
+    def apply(model: Model, base: String, encoding: RDFEncoding): ResponseStreamer =
+      new ResponseStreamer {
+        def stream(os: OutputStream): Unit =
+          encoding match {
+            case RDFXML => model.getWriter("RDF/XML-ABBREV").write(model, os, base)
+            case TURTLE => model.getWriter("TURTLE").write(model, os, base)
+          }
+      }
+  }
+
+  object ResponseResultSet {
+    def apply(rs: ResultSet): ResponseStreamer =
+      new ResponseStreamer {
+        def stream(os: OutputStream): Unit = ResultSetFormatter.outputAsXML(os, rs) 
+      }
+    def apply(result: Boolean): ResponseStreamer =
+      new ResponseStreamer {
+        def stream(os: OutputStream):Unit = ResultSetFormatter.outputAsXML(os, result) 
+      }
+  }
+
+  //Passing strings into mathod arguments, especially as these differ completely between rdf stacks is not so good
+  //passing objects is better
+  def modelFromInputStream(is:InputStream, base: String,  lang: RDFEncoding): Validation[Throwable, Model]=
+      modelFromInputStream(is, base, RDFEncoding.jena(lang))
+
+  def modelFromInputStream(
+      is: InputStream,
+      base: String,
+      lang: String = "RDF/XML-ABBREV"): Validation[Throwable, Model] =
+    try {
+      val m = ModelFactory.createDefaultModel()
+      m.read(is, base, lang)
+      m.success
+    } catch {
+      case t => t.fail
+    }
+  
+  def modelFromString(
+      s: String,
+      base: String,
+      lang: String = "RDF/XML-ABBREV"): Validation[Throwable, Model] =
+    try {
+      val reader = new StringReader(s)
+      val m = ModelFactory.createDefaultModel()
+      m.read(reader, base, lang)
+      m.success
+    } catch {
+      case t => t.fail
+    }
+
+  implicit def wrapValidation[E, S](v: Validation[E,S]): ValidationW[E, S] =
+    new ValidationW[E, S] { val validation = v }
+  
+  implicit def unwrap[E, F <: E, S <: E](v: Validation[F,S]): E = v.fold(e => e, s => s)
+  
+}
--- a/src/test/scala/util/specs.scala	Wed Oct 12 14:19:47 2011 +0200
+++ b/src/test/scala/util/specs.scala	Wed Oct 12 15:26:31 2011 +0200
@@ -23,7 +23,7 @@
   
   def resourceManager: ResourceManager
   
-  def setup = { _.filter(new ReadWriteWeb(resourceManager).read) }
+  def setup = { _.filter(new ReadWriteWeb(resourceManager).plan) }
  
 }