Toby Inkster avatar Toby Inkster committed a66f7fe Draft

sparql form with resultset support

Comments (0)

Files changed (5)

lib/Demiblog4/Resource/Endpoint.pm

 use Demiblog4::Sugar
 	-types => -all,
 	-base  => 'Magpie::Resource';
-use RDF::Query;
+use RDF::QueryX::Lazy;
 
 handle GET
 {
 
 handle show_form
 {
-	$ctxt->data("show SPARQL endpoint form");
-	$ctxt->data_type("Text");
+	$ctxt->data(<<'	FORM');
+	
+	<title>SPARQL Query Form</title>
+	<h1>SPARQL Query Form</h1>
+	
+	<form action="" method="post" class="sparql">
+		<div class="textarea">
+			<textarea name="query" rows="12" cols="60">SELECT ?name
+WHERE {
+   GRAPH ?g {
+      &lt;http://tobyinkster.co.uk/#i> foaf:name ?name .
+   }
+}
+</textarea>
+			</div>
+			<div class="button">
+				<input type="submit" value="Query">
+			</div>
+	</form>
+	
+	FORM
+	$ctxt->data_type("Document");
 	OK;
 }
 
 method process_query ($ctxt, $sparql)
 {	
-	my $query = RDF::Query::->new(
+	my $query = RDF::QueryX::Lazy::->new(
 		$sparql,
 		qwh(
 			lang       sparql11
 		if ($results->is_boolean)
 		{
 			$ctxt->data($results);
-			$ctxt->data_type('Boolean');
+			$ctxt->data_type('Boolean');  # TODO
 		}
 		elsif ($results->is_bindings)
 		{

lib/Demiblog4/Transformer/Document.pm

+package Demiblog4::Transformer::Document;
+
+use Demiblog4::Sugar
+	-types => -all,
+	-base  => 'Demiblog4::Transformer';
+use HTTP::Negotiate;
+use HTML::HTML5::Parser;
+use HTML::HTML5::Writer;
+
+__PACKAGE__->register_events(qw(transform));
+
+has content_negotiation_data => (
+	is         => read_only,
+	isa        => ArrayRef[ArrayRef],
+	lazy_build => true,
+);
+
+method _build_content_negotiation_data
+{
+	[
+		[ HTML      => ('1.000', 'text/html') ],
+		[ XHTML     => ('0.900', 'application/xhtml+xml') ],
+	]
+}
+
+method load_queue
+{
+	return qw(transform);
+}
+
+handle transform
+{
+	my $choice = choose(
+		$self->content_negotiation_data,
+		$self->request->headers,
+	);
+	
+	my ($mediatype) =
+		map  { $_->[2] }
+		grep { $_->[0] eq $choice }
+		@{ $self->content_negotiation_data };
+	
+	my $dom = $ctxt->data;
+	$dom = HTML::HTML5::Parser::->load_html(string => $dom) if $dom ~~ Str;
+	
+	my $writer = HTML::HTML5::Writer::->new(
+		markup   => $choice,
+		charset  => 'ascii',
+		polyglot => true,
+	);
+	$self->response->content_type($mediatype);
+	$self->response->body(
+		$writer->document(
+			$ctxt->munge_dom($dom),
+		),
+	);
+	OK;
+}
+
+

lib/Demiblog4/Transformer/Graph.pm

 	my $style;
 	$style ||= 'Demiblog4::BlogIndex'      if $ctxt->data_subject ~~ ArrayRef;
 	$style ||= 'Demiblog4::SingleResource' if $ctxt->data_subject ~~ UriStr;
-	$style ||= 'Demiblog4::General';       # style of last resort
+	$style ||= 'Demiblog4::General';       # style of last resort (TODO)
 	
 	my $entitler = $ctxt->app->entitler;
 	my $title;

lib/Demiblog4/Transformer/Resultset.pm

+package Demiblog4::Transformer::Resultset;
+
+use Demiblog4::Sugar
+	-types => -all,
+	-base  => 'Demiblog4::Transformer';
+use HTTP::Negotiate;
+use HTML::HTML5::Parser;
+use HTML::HTML5::Writer;
+
+__PACKAGE__->register_events(qw(transform));
+
+has content_negotiation_data => (
+	is         => read_only,
+	isa        => ArrayRef[ArrayRef],
+	lazy_build => true,
+);
+
+method _build_content_negotiation_data
+{
+	[
+# TODO: need HTML table-based view
+#		[ HTML      => ('1.000', 'text/html') ],
+#		[ XHTML     => ('0.900', 'application/xhtml+xml') ],
+		[ XML       => ('1.000', 'application/sparql-results+xml') ],
+		[ JSON      => ('0.900', 'application/x-sparql-results+json') ],
+		[ Text      => ('0.900', 'text/plain') ],
+	]
+}
+
+method load_queue
+{
+	return qw(transform);
+}
+
+handle transform
+{
+	my $choice = choose(
+		$self->content_negotiation_data,
+		$self->request->headers,
+	);
+	
+	my ($mediatype) =
+		map  { $_->[2] }
+		grep { $_->[0] eq $choice }
+		@{ $self->content_negotiation_data };
+	$self->response->content_type($mediatype);
+	
+	my $rs = $ctxt->data;
+
+	given ($choice)
+	{
+		when ('XML')  { $self->response->body( $rs->as_xml ) }
+		when ('JSON') { $self->response->body( $rs->as_json ) }
+		default       { $self->response->body( $rs->as_string ) }
+	}
+	
+	OK;
+}
+
+

root/styles/screen.css

 	text-decoration: none;
 }
 
+form.sparql textarea {
+	width: 100%;
+}
+
 code .hl_Char {
 	color: #C0C;
 }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.