<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml"
>

<channel>
	<title>LiquidFoot &#187; Programming</title>
	<atom:link href="http://www.liquidfoot.com/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.liquidfoot.com</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Sat, 17 Apr 2010 16:36:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=abc</generator>
		<item>
		<title>Openlayers and Mobile Devices</title>
		<link>http://www.liquidfoot.com/2009/11/25/openlayers-and-mobile-devices/</link>
		<comments>http://www.liquidfoot.com/2009/11/25/openlayers-and-mobile-devices/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 15:03:09 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[gis]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[openlayers]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=326</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p>After some really good conversations last week at the Institute on Enabling Geospatial Scholarship about mobile devices and mapping as an interpretive device, I mocked up a quick page to see how <a href="http://openlayers.org/">OpenLayers</a> looked on the Safari mobile browser. The theory to test out here was that you could pretty easily pull up your current location and plot your (approximate) location on a historic map (or any map for that matter) without having to install an application (like <a href="http://emergencestudios.com/historicearth/">Old Map App</a>). There are various hurdles in higher education to actually releasing software application through vendors like Apple&#8217;s App Store (restrictions on individual employees entering into contractual agreements), so we thought we&#8217;d explore using the browser to provide some of this functionality to users.</p>
<p>We have a few historic maps from our McGregor collection available through our <a href="http://geoserver.org">Geoserver</a> installation, so I looked up their layer ids and manually added them into a page with OpenLayers. Nothing fancy here, just a test to see what it looks like.</p>
<pre class="brush: jscript;">

var lat, long layer;
var zoom = 10;

var lat, lon, layer;
 var zoom = 10;

 map = new OpenLayers.Map('map');
 map.addControl(new OpenLayers.Control.LayerSwitcher());

 layer1 = new OpenLayers.Layer.WMS(&quot;Map of the Southern States&quot;,
 &quot;http://lat.lib.virginia.edu:8080/geoserver/gwc/service/wms&quot;,
 {layers: &quot;McGregor:000003056_00011&quot;}
 );
 layer2 = new OpenLayers.Layer.WMS(&quot;Nova Virginae tabula&quot;,
 &quot;http://lat.lib.virginia.edu:8080/geoserver/gwc/service/wms&quot;,
 {layers: &quot;McGregor:000003482_00011&quot;}
 );
 layer3 = new OpenLayers.Layer.WMS(&quot;A map of the most inhabited part of Virginia&quot;,
 &quot;http://lat.lib.virginia.edu:8080/geoserver/gwc/service/wms&quot;,
 {layers: &quot;McGregor:000003012_st1&quot;}
 );
 layer4 = new OpenLayers.Layer.WMS(&quot;Carte de la campagne en Virginie du Major General Mis. de la Fayette&quot;,
 &quot;http://lat.lib.virginia.edu:8080/geoserver/gwc/service/wms&quot;,
 {layers: &quot;McGregor:000003013_st1&quot;}
 );
 layer5 = new OpenLayers.Layer.WMS(&quot;Carte de la campagne en Virginie du Major General Mis. de la Fayette&quot;,
 &quot;http://lat.lib.virginia.edu:8080/geoserver/gwc/service/wms&quot;,
 {layers: &quot;McGregor:000003019_00011&quot;}
 );

 map.addLayer(layer1);
 map.addLayer(layer2);
 map.addLayer(layer3);
 map.addLayer(layer4);
 map.addLayer(layer5);

if(navigator.geolocation){
 navigator.geolocation.getCurrentPosition(function(position){
 lat = position.coords.latitude;
 lon = position.coords.longitude;
 map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);

 var vectorLayer = new OpenLayers.Layer.Vector(&quot;Overlay&quot;);
 var feature = new OpenLayers.Feature.Vector(
 new OpenLayers.Geometry.Point(lon, lat),
 {some:'data'},
 {externalGraphic: 'http://geocoder.ca/marker.png', graphicHeight: 64, graphicWidth: 48});
 vectorLayer.addFeatures(feature);
 map.addLayer(vectorLayer);
 });
 }

map.addControl(new OpenLayers.Control.PanZoomBar());
</pre>
<p>This actually worked surprisingly well the first time I launched it. With Firefox 3.5 I tested it on my laptop. At first I wasn&#8217;t using the <a href="http://geoserver.org/display/GEOSDOC/5.+GWC+-+GeoWebCache">geowebcache</a> we had set up, so it was a bit slow. I changed to the geowebcache WMS service and things in the browser were noticeably faster.</p>
<p>At lunch, I handed an iPhone to <a href="http://iconocla.st/">Schuyler Erle</a> who&#8217;s first instinct was to try to drag things around and zoom-in and out. Well, there was a fail as the controls you normally use in OpenLayers were far too small to actually be useful and it just didn&#8217;t feel right.</p>
<p>I then attempted to add in a touchHandler function to help with the interactions from the user. I found Ross Boucher&#8217;s post &#8220;<a title="Permanent Link: iPhone Touch Events in JavaScript" rel="bookmark" href="http://rossboucher.com/2008/08/19/iphone-touch-events-in-javascript/">iPhone Touch Events in JavaScript</a>&#8221; and used his code to get the sliding working:</p>
<pre class="brush: jscript;">

function touchHandler(event)
{
   var touches = event.changedTouches,
   first = touches[0],
   type = &quot;&quot;;

   switch(event.type)
   {
     case &quot;touchstart&quot;: type = &quot;mousedown&quot;; break;
     case &quot;touchmove&quot;:  type=&quot;mousemove&quot;; break;
     case &quot;touchend&quot;:   type=&quot;mouseup&quot;; break;
     default: return;
 }

 // initMouseEvent(type, canBubble, cancelable, view, clickCount,
 // screenX, screenY, clientX, clientY, ctrlKey,
 // altKey, shiftKey, metaKey, button, relatedTarget);

    var simulatedEvent = document.createEvent(&quot;MouseEvent&quot;);
    simulatedEvent.initMouseEvent(type, true, true, window, 1,
    first.screenX, first.screenY,
    first.clientX, first.clientY, false,
    false, false, false, 0/*left*/, null);

    first.target.dispatchEvent(simulatedEvent);
    event.preventDefault();
 }

 document.addEventListener(&quot;touchstart&quot;, touchHandler, true);
 document.addEventListener(&quot;touchmove&quot;, touchHandler, true);
 document.addEventListener(&quot;touchend&quot;, touchHandler, true);
 document.addEventListener(&quot;touchcancel&quot;, touchHandler, true);
</pre>
<p>Now the scrolling worked, but you could no longer zoom into the map (and we want real zoom, not just making the image bigger). I haven&#8217;t found a fix for this yet, but I have to say that this is a kind of cool way of interacting with these materials.</p>
<p>Something I need to talk with Joe about next week making your location a query to <a href="http://geonetwork-opensource.org/">Geonetwork</a> and then using the top n maps returned to build this interface. It&#8217;s a little like a coverage map for your current location.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2009/11/25/openlayers-and-mobile-devices/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>More on Omeka Packaging</title>
		<link>http://www.liquidfoot.com/2009/11/20/more-on-omeka-packaging/</link>
		<comments>http://www.liquidfoot.com/2009/11/20/more-on-omeka-packaging/#comments</comments>
		<pubDate>Fri, 20 Nov 2009 15:42:11 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[fedorea]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[omeka]]></category>
		<category><![CDATA[rpm]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=316</guid>
		<description><![CDATA[I had meant to get this info out there a bit earlier, but we were sponsoring an NEH Institute on Enabling Geospatial Scholarship. That&#8217;s a different post, but I did want to get back to Omeka and flush out building the RPM for Omeka. What I&#8217;m going to do here is go through the setup [...]]]></description>
			<content:encoded><![CDATA[<p>I had meant to get this info out there a bit earlier, but we were sponsoring an <a href="http://www2.lib.virginia.edu/scholarslab/geospatial/">NEH Institute on Enabling Geospatial Scholarship</a>. That&#8217;s a different post, but I did want to get back to Omeka and flush out building the RPM for Omeka.</p>
<p>What I&#8217;m going to do here is go through the setup for building the RPM and the spec file. This <em>should</em> work on just about any OS that uses RPM for installing software, but this isn&#8217;t tested very extensively.</p>
<p>So I guess the first thing to cover is what exactly an RPM is. RPM is the Redhat Package Manager and is an implementation of a container for other files. It allows you to quickly install software, including necessary programs to run the program, provides information about the program you are installing, informs users about potential conflicts between your program and the software currently installed on the system, and provides a path to install, upgrade, and remove the software.</p>
<p>Now, in the case of Omeka, you don&#8217;t really need a package manager if you&#8217;re a seasoned system administrator. However, if you&#8217;re wanting to run this yourself, and you have to convince others to manage the software for you (e.g. you&#8217;re running it at an institution), have an RPM that your systems administrator installs will save a lot of headaches, especially since upgrades to the software can be integrated into scheduled maintenance with kernel and other software upgrades.</p>
<p>Building RPMs requires two things, the source you want to install and a specification (spec) file that tells the software what to do. You&#8217;ll need to first set your system up to have the tools to build software which you can do with a couple of lines (as the root user):</p>
<pre class="brush: bash;">

yum groupinstall &quot;Development Tools&quot;
yum install rpmdevtools
</pre>
<p>Next we need the directory hierarchy for building the RPMs. You can do this manually, but there&#8217;s a handy tool for helping out called rpmdev-setuptree. In the terminal, if you run this command, it will create a new folder in your home directory named &#8220;rpmbuild&#8221; with the correct directories made for you.</p>
<pre class="brush: bash;">
rpmdev-setuptree
</pre>
<p>If you want these in a different location, say omeka_rpm, you can manually create the following hierarchy:</p>
<pre class="brush: bash;">

mkdir -p ~/omeka_rpm/BUILD
mkdir -p ~/omeka_rpm/BUILDROOT
mkdir -p ~/omeka_rpm/RPMS
mkdir -p ~/omeka_rpm/SOURCES
mkdir -p ~/omeka_rpm/SPECS
mkdir -p ~/omeka_rpm/SRPMS
</pre>
<p>For our purposes, we&#8217;re really going to be dealing in the SOURCES and SPEC directories. Let&#8217;s start with the setup for the source files. First you need to get the source files from <a href="http://omeka.org/download">Omeka&#8217;s website</a> and put it into your SOURCES folder. We have to do some additional work with this file since it&#8217;s packaged using zip and the RPM is expecting a gzipped tarball. The following code snip assumes you&#8217;re using the default structure from the rpmdev-setuptree command and if a release after Omeka 1.1 is the most current, you will need to update the revision numbers.</p>
<pre class="brush: bash;">

cd ~/rpmbuild/SOURCES
wget http://omeka.org/files/omeka-1.1.zip
unzip omeka-1.1.zip
mv omeka-1.1 omeka
tar -czvf omeka-1.1.tar.gz omeka
</pre>
<p>Now if take a look at the directory, you should see a new file named &#8220;omeka-1.1.tar.gz&#8221; which is in the correct format for using it to build our RPM. There are two more files we need in here, an httpd configuration file and a readme for its use. Let&#8217;s just touch these so they exist and we can come back and add content to them a little later after I discuss them.</p>
<pre class="brush: bash;">

cd ~/rpmbuild/SOURCES
touch fedora-http-conf
touch README.fedora.omeka
</pre>
<p>Ok, let&#8217;s look at the real meat of this now. You need to create an omeka.spec file in the SPECS directory. This is the script that tells the rpmbuild tool how to set up the system.</p>
<p>I use gedit when I have a GUI, but emacs or vi work just as well (better if you&#8217;re good at the commands).</p>
<p>The idea behind this setup is to set up Omeka much like other software on the system is set up. This assumes that there will be only one installation of Omeka running on the system and takes into account that MySQL may be running on another server, so only the php &amp;gt;= 5.2.4, httpd, php-mysql, and ImageMagick packages are required. The configuration for the database connection is set in /etc/omeka/db.ini and uses a symbolic link to the application files in /usr/share/omeka (though this isn&#8217;t quite working yet). Themes and the archive folder shouldn&#8217;t get overwritten, so those directories stay in place. An httpd configuration for omeka (which aliases &#8220;/omeka&#8221;) is added into the httpd.conf directory. Since this software does not actually need to be compiled for a processor architecture type, the build archicture is set to noarch.</p>
<pre class="brush: bash;">
Summary: Omeka web publishing software
URL: http://omeka.org
Name: omeka
Version: 1.1
Group: Application/Publishing
Release: 1%{?dist}
License: GPL
Source0: %{name}-%{version}.tar.gz
Source1: omeka-http-conf
Source2: README.fedora.omeka
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Requires: php &amp;gt;= 5.2.4, httpd, php-mysql, ImageMagick
BuildArch: noarch

%description
Omeka is a free and open source collections based web-based publishing platform for scholars, librarians, archivists, museum professionals, educators, and cultural enthusiasts.

%prep
%setup -q -n omeka

%install
 mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/omeka
 mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/omeka
 install -m 0644 -D -p %{SOURCE1} ${RPM_BUILD_ROOT}%{_sysconfdir}/httpd/conf.d/omeka.conf
 cp -pr * ${RPM_BUILD_ROOT}%{_datadir}/omeka
 #cat db.ini | sed -e &quot;s|dirname(__FILE__).'/'|'/usr/share/omeka/!|g&quot; &amp;gt; ${RPM_BUILD_ROOT}%{_sysconfdir}/omeka/db.ini
 #/bin/ln -sf ../../../etc/omeka/db.ini ${RPM_BUILD_ROOT}%{_datadir}/omeka/db.ini
 /bin/cp %{SOURCE2} ./README.fedora
 # Remove empty files for rmplint
 find ${RPM_BUILD_ROOT} -empty -exec rm -f {} \;
 # These are docs; remove and docify later
 rm -f ${RPM_BUILD_ROOT}%{_datadir}/omeka/{readme.txt,license.txt,release.txt,changelog.txt}

%clean
 rm -rf ${RPM_BUILD_ROOT}

%files
 %defattr(-,root,root,-)
 %config(noreplace) %{_sysconfdir}/httpd/conf.d/omeka.conf
 %dir %{_datadir}/omeka
 %{_datadir}/omeka/admin
 %{_datadir}/omeka/application
 %{_datadir}/omeka/archive
 %doc changelog.txt
 %config(noreplace) %{_sysconfdir}/omeka/db.ini
 %{_datadir}/omeka/index.php
 %doc license.txt
 %{_datadir}/omeka/paths.php
 %{_datadir}/omeka/install
 %{_datadir}/omeka/plugins
 %doc readme.txt
 %doc release.txt
 %{_datadir}/omeka/robots.txt
 %{_datadir}/omeka/themes
 %dir %{_sysconfdir}/omeka

%changelog
* Mon Nov 09 2009 Wayne Graham &amp;lt;wayne dot graham at virginia dot edu&amp;gt; - 1.1
- Initial build
</pre>
<p>Now we can add in the httpd configuration that will get written. Open up SOURCES/omeka-http-conf and add</p>
<pre class="brush: plain;">

Alias /omeka /var/www/omeka

&amp;lt;Directory /var/www/omeka&amp;gt;
 AllowOverride Options
&amp;lt;/Directory&amp;gt;
</pre>
<p>And README.fedora.omeka</p>
<pre class="brush: plain;">

Omeka is a database driven web publishing program.

Once this package is installed, there are a few configuration items which need
to be performed before Omeka is usable.  First, you need to establish a
username and password with which to connect to your MySQL database. You also need to make both
MySQL and Omeka aware of this configuration.  Let's start by creating the database and the
username / password inside MySQL first:

 # mysql
 mysql&amp;gt; create database omeka;
 Query OK, 1 row affected (0.00 sec)

 mysql&amp;gt; grant all privileges on omeka.* to omeka identified by '1superPrivateOmekaPassword!';
 Query OK, 0 rows affected (0.00 sec)

 mysql&amp;gt; flush privileges;
 Query OK, 0 rows affected (0.00 sec)

 mysql&amp;gt; exit
 Bye
 #

Under certain curcumstances, you may need to run variations of the &quot;grant&quot;
command:
mysql&amp;gt; grant all privileges on omeka.* to omeka@localhost identified by 'omeka';
 OR
mysql&amp;gt; grant all privileges on omeka.* to omeka@'%' identified by 'omeka';

This has created an empty database named 'omeka', created a user named
'omeka' with a password of '1superPrivateOmekaPassword!', and given the 'omeka' user total
permission over the 'omeka' database.  Obviously, you'll want to select a
different password, and you may want to choose different database and user
names depending on your installation.  The specific values you choose are
not constrained, they simply need to be consistent between the database and the
config file.

Next, you need to edit your /var/www/omeka/db.ini file to reflect the
values you've chosen.  These values will go in the appropriate places at the
beginning of that file.

Once that's done and the database server and web server have been started,
open a web browser to http://localhost/omeka/install/ and
follow the instructions given to you on the pages you see to set up the
database tables and begin publishing your Omeka instace.
</pre>
<p>Now everything is in place. Let&#8217;s try to build this thing. Go in to the SPEC directory and build the binary for the rpm.</p>
<pre class="brush: bash;">

cd ~/rpmbuild/SPECS
rpmbuild -bb omeka.spec
</pre>
<p>This takes a while, and if you&#8217;re running this through VMWare of VirtualServer, this process will demand some pretty hefty system resources and your system will slow down.</p>
<p>If everything has gone correctly, you should now have a nice new RPM package named omeka-1.1.fc11.noarch.rpm in the RPMS/noarch directory. You can test it out by installing the package with</p>
<pre class="brush: bash;">

rpm -Uvh omeka-1.1.fc11.noarch.rpm
</pre>
<h2>What&#8217;s Next</h2>
<p>For packaging RPMs like this, a few more infrastructure elements need to be in place. The following outlines some of them (if you have more, leave a comment).</p>
<ul>
<li>Put the build files into SCM (currently only in our private SVN repo)</li>
<li>Auto-install dependencies</li>
<li>Set up an RPM repository to work with yum
<ul>
<li>Target specific Linux builds</li>
</ul>
</li>
<li>Automate build</li>
<li>Run MySQL setup script after initial install</li>
<li>Build aptitude package (using <a href="http://packages.debian.org/lenny/alien">alien</a>?)</li>
</ul>
<h2>Additional Resources</h2>
<ul>
<li><a href="http://docs.fedoraproject.org//developers-guide/ch-rpm-building.html">Chapter 4. Building RPM Packages</a></li>
<li><a title="How To Build RPM Packages on Fedora" rel="bookmark" href="http://www.g-loaded.eu/2006/04/05/how-to-build-rpm-packages-on-fedora/">How To Build RPM Packages on Fedora</a></li>
<li><a href="http://fedoraproject.org/wiki/Packaging/ScriptletSnippets">RPM scriptlet recipes</a></li>
<li><a href="http://fedoraproject.org/wiki/Packaging/NamingGuidelines">Package Naming Guidelines</a></li>
<li><a href="http://fedoraproject.org/wiki/Packaging/Guidelines">Packaging Guidelines</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2009/11/20/more-on-omeka-packaging/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Map Hacking</title>
		<link>http://www.liquidfoot.com/2009/11/17/map-hacking/</link>
		<comments>http://www.liquidfoot.com/2009/11/17/map-hacking/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 02:28:37 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[gis]]></category>
		<category><![CDATA[mapping]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=314</guid>
		<description><![CDATA[We&#8217;ve been hosting an NEH Institute for Enabling Geospatial Scholarship this week and we have a lot of different folks coming together to talk about mapping issues in higher education. I almost haven&#8217;t been able to keep my delicious tagging up with all the kewl new tools folks have been talking about. One thing I [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;ve been hosting an NEH Institute for Enabling Geospatial Scholarship this week and we have a lot of different folks coming together to talk about mapping issues in higher education. I almost haven&#8217;t been able to keep my delicious tagging up with all the kewl new tools folks have been talking about.</p>
<p>One thing I did try out this evening when I got home was <a href="http://www.mapstraction.com/">Mapstraction</a>. My wife has a set of data (reading test scores) that she&#8217;s been wanting to look at to see if there were neighborhoods where students were underperforming. Using a short ruby script (with the graticule gem), I geocoded addresses, calculated a median score across five reading tests, then plotted them using Mapstraction. At the top, I added some slider controls for filtering the data points, and viola, a really quick-and-dirty interactive map that lets her quickly filter ranges of scores to start looking for patterns.</p>
<p>Now to tweak the algorithm for generating the scores&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2009/11/17/map-hacking/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<georss:point featurename="charlottesville, va">38.032130 -78.477529</georss:point>
	</item>
		<item>
		<title>Rails and GIS</title>
		<link>http://www.liquidfoot.com/2009/08/30/rails-and-gis/</link>
		<comments>http://www.liquidfoot.com/2009/08/30/rails-and-gis/#comments</comments>
		<pubDate>Sun, 30 Aug 2009 23:11:20 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=308</guid>
		<description><![CDATA[As a part of my research time, I've started dusting off an old project I always wanted to get back to. Back in 2005 I started working with some folks who were starting to write an article on the development of architectural identity in the early Chesapeake for the William and Mary Quarterly. I wrote the application in ColdFusion and used MSSQL as the backend. When the same data was used for another article in the Journal of Southern History, I quickly whipped up an app that would at least display the information. I was never happy with it, but didn't have the time to undertake this again.]]></description>
			<content:encoded><![CDATA[<p>As a part of my research time, I&#8217;ve started dusting off an old project I always wanted to get back to. Back in 2005 I started working with some folks who were starting to write an article on the development of architectural identity in the early Chesapeake for the William and Mary Quarterly. I wrote the application in ColdFusion and used MSSQL as the backend. When the same data was used for another article in the Journal of Southern History, I quickly whipped up an app that would at least display the information. I was never happy with it, but didn&#8217;t have the time to undertake this again.</p>
<p>One of the things I never liked the way I handled was describing the basic location. At first the architectural historians wanted to use UTM coordinates. I switched to latitute/longitude and wrote some conversion code to switch between the two. I was bothered, though, that describing a &#8220;site&#8221; by a point. Obviously a site is an area that contains some number n buildings. Even worse, the points were really just the centroids of the county/city of the information that was entered as the archaeologists didn&#8217;t have have information. There had to be a better way to approach the description of this information over time.</p>
<p>I started working at UVa earlier this spring and one of their big pushes has been GIS in the humanities. A light went off and I saw a rather nice use of using the concepts of GIS to better describe and interact with my information. I also really wanted to migrate the information to a more open format as well as really spend some time envisioning what the application should look like.</p>
<p>I&#8217;ve started working on this migration and have posted it on <a href="http://github.com/waynegraham/DECA">Github</a>. To give a brief explanation of how the application. I&#8217;m using PostGIS as the backend. On OS X, getting this ready took a bit, but I think I got it explained in the README file decently. It took a while to get the correct templates ready in PostgreSQL.</p>
<p>I&#8217;m using OpenLayers for interacting with the maps (through <a href="http://github.com/pka/map_layers/tree/master">map_layers</a>), and the <a href="http://github.com/fragility/spatial_adapter/tree/master">spatial_adapter</a> plugin and the <a href="http://georuby.rubyforge.org/">GeoRuby</a> gem.</p>
<p>I&#8217;m expecting there to be some refactoring of the data from MSSQL, but I think PostgreSQL will be a much better solution for my open source leanings.</p>
<p>I&#8217;ll try to keep this updated with my progress&#8230;at least until our development blog gets off the ground.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2009/08/30/rails-and-gis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>EndNote Migration</title>
		<link>http://www.liquidfoot.com/2008/11/19/endnote-migration/</link>
		<comments>http://www.liquidfoot.com/2008/11/19/endnote-migration/#comments</comments>
		<pubDate>Wed, 19 Nov 2008 20:03:24 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=121</guid>
		<description><![CDATA[I&#8217;ve been working with the folks over at the Center for Archaeological Research with a bibliography of their research reports. It&#8217;s a bit of an offshoot of the NEH Slave Quarters research I&#8217;ve been working on, but I wanted to have a way to work through their research reports, just to have an idea of [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working with the folks over at the <a href="http://web.wm.edu/wmcar/">Center for Archaeological Research</a> with a bibliography of their research reports. It&#8217;s a bit of an offshoot of the NEH Slave Quarters research I&#8217;ve been working on, but I wanted to have a way to work through their research reports, just to have an idea of what they have available.</p>
<p>The first thing I did is get them to give me the file in the crappy EndNote XML format. I was having issues bringing it into Zotero, so I installed the bibutils package (sudo apt-get install bibutils) and then ran the endx2xml program on it. This created a nice MODS file for me to start crunching on. What I wanted to do is make a tag cloud using some of the categories they created. I created a database with two tables to store the citation and author information. I&#8217;m on my development box, so this is MySQL</p>
<pre class="brush: sql;">&lt;/p&gt;
&lt;p&gt;--&lt;br&gt;
-- Create schema archaeology&lt;br&gt;
--&lt;/p&gt;
&lt;p&gt;CREATE DATABASE IF NOT EXISTS archaeology;&lt;br&gt;
USE archaeology;&lt;/p&gt;
&lt;p&gt;--&lt;br&gt;
-- Definition of table `archaeology`.`authors`&lt;br&gt;
--&lt;/p&gt;
&lt;p&gt;DROP TABLE IF EXISTS `archaeology`.`authors`;&lt;br&gt;
CREATE TABLE&amp;amp;nbsp; `archaeology`.`authors` (&lt;br&gt;
`id` char(36) NOT NULL,&lt;br&gt;
`citation_id` char(36) NOT NULL,&lt;br&gt;
`given` varchar(50) NOT NULL,&lt;br&gt;
`family` varchar(50) NOT NULL,&lt;br&gt;
`role` varchar(50) NOT NULL,&lt;br&gt;
PRIMARY KEY&amp;amp;nbsp; (`id`)&lt;br&gt;
) ENGINE=InnoDB DEFAULT CHARSET=latin1;&lt;/p&gt;
&lt;p&gt;--&lt;br&gt;
-- Definition of table `archaeology`.`citations`&lt;br&gt;
--&lt;/p&gt;
&lt;p&gt;DROP TABLE IF EXISTS `archaeology`.`citations`;&lt;br&gt;
CREATE TABLE&amp;amp;nbsp; `archaeology`.`citations` (&lt;br&gt;
`id` char(36) NOT NULL,&lt;br&gt;
`ref_id` varchar(25) NOT NULL,&lt;br&gt;
`title` varchar(500) NOT NULL,&lt;br&gt;
`year` int(11) NOT NULL,&lt;br&gt;
`publisher` varchar(500) NOT NULL,&lt;br&gt;
`added` timestamp NOT NULL default CURRENT_TIMESTAMP,&lt;br&gt;
`genre` varchar(50) NOT NULL,&lt;br&gt;
`subject` varchar(500) NOT NULL,&lt;br&gt;
PRIMARY KEY&amp;amp;nbsp; (`id`)&lt;br&gt;
) ENGINE=InnoDB DEFAULT CHARSET=latin1;&lt;/p&gt;
&lt;p&gt;</pre>
<p>I next needed to write the XSLT to actually transform the modsCollection into the schema. I haven&#8217;t worked with XSLT in a while and was (very) rusty <img src='http://www.liquidfoot.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Here&#8217;s a sampling of the output of converting the EndNote XML to MODS</p>
<pre class="brush: xml;">&lt;/p&gt;
&lt;p&gt;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br&gt;
&lt;modsCollection&gt;&lt;br&gt;
&lt;mods ID=&quot;Andre2007a&quot;&gt;&lt;br&gt;
&lt;titleInfo&gt;&lt;br&gt;
&lt;title&gt;Heritage Education and Interpretive Plan for the Smith River Blueway and Pedestrian Trails, Henry County, Virginia&lt;/title&gt;&lt;br&gt;
&lt;/titleInfo&gt;&lt;br&gt;
&lt;name type=&quot;personal&quot;&gt;&lt;br&gt;
&lt;namePart type=&quot;given&quot;&gt;Elizabeth&lt;/namePart&gt;&lt;br&gt;
&lt;namePart type=&quot;family&quot;&gt;Andre&lt;/namePart&gt;&lt;br&gt;
&lt;role&gt;&lt;br&gt;
&lt;roleTerm authority=&quot;marcrelator&quot; type=&quot;text&quot;&gt;author&lt;/roleTerm&gt;&lt;br&gt;
&lt;/role&gt;&lt;br&gt;
&lt;/name&gt;&lt;br&gt;
&lt;name type=&quot;personal&quot;&gt;&lt;br&gt;
&lt;namePart type=&quot;given&quot;&gt;Stephanie&lt;/namePart&gt;&lt;br&gt;
&lt;namePart type=&quot;family&quot;&gt;Sapp&lt;/namePart&gt;&lt;br&gt;
&lt;role&gt;&lt;br&gt;
&lt;roleTerm authority=&quot;marcrelator&quot; type=&quot;text&quot;&gt;author&lt;/roleTerm&gt;&lt;br&gt;
&lt;/role&gt;&lt;br&gt;
&lt;/name&gt;&lt;br&gt;
&lt;originInfo&gt;&lt;br&gt;
&lt;dateIssued&gt;2007&lt;/dateIssued&gt;&lt;br&gt;
&lt;publisher&gt;William and Mary Center for Archaeological Research, Williamsburg, Virginia. &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; Submitted to Virginia Department of Historic Resources, Roanoke&lt;/publisher&gt;&lt;br&gt;
&lt;/originInfo&gt;&lt;br&gt;
&lt;typeOfResource&gt;text&lt;/typeOfResource&gt;&lt;br&gt;
&lt;genre&gt;report&lt;/genre&gt;&lt;br&gt;
&lt;subject&gt;&lt;br&gt;
&lt;topic&gt;06-25/L-WMCAR Reports/Henry Co/Interp/18th/19th/20th/&lt;/topic&gt;&lt;br&gt;
&lt;/subject&gt;&lt;br&gt;
&lt;identifier type=&quot;citekey&quot;&gt;Andre2007a&lt;/identifier&gt;&lt;br&gt;
&lt;/mods&gt;&lt;br&gt;
&lt;mods ID=&quot;Andre2007b&quot;&gt;&lt;br&gt;
&lt;titleInfo&gt;&lt;br&gt;
&lt;title&gt;Architectural Evaluation of the Anderson Farm (047-0034-0010) for the Proposed Anderson-Hughes Development Project in Norge, Virginia&lt;/title&gt;&lt;br&gt;
&lt;/titleInfo&gt;&lt;br&gt;
&lt;name type=&quot;personal&quot;&gt;&lt;br&gt;
&lt;namePart type=&quot;given&quot;&gt;Elizabeth&lt;/namePart&gt;&lt;br&gt;
&lt;namePart type=&quot;given&quot;&gt;M&lt;/namePart&gt;&lt;br&gt;
&lt;namePart type=&quot;family&quot;&gt;Andre&lt;/namePart&gt;&lt;br&gt;
&lt;role&gt;&lt;br&gt;
&lt;roleTerm authority=&quot;marcrelator&quot; type=&quot;text&quot;&gt;author&lt;/roleTerm&gt;&lt;br&gt;
&lt;/role&gt;&lt;br&gt;
&lt;/name&gt;&lt;br&gt;
&lt;originInfo&gt;&lt;br&gt;
&lt;dateIssued&gt;2007&lt;/dateIssued&gt;&lt;br&gt;
&lt;publisher&gt;William and Mary Center for Archaeological Research, Williamsburg, Virginia. &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; Submitted to Anderson-Hughes, LLC, Newport News, Virginia&lt;/publisher&gt;&lt;br&gt;
&lt;/originInfo&gt;&lt;br&gt;
&lt;typeOfResource&gt;text&lt;/typeOfResource&gt;&lt;br&gt;
&lt;genre&gt;report&lt;/genre&gt;&lt;br&gt;
&lt;subject&gt;&lt;br&gt;
&lt;topic&gt;07-22/L-WMCAR Reports/ARCeval/19th/20th/James City Co/&lt;/topic&gt;&lt;br&gt;
&lt;/subject&gt;&lt;br&gt;
&lt;identifier type=&quot;citekey&quot;&gt;Andre2007b&lt;/identifier&gt;&lt;br&gt;
&lt;/mods&gt;&lt;br&gt;
&lt;modsCollection&gt;&lt;/p&gt;
&lt;p&gt;</pre>
<p>What I wanted to do is take each citation and insert it into the database, then relate the last-entered citation with its authors. At first I thought I could use MySQL&#8217;s last_insert_id() function&#8230;turns out those are only for auto-increment fields and I always use UUIDs for primary keys. What I ended up doing is adding in the added field with a timestamp (with a default value of CURRENT_TIMESTAMP). Then, I just went through the nodes and put the data where it needed to go.</p>
<pre class="brush: xml;">&lt;/p&gt;
&lt;p&gt;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br&gt;
&lt;xsl:stylesheet xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot; version=&quot;1.0&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;xsl:output method=&quot;text&quot; /&gt;&lt;br&gt;
&lt;xsl:strip-space elements=&quot;*&quot;/&gt;&lt;/p&gt;
&lt;p&gt;&lt;xsl:template match=&quot;/&quot;&gt;&lt;/p&gt;
&lt;p&gt;DELETE FROM citations;&lt;br&gt;
DELETE FROM authors;&lt;/p&gt;
&lt;p&gt;&lt;xsl:for-each select=&quot;modsCollection/mods&quot;&gt;&lt;/p&gt;
&lt;p&gt;INSERT INTO citations ( id, ref_id, title, year, publisher, genre, subject)&lt;br&gt;
VALUES (&lt;br&gt;
UUID(),&lt;br&gt;
'&lt;xsl:value-of select=&quot;@ID&quot; /&gt;',&lt;br&gt;
'&lt;xsl:call-template name=&quot;escapesinglequotes&quot;&gt;&lt;br&gt;
&lt;xsl:with-param name=&quot;arg1&quot;&gt;&lt;br&gt;
&lt;xsl:value-of select=&quot;titleInfo/title&quot;/&gt;&lt;br&gt;
&lt;/xsl:with-param&gt;&lt;br&gt;
&lt;/xsl:call-template&gt;',&lt;br&gt;
'&lt;xsl:value-of select=&quot;originInfo/dateIssued&quot;/&gt;',&lt;br&gt;
'&lt;xsl:call-template name=&quot;escapesinglequotes&quot;&gt;&lt;br&gt;
&lt;xsl:with-param name=&quot;arg1&quot;&gt;&lt;br&gt;
&lt;xsl:value-of select=&quot;originInfo/publisher&quot;/&gt;&lt;br&gt;
&lt;/xsl:with-param&gt;&lt;br&gt;
&lt;/xsl:call-template&gt;',&lt;br&gt;
'&lt;xsl:value-of select=&quot;genre&quot;/&gt;',&lt;br&gt;
'&lt;xsl:call-template name=&quot;escapesinglequotes&quot;&gt;&lt;br&gt;
&lt;xsl:with-param name=&quot;arg1&quot;&gt;&lt;br&gt;
&lt;xsl:value-of select=&quot;subject/topic&quot;/&gt;&lt;br&gt;
&lt;/xsl:with-param&gt;&lt;br&gt;
&lt;/xsl:call-template&gt;'&lt;br&gt;
);&lt;/p&gt;
&lt;p&gt;&lt;xsl:for-each select=&quot;name&quot;&gt;&lt;br&gt;
INSERT INTO authors (id, citation_id, given, family, role)&lt;br&gt;
VALUES(&lt;br&gt;
UUID(),&lt;br&gt;
(SELECT id FROM citations ORDER BY added desc limit 1),&lt;br&gt;
&lt;xsl:for-each select=&quot;.&quot;&gt;&lt;br&gt;
'&lt;xsl:value-of select=&quot;namePart[@type='given']&quot;/&gt; ',&lt;br&gt;
'&lt;xsl:value-of select=&quot;namePart[@type='family']&quot;/&gt;',&lt;br&gt;
'&lt;xsl:value-of select=&quot;role/roleTerm&quot;/&gt;'&lt;br&gt;
&lt;/xsl:for-each&gt;&lt;br&gt;
);&lt;br&gt;
&lt;/xsl:for-each&gt;&lt;br&gt;
&lt;/xsl:for-each&gt;&lt;br&gt;
&lt;/xsl:template&gt;&lt;/p&gt;
&lt;p&gt;&lt;xsl:template name=&quot;escapesinglequotes&quot;&gt;&lt;br&gt;
&lt;xsl:param name=&quot;arg1&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;xsl:variable name=&quot;apostrophe&quot;&gt;'&lt;/xsl:variable&gt;&lt;/p&gt;
&lt;p&gt;&lt;xsl:choose&gt;&lt;br&gt;
&lt;xsl:when test=&quot;contains($arg1, $apostrophe)&quot;&gt;&lt;br&gt;
&lt;xsl:if test=&quot;string-length(normalize-space(substring-before($arg1, $apostrophe))) &gt; 0&quot;&gt;&lt;xsl:value-of select=&quot;substring-before($arg1, $apostrophe)&quot; disable-output-escaping=&quot;yes&quot;/&gt;''&lt;/xsl:if&gt;&lt;br&gt;
&lt;xsl:call-template name=&quot;escapesinglequotes&quot;&gt;&lt;br&gt;
&lt;xsl:with-param name=&quot;arg1&quot;&gt;&lt;xsl:value-of select=&quot;substring-after($arg1, $apostrophe)&quot; disable-output-escaping=&quot;yes&quot;/&gt;&lt;/xsl:with-param&gt;&lt;br&gt;
&lt;/xsl:call-template&gt;&lt;/p&gt;
&lt;p&gt;&lt;/xsl:when&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- No quotes found in string, just print it --&gt;&lt;br&gt;
&lt;xsl:when test=&quot;string-length(normalize-space($arg1)) &gt; 0&quot;&gt;&lt;xsl:value-of select=&quot;normalize-space($arg1)&quot;/&gt;&lt;/xsl:when&gt;&lt;/p&gt;
&lt;p&gt;&lt;/xsl:choose&gt;&lt;br&gt;
&lt;/xsl:template&gt;&lt;/p&gt;
&lt;p&gt;&lt;/xsl:stylesheet&gt;&lt;/p&gt;
&lt;p&gt;</pre>
<p>I noticed that I also had to write a template to escape single quotes in the title, publisher, and topic because of some possesive language in those fields. It took the longest time to actually write the code for that (like I said, I was really rusty and forgot all about XSL branching).</p>
<p>In the end, what gets generated is a nice SQL script (this one pushes 30,000 lines) like this</p>
<pre class="brush: sql;">&lt;/p&gt;
&lt;p&gt;DELETE FROM citations;&lt;br&gt;
DELETE FROM authors;&lt;/p&gt;
&lt;p&gt;INSERT INTO citations ( id, ref_id, title, year, publisher, genre, subject)&lt;br&gt;
VALUES (&lt;br&gt;
UUID(),&lt;br&gt;
'Andre2007a',&lt;br&gt;
'Heritage Education and Interpretive Plan for the Smith River Blueway and Pedestrian Trails, Henry County, Virginia',&lt;br&gt;
'2007',&lt;br&gt;
'William and Mary Center for Archaeological Research, Williamsburg, Virginia. Submitted to Virginia Department of Historic Resources, Roanoke',&lt;br&gt;
'report',&lt;br&gt;
'06-25/L-WMCAR Reports/Henry Co/Interp/18th/19th/20th/'&lt;br&gt;
);&lt;/p&gt;
&lt;p&gt;INSERT INTO authors (id, citation_id, given, family, role)&lt;br&gt;
VALUES(&lt;br&gt;
UUID(),&lt;br&gt;
(SELECT id FROM citations ORDER BY added desc limit 1),&lt;br&gt;
'Elizabeth ',&lt;br&gt;
'Andre',&lt;br&gt;
'author'&lt;br&gt;
);&lt;/p&gt;
&lt;p&gt;INSERT INTO authors (id, citation_id, given, family, role)&lt;br&gt;
VALUES(&lt;br&gt;
UUID(),&lt;br&gt;
(SELECT id FROM citations ORDER BY added desc limit 1),&lt;br&gt;
'Stephanie ',&lt;br&gt;
'Sapp',&lt;br&gt;
'author'&lt;br&gt;
);&lt;/p&gt;
&lt;p&gt;INSERT INTO citations ( id, ref_id, title, year, publisher, genre, subject)&lt;br&gt;
VALUES (&lt;br&gt;
UUID(),&lt;br&gt;
'Andre2007b',&lt;br&gt;
'Architectural Evaluation of the Anderson Farm (047-0034-0010) for the Proposed Anderson-Hughes Development Project in Norge, Virginia',&lt;br&gt;
'2007',&lt;br&gt;
'William and Mary Center for Archaeological Research, Williamsburg, Virginia. Submitted to Anderson-Hughes, LLC, Newport News, Virginia',&lt;br&gt;
'report',&lt;br&gt;
'07-22/L-WMCAR Reports/ARCeval/19th/20th/James City Co/'&lt;br&gt;
);&lt;/p&gt;
&lt;p&gt;INSERT INTO authors (id, citation_id, given, family, role)&lt;br&gt;
VALUES(&lt;br&gt;
UUID(),&lt;br&gt;
(SELECT id FROM citations ORDER BY added desc limit 1),&lt;br&gt;
'Elizabeth ',&lt;br&gt;
'Andre',&lt;br&gt;
'author'&lt;br&gt;
);&lt;/p&gt;
&lt;p&gt;</pre>
<p>There&#8217;s still a lot of cleaning up to do (normalizing the authors table, exploding the subjects, generating the tags), but it did give me pause to remember how beautifully maddening XSLT can be.</p>
<p>I&#8217;ll post some screenshots when this gets a bit further along, but I thought this may save someone some time at some point.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2008/11/19/endnote-migration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Open Search</title>
		<link>http://www.liquidfoot.com/2008/11/06/open-search/</link>
		<comments>http://www.liquidfoot.com/2008/11/06/open-search/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 16:32:45 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[opensearch]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=116</guid>
		<description><![CDATA[It&#8217;s been a while since I last posted, but the NEH Slave Quarters project is coming to a close and the next grant is out the door (to build a digital archive of the newspaper articles of Elizabeth Stoddard). So I showed my student worker the search plugins I had made a few years ago [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a while since I last posted, but the NEH Slave Quarters project is coming to a close and the next grant is out the door (to build a digital archive of the newspaper articles of Elizabeth Stoddard).</p>
<p>So I showed my student worker the search plugins I had made a few years ago and he got really excited. They&#8217;re burried on our website right now (but then again, so is everything), but he like the convienence. He actually got me to start thinking about it a bit more. IE 7 and Firefox both use OpenSearch now for their search plugins. There&#8217;s not a whole lot to this description (and it&#8217;s a lot more convienent than the Sherlock format). What if I built a quick app that could generate the XML for these and them people could install them? We could quickly develop a collection of useful plugins that would help folks get to data (hopefully) faster.</p>
<p>I started looking at it yesterday and it&#8217;s pretty straight forward&#8230;with a few exceptions. Most search engines use a get method, but I&#8217;m finding a bunch of our most popular search engine providers (e.g. lexisnexis, factiva, etc.) use a post method with weird session variables.</p>
<p>Focusing on just the &#8220;easy&#8221; stuff first, I wrote a database table (which is still in flux) that recorded the basic OpenSearch fields first: short_name, description, input_encoding, and url. I populated the fields with some basic search engines that folks use here at William and Mary: all the libraries, Google Scholar, Ebrary, JStor, EbscoHost, ScienceDirect, and our federated searching engine). I wrote a search proxy to rewrite the search URLs, though it&#8217;s really not necessary (and I may change that).</p>
<p>Since I got on the kick, I figured I&#8217;d write something up real quick for Vufind too. By adding a few lines of code, folks will be able to add the Vufind instance to their search list without doing much!</p>
<p>After I get the code a bit cleaner, and work through some of the other &#8220;issues&#8221; with search providers who use &#8216;POST&#8217; for queries, I&#8217;ll add some code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2008/11/06/open-search/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CakePHP Authentication</title>
		<link>http://www.liquidfoot.com/2008/09/12/cakephp-authentication/</link>
		<comments>http://www.liquidfoot.com/2008/09/12/cakephp-authentication/#comments</comments>
		<pubDate>Fri, 12 Sep 2008 19:47:18 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=81</guid>
		<description><![CDATA[I found some great tutorials on implementing ACL authentication in CakePHP. However, for the longest time I couldn&#8217;t get the actual example code to work. The way to authenticate everything in your application is to create an app_controller.php file in your app folder (see Preparing to Add Auth). In every other controller I&#8217;ve created in [...]]]></description>
			<content:encoded><![CDATA[<p>I found some great tutorials on implementing ACL authentication in CakePHP. However, for the longest time I couldn&#8217;t get the actual example code to work. The way to authenticate everything in your application is to create an app_controller.php file in your app folder (see <a href="http://book.cakephp.org/view/643/Preparing-to-Add-Auth">Preparing to Add Auth</a>). In every other controller I&#8217;ve created in CakePHP, you follow this convention:</p>
<pre class="brush: php;">

&lt;?php

class FooBarsController extends AppController {

var $name = 'FooBars';

}

?&gt;
</pre>
<p>I followed the same convention (didn&#8217;t read the docs very closely) and just got all kinds of errors. After digging a bit deeper, turns out AppController extends Controller&#8230;apparently it can&#8217;t extend itself <img src='http://www.liquidfoot.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Hopefully this&#8217;ll save some time for someone, but the full controller for the example in the cookbook for the app_controller.php is this:</p>
<pre class="brush: php;">

&lt;?php

class AppController extends Controller {
var $components = array('Auth', 'Acl');

function beforeFilter() {
//Configure AuthComponent
$this-&gt;Auth-&gt;authorize = 'actions';
$this-&gt;Auth-&gt;loginAction = array('controller' =&gt; 'users', 'action' =&gt; 'login');
$this-&gt;Auth-&gt;logoutRedirect = array('controller' =&gt; 'users', 'action' =&gt; 'login');
$this-&gt;Auth-&gt;loginRedirect = array('controller' =&gt; 'posts', 'action' =&gt; 'add');
}
}
?&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2008/09/12/cakephp-authentication/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Vufind and Sirsi</title>
		<link>http://www.liquidfoot.com/2008/09/05/vufind-and-sirsi/</link>
		<comments>http://www.liquidfoot.com/2008/09/05/vufind-and-sirsi/#comments</comments>
		<pubDate>Fri, 05 Sep 2008 21:08:25 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[sirsi]]></category>
		<category><![CDATA[solrmarc]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[vufind]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=58</guid>
		<description><![CDATA[I committed a bunch of small fixes into the Solrmarc and Vufind projects today to deal with the release of Solr 1.3 RC 2. We&#8217;re using the multicore functionality of Solr for Vufind and we were having some issues with the resource loaders for the different cores. The fix was pretty minor, just creating a [...]]]></description>
			<content:encoded><![CDATA[<p>I committed a bunch of small fixes into the <a href="http://code.google.com/p/solrmarc">Solrmarc</a> and <a href="http://www.vufind.org">Vufind</a> projects today to deal with the release of Solr 1.3 RC 2. We&#8217;re using the multicore functionality of Solr for Vufind and we were having some issues with the resource loaders for the different cores. The fix was pretty minor, just creating a <a href="http://lucene.apache.org/solr/api/org/apache/solr/core/CoreContainer.html">CoreContainer</a> and set the SolrCore from that:</p>
<p><code>
<pre class="brush: java;">CoreContainer cc = new CoreContainer(solrCoreDir, configFile);
solrCore = cc.getCore(solrCorename);
</pre>
<p></code></p>
<p>Ok, so that was more of an update, but it got me to reindex the our marc content. Our 001 fields don&#8217;t always have info, so our Systems Librarian told me just to use the 035a for the id field. There was only one problem&#8230;they had a &#8220;(Sirsi)&#8221; as a prefix to the actual number. This wouldn&#8217;t be that big of an issue, but it was causing the queries sent to Solr to be off, and I wasn&#8217;t getting any results for a detail view.</p>
<p>Fortunately, Solrmarc already has a facility to deal with this: PatternMaps! To pull out just the number, I changed the id definition in the vufind.properties file to</p>
<p><code>
<pre class="brush: java;">
id = 035a, (pattern_map.id), first
</pre>
<p></code></p>
<p>This basically maps the id field in the schema.xml file to the 035a, using a patternMap named pattern_map.id, and only takes the first of the 035a if there are multiples. I know, there shouldn&#8217;t be, but I&#8217;ve seen funky things <img src='http://www.liquidfoot.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Now, to add the PatternMap definition:</p>
<p><code>
<pre class="brush: java;">pattern_map.id.pattern_0 = \\(Sirsi\\)\\ (.*)=&gt;$1</pre>
<p></code></p>
<p>It&#8217;s just a simple regex pattern definition that takes out the &#8220;(Sirsi)&#8221; and the space between it and the actual id we&#8217;re using.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2008/09/05/vufind-and-sirsi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Choosing a PHP Framework</title>
		<link>http://www.liquidfoot.com/2008/09/03/choosing-a-php-framework/</link>
		<comments>http://www.liquidfoot.com/2008/09/03/choosing-a-php-framework/#comments</comments>
		<pubDate>Wed, 03 Sep 2008 14:39:22 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[frameworks]]></category>
		<category><![CDATA[neh]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zend]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=38</guid>
		<description><![CDATA[I&#8217;m working on an NEH funded collaborative research grant entitled &#8220;Measuring the Social, Spatial, and Temporal Dimensions of Virginia Slave Housing.&#8221; The project is exciting because it&#8217;s taking existing architectural, archaeological, and documentary evidence to create a standard presentation for the information. A perhaps more important, though secondary (or I dare say tertiary) part is [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m working on an NEH funded collaborative research grant entitled &#8220;Measuring the Social, Spatial, and Temporal Dimensions of Virginia Slave Housing.&#8221; The project is exciting because it&#8217;s taking existing architectural, archaeological, and documentary evidence to create a standard presentation for the information. A perhaps more important, though secondary (or I dare say tertiary) part is a standardized form for recording the information in the field. Right now most of this information is in varying levels of completeness, based mostly on the researcher and the sponsoring institution&#8217;s goals.</p>
<p>So, through the process of generating the database schema, we developed about 25 relational tables that record varying degrees of information. The basic idea is that there is a meta-object (a site) that contains one-or-more buildings. Each of these buildings can have a one-or-more phases (adding editions) and then each phase has additional information on a room-by-room basis (doors, windows, fire places, etc.).</p>
<p>I had built a similar database for a project looking at Chesapeake architecture for the Jamestown 400th anniversary celebrations (<a href="http://www.historycooperative.org/journals/wm/64.3/graham.html">Adaptation and Innovation: Archaeological and Architectural Perspectives on the Seventeenth-Century Chesapeake</a>) in ColdFusion using <a href="http://trac.reactorframework.com/">Reactor</a> with an MSSQL backend. However, this project requied slightly different specs as it is being hosted in a different location that doesn&#8217;t offer ColdFusion hosting. They have the basic *AMP stack, so I started looking around at the different PHP frameworks to aid in the development of the application.</p>
<p>After a little investigation, I narrowed down the choices to what I&#8217;m calling the Big-Three: <a href="http://framework.zend.com/en/">Zend</a>, <a href="http://codeigniter.com/">CodeIgniter</a>, and <a href="http://cakephp.org/">CakePHP</a> (yes, I know there are more). While looking at these, I needed something that I can pick up quickly, let&#8217;s me quickly build the different forms needed to populate the information, have a sizable community to help solve issues that pop up, and also be flexible enough to quickly change the database backend when needed (and when working with academics, this happens more than you really want it to).</p>
<p>Zend has some great features. It&#8217;s backed by a company (Zend) who provides training. They have support and training courses, but this is a for-profit company, so the cost is a bit prohibitive for a small research project (with very little funding). Their site does provide good documentation, video examples, and a really cool integration with Lucene (<a href="http://framework.zend.com/manual/en/zend.search.lucene.html">Zend_Search_Lucene</a>). I thought the <a href="http://framework.zend.com/docs/quickstart">QuickStart</a> was a bit on the light side, but thought it had a really rich feature set (at least for what I need it to do).</p>
<p>Next up was <a href="http://codeigniter.com/">CodeIgniter</a>. I was a bit dazzled by this. I liked it small footprint and it seemed lighter and didn&#8217;t have strict naming conventions. It also had scaffolding! This is quite important in the development process as the database backend will change through the course of the site development. I know, it&#8217;s not a good idea to put this into a production environment, but we&#8217;re talking about maybe two other people working on this at one time. The video tutorials are pretty nice, and there seemed to be a good group of folks adding content all the time. There are some nice authentication libraries (FreakAuth) and it&#8217;s pretty easy to get something up on the screen.</p>
<p>I had played (briefly) with <a href="http://cakephp.org/">cakePHP</a> over the summer. I was intriged with &#8220;baking&#8221; the application (the metaphore gets a bit overplayed). Essentially they developed a script that will take the scaffolding and then generate the basic models, views, and controllers for the application. It even goes a step further with login permissions (though there&#8217;s a bit of manual updating there). I didn&#8217;t really dig how they really push the naming conventions, but I quickly figured out how to over ride most of them.</p>
<p>In the end, I&#8217;ve decided to go with cakePHP for this application. I really liked the fact that I could get away with writing very little code and generate most of what I&#8217;ll need to get the administrative backend up-and-running. I may be disappointed in this decision, but as I make progress on the project, I&#8217;ll add more posts on some of the pit-falls and successes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2008/09/03/choosing-a-php-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Luke for Lucene 2.4</title>
		<link>http://www.liquidfoot.com/2008/08/21/luke-for-lucene-24/</link>
		<comments>http://www.liquidfoot.com/2008/08/21/luke-for-lucene-24/#comments</comments>
		<pubDate>Thu, 21 Aug 2008 19:13:37 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[lucene]]></category>
		<category><![CDATA[luke]]></category>
		<category><![CDATA[solr]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=34</guid>
		<description><![CDATA[On the Vufind project, I&#8217;ve been migrating the Solrmarc codebase to use Solr 1.3. It&#8217;s got a lot of nifty changes (the multi-core and DataImportHandler are really nice additions), including moving to Lucene 2.4 for the actual indexing. On the down side, this means that Luke doesn&#8217;t have the correct analyzers or format interpretors (you [...]]]></description>
			<content:encoded><![CDATA[<p>On the Vufind project, I&#8217;ve been migrating the Solrmarc codebase to use Solr 1.3. It&#8217;s got a lot of nifty changes (the multi-core and DataImportHandler are really nice additions), including moving to Lucene 2.4 for the actual indexing.</p>
<p>On the down side, this means that <a href="http://www.getopt.org/luke/">Luke </a>doesn&#8217;t have the correct analyzers or format interpretors (you get an incorrect format excpetion).</p>
<p>The fix is pretty quick. Just download the source tarball/zip for Luke (at the bottom of the page) and extract them somewhere. Then, grab a build of the Lucene 2.4 core, analyzers, and snowball analyzer (I grabbed mine from the <a href="http://people.apache.org/builds/lucene/solr/nightly/">Solr nightly build</a>).</p>
<p>Just throw the jars into Luke&#8217;s lib folder (e.g. ~/luke-src-0.8-dev/lib) and then rebuild with Ant (ant). This will build the jars in the dist folder. You should be able to check out your index to make sure everything is good in the index.</p>
<p>If you&#8217;re lazy and just want the one I created, here you go: <a href="http://www.liquidfoot.com/wp-content/uploads/2008/08/luke-08-dev.jar">luke-08-dev</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2008/08/21/luke-for-lucene-24/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
