<?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; Projects</title>
	<atom:link href="http://www.liquidfoot.com/category/projects/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>Zotero + Ruby == Fun!</title>
		<link>http://www.liquidfoot.com/2010/04/17/zotero-ruby-fun/</link>
		<comments>http://www.liquidfoot.com/2010/04/17/zotero-ruby-fun/#comments</comments>
		<pubDate>Sat, 17 Apr 2010 16:36:10 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[gem]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[zotero]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=345</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p>Last week I was on a panel at the Organization of American Historian&#8217;s Annual Meeting up in DC with some folks from <a href="http://chnm.gmu.edu/">CHNM</a>. One of the really cool thing that I&#8217;ve noticed is every time I&#8217;m around those folks, I get ideas&#8230;which can be dangerous. I had been meaning to poke at the Zotero API for a while and after talking with <a href="http://twitter.com/tjowens/">@tjowens</a>, <a href="http://twitter.com/joegilbert">@joegilbert</a>, and <a href="http://twitter.com/clioweb">@clioweb</a> over some falafels, I started putting some ideas together on the train home.</p>
<p>Over the last couple of years, I&#8217;ve been working on-and-off on improving the <a href="http://deca.swem.wm.edu/">Database of Early Chesapeake Architecture</a>. I&#8217;d recently gotten the data (again) from Swem Library and had been working on pushing it to a more open framework (it was ColdFusion + MSSQL; now Rails + Postgresql). What I wanted to be able to add in is an extensible method of citation for the various buildings and sites used (check out the <a href="http://deca.heroku.com">work-in-progress</a>). At the time, I tried to use RefWorks (with very little success) to handle the citations, but with the improvements to Zotero (and it&#8217;s Group ability), I thought I&#8217;d go down this road and test if this is a viable method of citation management.</p>
<p>I first took a look at Jeremy&#8217;s <a href="http://github.com/clioweb/phpZotero">phpZotero code</a>. The first thing I noticed is that there&#8217;s a pretty funky way that you have to construct URLs for the &#8220;API&#8221; (I think the Zotero API is more of an RSS decorator than an API, but hopefully they&#8217;re working on that). Essentially you construct a URL requests to the Zotero API server with a user ID. Unfortunately, most people don&#8217;t know their user_id, so the PHP code goes and looks this up on a different server, parses out the user_id, then constructs an HTTP request for RSS data from the API server. I kind of brace a bit at the thought of every request needing to go to two servers (multiple points of failure, speed, etc.). When I started creating a ruby wrapper for these calls, I made the object use the user_id (Integer) and not the user_name (String). Knowing folks might not know their user_id, I whipped up a quick Sinatra app on heroku to look up Zotero User ids: <a href="http://zotero-id-finder.heroku.com/">zotero-id-finder</a> (source on <a href="http://github.com/waynegraham/Zotero-ID-Finder">github</a>).</p>
<p>Next, I needed something to not have to use Nokogiri all the time to grab info off the Zotero server. I made a basic Gem to wrap these requests named <a href="http://rubygems.org/gems/rzotero">rzotero</a>. This is really helpful, but what I really wanted to do is add citations to ActiveRecord models a la acts_as_taggable. To that end, I started mocking up <a href="http://github.com/waynegraham/acts_as_citable">acts_as_citable</a> which will allow you to add in citations identifiers to be used with rzotero plugin to record and display items in a collection in ActiveRecord contexts.</p>
<p>As a warning, all of these are in a pre-alpha-ish state and may (badly) break your code (especially since it&#8217;s lightly tested right now). As things progress, I&#8217;ll have more posts here, and over on the <a href="http://www.scholarslab.org">Scholars&#8217; Lab site</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2010/04/17/zotero-ruby-fun/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<georss:point featurename="[38.14150990148844, -79.0871000289917]">38.14150990148844 -79.0871000289917</georss:point>
	</item>
		<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[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 OpenLayers looked on the Safari mobile browser. The theory to test out here was that you could pretty easily pull up your current [...]]]></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>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>Sherlock/OpenSearch Plugins for Libraries</title>
		<link>http://www.liquidfoot.com/2009/01/15/sherlockopensearch-plugins-for-libraries/</link>
		<comments>http://www.liquidfoot.com/2009/01/15/sherlockopensearch-plugins-for-libraries/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 19:34:12 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[internet explorer]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[opensearch]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=240</guid>
		<description><![CDATA[Back in the day, I used to work on the <a href="http://mycroft.mozdev.org/">Mycroft Project</a>. At the time, only Firefox/Netscape could actually used these plugins as they were based on Apple's Sherlock specification (Mycroft is Sherlock Holmes' brother, btw). These plugins have been a staple in the Firefox browser, but the Sherlock spec was a little arcane. More recently, both Firefox and IE have implemented support for the <a href="http://www.opensearch.org/Home">OpenSearch specification</a>. I have to say that the OpenSearchDescription is a significant update (at least from a readability standpoint) than Sherlock.]]></description>
			<content:encoded><![CDATA[<p>Back in the day, I used to work on the <a href="http://mycroft.mozdev.org/">Mycroft Project</a>. At the time, only Firefox/Netscape could actually used these plugins as they were based on Apple&#8217;s Sherlock specification (Mycroft is Sherlock Holmes&#8217; brother, btw). These plugins have been a staple in the Firefox browser, but the Sherlock spec was a little arcane. More recently, both Firefox and IE have implemented support for the <a href="http://www.opensearch.org/Home">OpenSearch specification</a>. I have to say that the OpenSearchDescription is a significant update (at least from a readability standpoint) than Sherlock.</p>
<p>A few years ago, I had written a bunch of Sherlock plugins for <a href="http://swem.wm.edu/resources/tools/">searching various library</a> catalogs. Those pretty much lay dormant until I was talking with my student worker this last semester and he got quite excited about these, and wondered if there might be a way to also search the databases the library subscribes to, and provide off-campus access to these through our proxy server. This code is in a very basic stage right now, but essentially what I did was create a database driven application in PHP that generates OpenSearch XML for various targets to search against.</p>
<p>Right now, this only supports HTTP GET requests (POST parameters require an additional table), but here&#8217;s the DDL:</p>
<pre name="code" class="sql">CREATE TABLE `plugins` (
  `id` char(36) NOT NULL,
  `short_name` varchar(50) NOT NULL,
  `description` varchar(255) NOT NULL,
  `engine` varchar(25) NOT NULL,
  `image` varchar(25) NOT NULL,
  `input_encoding` varchar(10) NOT NULL,
  `url` varchar(550) NOT NULL,
  `method` varchar(4) NOT NULL default 'get',
  `proxy` tinyint(1) NOT NULL default '1',
  KEY `engine_index` (`engine`),
  KEY `short_name_index` (`short_name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1</pre>
<p>You don&#8217;t need all of these fields for every record, and here is some useful records&#8230;</p>
<pre name="code" class="sql">INSERT INTO plugins (id, short_name, engine, input_encoding, method, proxy, url)
VALUES (UUID(), ' JStor', 'jstor', 'UTF-8', 'get', 1, 'http://www.jstor.org/action/doBasicSearch?Query=');

INSERT INTO plugins (id, short_name, engine, input_encoding, method, proxy, url)
VALUES (UUID(), 'Google Your University', 'google', 'UTF-8', 'get', 1, 'http://www.google.com/univ/wm?hl=en&amp;ie=ISO-8859-1&amp;btnG=Google+Search&amp;q=');

INSERT INTO plugins (id, short_name, engine, input_encoding, method, proxy, url)
VALUES (UUID(), 'Google Scholar', 'googlescholar', 'UTF-8', 'get', 1, 'http://scholar.google.com/scholar?&amp;hl=en&amp;lr=&amp;btnG=Search&amp;q=');

INSERT INTO plugins (id, short_name, engine, input_encoding, method, proxy, url)
VALUES (UUID(), 'Ebrary', 'ebrary', 'UTF-8', 'get', 1, 'http://site.ebrary.com/lib//Top?layout=search&amp;nosr=1&amp;sch=sch&amp;frm=smp.x&amp;p00=');

INSERT INTO plugins (id, short_name, engine, input_encoding, method, proxy, url)
VALUES (UUID(), 'EbscoHost', 'ebsco', 'UTF-8', 'get', 1, 'http://search.ebscohost.com/login.aspx?db=aph&amp;direct=true&amp;bQuery=');

INSERT INTO plugins (id, short_name, engine, input_encoding, method, proxy, url)
VALUES (UUID(), 'LexisNexis', 'lexisnexis', 'UTF-8', 'get', 1, 'http://www.lexisnexis.com/us/lnacademic/search/homesubmitForm.do');

INSERT INTO plugins (id, short_name, engine, input_encoding, method, proxy, url)
VALUES (UUID(), 'Proquest UMI', 'umi', 'UTF-8', 'get', 1, 'http://proquest.umi.com/pqdweb?RQT=305&amp;FT=1&amp;DBId=414&amp;SQ=');

INSERT INTO plugins (id, short_name, engine, input_encoding, method, proxy, url)
VALUES (UUID(), 'Science Direct', 'sciencedirect', 'UTF-8', 'get', 1, 'http://www.sciencedirect.com/science/quicksearch?query=');</pre>
<p>Apparently I wrote the queries with MDB2, I&#8217;ve since moved most of my interactions to Zend Db (you should be able to write that part pretty quickly) and just dump the names of the plugins in the tableon a view:</p>
<pre name="code" class="php">foreach($plugins as $plugin):

    echo('&amp;lt;li&amp;gt;' . $plugin['short_name'] . ': ');
       echo(' &amp;lt;a href="openSearch.php?id=' . $plugin['id'] . '"&amp;gt;&amp;lt;img src="images/a9.png" title="OpenSearch" /&amp;gt;&amp;lt;/a&amp;gt;'); 

        if(strlen($plugin['url']) &amp;gt; 0){
        	echo(' &amp;lt;a href="search.php?engine=' . $plugin['engine'] . '&amp;q=regulators"&amp;gt;test search');
            echo(' | &amp;lt;a href="#" title="Ref: ' . $plugin['engine'] . '" onClick="addOpenSearch(\'' . $plugin['engine'] . '\', \'gif\', \'Education\', \'' . $plugin['id'] . '\'); return false;"&amp;gt;add&amp;lt;/a&amp;gt;');
        }

        echo('&amp;lt;/li&amp;gt;);

');
endforeach;</pre>
<p>The add code is straight-forward</p>
<pre name="code" class="php">$result = $result[0];

$short_name = $result['short_name'];
$description = $result['description'];
$engine = $result['engine'];
$id = $result['id'];

$xml = &amp;lt;&amp;lt;&amp;lt;EOT
&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
xmlns:moz="http://www.mozilla.org/2006/browser/search/"&amp;gt;
&amp;lt;ShortName&amp;gt;$short_name&amp;lt;/ShortName&amp;gt;
&amp;lt;Description&amp;gt;$description&amp;lt;/Description&amp;gt;
&amp;lt;Url type="text/html" method="get" template="http://&amp;lt;your_server&amp;gt;/plugins/proxy.php?engine=$engine&amp;q="/&amp;gt;
&amp;lt;Contact&amp;gt;libsys@wm.edu&amp;lt;/Contact&amp;gt;
&amp;lt;Image width="16" height="16"&amp;gt;http://&amp;lt;your_server&amp;gt;/favicon.ico&amp;lt;/Image&amp;gt;
&amp;lt;Developer&amp;gt;Wayne Graham&amp;lt;/Developer&amp;gt;
&amp;lt;InputEncoding&amp;gt;UTF-8&amp;lt;/InputEncoding&amp;gt;
&amp;lt;moz:SearchForm&amp;gt;http://&amp;lt;your_server&amp;gt;/plugins/search.php?engine=$engine&amp;lt;/moz:SearchForm&amp;gt;
&amp;lt;moz:UpdateUrl&amp;gt;http://&amp;lt;your_server&amp;gt;/plugins/opensearch.php?$id&amp;lt;/moz:UpdateUrl&amp;gt;
&amp;lt;moz:IconUpdateUrl&amp;gt;http://swem.wm.edu/favicon.ico&amp;lt;/moz:IconUpdateUrl&amp;gt;
&amp;lt;moz:UpdateInterval&amp;gt;7&amp;lt;/moz:UpdateInterval&amp;gt;
&amp;lt;/OpenSearchDescription&amp;gt;
EOT;
header("Content-Type: text/xml");
echo($xml);</pre>
<p>You just need a little JavaScript to add this in to IE and Firefox:</p>
<pre name="code" class="JavaScript">
function addOpenSearch(name,ext,cat,pid,meth)
{
  if ((typeof window.external == "object") &#038;&#038; ((typeof window.external.AddSearchProvider == "unknown") || (typeof window.external.AddSearchProvider == "function"))) {
    // See bugs 430058/430067/430070 for Camino
    if (((typeof window.external.AddSearchProvider == "unknown") || (window.navigator.vendor == 'Camino'))&#038;&#038; meth == "p") {
      alert("This plugin uses POST which is not currently supported by your browser's implementation of OpenSearch.");
    } else {
      window.external.AddSearchProvider("http://<your_server>/plugins/install.php?id=" + pid);
    }
  } else {
    alert("You will need a browser which supports OpenSearch to install this plugin.");
  }
}
</pre>
<p>If I get some time soon, I&#8217;ll wrap this up into a package; rudimentary, but a decent start to your own app!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2009/01/15/sherlockopensearch-plugins-for-libraries/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Library Search Google Gadget</title>
		<link>http://www.liquidfoot.com/2009/01/15/library-search-google-gadget/</link>
		<comments>http://www.liquidfoot.com/2009/01/15/library-search-google-gadget/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 16:26:18 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[igoogle]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=223</guid>
		<description><![CDATA[I’ve been going through a bunch of old stuff I’ve written as I clean up things. There will be a rash of posts where I take code I’ve written in different projects to see how things work and that are potentially useful, just no implemented in anything that I may need in the future. The first one here is some code for a Google gadget I wrote to search our online catalog a few years ago when the API was released.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been going through a bunch of old stuff I&#8217;ve written as I clean up things. There will be a rash of posts where I take code I&#8217;ve written in different projects to see how things work and that are potentially useful, just no implemented in anything that I may need in the future. The first one here is some code for a Google gadget I wrote to search our online catalog a few years ago when the API was released.</p>
<p>If you&#8217;re not one of the of the cool kids who uses <a href="http://www.google.com/ig">iGoogle</a>, you&#8217;ll need to set yourself up to use this code. I just looked at the <a href="http://code.google.com/apis/gadgets/docs/dev_guide.html">developer&#8217;s guide</a>, and it seems a bit more fleshed out than it was when I first took a whack at the code <img src='http://www.liquidfoot.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  The really cool thing about these gadgets is that they are essentailly just an XML file with some JavaScript/HTML thrown in.</p>
<p>I thought it might be a nice feature to just provide a search box for people to launch a catalog search. This is just a simple HTML form.</p>
<pre class="html">&amp;lt;form target="_parent" name="searchform" action="http://lion.wm.edu/uhtbin/cgisirsi/0/0/057/5" id="searchform"&gt;
    &amp;lt;input id="searchInput" style="width: 100%;" name="searchdata1" type="text" accesskey="f" /&gt;
    &amp;lt;input id="library" name="library" type="hidden" value="SWEM" /&gt;
    &amp;lt;input id="user_id" name="user_id" type="hidden" value="SWEPUB" /&gt;
    &amp;lt;input id="sourceid" name="sourceid" type="hidden" value="gadget" /&gt;
&amp;lt;/form&gt;</pre>
<p>This is just HTML code that you would use on any search page. Nothing fancy. Now on to creating the gadget..</p>
<p>There are two parts to the XML code for the spec. The root node (Module) has two elements, ModulePrefs and Content. The ModulePrefs element is relatively straight-forward:</p>
<pre class="xml">&amp;lt;ModulePrefs
    title="Swem Catalog Search"
    height="40"
    description="Search Swem's online catalog from iGoogle"
    author="Wayne Graham"
    author_email="dontspamme@gmail.com" screenshot=""
    author_location="Williamsburg, Virginia"
    title_url="http://swem.wm.edu"&gt;

    &amp;lt;Require feature="analytics" /&amp;gt;

&amp;lt;/ModulePrefs&amp;gt;</pre>
<p>The attributes of the ModulePrefs element (title, height, description, etc.) should be pretty self explanitory. I wanted to be able to track usage of the gadget, so I eneabled Google analytics for the widget by requiring the analytics feature. Now for the meat.</p>
<p>What I did was write a short CSS definition and some JavaScript to actually display a form in the Content element of the Module.</p>
<pre class="xml">&amp;lt;Content type="html"&amp;gt;&amp;lt;![CDATA[
&amp;lt;style&amp;gt;
    #subLibrary {
        font-family:arial, sans-serif;
        font-size:10px;
        color:#676767;
    }
    #link {
        font-family:Garamond, serif;
        font-size:32px;
        color:black;
        text-decoration:none;
    }
    #searchGoButton {
        font-weight:bold;
    }
&amp;lt;/style&amp;gt;
&amp;lt;script&amp;gt;
function displaySearchBar (prefs) {
    var lang = prefs.getString("mylang");

    if (lang == "") {
        lang = prefs.getString(".lang");
    }

    var html =
        '&amp;lt;form target="_parent" name="searchform" action="http://lion.wm.edu/uhtbin/cgisirsi/0/0/0/57/5" id="searchform"&amp;gt;' +
        '&amp;lt;table style="width:100%"&amp;gt;' +
        '&amp;lt;tr&amp;gt;' +
        '&amp;lt;td style="padding-bottom:4px"&amp;gt;' +
        '&amp;lt;a target="_parent" id="link" href="http://lion.wm.edu/uhtbin/webcat"&amp;gt;Catalog&amp;lt;/a&amp;gt;' +
        '&amp;lt;span style="vertical-align: sub;"&amp;gt;Swem&amp;lt;/span&amp;gt;' +
        '&amp;lt;/td&amp;gt;' +
        '&amp;lt;td width=100%&amp;gt;' +
        '&amp;lt;input id="searchInput" style="width:100%" name="searchdata1" type="text" accesskey="f" value="" /&amp;gt;' +
        '&amp;lt;input id="library" name="library" type="hidden" value="SWEM" /&amp;gt;' +
        '&amp;lt;input id="user_id" name="user_id" type="hidden" value="SWEPUB" /&amp;gt;' +
        '&amp;lt;input id="sourceid" name="sourceid" type="hidden" value="gadget" /&amp;gt;' +
        '&amp;lt;/td&amp;gt;' +
        '&amp;lt;td&amp;gt;' +
        '&amp;lt;input type="submit" name="go" id="searchGoButton" value="Search" /&amp;gt;' +
        '&amp;lt;/td&amp;gt;' +
        '&amp;lt;td&amp;gt;' +
        '&amp;amp;amp;nbsp;' +
        '&amp;lt;/td&amp;gt;' +
        '&amp;lt;/tr&amp;gt;' +
        '&amp;lt;/table&amp;gt;'
        '&amp;lt;form&amp;gt;';
    document.write(html);
}

displaySearchBar(new _IG_Prefs(__MODULE_ID__));
_IG_Analytics("analytics-id", "/google-gadget");
&amp;lt;/script&amp;gt;
]]&amp;gt;
&amp;lt;/Content&amp;gt;</pre>
<p>Once you&#8217;re done, you can test everything with the directions on the <a href="http://code.google.com/apis/gadgets/docs/tools.html">Developer Tools page</a>. There are even really nice resources to tell you how to <a href="http://code.google.com/apis/gadgets/docs/tools.html#Host">host this on Google Code</a>.</p>
<p>As a finished product, this is what the gadget looks like in iGoogle:</p>
<p><img class="alignnone size-medium wp-image-235" title="gadget" src="http://www.liquidfoot.com/wp-content/uploads/2009/01/gadget-300x46.png" alt="gadget" width="300" height="46" /></p>
<p>For the folks that use iGoogle as their home page, this can be valuable tool for them. Next up, I need to brush off my code for generating Sherlock/Opensearch extensions for Firefox and IE&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2009/01/15/library-search-google-gadget/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Updated XSL for MODS</title>
		<link>http://www.liquidfoot.com/2008/11/21/updated-xsl-for-mods/</link>
		<comments>http://www.liquidfoot.com/2008/11/21/updated-xsl-for-mods/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 20:57:09 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[xslt]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=141</guid>
		<description><![CDATA[David noticed that not all the authors were being inserted into the database. I looked at it and it turns out that an author can have an arbitrary number of given names to handle the inclusion of middle names. I had thought I was only pulling the first node, but it turns out I wasn&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>David noticed that not all the authors were being inserted into the database. I looked at it and it turns out that an author can have an arbitrary number of given names to handle the inclusion of middle names. I had thought I was only pulling the first node, but it turns out I wasn&#8217;t and the SQL to insert the authors with was erroring out so there were a lot of citations without authors.</p>
<p>I went back in and modified the XSLT that was processing the given names to now read:</p>
<pre class="brush: xml;">

&lt;xsl:variable name=&quot;ref_id&quot;&gt;
    &lt;xsl:value-of select=&quot;@ID&quot; /&gt;
&lt;/xsl:variable&gt;
...
&lt;xsl:for-each select=&quot;name&quot;&gt;
INSERT INTO authors (id, ref_id, given, family, role)
VALUES(
    UUID(),
    &lt;!--(SELECT id FROM citations ORDER BY added desc limit 1),--&gt;
    '&lt;xsl:value-of select=&quot;$ref_id&quot;/&gt;',
    &lt;xsl:for-each select=&quot;.&quot;&gt;
        '&lt;xsl:for-each select=&quot;namePart[@type='given']&quot;&gt;
            &lt;xsl:value-of select=&quot;.&quot;/&gt;
            &lt;xsl:text&gt; &lt;/xsl:text&gt;
        &lt;/xsl:for-each&gt;',

        '&lt;xsl:value-of select=&quot;namePart[@type='family']&quot;/&gt;',
        '&lt;xsl:value-of select=&quot;role/roleTerm&quot;/&gt;'
    &lt;/xsl:for-each&gt;
    );
&lt;/xsl:for-each&gt;
</pre>
<p>It looked like the SQL to grab the last item didn&#8217;t always return a record for whatever reason (a locking issue?). Since there was already a key in the field, I just switched over to use that in the inserts. Still need to go through and regularize the fields so MySQL isn&#8217;t attempting to pull a foreign key index on a variable width field, but this is an update to yesterday&#8217;s code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2008/11/21/updated-xsl-for-mods/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>NFS Geek Out</title>
		<link>http://www.liquidfoot.com/2008/10/01/nfs-geek-out/</link>
		<comments>http://www.liquidfoot.com/2008/10/01/nfs-geek-out/#comments</comments>
		<pubDate>Wed, 01 Oct 2008 23:23:34 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[geek]]></category>
		<category><![CDATA[nfs]]></category>
		<category><![CDATA[storage]]></category>

		<guid isPermaLink="false">http://www.liquidfoot.com/?p=112</guid>
		<description><![CDATA[And that&#8217;s not Need for Speed A while back I got a couple of Sun Thumpers (24TB each) to help out with our storage needs in the library. I&#8217;ve gotten to the point to deploy them. I have to admit I really dig the Solaris admin tools (web based ILOM) and the ZFS configuration tools. [...]]]></description>
			<content:encoded><![CDATA[<p>And that&#8217;s not Need for Speed <img src='http://www.liquidfoot.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>A while back I got a couple of Sun Thumpers (24TB each) to help out with our storage needs in the library. I&#8217;ve gotten to the point to deploy them. I have to admit I really dig the Solaris admin tools (web based ILOM) and the ZFS configuration tools.</p>
<p>The idea for the first Thumper is to make that the primary storage for of content for our institutional repository (we&#8217;re running DSpace). The last couple of days I&#8217;ve been getting down to a really geeky level in systems administration. I created an NFS share, but the question was on how to mount it. We use nfs3 in the integrated graphics labs to mount the high performance computing clusters, so I did this for DSpace and added an fstab entry</p>
<p>&lt;server&gt;:/dspace /dspace_nfs nfs rw,nosuid,hard,intr,rsize=32768,wsize=32768,tcp 0 0</p>
<p>I then ran some test to see what kind of throughput I could get.</p>
<p>time dd if=/dev/zero of=/dspace_nfs/dspace/testfile bs=16 count=16384</p>
<p>I got a result of</p>
<p>262144 bytes (262 kB) copied, 0.088866 seconds, 2.9 MB/s</p>
<p>Then, just to compare it against normal disk I/O, I did the same on the local hard drive</p>
<p>time dd if=dev/zero of=~/testfile bs=16 count=16384</p>
<p>This was quite a bit faster (as you probably would guess)</p>
<p>262144 bytes (262 kB) copied, 0.041865 seconds, 6.3 MB/s</p>
<p>To test the read speed, I took the same file and brought it back.</p>
<p>time dd if=/dspace_nfs/dspace/testfile of=/dev/null bs=16</p>
<p>On the NFS mount I got</p>
<p>262144 bytes (262 kB) copied, 0.017822 seconds, 14.7 MB/s</p>
<p>and on the local file system I got</p>
<p>262144 bytes (262 kB) copied, 0.015867 seconds, 16.5 MB/s</p>
<p>I was kind of surprised at how close the reads were. It&#8217;s not a huge file it&#8217;s moving (our larger files are around 350MB), but it&#8217;s reasonably consistence with an arbitrary file size of the PDFs we have in the collection.</p>
<p>I was corresponding with a colleague who&#8217;s been doing this way longer than I have and he suggested using a larger blocksize and writing/reading some files larger than the RAM size. I also wanted to test against NFS4 (I was using NFS3 in the fstab entry).</p>
<p>To do this, I just created a mount point and mounted the filesystem.</p>
<p>mkdir /mnt/nfs4<br />
mount -t nfs4 &lt;server&gt;:/dspace /mnt/nfs4</p>
<p>I ran the same test on the new mount and got a result of</p>
<p>262144 bytes (262 kB) copied, 0.055023 seconds, 4.8 MB/s</p>
<p>and for the read</p>
<p>262144 bytes (262 kB) copied, 0.014205 seconds, 18.5 MB/s</p>
<p>So, it looks like NFSv4 is much improved over NFSv3!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.liquidfoot.com/2008/10/01/nfs-geek-out/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>
	</channel>
</rss>
