<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Gareth Jones &#187; techy solutions</title>
	<atom:link href="http://blog.garethj.com/category/techy-solutions/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.garethj.com</link>
	<description></description>
	<lastBuildDate>Tue, 07 Sep 2010 17:37:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Map controls for a single image with OpenLayers</title>
		<link>http://blog.garethj.com/2010/09/map-controls-for-a-single-image-with-openlayers/</link>
		<comments>http://blog.garethj.com/2010/09/map-controls-for-a-single-image-with-openlayers/#comments</comments>
		<pubDate>Tue, 07 Sep 2010 17:37:34 +0000</pubDate>
		<dc:creator>gareth</dc:creator>
				<category><![CDATA[techy solutions]]></category>
		<category><![CDATA[controls]]></category>
		<category><![CDATA[coordinates]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[mapping]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[marker]]></category>
		<category><![CDATA[markers]]></category>
		<category><![CDATA[openlayers]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[overlay]]></category>
		<category><![CDATA[overlays]]></category>
		<category><![CDATA[pan]]></category>
		<category><![CDATA[zoom]]></category>

		<guid isPermaLink="false">http://blog.garethj.com/?p=237</guid>
		<description><![CDATA[For a demo recently I needed to display a map, have pan/zoom controls, add markers and overlays etc etc. Google Maps (or similar) to the rescue right? Not in this case. Unfortunately the place wasn&#8217;t real, it was a location &#8230; <a href="http://blog.garethj.com/2010/09/map-controls-for-a-single-image-with-openlayers/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For a demo recently I needed to display a map, have pan/zoom controls, add markers and overlays etc etc. <a href="http://code.google.com/apis/maps/documentation/javascript/">Google Maps</a> (or similar) to the rescue right? Not in this case. Unfortunately the place wasn&#8217;t real, it was a location within the <a href="http://en.wikipedia.org/wiki/Battlefield_2">Battlefield 2 game</a> being used for some simulation of research we were doing. Now I know it&#8217;s possible to use something like Google Maps to display my own map tiles etc but it looked complicated and I think I&#8217;d have to pretend I was working with real latitude/longitudes etc. Then I stumbled upon <a href="http://openlayers.org/">OpenLayers</a>. I actually knew about OpenLayers before, as an open-source client-side library for mapping controls. What I didn&#8217;t realise was how flexible it was and that I could simply give it a single image and my own coordinate system and then let it do all the rest. <a href="http://openlayers.org/dev/examples/image-layer.html">This example</a> from the <a href="http://openlayers.org/dev/examples/">handy list of OpenLayers examples</a> demonstrates how it works in just a few lines of JavaScript. Perfect.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.garethj.com/2010/09/map-controls-for-a-single-image-with-openlayers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Programmatic page layouts using dojo and existing markup</title>
		<link>http://blog.garethj.com/2010/08/programmatic-page-layouts-using-dojo-and-existing-markup/</link>
		<comments>http://blog.garethj.com/2010/08/programmatic-page-layouts-using-dojo-and-existing-markup/#comments</comments>
		<pubDate>Mon, 09 Aug 2010 10:35:37 +0000</pubDate>
		<dc:creator>gareth</dc:creator>
				<category><![CDATA[techy solutions]]></category>
		<category><![CDATA[dijit]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[layout]]></category>
		<category><![CDATA[markup]]></category>
		<category><![CDATA[programmatic]]></category>

		<guid isPermaLink="false">http://blog.garethj.com/?p=215</guid>
		<description><![CDATA[The layout tutorials for dojo that I&#8217;ve seen all seem to fall into two categories: Markup-based: adding dojoType properties to HTML elements in the markup Programmatic: creating HTML elements in JavaScript When using a toolkit such as dojo for layout &#8230; <a href="http://blog.garethj.com/2010/08/programmatic-page-layouts-using-dojo-and-existing-markup/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://docs.dojocampus.org/dijit/layout">layout tutorials</a> for <a href="http://www.dojotoolkit.org/">dojo</a> that I&#8217;ve seen all seem to fall into two categories:</p>
<ul>
<li><strong>Markup-based</strong>: adding dojoType properties to HTML elements in the markup</li>
<li><strong>Programmatic:</strong> creating HTML elements in JavaScript</li>
</ul>
<p>When using a toolkit such as dojo for layout rather than standard CSS, my preference would be to keep the dojo layout stuff entirely in JavaScript, separate from the markup, whilst still using HTML to describe my content. This allows an easy transition to/from dojo and CSS layout techniques, doesn&#8217;t clutter the markup with dojo specific stuff that would only be needed when JavaScript is enabled, and just provides a cleaner separation. I was sure this must be possible in dojo and it is; it just doesn&#8217;t seem to be well documented anywhere.<br />
<span id="more-215"></span><br />
After playing for a while (and with quite a bit of help from <a href="http://twitter.com/thomasj">James</a>), I turned this&#8230;</p>
<pre>&lt;script type="text/javascript"&gt;
dojo.require("dijit.layout.BorderContainer");
dojo.require("dijit.layout.TabContainer");
dojo.require("dijit.layout.AccordionContainer");
dojo.require("dijit.layout.ContentPane");
&lt;/script&gt;

&lt;div dojoType="dijit.layout.BorderContainer"
  style="width: 100%; height: 100%;"&gt;
  &lt;div dojoType="dijit.layout.ContentPane" region="top"&gt;
    Top pane
  &lt;/div&gt;
  &lt;div dojoType="dijit.layout.AccordionContainer" region="leading"&gt;
    &lt;div dojoType="dijit.layout.AccordionPane" title="pane #1"&gt;
      accordion pane #1
    &lt;/div&gt;
    &lt;div dojoType="dijit.layout.AccordionPane" title="pane #2"&gt;
      accordion pane #2
    &lt;/div&gt;
    &lt;div dojoType="dijit.layout.AccordionPane" title="pane #3"&gt;
      accordion pane #3
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div dojoType="dijit.layout.TabContainer" region="center"&gt;
    &lt;div dojoType="dijit.layout.ContentPane" title="tab #1"&gt;
      tab pane #1
    &lt;/div&gt;
    &lt;div dojoType="dijit.layout.ContentPane" title="tab #2"&gt;
      tab pane #2
    &lt;/div&gt;
    &lt;div dojoType="dijit.layout.ContentPane" title="tab #3"&gt;
      tab pane #3
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div dojoType="dijit.layout.ContentPane" region="trailing"&gt;
    Trailing pane
  &lt;/div&gt;
  &lt;div dojoType="dijit.layout.ContentPane" region="bottom"&gt;
    Bottom pane
  &lt;/div&gt;
&lt;/div&gt;

&lt;style type="text/css"&gt;
 html, body {
 width: 100%;
 height: 100%;
 margin: 0;
 }
&lt;/style&gt;</pre>
<p>&#8230;into this&#8230;</p>
<pre>&lt;script type="text/javascript"&gt;
  dojo.require("dijit.layout.BorderContainer");
  dojo.require("dijit.layout.TabContainer");
  dojo.require("dijit.layout.AccordionContainer");
  dojo.require("dijit.layout.ContentPane");

  dojo.ready(function () {
    var mainContainer = new dijit.layout.BorderContainer(
      {}, 'mainContainer');
    var topPane = new dijit.layout.ContentPane(
      {'region': 'top'}, 'topPane');
    mainContainer.addChild(topPane);
    var leftPane = new dijit.layout.AccordionContainer(
      {'region': 'leading'}, 'leftPane');
    var accordionPane1 = new dijit.layout.AccordionPane(
      {'title': 'pane #1'}, 'accordionPane1');
    var accordionPane2 = new dijit.layout.AccordionPane(
      {'title': 'pane #2'}, 'accordionPane2');
    var accordionPane3 = new dijit.layout.AccordionPane(
      {'title': 'pane #3'}, 'accordionPane3');
    leftPane.addChild(accordionPane1);
    leftPane.addChild(accordionPane2);
    leftPane.addChild(accordionPane3);
    mainContainer.addChild(leftPane);
    var centerPane = new dijit.layout.TabContainer(
      {'region': 'center'}, 'centerPane');
    var tabPane1 = new dijit.layout.AccordionPane(
      {'title': 'tab #1'}, 'tabPane1');
    var tabPane2 = new dijit.layout.AccordionPane(
      {'title': 'tab #2'}, 'tabPane2');
    var tabPane3 = new dijit.layout.AccordionPane(
      {'title': 'tab #3'}, 'tabPane3');
    centerPane.addChild(tabPane1);
    centerPane.addChild(tabPane2);
    centerPane.addChild(tabPane3);
    mainContainer.addChild(centerPane);
    var rightPane = new dijit.layout.ContentPane(
      {'region': 'trailing'}, 'rightPane');
    mainContainer.addChild(rightPane);
    var bottomPane = new dijit.layout.ContentPane(
      {'region': 'bottom'}, 'bottomPane');
    mainContainer.addChild(bottomPane);
    mainContainer.startup();
  });
&lt;/script&gt;

&lt;div id="mainContainer"&gt;
  &lt;div id="topPane"&gt;Top pane&lt;/div&gt;
  &lt;div id="leftPane"&gt;
    &lt;div id="accordionPane1"&gt;accordion pane #1&lt;/div&gt;
    &lt;div id="accordionPane2"&gt;accordion pane #2&lt;/div&gt;
    &lt;div id="accordionPane3"&gt;accordion pane #3&lt;/div&gt;
  &lt;/div&gt;
  &lt;div id="centerPane"&gt;
    &lt;div id="tabPane1"&gt;tab pane #1&lt;/div&gt;
    &lt;div id="tabPane2"&gt;tab pane #2&lt;/div&gt;
    &lt;div id="tabPane3"&gt;tab pane #3&lt;/div&gt;
  &lt;/div&gt;
  &lt;div id="rightPane"&gt;Trailing pane&lt;/div&gt;
  &lt;div id="bottomPane"&gt;Bottom pane&lt;/div&gt;
&lt;/div&gt;

&lt;style type="text/css"&gt;
  html, body, #mainContainer {
    width: 100%;
    height: 100%;
    margin: 0;
  }
&lt;/style&gt;</pre>
<p>There&#8217;s lots of code but I prefer the separation. In reality I&#8217;d move the JavaScript etc into a separate files but it&#8217;s easier to demonstrate like this.</p>
<p>A couple of gotchas:</p>
<ul>
<li> <strong>Adding extra HTML elements dynamically</strong><br />
Sometimes dojo will require extra <code>div</code>s for layout purposes (for different digit classes, e.g. dijit.layout.BorderContainer). Clearly it would be wrong to modify markup to include extra <code>div</code>s just for this so you&#8217;ll probably want to create them programmatically. This is fine, but instead of using <code>addChild</code> to append a child, you&#8217;ll need to place the new element in the DOM yourself using <code>dojo.place(myDynamicElement.domNode, myExistingElement.domNode);</code>.</li>
<li> <strong>Specifying the top level widget</strong><br />
If you use dojo&#8217;s markup method (with <code>djConfig="parseOnLoad:true"</code> set or running <code>dojo.parser.parse()</code>), the top level widgets are determined automatically. With this method, we need to manually start it by calling <code>startup()</code> on the top level widget (in our case, the <code>mainContainer</code> element). Otherwise, no layout occurs at all.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.garethj.com/2010/08/programmatic-page-layouts-using-dojo-and-existing-markup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Presenting from a single canvas with HTML5</title>
		<link>http://blog.garethj.com/2010/07/presenting-from-a-single-canvas-with-html5/</link>
		<comments>http://blog.garethj.com/2010/07/presenting-from-a-single-canvas-with-html5/#comments</comments>
		<pubDate>Tue, 27 Jul 2010 17:37:45 +0000</pubDate>
		<dc:creator>gareth</dc:creator>
				<category><![CDATA[techy solutions]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[presentation]]></category>
		<category><![CDATA[slide]]></category>
		<category><![CDATA[transform]]></category>

		<guid isPermaLink="false">http://blog.garethj.com/?p=184</guid>
		<description><![CDATA[I&#8217;ve always been a fan of non-standard presentation techniques to help engage the audience. One that&#8217;s caught my eye recently is the idea of presenting from a single canvas, using a defined path but with the ability to digress. The &#8230; <a href="http://blog.garethj.com/2010/07/presenting-from-a-single-canvas-with-html5/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve always been a fan of non-standard presentation techniques to help engage the audience. One that&#8217;s caught my eye recently is the idea of presenting from a single canvas, using a defined path but with the ability to digress. The two current offerings I know about for this technique are <a href="http://prezi.com/">Prezi</a> and <a href="http://code.google.com/p/jessyink/">JessyInk</a> (see <a href="http://people.w3.org/~dom/archives/2009/10/prezi-vs-jessyink/">here</a> and <a href="http://www.raphink.info/2009/10/dynamic-presentations-with-jessyink.html">here</a> for some comparisons between the two).</p>
<p>I figured that it would be nice to use some of the new features in HTML5/CSS3 to do this so you can just put together a standard HTML page (which is your 2D canvas &#8211; not to be confused with the new <code>canvas</code> element!) and have the traversing/zooming/rotating for free. This would also mean no need to require browser plug-ins (e.g. Flash for Prezi). SVG is a nice option but I&#8217;m guessing more people have standard HTML skills.</p>
<p>I&#8217;ve put together some code (called fivePrez for want of a better name), a rough attempt at doing some of this stuff. Unfortunately it currently only works on Firefox 4 which is still in beta. I haven&#8217;t even managed getting it working on Chrome because Webkit seems to do things differently (possibly positioning differences when you&#8217;ve scaled an element?). So if you have a version of Firefox 4 running, please try <a href="http://garethj.com/fivePrez">the demo</a>. Otherwise, check out the video below. It&#8217;s not the best example but hopefully it gets the point across. Remember, the elements on the canvas are not moving/scaling/rotating into view, the canvas itself is moving so all the elements stay where they are in relation to each other.</p>
<p><iframe class="youtube-player" type="text/html" width="640" height="385" src="http://www.youtube.com/embed/w7486ewyZHA" frameborder="0"></iframe></p>
<p>Currently fivePrez works simply by including the <a href="http://garethj.com/fivePrez/fivePrez.js">fivePrez.js</a> JavaScript file (and <a href="http://jquery.com/">jQuery</a>) and specifying (using JavaScript) a list of CSS selectors to define the path to traverse (e.g. <code>fivePrez.setPath(['#element1', '#element2']);</code>). Keyboard and mouse controls are option and work by including the appropriate <a href="http://garethj.com/fivePrez/fivePrez.controls.keyboard.js">keyboard</a>/<a href="http://garethj.com/fivePrez/fivePrez.controls.mouse.js">mouse</a> script. The keyboard module allows you to traverse the path as follows (which should allow for using a remote clicker):</p>
<ul>
<li>Right/Page Down: next</li>
<li>Left/Page Up: previous</li>
<li>Up: home (i.e. standard rendering for the page)</li>
</ul>
<p>The mouse navigation allows you to double-click an element on the path to zoom straight to it.</p>
<p>I&#8217;ve also implemented a callback option to allow you to be notified when an item on the path is being moved to / away from as follows:<br />
<code><br />
fivePrez.viewChange(<br />
&nbsp;&nbsp;function (viewId, viewSelector) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;// View displayed<br />
&nbsp;&nbsp;},<br />
&nbsp;&nbsp;function (viewId, viewSelector) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;// View hidden<br />
&nbsp;&nbsp;}));<br />
</code><br />
This is useful for e.g. starting/stopping video as I do in <a href="http://garethj.com/fivePrez/about.js">my example</a>.</p>
<p>The code generally works by finding the element using the CSS selector provided in the path, determining the element&#8217;s current position, rotation etc and then performing a CSS transform on a parent container (generated by fivePrez) so all elements move with each other and the selected element is moved to the centre of the window and rotated appropriately.</p>
<p>Obviously this is very rough round the edges but interesting for a proof of concept. I might give it a go for my next speaking engagement if I&#8217;m confident it&#8217;ll do the trick. The main problems at present seem to be to do with editing rather than viewing; ideally it would at least have some user interface controls and the ability to drag around the canvas with the mouse.</p>
<p>Worth noting that Google have put together <a href="http://slides.html5rocks.com/">a nice example</a> using HTML5 as a presentation technology to demonstrate the new standard (and Chrome of course).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.garethj.com/2010/07/presenting-from-a-single-canvas-with-html5/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Installing Firefox beta nightlies in Ubuntu</title>
		<link>http://blog.garethj.com/2010/07/installing-firefox-beta-nightlies-in-ubuntu/</link>
		<comments>http://blog.garethj.com/2010/07/installing-firefox-beta-nightlies-in-ubuntu/#comments</comments>
		<pubDate>Fri, 16 Jul 2010 10:18:15 +0000</pubDate>
		<dc:creator>gareth</dc:creator>
				<category><![CDATA[techy solutions]]></category>

		<guid isPermaLink="false">http://blog.garethj.com/?p=176</guid>
		<description><![CDATA[There&#8217;s a handy PPA for installing Mozilla Firefox nightly builds on Ubuntu but as well as the Firefox 4 builds, it also contains Firefox 3 nightly builds. Thanks to Dom I learned how to reduce the priority of the Mozilla &#8230; <a href="http://blog.garethj.com/2010/07/installing-firefox-beta-nightlies-in-ubuntu/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s a <a href="https://launchpad.net/~ubuntu-mozilla-daily/+archive/ppa">handy PPA</a> for installing Mozilla Firefox nightly builds on Ubuntu but as well as the Firefox 4 builds, it also contains Firefox 3 nightly builds. <a href="https://twitter.com/oldmanuk/statuses/18673358922">Thanks to Dom</a> I learned how to <a href="https://help.ubuntu.com/community/PinningHowto#Pinning%20the%20ubuntu-mozilla-daily%20PPA">reduce the priority of the Mozilla daily PPA using pinning</a> so packages from the standard repositories take priority over any from the Mozilla one, even with a higher version number. Instructions are as follows (tested on Ubuntu 10.04):</p>
<p>First add the <a href="https://launchpad.net/~ubuntu-mozilla-daily/+archive/ppa">PPA</a>. Then edit <code>/etc/apt/preferences.d/ubuntu-mozilla-daily-pin-400</code> and <code>/var/lib/synaptic/preferences</code> (the latter to ensure &#8216;Mark all upgrades&#8217; in Synaptic does the same as Update Manager / <code>apt-get</code>) to contain the following:<br />
<code><br />
Package: *<br />
Pin: release o=LP-PPA-ubuntu-mozilla-daily<br />
Pin-Priority: 400<br />
</code></p>
<p>Now the <code>firefox-4.0</code> and <code>firefox-4.0-gnome-support </code> packages are theoretically ready to be installed. However, I had some installation issues which were solved by created a couple of files:</p>
<ul>
<li><code>/usr/bin/firefox-4.0sudo</code> (link to the executable using &#8216;<code>ln -s /usr/lib/firefox-4.0b2pre/firefox-4.0 /usr/bin/firefox-4.0</code>&#8216;)</li>
<li><code>/usr/lib/firefox-4.0b2pre/firefox-4.0-restart-required.update-notifier</code> (just create an empty file)</li>
</ul>
<p>Now your Firefox 4 nightly build should be regularly updated and can be run by executing the <code>firefox-4.0</code> command. Your existing stable Firefox 3 build should be unaffected.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.garethj.com/2010/07/installing-firefox-beta-nightlies-in-ubuntu/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using Jena as a SPARQL endpoint</title>
		<link>http://blog.garethj.com/2010/01/using-jena-as-a-sparql-endpoint/</link>
		<comments>http://blog.garethj.com/2010/01/using-jena-as-a-sparql-endpoint/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 15:27:30 +0000</pubDate>
		<dc:creator>gareth</dc:creator>
				<category><![CDATA[techy solutions]]></category>
		<category><![CDATA[arc]]></category>
		<category><![CDATA[arq]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[endpoint]]></category>
		<category><![CDATA[graph]]></category>
		<category><![CDATA[jena]]></category>
		<category><![CDATA[joseki]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[named]]></category>
		<category><![CDATA[optional]]></category>
		<category><![CDATA[owl]]></category>
		<category><![CDATA[rdf]]></category>
		<category><![CDATA[semantic]]></category>
		<category><![CDATA[semantic web]]></category>
		<category><![CDATA[sparql]]></category>
		<category><![CDATA[sparql-update]]></category>
		<category><![CDATA[sparul]]></category>
		<category><![CDATA[specification]]></category>
		<category><![CDATA[store]]></category>
		<category><![CDATA[triple]]></category>
		<category><![CDATA[triple store]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.garethj.com/?p=154</guid>
		<description><![CDATA[I&#8217;ve been involved in a few projects at work over the last couple of years that have made use of Semantic Web technologies (triple stores, RDF, OWL, SPARQL etc). For most of these I&#8217;ve made of ARC, a really great &#8230; <a href="http://blog.garethj.com/2010/01/using-jena-as-a-sparql-endpoint/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been involved in a few projects at work over the last couple of years that have made use of Semantic Web technologies (triple stores, RDF, OWL, SPARQL etc). For most of these I&#8217;ve made of <a href="http://arc.semsol.org/">ARC</a>, a really great PHP library by <a href="http://twitter.com/bengee">Ben Nowack</a> for interacting with RDF and triple stores. As great as ARC is, it does have a few drawbacks such as being limited to MySQL triple stores, <a href="http://arc.semsol.org/community/arc-dev/archives/2009/12/PM-GA.20091215173026.C408A.2.1D@semsol.com">some issues with OPTIONAL queries</a> and it <a href="http://www.w3.org/2001/sw/DataAccess/tests/implementations">doesn&#8217;t entirely support the SPARQL specification</a>.</p>
<p>For these reasons and for general flexibility, my current project wanted to be able to easily swap the underlying triple store from ARC to Jena as needed so I needed to investigate how to expose a Jena triple store as a SPARQL endpoint. After working this out, I now really really appreciate <a href="http://arc.semsol.org/docs/v2/endpoint">how easy ARC makes this</a>.</p>
<p>Jena doesn&#8217;t appear to ship with the ability to expose the <a href="http://jena.sourceforge.net/ARQ/">ARQ SPARQL processor</a> as a SPARQL endpoint and hence you need to make use of a separate piece of software called <a href="http://www.joseki.org/">Joseki</a>. The following is the list of things I needed to do to get this working in my environment. Note that your setup may have different requirements and also I may have completely misunderstood the best way of doing this!</p>
<ol>
<li>Setup a database to use as your triple store and get a JDBC driver so Joseki can interact with it from Java</li>
<li><a href="http://joseki.sourceforge.net/download.html">Download</a> and extract Joseki</li>
<li>Add the JDBC driver to the Joseki classpath (e.g. for Windows by adding the following line to <code>bin\joseki_path.bat</code>: <code>set CP=%CP%;C:\my_jdbc_driver\my_jdbc_driver.jar</code>)</li>
<li>Add the following to joseki-config.ttl:
<pre>
 <#myProjectUpdate>
   rdf:type            joseki:Service ;
   rdfs:label          "My Project SPARQL/Update" ;
   joseki:serviceRef   "sparql/myproject/update" ;
   joseki:dataset      <#myProject> ;
   joseki:processor    joseki:ProcessorSPARQLUpdate .

 <#myProjectRead>
   rdf:type            joseki:Service ;
   rdfs:label          "SPARQL" ;
   joseki:serviceRef   "sparql/myproject/read" ;
   joseki:dataset      <#myProject> ;
   joseki:processor    joseki:ProcessorSPARQL_FixedDS .

 <#myProject>
   rdf:type            ja:RDFDataset ;
   rdfs:label          "My Project" ;
   ja:defaultGraph     <#myProjectDB> .

 <#myProjectDB>
   rdf:type            ja:RDBModel ;
   ja:connection       [
                         ja:dbType "MySQL" ;
                         ja:dbURL          <jdbc:mysql://localhost/myproject-database> ;
                         ja:dbUser         "myproject-database-username" ;
                         ja:dbPassword     "myproject-database-password" ;
                         ja:dbClass        "com.mysql.jdbc.Driver"
                        ] ;
   ja:reificationMode    ja:minimal ;
   ja:modelName        "DEFAULT" .
    </pre>
</li>
<li>Set the <code>JOSEKIROOT</code> environment variable to the location you extracted Joskei</li>
<li>Run Joseki (from it&#8217;s directory) by executing <code>bin/rdfserver.bat</code></li>
</ol>
<p>Note that I wanted to be able to make use of <a href="http://www.w3.org/Submission/SPARQL-Update/">SPARUL</a> to update data using the SPARQL endpoint. In ARC I can use <a href="http://arc.semsol.org/docs/v2/sparql+">SPARQL+</a> (which is effectively the same for my purposes) on the same endpoint as normal SPARQL queries. For Joseki however, I needed to expose two different endpoints, one for standard SPARQL queries and one for updating.</p>
<p>The one thing I haven&#8217;t yet worked out how to do it to be able to use named graphs in my Jena triple store when inserting data. I discovered that the SPARUL update specification <a href="http://www.w3.org/Submission/SPARQL-Update/#t415">requires you to create the graph first</a> (unlike ARC&#8217;s SPARQL+) but executing e.g. <code>CREATE GRAPH &lt;http://mygraph/&gt;</code> seems to fail silently as any following <code>INSERT INTO &lt;http://mygraph/&gt;</code> statement fails saying that the graph doesn&#8217;t exist. Something to keep investigating. It may be something to do with support for the different types of Jena store (RDB, SDB, TDB, etc) which I don&#8217;t fully understand yet (I think my instructions above are using RDB which appears to be old but I couldn&#8217;t get TDB or SDB working at all).</p>
<p>So all in all I&#8217;m pleased to have worked out how to set this up but I will most certainly continue to use ARC where possible as Jena environments seem unnecessarily complex (although this might simply be because it tends to support the W3 specifications fully!).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.garethj.com/2010/01/using-jena-as-a-sparql-endpoint/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Wireless on a Dell Mini 10v in Ubuntu 9.10</title>
		<link>http://blog.garethj.com/2009/10/wireless-on-a-dell-mini-10v-in-ubuntu-9-10/</link>
		<comments>http://blog.garethj.com/2009/10/wireless-on-a-dell-mini-10v-in-ubuntu-9-10/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 18:09:00 +0000</pubDate>
		<dc:creator>gareth</dc:creator>
				<category><![CDATA[techy solutions]]></category>
		<category><![CDATA[10v]]></category>
		<category><![CDATA[9.10]]></category>
		<category><![CDATA[broadcom]]></category>
		<category><![CDATA[dell]]></category>
		<category><![CDATA[driver]]></category>
		<category><![CDATA[drivers]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[karmic]]></category>
		<category><![CDATA[mini]]></category>
		<category><![CDATA[netbook]]></category>
		<category><![CDATA[nr]]></category>
		<category><![CDATA[proprietary]]></category>
		<category><![CDATA[remix]]></category>
		<category><![CDATA[sta]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[wifi]]></category>
		<category><![CDATA[wireless]]></category>

		<guid isPermaLink="false">http://blog.garethj.com/?p=147</guid>
		<description><![CDATA[I installed the Ubuntu 9.10 Netbook Remix release candidate on my new Dell Mini 10v and the wireless didn&#8217;t work out of the box. I think this is because there isn&#8217;t an open source driver and Ubuntu doesn&#8217;t ship with &#8230; <a href="http://blog.garethj.com/2009/10/wireless-on-a-dell-mini-10v-in-ubuntu-9-10/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I installed the Ubuntu 9.10 Netbook Remix release candidate on my new Dell Mini 10v and the wireless didn&#8217;t work out of the box. I think this is because there isn&#8217;t an open source driver and Ubuntu doesn&#8217;t ship with proprietary drivers installed. Now the 9.10 has been released this problem may have disappeared, but in case anyone else sees this, the way to solve it is to install the proprietary wireless driver (Broadcom STA) yourself.</p>
<p>This is pretty easy using the Ubuntu restricted drivers tools: Ubuntu Menu -> System -> Hardware Drivers (in the 2nd box of applications). Note that you&#8217;ll need an Internet connection to actually install this so hopefully you can make use of a wired connection temporarily! When I initially installed this driver there were actually two to choose from but it was the Broadcom STA driver that worked. Now I only see a single option available.</p>
<p><img src="http://blog.garethj.com/wp-content/uploads/2009/10/Hardware-Drivers.png" alt="Hardware Drivers" title="Hardware Drivers" width="502" height="575" class="aligncenter size-full wp-image-149" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.garethj.com/2009/10/wireless-on-a-dell-mini-10v-in-ubuntu-9-10/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Indicator applet API changes in Ubuntu 9.10</title>
		<link>http://blog.garethj.com/2009/10/indicator-applet-api-changes-in-ubuntu-9-10/</link>
		<comments>http://blog.garethj.com/2009/10/indicator-applet-api-changes-in-ubuntu-9-10/#comments</comments>
		<pubDate>Thu, 22 Oct 2009 13:20:25 +0000</pubDate>
		<dc:creator>gareth</dc:creator>
				<category><![CDATA[techy solutions]]></category>
		<category><![CDATA[9.10]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[applet]]></category>
		<category><![CDATA[attention]]></category>
		<category><![CDATA[changes]]></category>
		<category><![CDATA[draw-attention]]></category>
		<category><![CDATA[indicator]]></category>
		<category><![CDATA[karmic]]></category>
		<category><![CDATA[libindicate]]></category>
		<category><![CDATA[notification]]></category>
		<category><![CDATA[notifications]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[python-indicate]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://blog.garethj.com/?p=139</guid>
		<description><![CDATA[The API for the indicator applet has changed in Karmic and a little internal IBM Python application that I&#8217;ve written stopped working. Only a couple of minor changes were needed but trying to track down exactly what these were was &#8230; <a href="http://blog.garethj.com/2009/10/indicator-applet-api-changes-in-ubuntu-9-10/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The API for the <a href="https://wiki.ubuntu.com/MessagingMenu">indicator applet</a> has <a href="https://wiki.ubuntu.com/MessagingMenu/UDSKarmic">changed in Karmic</a> and a little internal IBM Python application that I&#8217;ve written stopped working. Only a couple of minor changes were needed but trying to track down exactly what these were was not as easy a task as I&#8217;d have liked.</p>
<p><strong>Creating the indicator</strong><br />
The class used to represent an indicator appears to have changed from <code>IndicatorMessage</code> to <code>Indicator</code> so I threw in the following code to try the new one and fallback to the old one:<br />
<code><br />
try:<br />
&nbsp;&nbsp;# Ubuntu 9.10 and above<br />
&nbsp;&nbsp;indicator = indicate.Indicator()<br />
except:<br />
&nbsp;&nbsp;# Ubuntu 9.04<br />
&nbsp;&nbsp;indicator = indicate.IndicatorMessage()<br />
</code><br />
<strong>Drawing attention</strong><br />
Previously, indicators automatically made the indicator applet draw your attention with a green dot. In Karmic the green dot appears to have been replaced with a change of the envelope colour to black but it is no longer automatic. To make this work you need to set the <code>draw-attention</code> property:</p>
<p><code>indicator.set_property('draw-attention', 'true');</code></p>
<p>Note that they&#8217;ve also added a <code>count</code> property to display how many notifications are from the same source.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.garethj.com/2009/10/indicator-applet-api-changes-in-ubuntu-9-10/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Building .deb packages for Python applications</title>
		<link>http://blog.garethj.com/2009/06/building-deb-packages-for-python-applications/</link>
		<comments>http://blog.garethj.com/2009/06/building-deb-packages-for-python-applications/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 15:29:00 +0000</pubDate>
		<dc:creator>gareth</dc:creator>
				<category><![CDATA[techy solutions]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[deb]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[packaging]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://blog.garethj.com/?p=132</guid>
		<description><![CDATA[Building .deb packages for Python applications Recently I wanted to build a .deb package for an internal IBM application I was writing so that users could easily install it and also so we could distribute them through some internal repositories. &#8230; <a href="http://blog.garethj.com/2009/06/building-deb-packages-for-python-applications/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Building .deb packages for Python applications</p>
<p>Recently I wanted to build a .deb package for an internal IBM application I was writing so that users could easily install it and also so we could distribute them through some internal repositories. This proved a bit harder than I expected so this is a quick summary of how I ended up doing it. Note that your requirements might be entirely different!</p>
<p>The first thing to do is to create the files required by the packaging process. I discovered that the <code>dh_make</code> command can create a load of sample files that can be used as part of this process. To do this, create a directory in the format [package-name]-[version] (e.g. my-great-app-1.0) and run <code>dh_make</code> from within it (I specified &#8216;s&#8217; for single binary when prompted). This will create a load of sample files in a &#8216;debian&#8217; subdirectory. Delete any of these you don&#8217;t need (which is probably most of them); I kept the following:</p>
<ul>
<li><strong>changelog</strong> &#8211; change history for all versions of the app (keep to the <a href="http://www.debian.org/doc/debian-policy/ch-source.html#s-dpkgchangelog">format specified by the Debian Policy Manual</a>)</li>
<li><strong>compat</strong> &#8211; no idea why I needed this but things don&#8217;t work properly later if I don&#8217;t</li>
<li><strong>control</strong> &#8211; the details of the package you are creating (see <a href="http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-sourcecontrolfiles">the specification</a> for all configuration options)</li>
<li><strong>dirs</strong> &#8211; the list of directories in which your app will install files (e.g. /usr/bin, /usr/share/pyshared/my-great-app, /usr/share/applications)</li>
<li><strong>README.Debian</strong> &#8211; the README for your app</li>
<li><strong>rules</strong> &#8211; a MakeFile with instructions for how to create the package (for my Python app the important bit here was in the &#8216;install&#8217; section; here I created a <code>$(CURDIR)/debian/my-great-app</code> subdirectory and copied all files into it as if it were <code>/</code>, e.g. binary to <code>$(CURDIR)/debian/my-great-app/usr/bin/my-great-app</code>)</li>
</ul>
<p>Once I&#8217;d created all those files and put them in <code>my-great-app/packaging/debian</code> and my source in <code>my-great-app/src</code> I created a simple build script <code>my-great-app/bin/build</code>. This looked something like the following:</p>
<p><code><br />
#!/bin/bash</p>
<p>export VERSION=1.0<br />
export DEBFULLNAME="Gareth Jones"<br />
export DEBEMAIL="my-real-email-not-this@somewhere.com"</p>
<p>cd ../build<br />
sudo rm -rf my-great-app*<br />
mkdir -p my-great-app-$VERSION<br />
cp -u ../src/*.py ../src/*.desktop ../src/*.ico ../packaging/my-great-app my-great-app-$VERSION<br />
tar -czf my-great-app-$VERSION.orig.tar.gz my-great-app-$VERSION/<br />
cd my-great-app-$VERSION<br />
mkdir debian<br />
cp -u ../../packaging/debian/* debian/<br />
gksu dpkg-buildpackage<br />
</code></p>
<p>This should create you a <code>my-great-app_1.0-1_all.deb</code> and the <code>my-great-app_1.0-1_i386.changes</code>, <code>my-great-app_1.0-1.dsc</code> and <code>my-great-app_1.0-1.tar.gz</code> files your repository maintainer might want.</p>
<p>A really useful video I found for helping me fill in the contents of the debian control files (and getting me through the whole process) was <a href="http://wiki.showmedo.com/index.php/LinuxJensMakingDeb">here</a>. Definitely worth checking out if you need to do this yourself.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.garethj.com/2009/06/building-deb-packages-for-python-applications/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Building a RESTful Web application with PHP</title>
		<link>http://blog.garethj.com/2009/02/building-a-restful-web-application-with-php/</link>
		<comments>http://blog.garethj.com/2009/02/building-a-restful-web-application-with-php/#comments</comments>
		<pubDate>Tue, 17 Feb 2009 16:52:22 +0000</pubDate>
		<dc:creator>gareth</dc:creator>
				<category><![CDATA[techy solutions]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[client applications]]></category>
		<category><![CDATA[delete]]></category>
		<category><![CDATA[format]]></category>
		<category><![CDATA[get]]></category>
		<category><![CDATA[header]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[post]]></category>
		<category><![CDATA[put]]></category>
		<category><![CDATA[request]]></category>
		<category><![CDATA[response]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[REST Service]]></category>
		<category><![CDATA[rewriting]]></category>
		<category><![CDATA[status]]></category>
		<category><![CDATA[status code]]></category>
		<category><![CDATA[url]]></category>
		<category><![CDATA[Web application]]></category>
		<category><![CDATA[Web interfaces]]></category>

		<guid isPermaLink="false">http://blog.garethj.com/?p=127</guid>
		<description><![CDATA[Recently I&#8217;ve been putting together a Web application for a research project. I decided it was about time I really looked properly into REST so my Web interfaces are better structured. I won&#8217;t go into all the benefits here, you &#8230; <a href="http://blog.garethj.com/2009/02/building-a-restful-web-application-with-php/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Recently I&#8217;ve been putting together a Web application for a research project. I decided it was about time I really looked properly into <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">REST</a> so my Web interfaces are better structured. I won&#8217;t go into all the benefits here, you can <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer#Claimed_benefits">read for yourself</a>. Suffice to say it seems like a good approach to take.</p>
<p>This is quite a long article and you might only be interested in some of it so here are the sections:</p>
<ul>
<li><a href="/2009/02/17/building-a-restful-web-application-with-php/#requestData">Getting access to request data</a></li>
<li><a href="/2009/02/17/building-a-restful-web-application-with-php/#returningResponses">Returning appropriate responses</a></li>
<li><a href="/2009/02/17/building-a-restful-web-application-with-php/#dataFormats">Handling different data formats</a></li>
<li><a href="/2009/02/17/building-a-restful-web-application-with-php/#singleScript">Passing all requests to a single PHP script</a></li>
<li><a href="/2009/02/17/building-a-restful-web-application-with-php/#requestedUrl">Determining the full requested URL</a></li>
<li><a href="/2009/02/17/building-a-restful-web-application-with-php/#genericService">A generic REST Service class</a></li>
</ul>
<p>If you have an suggestions for improvement, please let me know &#8211; this was a first attempt!<br />
<span id="more-127"></span></p>
<p>Some credit for this article should go to <a href="http://www.lornajane.net/">lornajane</a> for her PHP REST Server articles (<a href="http://www.lornajane.net/posts/2008/PHP-Rest-Server-part-1-of-3">Part 1</a>, <a href="http://www.lornajane.net/posts/2008/PHP-Rest-Server-part-2-of-3">Part 2</a>, <a href="http://www.lornajane.net/posts/2008/PHP-Rest-Server-part-3-of-3">Part 3</a>) which I used as a good starting point.</p>
<p><strong><a name="requestData">Getting access to request data</a></strong></p>
<p>Getting access to HTTP <a href="http://php.net/manual/en/reserved.variables.get.php">GET arguments</a> or <a href="http://php.net/manual/en/reserved.variables.post.php">POST data</a> is well known and easy. With a REST interface you are likely to support other HTTP verbs such as PUT and DELETE. Getting data from these requests is not obvious but luckily <a href="http://www.lornajane.net/">lornajane</a> had <a href="http://www.lornajane.net/posts/2008/Accessing-Incoming-PUT-Data-from-PHP">worked this out</a> for me:<br />
<code><br />
parse_str(file_get_contents('php://input'), $arguments);<br />
</code></p>
<p><strong><a name="returningResponses">Returning appropriate responses</a></strong></p>
<p>With REST you should really make use of the HTTP <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">Status Codes</a> for all requests (rather that using <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1">200 OK</a> for everything). In PHP, this can be done with the <a href="http://php.net/header"><code>header</code></a> function in a couple of ways:<br />
<code><br />
// When setting just the status code<br />
header('HTTP/1.1 405 Method Not Allowed');<br />
// When you're setting another header at the same time<br />
header('Allow: GET, HEAD, POST, DELETE', true, 405);<br />
</code></p>
<p>I haven&#8217;t found a way of sending just the status code number (e.g. 405) without specifying the exact text (&#8216;Method Not Allowed&#8217;) but these are part of a fixed specification so it&#8217;s not a huge problem.</p>
<p>The following is a list of status codes that I&#8217;ve used and why:</p>
<ul>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1">200 OK</a>: successful request when data is returned</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.2">201 Created</a>: Successful request when something is created at another URL (specified by the value returned in the <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.30">Location</a> header)</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5">204 No Content</a>: Successful request when no data is returned</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1">400 Bad Request</a>: Incorrect parameters specified on request</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5">404 Not Found</a>: No resource at the specified URL</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.6">405 Method Not Allowed</a>: when a client makes a request using an HTTP verb not supported at the requested URL (supported verbs are returned in the <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7">Allow</a> header)</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.7">406 Not Acceptable</a>: Requested data format not supported</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1">500 Internal Server Error</a>: An unexpected error occurred</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.2">501 Not Implemented</a>: when a client makes a request using an unknown HTTP verb</li>
</ul>
<p><strong><a name="dataFormats">Handling different data formats</a></strong></p>
<p>As URLs are supposed to represent resources in REST, it is a feasible requirement that client applications would like to receive responses from the same URL in different formats. Clients can specify the data formats they are capable of understanding using the <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1">HTTP Accept header</a>. In Javacript this can be set using the <a href="http://www.w3.org/TR/XMLHttpRequest/#setrequestheader"><code>setRequestHeader</code></a> method on the <a href="http://www.w3.org/TR/XMLHttpRequest/">XMLHttpRequest object</a>. Using jQuery as my current Javascript library of choice, the code for doing this is as follows:<br />
<code><br />
$.ajax({<br />
&nbsp;&nbsp;type: method, // GET, POST, PUT, DELETE etc.<br />
&nbsp;&nbsp;url: url, // The actual URL to make the request<br />
&nbsp;&nbsp;data: data,  // Any data/parameters to send to the server<br />
&nbsp;&nbsp;beforeSend: function(xmlHttpRequest) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;xmlHttpRequest.setRequestHeader('Accept', format); // <a href="http://www.w3schools.com/media/media_mimeref.asp">MIME Type</a><br />
&nbsp;&nbsp;}<br />
});<br />
</code></p>
<p>This then needs to be handled by the server. In PHP this data can be retrieved using <a href="http://uk3.php.net/reserved.variables.server">$_SERVER['HTTP_ACCEPT']</a>. I also found a handy library for parsing this header according to <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1">the specification</a> (not trivial), cleverly named &#8216;<a href="http://kevinlocke.name/programs/http_accept.php">HTTP_ACCEPT</a>&#8216;. I then wanted a way of knowing the most appropriate format from a list of formats I would support so I threw the following code together:<br />
<code><br />
$accept = new HTTP_Accept($_SERVER['HTTP_ACCEPT']);<br />
foreach ($supportedFormats as $supportedFormat) {<br />
&nbsp;&nbsp;$supportedFormatQuality = $accept->getQuality($supportedFormat);<br />
&nbsp;&nbsp;if ((!isset($bestFormat) &#038;&#038; $supportedFormatQuality > 0) ||<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $bestQuality < $supportedFormatQuality) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;$bestFormat = $supportedFormat;<br />
&nbsp;&nbsp;&nbsp;&nbsp;$bestQuality = $supportedFormatQuality;<br />
&nbsp;&nbsp;}<br />
}<br />
</code></p>
<p>The server also needs to specify the type of content it is returning; this can be done using the <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17">Content-Type</a> header as follows:<br />
<code><br />
header("Content-Type: $format");<br />
</code></p>
<p><strong><a name="singleScript">Passing all requests to a single PHP script</a></strong></p>
<p>I needed all requests with a certain URL prefix to be handled by a single script. This was easily solved using the following URL re-writing rule in a <a href="http://httpd.apache.org/docs/trunk/howto/htaccess.html">.htaccess</a> file:<br />
<code><br />
Options +FollowSymLinks<br />
RewriteEngine on<br />
RewriteRule ^.*$ index.php<br />
</code></p>
<p>Note that I had to enable the <a href="http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html">mod_rewrite</a> module in Apache and ensure that directives could be <a href="http://httpd.apache.org/docs/2.0/mod/core.html#allowoverride">overridden</a> with the following:<br />
<code><br />
&lt;Directory /var/www/&gt;<br />
&nbsp;&nbsp;AllowOverride All<br />
&lt;/Directory&gt;<br />
</code></p>
<p><strong><a name="requestedUrl">Determining the full requested URL</a></strong></p>
<p>Another requirement of my application complicated by URL rewriting was that I needed access to the full URL. I achieved this with the following bit of code:<br />
<code><br />
$protocol = $_SERVER['HTTPS'] == 'on' ? 'https' : 'http';<br />
$location = $_SERVER['REQUEST_URI'];<br />
if ($_SERVER['QUERY_STRING']) {<br />
&nbsp;&nbsp;$location = substr($location, 0, strrpos($location, $_SERVER['QUERY_STRING']) - 1);<br />
}<br />
$url = $protocol.'://'.$_SERVER['HTTP_HOST'].$location;<br />
</code></p>
<p><strong><a name="genericService">A generic REST Service class</a></strong></p>
<p>To allow me to reuse some of the REST code I'd created, I put it into a generic REST Service class which I subclassed and replaced different methods for different means:</p>
<pre>
class RestService {

  private $supportedMethods;

  public function __construct($supportedMethods) {
    $this->supportedMethods = $supportedMethods;
  }

  public function handleRawRequest($_SERVER, $_GET, $_POST) {
    $url = $this->getFullUrl($_SERVER);
    $method = $_SERVER['REQUEST_METHOD'];
    switch ($method) {
      case 'GET':
      case 'HEAD':
        $arguments = $_GET;
        break;
      case 'POST':
        $arguments = $_POST;
        break;
      case 'PUT':
      case 'DELETE':
        parse_str(file_get_contents('php://input'), $arguments);
        break;
    }
    $accept = $_SERVER['HTTP_ACCEPT'];
    $this->handleRequest($url, $method, $arguments, $accept);
  }

  protected function getFullUrl($_SERVER) {
    $protocol = $_SERVER['HTTPS'] == 'on' ? 'https' : 'http';
    $location = $_SERVER['REQUEST_URI'];
    if ($_SERVER['QUERY_STRING']) {
      $location = substr($location, 0, strrpos($location, $_SERVER['QUERY_STRING']) - 1);
    }
    return $protocol.'://'.$_SERVER['HTTP_HOST'].$location;
  }

  public function handleRequest($url, $method, $arguments, $accept) {
    switch($method) {
      case 'GET':
        $this->performGet($url, $arguments, $accept);
        break;
      case 'HEAD':
        $this->performHead($url, $arguments, $accept);
        break;
      case 'POST':
        $this->performPost($url, $arguments, $accept);
        break;
      case 'PUT':
        $this->performPut($url, $arguments, $accept);
        break;
      case 'DELETE':
        $this->performDelete($url, $arguments, $accept);
        break;
      default:
        /* 501 (Not Implemented) for any unknown methods */
        header('Allow: ' . $this->supportedMethods, true, 501);
    }
  }

  protected function methodNotAllowedResponse() {
    /* 405 (Method Not Allowed) */
    header('Allow: ' . $this->supportedMethods, true, 405);
  }

  public function performGet($url, $arguments, $accept) {
    $this->methodNotAllowedResponse();
  }

  public function performHead($url, $arguments, $accept) {
    $this->methodNotAllowedResponse();
  }

  public function performPost($url, $arguments, $accept) {
    $this->methodNotAllowedResponse();
  }

  public function performPut($url, $arguments, $accept) {
    $this->methodNotAllowedResponse();
  }

  public function performDelete($url, $arguments, $accept) {
    $this->methodNotAllowedResponse();
  }

}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.garethj.com/2009/02/building-a-restful-web-application-with-php/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Merging and converting OpenOffice and PDF documents</title>
		<link>http://blog.garethj.com/2009/01/merging-and-converting-openoffice-and-pdf-documents/</link>
		<comments>http://blog.garethj.com/2009/01/merging-and-converting-openoffice-and-pdf-documents/#comments</comments>
		<pubDate>Wed, 28 Jan 2009 09:33:12 +0000</pubDate>
		<dc:creator>gareth</dc:creator>
				<category><![CDATA[techy solutions]]></category>
		<category><![CDATA[bsl]]></category>
		<category><![CDATA[convert]]></category>
		<category><![CDATA[document]]></category>
		<category><![CDATA[merge]]></category>
		<category><![CDATA[odt]]></category>
		<category><![CDATA[openoffice]]></category>
		<category><![CDATA[pdf]]></category>
		<category><![CDATA[pdftk]]></category>
		<category><![CDATA[portfolio]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[unoconv]]></category>

		<guid isPermaLink="false">http://blog.garethj.com/?p=121</guid>
		<description><![CDATA[For my BSL level 3 course I have a variety of OpenOffice documents for different forms etc which make up the portfolio. I wanted a way to merge these into a single document but they each had different margins and &#8230; <a href="http://blog.garethj.com/2009/01/merging-and-converting-openoffice-and-pdf-documents/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For my BSL level 3 course I have a variety of OpenOffice documents for different forms etc which make up the portfolio. I wanted a way to merge these into a single document but they each had different margins and all sorts; this meant doing it within OpenOffice was proving to be a pain. My solution was to write a quick shell script to convert each document into PDF and then merge the multiple PDFs. The script looks something like the following:</p>
<p><code><br />
# convert to pdf<br />
<a href="http://dag.wieers.com/home-made/unoconv/">unoconv</a> -f pdf myfile1.odt myfile2.odt ...<br />
# merge pdfs<br />
<a href="http://www.pdfhacks.com/pdftk/">pdftk</a> myfile1.pdf myfile2.pdf ...<br />
# remove individual pdf documents<br />
rm myfile1.pdf myfile2.pdf ...<br />
</code></p>
<p>A handy little hack to generate my entire portfolio.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.garethj.com/2009/01/merging-and-converting-openoffice-and-pdf-documents/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
