package io.trygvis.cj
import scala.collection.JavaConversions._
import scala.xml.{Group, NodeSeq, Elem}
import java.net.{MalformedURLException, URL, URI, URLEncoder}
import org.json4s.native.JsonMethods
import java.io.{PrintWriter, StringWriter, Writer}
class Views(baseUrl: String) {
val notSet = Not set
def tryLink(s: String) = try {
val url = new URL(s)
{s}
} catch {
case _: MalformedURLException => {s}
}
def render(uri: URI) = {
val s = uri.toURL.toExternalForm
baseUrl + "render?url=" + URLEncoder.encode(s, "utf-8")
}
def delete(uri: URI) = {
val s = uri.toURL.toExternalForm
baseUrl + "render?url=" + URLEncoder.encode(s, "utf-8") + "&action=delete"
}
def examples: Array[Elem] = Array("minimal", "collection", "item", "queries", "template", "error") map { name =>
val cj = baseUrl + "examples/from-spec/" + name + ".collection+json"
{name}
}
def getStackTrace(aThrowable: Throwable) = {
val result: Writer = new StringWriter()
val printWriter: PrintWriter = new PrintWriter(result)
aThrowable.printStackTrace(printWriter)
result.toString
}
def getName(link: Link, prefix: String, i: Int) = {
prefix + link.name.orElse(link.prompt).getOrElse("#" + i)
}
def index = {
def innerContent =
❤ Collection+JSON ❤
About
This is an interactive explorer for the Collection+JSON hypermedia. Give it an URL and it will render is as good as it can.
The purpose is twofold: it is a useful tool to inspect
collections while developing or debugging an application. At
the same time it's useful to show the power of
hypermedia
by showing how much a generic user agent can do by using
only the generic Collection+JSON specification and not
knowing anything about your application.
See also
There's a growing C+J community that's discussing on the Google Group.
Reading the (quite light) formal specification is
useful. It also has a tutorial and some examples.
Using
Feel to use this service! However, note that it's running on a free
Heroku
instance so it might fail, be slow or otherwise useless.
If you want to run it against your own local servers you can either run it yourself, or use apps like
localtunnel.com to make your application publicly available.
}}
{cj.links match {
case Nil =>
NodeSeq.Empty
case _ =>
Collection Links
{cj.links.zipWithIndex.map { case (l, i) =>
val title = l.prompt.orElse(l.name).map(": " + _).getOrElse("")
Group(Seq(
{"Collection link #" + (i + 1) + title}
, link(l)))
}}
}}
// TODO: If the collection has prev/next links, add buttons to automatically navigate those.
// TODO: Add ability to show the raw part of the collection.
def items(cj: Collection) = {
def itemLinks(cj: Collection) = {
val first = cj.findLinkByRel("first")
val prev = cj.findLinkByRel("prev")
val next = cj.findLinkByRel("next")
val last = cj.findLinkByRel("last")
if(first.isDefined || prev.isDefined || next.isDefined || last.isDefined) {
{links.zipWithIndex.map { case (l, i2) =>
Group(Seq(
Item Link #{i2 + 1}
, link(l)))
}}
}}
Data
{item.data map { d =>
{d.name}
{d.value getOrElse ""}
}}
{if(item.href.isDefined) {
val uri = item.href.get
Data
}}
}
}
{itemLinks(cj)}
}
def queries(implicit cj: Collection) = {
{cj.queries.zipWithIndex map { case (query, i) =>
val prompt = query.prompt
val name = query.name
val title = prompt.orElse(name).getOrElse("Unnamed query #" + (i + 1))
{title}
}}
}
def template(implicit cj: Collection) =
def error(implicit cj: Collection) = {
val e = cj.error.get
val message = e.message map { m =>
val lines = m.split('\n')
lines.map(s => scala.xml.Text(s): NodeSeq).reduce(_ ++ ++ _)
}