POST image to container webid
authorHenry Story <henry.story@bblfish.net>
Fri, 13 Apr 2012 23:22:11 +0200
branchwebid
changeset 199 af8ab11f6192
parent 198 014d92d1bb13
child 200 9c6bd1aa7ea9
POST image to container
src/main/scala/Filesystem.scala
src/main/scala/GraphCache.scala
src/main/scala/Image.scala
src/main/scala/Post.scala
src/main/scala/ReadWriteWeb.scala
src/main/scala/Representation.scala
src/main/scala/Resource.scala
--- a/src/main/scala/Filesystem.scala	Fri Apr 13 17:43:15 2012 +0200
+++ b/src/main/scala/Filesystem.scala	Fri Apr 13 23:22:11 2012 +0200
@@ -12,6 +12,7 @@
 import scala.sys
 import java.nio.file.{StandardOpenOption, Files}
 import com.hp.hpl.jena.vocabulary.RDF
+import org.w3.readwriteweb.Image
 
 class Filesystem(
   baseDirectory: File,
@@ -144,13 +145,19 @@
       case e: IOException => e.fail
     }
 
-    def create(): Validation[Throwable, Resource] = {
+    def create(contentType: Representation): Validation[Throwable, Resource] = {
       if (!fileOnDisk.exists())
         new Throwable("Must first create " + name()).fail
       else if (!fileOnDisk.isDirectory)
         new Throwable("Can only create a resource in a directory/collection which this is not " + name()).fail
       else try {
-        val path = Files.createTempFile(fileOnDisk.toPath, "res", lang.suffix)
+        //todo: the class hierarchy of content types needs to be improved.
+        val suffix = contentType match {
+          case RDFRepr(lang) => lang.suffix
+          case ImageRepr(tpe) => tpe.suffix
+          case l => lang.suffix
+        }
+        val path = Files.createTempFile(fileOnDisk.toPath, "res", suffix)
         resource(new URL(name(), path.getFileName.toString)).success
       } catch {
         case ioe: IOException => ioe.fail
--- a/src/main/scala/GraphCache.scala	Fri Apr 13 17:43:15 2012 +0200
+++ b/src/main/scala/GraphCache.scala	Fri Apr 13 23:22:11 2012 +0200
@@ -122,7 +122,7 @@
 
     def delete = throw new MethodNotSupportedException("not implemented")
 
-    def create() = throw new MethodNotSupportedException("not implemented")
+    def create(ct: Representation) = throw new MethodNotSupportedException("not implemented")
 
     def getStream = throw new MethodNotSupportedException("not implemented")
 
--- a/src/main/scala/Image.scala	Fri Apr 13 17:43:15 2012 +0200
+++ b/src/main/scala/Image.scala	Fri Apr 13 23:22:11 2012 +0200
@@ -40,11 +40,7 @@
     case PNG => ".png"
   }
 
-  def contentType = this match {
-    case JPEG => "image/jpeg"
-    case GIF => "image/gif"
-    case PNG => "image/png"
-  }
+  def contentType : String
 
 }
 
@@ -68,6 +64,12 @@
     }
 }
 
-case object JPEG extends Image
-case object GIF extends Image
-case object PNG extends Image
+case object JPEG extends Image {
+  val contentType = "image/jpeg"
+}
+case object GIF extends Image {
+  val contentType = "image/gif"
+}
+case object PNG extends Image {
+  val contentType = "image/png"
+}
--- a/src/main/scala/Post.scala	Fri Apr 13 17:43:15 2012 +0200
+++ b/src/main/scala/Post.scala	Fri Apr 13 23:22:11 2012 +0200
@@ -15,6 +15,7 @@
 case class PostUpdate(update: UpdateRequest) extends Post
 case class PostRDF(model: Model) extends Post
 case class PostQuery(query: Query) extends Post
+case class PostBinary(in: InputStream) extends Post
 case object PostUnknown extends Post
 
 import scalaz._
@@ -23,7 +24,7 @@
 object Post {
   
   val SPARQL = "application/sparql-query"
-  val supportContentTypes = Lang.supportContentTypes + SPARQL
+  val supportContentTypes = Lang.supportContentTypes + SPARQL ++ Image.supportedImages.map(_.contentType)
   val supportedAsString = supportContentTypes mkString ", "
 
   
@@ -34,41 +35,36 @@
       base: URL,
       contentType: String): Post = {
     assert(supportContentTypes contains contentType)
-    val source = Source.fromInputStream(is, "UTF-8")
-    val s = source.getLines.mkString("\n")
-    parse(s, base, contentType)
-  }
-  
-  def parse(
-      s: String,
-      base: URL,
-      contentType: String): Post = {
-    assert(supportContentTypes contains contentType)
-    
-    val reader = new StringReader(s)
-    
+
+    def inAsString = {
+       val source = Source.fromInputStream(is, "UTF-8")
+       source.getLines.mkString("\n")
+    }
+
     def postUpdate =
       try {
-        val update: UpdateRequest = UpdateFactory.create(s, base.toString)
+        val update: UpdateRequest = UpdateFactory.create(inAsString, base.toString)
         PostUpdate(update).success
       } catch {
         case qpe: QueryParseException => qpe.fail
       }
       
     def postRDF(lang: Lang) =
-      modelFromString(s, base, lang) flatMap { model => PostRDF(model).success }
+      modelFromString(inAsString, base, lang) flatMap { model => PostRDF(model).success }
     
     def postQuery =
       try {
-        val query = QueryFactory.create(s)
+        val query = QueryFactory.create(inAsString)
         PostQuery(query).success
       } catch {
         case qe: QueryException => qe.fail
       }
+
     
     contentType match {
       case SPARQL => postUpdate | (postQuery | PostUnknown)
       case RequestLang(lang) => postRDF(lang) | PostUnknown
+      case GIF.contentType | JPEG.contentType | PNG.contentType => PostBinary(is)
     }
 
   }
--- a/src/main/scala/ReadWriteWeb.scala	Fri Apr 13 17:43:15 2012 +0200
+++ b/src/main/scala/ReadWriteWeb.scala	Fri Apr 13 23:22:11 2012 +0200
@@ -23,6 +23,7 @@
 import unfiltered.response._
 
 import com.hp.hpl.jena.rdf.model.Model
+import javax.naming.BinaryRefAddr
 
 //object ReadWriteWeb {
 //
@@ -127,7 +128,8 @@
             case PUT(_) =>
               BadRequest ~> ResponseString("Content-Type MUST be one of: " + Lang.supportedAsString)
             case POST(_) & RequestContentType(ct) if representation == DirectoryRepr =>
-              r.create() failMap { t => NotFound ~> ResponseString(t.getStackTraceString)} flatMap { rNew =>
+              val createType = Representation.fromAcceptedContentTypes(List(ct))
+              r.create(createType) failMap { t => NotFound ~> ResponseString(t.getStackTraceString)} flatMap { rNew =>
                 Post.parse(Body.stream(req), rNew.name, ct) match {
                   case PostRDF(model) => {
                     logger.info("RDF content:\n" + model.toString())
@@ -137,6 +139,10 @@
                       }
                     } yield Created ~> ResponseHeader("Location",Seq(rNew.name.toString))
                   }
+                  case PostBinary(is) => {
+                    for (_ <- rNew.putStream(is) failMap { t=> InternalServerError ~> ResponseString(t.getStackTraceString)})
+                    yield Created ~> ResponseHeader("Location",Seq(rNew.name.toString))
+                  }
                   case _ => {
                     logger.info("Couldn't parse the request")
                     (BadRequest ~> ResponseString("You MUST provide valid content for given Content-Type: " + ct)).success
--- a/src/main/scala/Representation.scala	Fri Apr 13 17:43:15 2012 +0200
+++ b/src/main/scala/Representation.scala	Fri Apr 13 23:22:11 2012 +0200
@@ -14,7 +14,7 @@
       case "turtle" | "ttl" => RDFRepr(TURTLE)
       case "rdf" => RDFRepr(RDFXML)
       case "htm" | "html" | "xhtml" => HTMLRepr
-      case "jpeg" => ImageRepr(JPEG)
+      case "jpeg" | "jpg" => ImageRepr(JPEG)
       case "png" => ImageRepr(PNG)
       case "gif" => ImageRepr(GIF)
       case "/" => DirectoryRepr
@@ -58,6 +58,9 @@
       case Some(repr) => repr
     }
   }
+
+
+
 }
 
 case class RDFRepr(lang: Lang) extends Representation
--- a/src/main/scala/Resource.scala	Fri Apr 13 17:43:15 2012 +0200
+++ b/src/main/scala/Resource.scala	Fri Apr 13 23:22:11 2012 +0200
@@ -55,6 +55,12 @@
 
   //These two methods only work when called on directories
   def createDirectory: Validation[Throwable, Unit]
-  def create(): Validation[Throwable, Resource]
+
+  /**
+   *
+   * @param contentType this should be Lang or ContentType, which should be a superinterface on all CTs
+   * @return
+   */
+  def create(contentType: Representation): Validation[Throwable, Resource]
 }