Index: gs3-extensions/solr/trunk/src/bin/script/solr_passes.pl
===================================================================
--- gs3-extensions/solr/trunk/src/bin/script/solr_passes.pl	(revision 24446)
+++ gs3-extensions/solr/trunk/src/bin/script/solr_passes.pl	(revision 24446)
@@ -0,0 +1,431 @@
+#!/usr/bin/perl -w
+
+###########################################################################
+#
+# solr_passes.pl -- perl wrapper, akin to mgpp_passes, for Solr
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+# Heavily based on lucene_passes.pl, but does not need a SolrWrapper.jar
+# style solution as Solr has its own XML syntax:
+#
+#  http://wiki.apache.org/solr/UpdateXmlMessages
+#
+# This syntax is rather similar to what we already use, so the
+# main task of monitor_xml() is to translate the XML syntax Greenstone uses
+# into that needed by the solr server.  
+
+my $jetty_stop_key="greenstone-solr";
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    die "GEXT_SOLR not set\n" unless defined $ENV{'GEXT_SOLR'};
+}
+
+use strict;
+use util;
+
+
+# Not quite OO, but close enough for now
+#
+my $self = { 'full_server_jar' => undef,
+##	     'full_post_jar'   = undef,
+##	     'full_index_propfile' = undef,
+	     'jetty_explicitly_started' => undef
+	 };
+
+
+
+sub locate_file
+{
+    my ($search_path,$suffix) = @_;
+        
+    foreach my $sp (@$search_path) {
+	my $full_path = &util::filename_cat($sp,$suffix);
+	
+	if (-f $full_path) {
+	    return $full_path;
+	}
+    }
+    
+    # if get to here, then failed to find match
+
+    print STDERR "Error: Failed to find '$suffix'\n";
+    print STDERR "  Looked in: ", join(", ", @$search_path), "\n";
+    exit -1;
+}
+
+sub start_solr_server
+{
+    my ($search_path) = @_;
+
+    my $solr_home       = $ENV{'GEXT_SOLR'};
+    my $jetty_stop_port = $ENV{'JETTY_STOP_PORT'};
+
+    chdir($solr_home);
+    
+    my $solr_etc = &util::filename_cat($solr_home,"etc");
+
+    my $server_props = "-DSTOP.PORT=$jetty_stop_port";
+    $server_props .= " -DSTOP.KEY=$jetty_stop_key";
+    $server_props .= " -Dsolr.solr.home=$solr_etc";
+
+    my $server_jar = &util::filename_cat("lib","java","solr-jetty-server.jar");
+    my $full_server_jar = locate_file($search_path,$server_jar);
+    $self->{'full_server_jar'} = $full_server_jar;
+    
+    my $server_java_cmd = "java $server_props -jar \"$full_server_jar\"";
+#    if ($ENV{'GSDLOS'} eq "windows") {
+#	$server_java_cmd = "start $server_java_cmd";
+#    }
+#    else {
+#	$server_java_cmd .= " &";
+#    }
+    
+
+    if (open(SIN,"$server_java_cmd 2>&1 |")) {
+	
+	my $line;
+	while (defined($line=<SIN>)) {
+	    # Scan through output until you see a line like:
+	    #   2011-08-22 .. :INFO::Started SocketConnector@0.0.0.0:8983
+	    # which signifies that the server has started up and is
+	    # "ready and listening"
+	    
+	    last if ($line =~ m/INFO::Started SocketConnector/);
+	}
+
+	print STDERR "Jetty server ready and listening for connections\n";
+
+	# now we know the server is ready to accept connections, fork a
+	# child process that continues to listen to the output and
+	# prints out any lines that are not INFO lines
+
+	if (fork()==0) {
+	    # child process
+	    
+	    my $line;
+	    while (defined ($line = <SIN>)) {
+		next if ($line =~ m/^INFO:/);
+		next if ($line =~ m/^[0-9 :-]*INFO::/);
+		next if ($line =~ m/^\d{2}\/\d{2}\/\d{4}\s+/); 
+	    }
+	    close(SIN);
+	    
+	    # And now stop nicely
+	    exit 0;
+	}
+    }
+    else {
+	print STDERR "Error: failed to start solr-jetty-server\n";
+	print STDERR "!$\n";
+	exit -1;
+    }
+
+    # If get to here then server started (and ready and listening)
+    # *and* we are the parent process of the fork()
+
+    $self->{'jetty_explicitly_started'} = 1;
+
+}
+
+
+
+sub stop_solr_server
+{
+    my $full_server_jar = $self->{'full_server_jar'};
+    my $jetty_stop_port = $ENV{'JETTY_STOP_PORT'};
+    
+    my $server_props = "-DSTOP.PORT=$jetty_stop_port -DSTOP.KEY=$jetty_stop_key";
+    my $server_java_cmd = "java $server_props -jar \"$full_server_jar\" --stop";
+
+    my $server_status = system($server_java_cmd);
+    
+    if ($server_status!=0) {
+	print STDERR "Error: failed to stop solr-jetty-server\n";
+	print STDERR "!$\n";
+	exit -1;
+    }
+    else {
+	wait(); # let the child process finish
+    }
+}
+
+
+sub open_java_solr
+{
+  my ($collect, $doc_tag_level,$full_builddir,$indexdir,$removeold) = @_;
+
+
+  # if removeold set, then delete the curring $full_builddir
+  if ($removeold) {
+      my $full_indexdir = &util::filename_cat($full_builddir,$indexdir);
+      &util::rm_r($full_indexdir);
+  }
+
+# No longer used, as solr now run as two cores per collection (-Doc and -Sec)
+#
+#  # Set up an 'index.properties' file in $full_builddir, with the line
+#  #   index=$indexdir
+#  $full_index_propfile = &util::filename_cat($full_builddir,"index.properties");
+
+#  if (open(IPOUT,">$full_index_propfile")) {
+#      print IPOUT "index=$indexdir\n";
+#      close(IPOUT);
+#  }
+#  else {
+#      print STDERR "Failed to create $full_index_propfile\n";
+#      print STDERR "!$\n";
+#      exit -2;
+#  }
+
+  
+
+  my $search_path = [];
+
+  push(@$search_path,$ENV{'GSDLCOLLECTDIR'}) if defined $ENV{'GSDLCOLLECTDIR'};
+  push(@$search_path,$ENV{'GSDLHOME'})       if defined $ENV{'GSDLHOME'};
+  push(@$search_path,$ENV{'GEXT_SOLR'})      if defined $ENV{'GEXT_SOLR'};
+
+
+  # The following returns once Jetty has generated its 
+  # "reading and listening" line
+  #
+  start_solr_server($search_path);
+
+
+  # Now run the solr-post command
+
+  chdir($ENV{'GEXT_SOLR'});
+
+  
+  my $post_jar   = &util::filename_cat("lib","java","solr-post.jar");
+  my $full_post_jar   = locate_file($search_path,$post_jar);
+##  $self->{'full_post_jar'} = $full_post_jar;
+
+  my $jetty_server_port = $ENV{'SOLR_JETTY_PORT'};
+
+  # Now run solr-post command
+  my $post_props = "-Durl=http://localhost:$jetty_server_port/solr/$collect-$doc_tag_level/update";
+  $post_props .= " -Ddata=stdin";
+  $post_props .= " -Dcommit=yes";
+
+  my $post_java_cmd = "java $post_props -jar \"$full_post_jar\"";
+
+  print STDERR "**** post cmd = $post_java_cmd\n";
+  
+  open (PIPEOUT, "| $post_java_cmd") 
+      || die "Error in solr_passes.pl: Failed to run $post_java_cmd\n!$\n";
+}
+
+
+
+sub close_java_solr
+{
+    # closing the pipe has the effect of shutting down solr-post.jar
+    close(PIPEOUT);
+    
+    if ($self->{'jetty_explicitly_started'}) {
+	stop_solr_server();
+    }
+
+#  No longer used
+#    # $full_index_propfile is set up as a global variable so it can be shared
+#    # between open_java_solr() and here
+#    &util::rm($full_index_propfile);
+}
+
+
+
+
+
+sub save_xml_doc
+{
+    # This is identical to the one in lucene_passes.pl, and should be
+    # moved in to a package and shared ####
+
+    my ($full_textdir,$output_filename,$doc_xml) = @_;
+
+    my $dir_sep = &util::get_os_dirsep();
+
+    my $full_output_filename = &util::filename_cat($full_textdir,$output_filename);
+    my ($full_output_dir) = ($full_output_filename =~ m/^(.*$dir_sep)/x);
+    &util::mk_all_dir($full_output_dir);
+
+    open(DOCOUT,">$full_output_filename")
+	|| die "Unable to open $full_output_filename";
+
+    print DOCOUT $doc_xml;
+    close(DOCOUT);
+
+    # What this the purpose of the following? ####
+    my @secs =  ($doc_xml =~ m/<Sec\s+gs2:id="\d+"\s*>.*?<\/Sec>/sg);
+}
+
+
+sub compress_xml_doc
+{
+    # This is identical to the one in lucene_passes.pl, and should be
+    # moved in to a package and shared ####
+
+    my ($full_textdir,$output_filename) = @_;
+
+    my $full_output_filename
+	= &util::filename_cat($full_textdir,$output_filename);
+
+    # Greenstone ships with gzip for Windows
+    `gzip $full_output_filename`;
+}
+
+
+sub monitor_xml_stream
+{
+    # based on lucene's monitor_xml_stream, but simplified
+    # as only now used when in "text" mode
+
+    my ($full_textdir) = @_;
+
+    my $doc_xml = "";
+    my $output_filename = "";
+
+    my $line;
+    while (defined ($line = <STDIN>)) {
+
+	$doc_xml .= $line;
+
+	if ($line =~ m/^<Doc.+file=\"(.*?)\".*>$/) {
+	    $output_filename = $1;	    
+	}
+	
+	if ($line =~ m/^<\/Doc>$/) {
+	    save_xml_doc($full_textdir,$output_filename,$doc_xml);
+
+	    # Compress file
+	    # 
+	    # The compress option was taken out for efficiency
+	    # reasons.  Consider putting it back in but making it a 
+	    # switch so a collection builder can decide for themselves on a
+	    # case by case basis if they want to save on diskspace, but have
+	    # the overhead of uncompressing at runtime
+	    
+###	    compress_xml_doc($full_textdir,$output_filename);
+
+	    $doc_xml = "";
+	    $output_filename = "";
+	}
+    }
+}
+
+
+sub pass_on_xml_stream
+{
+    my $line;
+    while (defined ($line = <STDIN>)) {
+	print PIPEOUT $line;
+    }
+}
+
+
+
+
+# /** This checks the arguments on the command line, filters the
+#  *  unknown command line arguments and then calls the open_java_solr
+#  *  function to begin processing.
+#  */
+sub main
+{
+  my (@argv) = @_;
+  my $argc = scalar(@argv);
+
+  my $removeold = 0;
+  my @filtered_argv = ();
+
+  my $i = 0;
+  while ($i<$argc) {
+    if ($argv[$i] =~ m/^\-(.*)$/) {
+
+      my $option = $1;
+
+      # -removeold causes the existing index to be overwritten
+      if ($option eq "removeold") {
+        print STDERR "\n-removeold set (new index will be created)\n";
+        $removeold = 1;
+      }
+      # -verbosity <num>
+      elsif ($option eq "verbosity") {
+        $i++;
+        if ($i<$argc)
+	{
+	  # solr indexing has no support for verbosity 
+	  # => parse to be compatible with calling program, but supress it
+	  #    for solr-post.jar
+        }
+      }
+      else {
+        print STDERR "Unrecognised minus option: -$option\n";
+      }
+    }
+    else {
+        push(@filtered_argv,$argv[$i]);
+    }
+    $i++;
+  }
+
+  my $filtered_argc = scalar(@filtered_argv);
+
+  if ($filtered_argc < 5) {
+    print STDERR "Usage: solr_passes.pl [-removeold|-verbosity num] collect \"text\"|\"index\" doc-tag-level build-dir index-name\n";
+    exit 1;
+  }
+
+  my $collect       = $filtered_argv[0];
+  my $mode          = $filtered_argv[1];
+  my $doc_tag_level = $filtered_argv[2];
+  my $full_builddir = $filtered_argv[3];
+  my $indexdir      = $filtered_argv[4];
+
+  # We only need the Solr handle opened if we are indexing the
+  # documents, not if we are just storing the text
+  if ($mode eq "index") {
+    open_java_solr($collect, $doc_tag_level, $full_builddir, $indexdir, $removeold);
+  }
+
+  if ($mode eq "text") {
+      print STDERR "Monitoring for input!\n";
+      my $full_textdir = &util::filename_cat($full_builddir,"text");
+      monitor_xml_stream($full_textdir);
+  }
+  else {
+      print STDERR "Streaming input onto solr server!\n";
+      pass_on_xml_stream();
+  }
+
+
+  if ($mode eq "index") {
+    close_java_solr();
+  }
+}
+
+
+&main(@ARGV);
Index: gs3-extensions/solr/trunk/src/etc/README.txt
===================================================================
--- gs3-extensions/solr/trunk/src/etc/README.txt	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/README.txt	(revision 24446)
@@ -0,0 +1,54 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+Example "Solr Home" Directory
+=============================
+
+This directory is provided as an example of what a "Solr Home" directory
+should look like.
+
+It's not strictly necessary that you copy all of the files in this
+directory when setting up a new instance of Solr, but it is recommended.
+
+
+Basic Directory Structure
+-------------------------
+
+The Solr Home directory typically contains the following subdirectories...
+
+   conf/
+        This directory is mandatory and must contain your solrconfig.xml
+        and schema.xml.  Any other optional configuration files would also 
+        be kept here.
+
+   data/
+        This directory is the default location where Solr will keep your
+        index, and is used by the replication scripts for dealing with
+        snapshots.  You can override this location in the solrconfig.xml
+        and scripts.conf files. Solr will create this directory if it
+        does not already exist.
+
+   lib/
+        This directory is optional.  If it exists, Solr will load any Jars
+        found in this directory and use them to resolve any "plugins"
+        specified in your solrconfig.xml or schema.xml (ie: Analyzers,
+        Request Handlers, etc...).  Alternatively you can use the <lib>
+        syntax in solrconfig.xml to direct Solr to your plugins.  See the
+        example solrconfig.xml file for details.
+
+   bin/
+        This directory is optional.  It is the default location used for
+        keeping the replication scripts.
Index: gs3-extensions/solr/trunk/src/etc/conf/admin-extra.html
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/admin-extra.html	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/admin-extra.html	(revision 24446)
@@ -0,0 +1,31 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- The content of this page will be statically included into the top
+of the admin page.  Uncomment this as an example to see there the content
+will show up.
+
+<hr>
+<i>This line will appear before the first table</i>
+<tr>
+<td colspan="2">
+This row will be appended to the end of the first table
+</td>
+</tr>
+<hr>
+
+-->
Index: gs3-extensions/solr/trunk/src/etc/conf/elevate.xml
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/elevate.xml	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/elevate.xml	(revision 24446)
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- If this file is found in the config directory, it will only be
+     loaded once at startup.  If it is found in Solr's data
+     directory, it will be re-loaded every commit.
+-->
+
+<elevate>
+ <query text="foo bar">
+  <doc id="1" />
+  <doc id="2" />
+  <doc id="3" />
+ </query>
+ 
+ <query text="ipod">
+   <doc id="MA147LL/A" />  <!-- put the actual ipod at the top -->
+   <doc id="IW-02" exclude="true" /> <!-- exclude this cable -->
+ </query>
+ 
+</elevate>
Index: gs3-extensions/solr/trunk/src/etc/conf/mapping-FoldToASCII.txt
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/mapping-FoldToASCII.txt	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/mapping-FoldToASCII.txt	(revision 24446)
@@ -0,0 +1,3834 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# This map converts alphabetic, numeric, and symbolic Unicode characters
+# which are not in the first 127 ASCII characters (the "Basic Latin" Unicode
+# block) into their ASCII equivalents, if one exists.
+#
+# Characters from the following Unicode blocks are converted; however, only
+# those characters with reasonable ASCII alternatives are converted:
+#
+# - C1 Controls and Latin-1 Supplement: http://www.unicode.org/charts/PDF/U0080.pdf
+# - Latin Extended-A: http://www.unicode.org/charts/PDF/U0100.pdf
+# - Latin Extended-B: http://www.unicode.org/charts/PDF/U0180.pdf
+# - Latin Extended Additional: http://www.unicode.org/charts/PDF/U1E00.pdf
+# - Latin Extended-C: http://www.unicode.org/charts/PDF/U2C60.pdf
+# - Latin Extended-D: http://www.unicode.org/charts/PDF/UA720.pdf
+# - IPA Extensions: http://www.unicode.org/charts/PDF/U0250.pdf
+# - Phonetic Extensions: http://www.unicode.org/charts/PDF/U1D00.pdf
+# - Phonetic Extensions Supplement: http://www.unicode.org/charts/PDF/U1D80.pdf
+# - General Punctuation: http://www.unicode.org/charts/PDF/U2000.pdf
+# - Superscripts and Subscripts: http://www.unicode.org/charts/PDF/U2070.pdf
+# - Enclosed Alphanumerics: http://www.unicode.org/charts/PDF/U2460.pdf
+# - Dingbats: http://www.unicode.org/charts/PDF/U2700.pdf
+# - Supplemental Punctuation: http://www.unicode.org/charts/PDF/U2E00.pdf
+# - Alphabetic Presentation Forms: http://www.unicode.org/charts/PDF/UFB00.pdf
+# - Halfwidth and Fullwidth Forms: http://www.unicode.org/charts/PDF/UFF00.pdf
+#  
+# See: http://en.wikipedia.org/wiki/Latin_characters_in_Unicode
+#
+# The set of character conversions supported by this map is a superset of
+# those supported by the map represented by mapping-ISOLatin1Accent.txt.
+#
+# See the bottom of this file for the Perl script used to generate the contents
+# of this file (without this header) from ASCIIFoldingFilter.java.
+
+
+# Syntax:
+#   "source" => "target"
+#     "source".length() > 0 (source cannot be empty.)
+#     "target".length() >= 0 (target can be empty.)
+
+
+# Ã  [LATIN CAPITAL LETTER A WITH GRAVE]
+"\u00C0" => "A"
+
+# Ã  [LATIN CAPITAL LETTER A WITH ACUTE]
+"\u00C1" => "A"
+
+# Ã  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX]
+"\u00C2" => "A"
+
+# Ã  [LATIN CAPITAL LETTER A WITH TILDE]
+"\u00C3" => "A"
+
+# Ã  [LATIN CAPITAL LETTER A WITH DIAERESIS]
+"\u00C4" => "A"
+
+# Ã
+  [LATIN CAPITAL LETTER A WITH RING ABOVE]
+"\u00C5" => "A"
+
+# Ä  [LATIN CAPITAL LETTER A WITH MACRON]
+"\u0100" => "A"
+
+# Ä  [LATIN CAPITAL LETTER A WITH BREVE]
+"\u0102" => "A"
+
+# Ä  [LATIN CAPITAL LETTER A WITH OGONEK]
+"\u0104" => "A"
+
+# Æ  http://en.wikipedia.org/wiki/Schwa  [LATIN CAPITAL LETTER SCHWA]
+"\u018F" => "A"
+
+# Ç  [LATIN CAPITAL LETTER A WITH CARON]
+"\u01CD" => "A"
+
+# Ç  [LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON]
+"\u01DE" => "A"
+
+# Ç   [LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON]
+"\u01E0" => "A"
+
+# Çº  [LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE]
+"\u01FA" => "A"
+
+# È  [LATIN CAPITAL LETTER A WITH DOUBLE GRAVE]
+"\u0200" => "A"
+
+# È  [LATIN CAPITAL LETTER A WITH INVERTED BREVE]
+"\u0202" => "A"
+
+# ÈŠ  [LATIN CAPITAL LETTER A WITH DOT ABOVE]
+"\u0226" => "A"
+
+# Èº  [LATIN CAPITAL LETTER A WITH STROKE]
+"\u023A" => "A"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL A]
+"\u1D00" => "A"
+
+# áž  [LATIN CAPITAL LETTER A WITH RING BELOW]
+"\u1E00" => "A"
+
+# áº   [LATIN CAPITAL LETTER A WITH DOT BELOW]
+"\u1EA0" => "A"
+
+# áº¢  [LATIN CAPITAL LETTER A WITH HOOK ABOVE]
+"\u1EA2" => "A"
+
+# áº€  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE]
+"\u1EA4" => "A"
+
+# áºŠ  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE]
+"\u1EA6" => "A"
+
+# áºš  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE]
+"\u1EA8" => "A"
+
+# áºª  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE]
+"\u1EAA" => "A"
+
+# áº¬  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW]
+"\u1EAC" => "A"
+
+# áº®  [LATIN CAPITAL LETTER A WITH BREVE AND ACUTE]
+"\u1EAE" => "A"
+
+# áº°  [LATIN CAPITAL LETTER A WITH BREVE AND GRAVE]
+"\u1EB0" => "A"
+
+# áº²  [LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE]
+"\u1EB2" => "A"
+
+# áºŽ  [LATIN CAPITAL LETTER A WITH BREVE AND TILDE]
+"\u1EB4" => "A"
+
+# áº¶  [LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW]
+"\u1EB6" => "A"
+
+# â¶  [CIRCLED LATIN CAPITAL LETTER A]
+"\u24B6" => "A"
+
+# ïŒ¡  [FULLWIDTH LATIN CAPITAL LETTER A]
+"\uFF21" => "A"
+
+# Ã   [LATIN SMALL LETTER A WITH GRAVE]
+"\u00E0" => "a"
+
+# Ã¡  [LATIN SMALL LETTER A WITH ACUTE]
+"\u00E1" => "a"
+
+# Ã¢  [LATIN SMALL LETTER A WITH CIRCUMFLEX]
+"\u00E2" => "a"
+
+# Ã£  [LATIN SMALL LETTER A WITH TILDE]
+"\u00E3" => "a"
+
+# Ã€  [LATIN SMALL LETTER A WITH DIAERESIS]
+"\u00E4" => "a"
+
+# Ã¥  [LATIN SMALL LETTER A WITH RING ABOVE]
+"\u00E5" => "a"
+
+# Ä  [LATIN SMALL LETTER A WITH MACRON]
+"\u0101" => "a"
+
+# Ä  [LATIN SMALL LETTER A WITH BREVE]
+"\u0103" => "a"
+
+# Ä
+  [LATIN SMALL LETTER A WITH OGONEK]
+"\u0105" => "a"
+
+# Ç  [LATIN SMALL LETTER A WITH CARON]
+"\u01CE" => "a"
+
+# Ç  [LATIN SMALL LETTER A WITH DIAERESIS AND MACRON]
+"\u01DF" => "a"
+
+# Ç¡  [LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON]
+"\u01E1" => "a"
+
+# Ç»  [LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE]
+"\u01FB" => "a"
+
+# È  [LATIN SMALL LETTER A WITH DOUBLE GRAVE]
+"\u0201" => "a"
+
+# È  [LATIN SMALL LETTER A WITH INVERTED BREVE]
+"\u0203" => "a"
+
+# È§  [LATIN SMALL LETTER A WITH DOT ABOVE]
+"\u0227" => "a"
+
+# É  [LATIN SMALL LETTER TURNED A]
+"\u0250" => "a"
+
+# É  [LATIN SMALL LETTER SCHWA]
+"\u0259" => "a"
+
+# É  [LATIN SMALL LETTER SCHWA WITH HOOK]
+"\u025A" => "a"
+
+# á¶  [LATIN SMALL LETTER A WITH RETROFLEX HOOK]
+"\u1D8F" => "a"
+
+# á¶  [LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK]
+"\u1D95" => "a"
+
+# áº¡  [LATIN SMALL LETTER A WITH RING BELOW]
+"\u1E01" => "a"
+
+# áº£  [LATIN SMALL LETTER A WITH RIGHT HALF RING]
+"\u1E9A" => "a"
+
+# áº¡  [LATIN SMALL LETTER A WITH DOT BELOW]
+"\u1EA1" => "a"
+
+# áº£  [LATIN SMALL LETTER A WITH HOOK ABOVE]
+"\u1EA3" => "a"
+
+# áº¥  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE]
+"\u1EA5" => "a"
+
+# áº§  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE]
+"\u1EA7" => "a"
+
+# áº©  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE]
+"\u1EA9" => "a"
+
+# áº«  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE]
+"\u1EAB" => "a"
+
+# áº­  [LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW]
+"\u1EAD" => "a"
+
+# áº¯  [LATIN SMALL LETTER A WITH BREVE AND ACUTE]
+"\u1EAF" => "a"
+
+# áº±  [LATIN SMALL LETTER A WITH BREVE AND GRAVE]
+"\u1EB1" => "a"
+
+# áº³  [LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE]
+"\u1EB3" => "a"
+
+# áºµ  [LATIN SMALL LETTER A WITH BREVE AND TILDE]
+"\u1EB5" => "a"
+
+# áº·  [LATIN SMALL LETTER A WITH BREVE AND DOT BELOW]
+"\u1EB7" => "a"
+
+# â  [LATIN SUBSCRIPT SMALL LETTER A]
+"\u2090" => "a"
+
+# â  [LATIN SUBSCRIPT SMALL LETTER SCHWA]
+"\u2094" => "a"
+
+# â  [CIRCLED LATIN SMALL LETTER A]
+"\u24D0" => "a"
+
+# â±¥  [LATIN SMALL LETTER A WITH STROKE]
+"\u2C65" => "a"
+
+# â±¯  [LATIN CAPITAL LETTER TURNED A]
+"\u2C6F" => "a"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER A]
+"\uFF41" => "a"
+
+# ê²  [LATIN CAPITAL LETTER AA]
+"\uA732" => "AA"
+
+# Ã  [LATIN CAPITAL LETTER AE]
+"\u00C6" => "AE"
+
+# Ç¢  [LATIN CAPITAL LETTER AE WITH MACRON]
+"\u01E2" => "AE"
+
+# ÇŒ  [LATIN CAPITAL LETTER AE WITH ACUTE]
+"\u01FC" => "AE"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL AE]
+"\u1D01" => "AE"
+
+# êŽ  [LATIN CAPITAL LETTER AO]
+"\uA734" => "AO"
+
+# ê¶  [LATIN CAPITAL LETTER AU]
+"\uA736" => "AU"
+
+# êž  [LATIN CAPITAL LETTER AV]
+"\uA738" => "AV"
+
+# êº  [LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR]
+"\uA73A" => "AV"
+
+# êŒ  [LATIN CAPITAL LETTER AY]
+"\uA73C" => "AY"
+
+# â  [PARENTHESIZED LATIN SMALL LETTER A]
+"\u249C" => "(a)"
+
+# ê³  [LATIN SMALL LETTER AA]
+"\uA733" => "aa"
+
+# ÃŠ  [LATIN SMALL LETTER AE]
+"\u00E6" => "ae"
+
+# Ç£  [LATIN SMALL LETTER AE WITH MACRON]
+"\u01E3" => "ae"
+
+# Çœ  [LATIN SMALL LETTER AE WITH ACUTE]
+"\u01FD" => "ae"
+
+# áŽ  [LATIN SMALL LETTER TURNED AE]
+"\u1D02" => "ae"
+
+# êµ  [LATIN SMALL LETTER AO]
+"\uA735" => "ao"
+
+# ê·  [LATIN SMALL LETTER AU]
+"\uA737" => "au"
+
+# ê¹  [LATIN SMALL LETTER AV]
+"\uA739" => "av"
+
+# ê»  [LATIN SMALL LETTER AV WITH HORIZONTAL BAR]
+"\uA73B" => "av"
+
+# êœ  [LATIN SMALL LETTER AY]
+"\uA73D" => "ay"
+
+# Æ  [LATIN CAPITAL LETTER B WITH HOOK]
+"\u0181" => "B"
+
+# Æ  [LATIN CAPITAL LETTER B WITH TOPBAR]
+"\u0182" => "B"
+
+# É  [LATIN CAPITAL LETTER B WITH STROKE]
+"\u0243" => "B"
+
+# Ê  [LATIN LETTER SMALL CAPITAL B]
+"\u0299" => "B"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL BARRED B]
+"\u1D03" => "B"
+
+# áž  [LATIN CAPITAL LETTER B WITH DOT ABOVE]
+"\u1E02" => "B"
+
+# áž  [LATIN CAPITAL LETTER B WITH DOT BELOW]
+"\u1E04" => "B"
+
+# áž  [LATIN CAPITAL LETTER B WITH LINE BELOW]
+"\u1E06" => "B"
+
+# â·  [CIRCLED LATIN CAPITAL LETTER B]
+"\u24B7" => "B"
+
+# ïŒ¢  [FULLWIDTH LATIN CAPITAL LETTER B]
+"\uFF22" => "B"
+
+# Æ  [LATIN SMALL LETTER B WITH STROKE]
+"\u0180" => "b"
+
+# Æ  [LATIN SMALL LETTER B WITH TOPBAR]
+"\u0183" => "b"
+
+# É  [LATIN SMALL LETTER B WITH HOOK]
+"\u0253" => "b"
+
+# áµ¬  [LATIN SMALL LETTER B WITH MIDDLE TILDE]
+"\u1D6C" => "b"
+
+# á¶  [LATIN SMALL LETTER B WITH PALATAL HOOK]
+"\u1D80" => "b"
+
+# áž  [LATIN SMALL LETTER B WITH DOT ABOVE]
+"\u1E03" => "b"
+
+# áž
+  [LATIN SMALL LETTER B WITH DOT BELOW]
+"\u1E05" => "b"
+
+# áž  [LATIN SMALL LETTER B WITH LINE BELOW]
+"\u1E07" => "b"
+
+# â  [CIRCLED LATIN SMALL LETTER B]
+"\u24D1" => "b"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER B]
+"\uFF42" => "b"
+
+# â  [PARENTHESIZED LATIN SMALL LETTER B]
+"\u249D" => "(b)"
+
+# Ã  [LATIN CAPITAL LETTER C WITH CEDILLA]
+"\u00C7" => "C"
+
+# Ä  [LATIN CAPITAL LETTER C WITH ACUTE]
+"\u0106" => "C"
+
+# Ä  [LATIN CAPITAL LETTER C WITH CIRCUMFLEX]
+"\u0108" => "C"
+
+# Ä  [LATIN CAPITAL LETTER C WITH DOT ABOVE]
+"\u010A" => "C"
+
+# Ä  [LATIN CAPITAL LETTER C WITH CARON]
+"\u010C" => "C"
+
+# Æ  [LATIN CAPITAL LETTER C WITH HOOK]
+"\u0187" => "C"
+
+# È»  [LATIN CAPITAL LETTER C WITH STROKE]
+"\u023B" => "C"
+
+# Ê  [LATIN LETTER STRETCHED C]
+"\u0297" => "C"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL C]
+"\u1D04" => "C"
+
+# áž  [LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE]
+"\u1E08" => "C"
+
+# âž  [CIRCLED LATIN CAPITAL LETTER C]
+"\u24B8" => "C"
+
+# ïŒ£  [FULLWIDTH LATIN CAPITAL LETTER C]
+"\uFF23" => "C"
+
+# Ã§  [LATIN SMALL LETTER C WITH CEDILLA]
+"\u00E7" => "c"
+
+# Ä  [LATIN SMALL LETTER C WITH ACUTE]
+"\u0107" => "c"
+
+# Ä  [LATIN SMALL LETTER C WITH CIRCUMFLEX]
+"\u0109" => "c"
+
+# Ä  [LATIN SMALL LETTER C WITH DOT ABOVE]
+"\u010B" => "c"
+
+# Ä  [LATIN SMALL LETTER C WITH CARON]
+"\u010D" => "c"
+
+# Æ  [LATIN SMALL LETTER C WITH HOOK]
+"\u0188" => "c"
+
+# ÈŒ  [LATIN SMALL LETTER C WITH STROKE]
+"\u023C" => "c"
+
+# É  [LATIN SMALL LETTER C WITH CURL]
+"\u0255" => "c"
+
+# áž  [LATIN SMALL LETTER C WITH CEDILLA AND ACUTE]
+"\u1E09" => "c"
+
+# â  [LATIN SMALL LETTER REVERSED C]
+"\u2184" => "c"
+
+# â  [CIRCLED LATIN SMALL LETTER C]
+"\u24D2" => "c"
+
+# êŸ  [LATIN CAPITAL LETTER REVERSED C WITH DOT]
+"\uA73E" => "c"
+
+# ê¿  [LATIN SMALL LETTER REVERSED C WITH DOT]
+"\uA73F" => "c"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER C]
+"\uFF43" => "c"
+
+# â  [PARENTHESIZED LATIN SMALL LETTER C]
+"\u249E" => "(c)"
+
+# Ã  [LATIN CAPITAL LETTER ETH]
+"\u00D0" => "D"
+
+# Ä  [LATIN CAPITAL LETTER D WITH CARON]
+"\u010E" => "D"
+
+# Ä  [LATIN CAPITAL LETTER D WITH STROKE]
+"\u0110" => "D"
+
+# Æ  [LATIN CAPITAL LETTER AFRICAN D]
+"\u0189" => "D"
+
+# Æ  [LATIN CAPITAL LETTER D WITH HOOK]
+"\u018A" => "D"
+
+# Æ  [LATIN CAPITAL LETTER D WITH TOPBAR]
+"\u018B" => "D"
+
+# áŽ
+  [LATIN LETTER SMALL CAPITAL D]
+"\u1D05" => "D"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL ETH]
+"\u1D06" => "D"
+
+# áž  [LATIN CAPITAL LETTER D WITH DOT ABOVE]
+"\u1E0A" => "D"
+
+# áž  [LATIN CAPITAL LETTER D WITH DOT BELOW]
+"\u1E0C" => "D"
+
+# áž  [LATIN CAPITAL LETTER D WITH LINE BELOW]
+"\u1E0E" => "D"
+
+# áž  [LATIN CAPITAL LETTER D WITH CEDILLA]
+"\u1E10" => "D"
+
+# áž  [LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW]
+"\u1E12" => "D"
+
+# â¹  [CIRCLED LATIN CAPITAL LETTER D]
+"\u24B9" => "D"
+
+# ê¹  [LATIN CAPITAL LETTER INSULAR D]
+"\uA779" => "D"
+
+# ïŒ€  [FULLWIDTH LATIN CAPITAL LETTER D]
+"\uFF24" => "D"
+
+# Ã°  [LATIN SMALL LETTER ETH]
+"\u00F0" => "d"
+
+# Ä  [LATIN SMALL LETTER D WITH CARON]
+"\u010F" => "d"
+
+# Ä  [LATIN SMALL LETTER D WITH STROKE]
+"\u0111" => "d"
+
+# Æ  [LATIN SMALL LETTER D WITH TOPBAR]
+"\u018C" => "d"
+
+# È¡  [LATIN SMALL LETTER D WITH CURL]
+"\u0221" => "d"
+
+# É  [LATIN SMALL LETTER D WITH TAIL]
+"\u0256" => "d"
+
+# É  [LATIN SMALL LETTER D WITH HOOK]
+"\u0257" => "d"
+
+# áµ­  [LATIN SMALL LETTER D WITH MIDDLE TILDE]
+"\u1D6D" => "d"
+
+# á¶  [LATIN SMALL LETTER D WITH PALATAL HOOK]
+"\u1D81" => "d"
+
+# á¶  [LATIN SMALL LETTER D WITH HOOK AND TAIL]
+"\u1D91" => "d"
+
+# áž  [LATIN SMALL LETTER D WITH DOT ABOVE]
+"\u1E0B" => "d"
+
+# áž  [LATIN SMALL LETTER D WITH DOT BELOW]
+"\u1E0D" => "d"
+
+# áž  [LATIN SMALL LETTER D WITH LINE BELOW]
+"\u1E0F" => "d"
+
+# áž  [LATIN SMALL LETTER D WITH CEDILLA]
+"\u1E11" => "d"
+
+# áž  [LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW]
+"\u1E13" => "d"
+
+# â  [CIRCLED LATIN SMALL LETTER D]
+"\u24D3" => "d"
+
+# êº  [LATIN SMALL LETTER INSULAR D]
+"\uA77A" => "d"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER D]
+"\uFF44" => "d"
+
+# Ç  [LATIN CAPITAL LETTER DZ WITH CARON]
+"\u01C4" => "DZ"
+
+# Ç±  [LATIN CAPITAL LETTER DZ]
+"\u01F1" => "DZ"
+
+# Ç
+  [LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON]
+"\u01C5" => "Dz"
+
+# Ç²  [LATIN CAPITAL LETTER D WITH SMALL LETTER Z]
+"\u01F2" => "Dz"
+
+# â  [PARENTHESIZED LATIN SMALL LETTER D]
+"\u249F" => "(d)"
+
+# Èž  [LATIN SMALL LETTER DB DIGRAPH]
+"\u0238" => "db"
+
+# Ç  [LATIN SMALL LETTER DZ WITH CARON]
+"\u01C6" => "dz"
+
+# Ç³  [LATIN SMALL LETTER DZ]
+"\u01F3" => "dz"
+
+# Ê£  [LATIN SMALL LETTER DZ DIGRAPH]
+"\u02A3" => "dz"
+
+# Ê¥  [LATIN SMALL LETTER DZ DIGRAPH WITH CURL]
+"\u02A5" => "dz"
+
+# Ã  [LATIN CAPITAL LETTER E WITH GRAVE]
+"\u00C8" => "E"
+
+# Ã  [LATIN CAPITAL LETTER E WITH ACUTE]
+"\u00C9" => "E"
+
+# Ã  [LATIN CAPITAL LETTER E WITH CIRCUMFLEX]
+"\u00CA" => "E"
+
+# Ã  [LATIN CAPITAL LETTER E WITH DIAERESIS]
+"\u00CB" => "E"
+
+# Ä  [LATIN CAPITAL LETTER E WITH MACRON]
+"\u0112" => "E"
+
+# Ä  [LATIN CAPITAL LETTER E WITH BREVE]
+"\u0114" => "E"
+
+# Ä  [LATIN CAPITAL LETTER E WITH DOT ABOVE]
+"\u0116" => "E"
+
+# Ä  [LATIN CAPITAL LETTER E WITH OGONEK]
+"\u0118" => "E"
+
+# Ä  [LATIN CAPITAL LETTER E WITH CARON]
+"\u011A" => "E"
+
+# Æ  [LATIN CAPITAL LETTER REVERSED E]
+"\u018E" => "E"
+
+# Æ  [LATIN CAPITAL LETTER OPEN E]
+"\u0190" => "E"
+
+# È  [LATIN CAPITAL LETTER E WITH DOUBLE GRAVE]
+"\u0204" => "E"
+
+# È  [LATIN CAPITAL LETTER E WITH INVERTED BREVE]
+"\u0206" => "E"
+
+# Èš  [LATIN CAPITAL LETTER E WITH CEDILLA]
+"\u0228" => "E"
+
+# É  [LATIN CAPITAL LETTER E WITH STROKE]
+"\u0246" => "E"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL E]
+"\u1D07" => "E"
+
+# áž  [LATIN CAPITAL LETTER E WITH MACRON AND GRAVE]
+"\u1E14" => "E"
+
+# áž  [LATIN CAPITAL LETTER E WITH MACRON AND ACUTE]
+"\u1E16" => "E"
+
+# áž  [LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW]
+"\u1E18" => "E"
+
+# áž  [LATIN CAPITAL LETTER E WITH TILDE BELOW]
+"\u1E1A" => "E"
+
+# áž  [LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE]
+"\u1E1C" => "E"
+
+# áºž  [LATIN CAPITAL LETTER E WITH DOT BELOW]
+"\u1EB8" => "E"
+
+# áºº  [LATIN CAPITAL LETTER E WITH HOOK ABOVE]
+"\u1EBA" => "E"
+
+# áºŒ  [LATIN CAPITAL LETTER E WITH TILDE]
+"\u1EBC" => "E"
+
+# áºŸ  [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE]
+"\u1EBE" => "E"
+
+# á»  [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE]
+"\u1EC0" => "E"
+
+# á»  [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE]
+"\u1EC2" => "E"
+
+# á»  [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE]
+"\u1EC4" => "E"
+
+# á»  [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW]
+"\u1EC6" => "E"
+
+# âº  [CIRCLED LATIN CAPITAL LETTER E]
+"\u24BA" => "E"
+
+# â±»  [LATIN LETTER SMALL CAPITAL TURNED E]
+"\u2C7B" => "E"
+
+# ïŒ¥  [FULLWIDTH LATIN CAPITAL LETTER E]
+"\uFF25" => "E"
+
+# Ãš  [LATIN SMALL LETTER E WITH GRAVE]
+"\u00E8" => "e"
+
+# Ã©  [LATIN SMALL LETTER E WITH ACUTE]
+"\u00E9" => "e"
+
+# Ãª  [LATIN SMALL LETTER E WITH CIRCUMFLEX]
+"\u00EA" => "e"
+
+# Ã«  [LATIN SMALL LETTER E WITH DIAERESIS]
+"\u00EB" => "e"
+
+# Ä  [LATIN SMALL LETTER E WITH MACRON]
+"\u0113" => "e"
+
+# Ä  [LATIN SMALL LETTER E WITH BREVE]
+"\u0115" => "e"
+
+# Ä  [LATIN SMALL LETTER E WITH DOT ABOVE]
+"\u0117" => "e"
+
+# Ä  [LATIN SMALL LETTER E WITH OGONEK]
+"\u0119" => "e"
+
+# Ä  [LATIN SMALL LETTER E WITH CARON]
+"\u011B" => "e"
+
+# Ç  [LATIN SMALL LETTER TURNED E]
+"\u01DD" => "e"
+
+# È
+  [LATIN SMALL LETTER E WITH DOUBLE GRAVE]
+"\u0205" => "e"
+
+# È  [LATIN SMALL LETTER E WITH INVERTED BREVE]
+"\u0207" => "e"
+
+# È©  [LATIN SMALL LETTER E WITH CEDILLA]
+"\u0229" => "e"
+
+# É  [LATIN SMALL LETTER E WITH STROKE]
+"\u0247" => "e"
+
+# É  [LATIN SMALL LETTER REVERSED E]
+"\u0258" => "e"
+
+# É  [LATIN SMALL LETTER OPEN E]
+"\u025B" => "e"
+
+# É  [LATIN SMALL LETTER REVERSED OPEN E]
+"\u025C" => "e"
+
+# É  [LATIN SMALL LETTER REVERSED OPEN E WITH HOOK]
+"\u025D" => "e"
+
+# É  [LATIN SMALL LETTER CLOSED REVERSED OPEN E]
+"\u025E" => "e"
+
+# Ê  [LATIN SMALL LETTER CLOSED OPEN E]
+"\u029A" => "e"
+
+# áŽ  [LATIN SMALL LETTER TURNED OPEN E]
+"\u1D08" => "e"
+
+# á¶  [LATIN SMALL LETTER E WITH RETROFLEX HOOK]
+"\u1D92" => "e"
+
+# á¶  [LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK]
+"\u1D93" => "e"
+
+# á¶  [LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK]
+"\u1D94" => "e"
+
+# áž  [LATIN SMALL LETTER E WITH MACRON AND GRAVE]
+"\u1E15" => "e"
+
+# áž  [LATIN SMALL LETTER E WITH MACRON AND ACUTE]
+"\u1E17" => "e"
+
+# áž  [LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW]
+"\u1E19" => "e"
+
+# áž  [LATIN SMALL LETTER E WITH TILDE BELOW]
+"\u1E1B" => "e"
+
+# áž  [LATIN SMALL LETTER E WITH CEDILLA AND BREVE]
+"\u1E1D" => "e"
+
+# áº¹  [LATIN SMALL LETTER E WITH DOT BELOW]
+"\u1EB9" => "e"
+
+# áº»  [LATIN SMALL LETTER E WITH HOOK ABOVE]
+"\u1EBB" => "e"
+
+# áºœ  [LATIN SMALL LETTER E WITH TILDE]
+"\u1EBD" => "e"
+
+# áº¿  [LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE]
+"\u1EBF" => "e"
+
+# á»  [LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE]
+"\u1EC1" => "e"
+
+# á»  [LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE]
+"\u1EC3" => "e"
+
+# á»
+  [LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE]
+"\u1EC5" => "e"
+
+# á»  [LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW]
+"\u1EC7" => "e"
+
+# â  [LATIN SUBSCRIPT SMALL LETTER E]
+"\u2091" => "e"
+
+# â  [CIRCLED LATIN SMALL LETTER E]
+"\u24D4" => "e"
+
+# â±ž  [LATIN SMALL LETTER E WITH NOTCH]
+"\u2C78" => "e"
+
+# ïœ
+  [FULLWIDTH LATIN SMALL LETTER E]
+"\uFF45" => "e"
+
+# â   [PARENTHESIZED LATIN SMALL LETTER E]
+"\u24A0" => "(e)"
+
+# Æ  [LATIN CAPITAL LETTER F WITH HOOK]
+"\u0191" => "F"
+
+# áž  [LATIN CAPITAL LETTER F WITH DOT ABOVE]
+"\u1E1E" => "F"
+
+# â»  [CIRCLED LATIN CAPITAL LETTER F]
+"\u24BB" => "F"
+
+# ê°  [LATIN LETTER SMALL CAPITAL F]
+"\uA730" => "F"
+
+# ê»  [LATIN CAPITAL LETTER INSULAR F]
+"\uA77B" => "F"
+
+# ê»  [LATIN EPIGRAPHIC LETTER REVERSED F]
+"\uA7FB" => "F"
+
+# ïŒŠ  [FULLWIDTH LATIN CAPITAL LETTER F]
+"\uFF26" => "F"
+
+# Æ  [LATIN SMALL LETTER F WITH HOOK]
+"\u0192" => "f"
+
+# áµ®  [LATIN SMALL LETTER F WITH MIDDLE TILDE]
+"\u1D6E" => "f"
+
+# á¶  [LATIN SMALL LETTER F WITH PALATAL HOOK]
+"\u1D82" => "f"
+
+# áž  [LATIN SMALL LETTER F WITH DOT ABOVE]
+"\u1E1F" => "f"
+
+# áº  [LATIN SMALL LETTER LONG S WITH DOT ABOVE]
+"\u1E9B" => "f"
+
+# â  [CIRCLED LATIN SMALL LETTER F]
+"\u24D5" => "f"
+
+# êŒ  [LATIN SMALL LETTER INSULAR F]
+"\uA77C" => "f"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER F]
+"\uFF46" => "f"
+
+# â¡  [PARENTHESIZED LATIN SMALL LETTER F]
+"\u24A1" => "(f)"
+
+# ï¬  [LATIN SMALL LIGATURE FF]
+"\uFB00" => "ff"
+
+# ï¬  [LATIN SMALL LIGATURE FFI]
+"\uFB03" => "ffi"
+
+# ï¬  [LATIN SMALL LIGATURE FFL]
+"\uFB04" => "ffl"
+
+# ï¬  [LATIN SMALL LIGATURE FI]
+"\uFB01" => "fi"
+
+# ï¬  [LATIN SMALL LIGATURE FL]
+"\uFB02" => "fl"
+
+# Ä  [LATIN CAPITAL LETTER G WITH CIRCUMFLEX]
+"\u011C" => "G"
+
+# Ä  [LATIN CAPITAL LETTER G WITH BREVE]
+"\u011E" => "G"
+
+# Ä   [LATIN CAPITAL LETTER G WITH DOT ABOVE]
+"\u0120" => "G"
+
+# Ä¢  [LATIN CAPITAL LETTER G WITH CEDILLA]
+"\u0122" => "G"
+
+# Æ  [LATIN CAPITAL LETTER G WITH HOOK]
+"\u0193" => "G"
+
+# Ç€  [LATIN CAPITAL LETTER G WITH STROKE]
+"\u01E4" => "G"
+
+# Ç¥  [LATIN SMALL LETTER G WITH STROKE]
+"\u01E5" => "G"
+
+# ÇŠ  [LATIN CAPITAL LETTER G WITH CARON]
+"\u01E6" => "G"
+
+# Ç§  [LATIN SMALL LETTER G WITH CARON]
+"\u01E7" => "G"
+
+# ÇŽ  [LATIN CAPITAL LETTER G WITH ACUTE]
+"\u01F4" => "G"
+
+# É¢  [LATIN LETTER SMALL CAPITAL G]
+"\u0262" => "G"
+
+# Ê  [LATIN LETTER SMALL CAPITAL G WITH HOOK]
+"\u029B" => "G"
+
+# áž   [LATIN CAPITAL LETTER G WITH MACRON]
+"\u1E20" => "G"
+
+# âŒ  [CIRCLED LATIN CAPITAL LETTER G]
+"\u24BC" => "G"
+
+# êœ  [LATIN CAPITAL LETTER INSULAR G]
+"\uA77D" => "G"
+
+# êŸ  [LATIN CAPITAL LETTER TURNED INSULAR G]
+"\uA77E" => "G"
+
+# ïŒ§  [FULLWIDTH LATIN CAPITAL LETTER G]
+"\uFF27" => "G"
+
+# Ä  [LATIN SMALL LETTER G WITH CIRCUMFLEX]
+"\u011D" => "g"
+
+# Ä  [LATIN SMALL LETTER G WITH BREVE]
+"\u011F" => "g"
+
+# Ä¡  [LATIN SMALL LETTER G WITH DOT ABOVE]
+"\u0121" => "g"
+
+# Ä£  [LATIN SMALL LETTER G WITH CEDILLA]
+"\u0123" => "g"
+
+# Çµ  [LATIN SMALL LETTER G WITH ACUTE]
+"\u01F5" => "g"
+
+# É   [LATIN SMALL LETTER G WITH HOOK]
+"\u0260" => "g"
+
+# É¡  [LATIN SMALL LETTER SCRIPT G]
+"\u0261" => "g"
+
+# áµ·  [LATIN SMALL LETTER TURNED G]
+"\u1D77" => "g"
+
+# áµ¹  [LATIN SMALL LETTER INSULAR G]
+"\u1D79" => "g"
+
+# á¶  [LATIN SMALL LETTER G WITH PALATAL HOOK]
+"\u1D83" => "g"
+
+# áž¡  [LATIN SMALL LETTER G WITH MACRON]
+"\u1E21" => "g"
+
+# â  [CIRCLED LATIN SMALL LETTER G]
+"\u24D6" => "g"
+
+# ê¿  [LATIN SMALL LETTER TURNED INSULAR G]
+"\uA77F" => "g"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER G]
+"\uFF47" => "g"
+
+# â¢  [PARENTHESIZED LATIN SMALL LETTER G]
+"\u24A2" => "(g)"
+
+# Ä€  [LATIN CAPITAL LETTER H WITH CIRCUMFLEX]
+"\u0124" => "H"
+
+# ÄŠ  [LATIN CAPITAL LETTER H WITH STROKE]
+"\u0126" => "H"
+
+# È  [LATIN CAPITAL LETTER H WITH CARON]
+"\u021E" => "H"
+
+# Ê  [LATIN LETTER SMALL CAPITAL H]
+"\u029C" => "H"
+
+# áž¢  [LATIN CAPITAL LETTER H WITH DOT ABOVE]
+"\u1E22" => "H"
+
+# áž€  [LATIN CAPITAL LETTER H WITH DOT BELOW]
+"\u1E24" => "H"
+
+# ážŠ  [LATIN CAPITAL LETTER H WITH DIAERESIS]
+"\u1E26" => "H"
+
+# ážš  [LATIN CAPITAL LETTER H WITH CEDILLA]
+"\u1E28" => "H"
+
+# ážª  [LATIN CAPITAL LETTER H WITH BREVE BELOW]
+"\u1E2A" => "H"
+
+# âœ  [CIRCLED LATIN CAPITAL LETTER H]
+"\u24BD" => "H"
+
+# â±§  [LATIN CAPITAL LETTER H WITH DESCENDER]
+"\u2C67" => "H"
+
+# â±µ  [LATIN CAPITAL LETTER HALF H]
+"\u2C75" => "H"
+
+# ïŒš  [FULLWIDTH LATIN CAPITAL LETTER H]
+"\uFF28" => "H"
+
+# Ä¥  [LATIN SMALL LETTER H WITH CIRCUMFLEX]
+"\u0125" => "h"
+
+# Ä§  [LATIN SMALL LETTER H WITH STROKE]
+"\u0127" => "h"
+
+# È  [LATIN SMALL LETTER H WITH CARON]
+"\u021F" => "h"
+
+# É¥  [LATIN SMALL LETTER TURNED H]
+"\u0265" => "h"
+
+# ÉŠ  [LATIN SMALL LETTER H WITH HOOK]
+"\u0266" => "h"
+
+# Ê®  [LATIN SMALL LETTER TURNED H WITH FISHHOOK]
+"\u02AE" => "h"
+
+# Ê¯  [LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL]
+"\u02AF" => "h"
+
+# áž£  [LATIN SMALL LETTER H WITH DOT ABOVE]
+"\u1E23" => "h"
+
+# áž¥  [LATIN SMALL LETTER H WITH DOT BELOW]
+"\u1E25" => "h"
+
+# áž§  [LATIN SMALL LETTER H WITH DIAERESIS]
+"\u1E27" => "h"
+
+# áž©  [LATIN SMALL LETTER H WITH CEDILLA]
+"\u1E29" => "h"
+
+# áž«  [LATIN SMALL LETTER H WITH BREVE BELOW]
+"\u1E2B" => "h"
+
+# áº  [LATIN SMALL LETTER H WITH LINE BELOW]
+"\u1E96" => "h"
+
+# â  [CIRCLED LATIN SMALL LETTER H]
+"\u24D7" => "h"
+
+# â±š  [LATIN SMALL LETTER H WITH DESCENDER]
+"\u2C68" => "h"
+
+# â±¶  [LATIN SMALL LETTER HALF H]
+"\u2C76" => "h"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER H]
+"\uFF48" => "h"
+
+# Ç¶  http://en.wikipedia.org/wiki/Hwair  [LATIN CAPITAL LETTER HWAIR]
+"\u01F6" => "HV"
+
+# â£  [PARENTHESIZED LATIN SMALL LETTER H]
+"\u24A3" => "(h)"
+
+# Æ  [LATIN SMALL LETTER HV]
+"\u0195" => "hv"
+
+# Ã  [LATIN CAPITAL LETTER I WITH GRAVE]
+"\u00CC" => "I"
+
+# Ã  [LATIN CAPITAL LETTER I WITH ACUTE]
+"\u00CD" => "I"
+
+# Ã  [LATIN CAPITAL LETTER I WITH CIRCUMFLEX]
+"\u00CE" => "I"
+
+# Ã  [LATIN CAPITAL LETTER I WITH DIAERESIS]
+"\u00CF" => "I"
+
+# Äš  [LATIN CAPITAL LETTER I WITH TILDE]
+"\u0128" => "I"
+
+# Äª  [LATIN CAPITAL LETTER I WITH MACRON]
+"\u012A" => "I"
+
+# Ä¬  [LATIN CAPITAL LETTER I WITH BREVE]
+"\u012C" => "I"
+
+# Ä®  [LATIN CAPITAL LETTER I WITH OGONEK]
+"\u012E" => "I"
+
+# Ä°  [LATIN CAPITAL LETTER I WITH DOT ABOVE]
+"\u0130" => "I"
+
+# Æ  [LATIN CAPITAL LETTER IOTA]
+"\u0196" => "I"
+
+# Æ  [LATIN CAPITAL LETTER I WITH STROKE]
+"\u0197" => "I"
+
+# Ç  [LATIN CAPITAL LETTER I WITH CARON]
+"\u01CF" => "I"
+
+# È  [LATIN CAPITAL LETTER I WITH DOUBLE GRAVE]
+"\u0208" => "I"
+
+# È  [LATIN CAPITAL LETTER I WITH INVERTED BREVE]
+"\u020A" => "I"
+
+# Éª  [LATIN LETTER SMALL CAPITAL I]
+"\u026A" => "I"
+
+# áµ»  [LATIN SMALL CAPITAL LETTER I WITH STROKE]
+"\u1D7B" => "I"
+
+# áž¬  [LATIN CAPITAL LETTER I WITH TILDE BELOW]
+"\u1E2C" => "I"
+
+# áž®  [LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE]
+"\u1E2E" => "I"
+
+# á»  [LATIN CAPITAL LETTER I WITH HOOK ABOVE]
+"\u1EC8" => "I"
+
+# á»  [LATIN CAPITAL LETTER I WITH DOT BELOW]
+"\u1ECA" => "I"
+
+# âŸ  [CIRCLED LATIN CAPITAL LETTER I]
+"\u24BE" => "I"
+
+# êŸ  [LATIN EPIGRAPHIC LETTER I LONGA]
+"\uA7FE" => "I"
+
+# ïŒ©  [FULLWIDTH LATIN CAPITAL LETTER I]
+"\uFF29" => "I"
+
+# Ã¬  [LATIN SMALL LETTER I WITH GRAVE]
+"\u00EC" => "i"
+
+# Ã­  [LATIN SMALL LETTER I WITH ACUTE]
+"\u00ED" => "i"
+
+# Ã®  [LATIN SMALL LETTER I WITH CIRCUMFLEX]
+"\u00EE" => "i"
+
+# Ã¯  [LATIN SMALL LETTER I WITH DIAERESIS]
+"\u00EF" => "i"
+
+# Ä©  [LATIN SMALL LETTER I WITH TILDE]
+"\u0129" => "i"
+
+# Ä«  [LATIN SMALL LETTER I WITH MACRON]
+"\u012B" => "i"
+
+# Ä­  [LATIN SMALL LETTER I WITH BREVE]
+"\u012D" => "i"
+
+# Ä¯  [LATIN SMALL LETTER I WITH OGONEK]
+"\u012F" => "i"
+
+# Ä±  [LATIN SMALL LETTER DOTLESS I]
+"\u0131" => "i"
+
+# Ç  [LATIN SMALL LETTER I WITH CARON]
+"\u01D0" => "i"
+
+# È  [LATIN SMALL LETTER I WITH DOUBLE GRAVE]
+"\u0209" => "i"
+
+# È  [LATIN SMALL LETTER I WITH INVERTED BREVE]
+"\u020B" => "i"
+
+# Éš  [LATIN SMALL LETTER I WITH STROKE]
+"\u0268" => "i"
+
+# áŽ  [LATIN SMALL LETTER TURNED I]
+"\u1D09" => "i"
+
+# áµ¢  [LATIN SUBSCRIPT SMALL LETTER I]
+"\u1D62" => "i"
+
+# áµŒ  [LATIN SMALL LETTER IOTA WITH STROKE]
+"\u1D7C" => "i"
+
+# á¶  [LATIN SMALL LETTER I WITH RETROFLEX HOOK]
+"\u1D96" => "i"
+
+# áž­  [LATIN SMALL LETTER I WITH TILDE BELOW]
+"\u1E2D" => "i"
+
+# áž¯  [LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE]
+"\u1E2F" => "i"
+
+# á»  [LATIN SMALL LETTER I WITH HOOK ABOVE]
+"\u1EC9" => "i"
+
+# á»  [LATIN SMALL LETTER I WITH DOT BELOW]
+"\u1ECB" => "i"
+
+# â±  [SUPERSCRIPT LATIN SMALL LETTER I]
+"\u2071" => "i"
+
+# â  [CIRCLED LATIN SMALL LETTER I]
+"\u24D8" => "i"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER I]
+"\uFF49" => "i"
+
+# Ä²  [LATIN CAPITAL LIGATURE IJ]
+"\u0132" => "IJ"
+
+# â€  [PARENTHESIZED LATIN SMALL LETTER I]
+"\u24A4" => "(i)"
+
+# Ä³  [LATIN SMALL LIGATURE IJ]
+"\u0133" => "ij"
+
+# ÄŽ  [LATIN CAPITAL LETTER J WITH CIRCUMFLEX]
+"\u0134" => "J"
+
+# É  [LATIN CAPITAL LETTER J WITH STROKE]
+"\u0248" => "J"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL J]
+"\u1D0A" => "J"
+
+# â¿  [CIRCLED LATIN CAPITAL LETTER J]
+"\u24BF" => "J"
+
+# ïŒª  [FULLWIDTH LATIN CAPITAL LETTER J]
+"\uFF2A" => "J"
+
+# Äµ  [LATIN SMALL LETTER J WITH CIRCUMFLEX]
+"\u0135" => "j"
+
+# Ç°  [LATIN SMALL LETTER J WITH CARON]
+"\u01F0" => "j"
+
+# È·  [LATIN SMALL LETTER DOTLESS J]
+"\u0237" => "j"
+
+# É  [LATIN SMALL LETTER J WITH STROKE]
+"\u0249" => "j"
+
+# É  [LATIN SMALL LETTER DOTLESS J WITH STROKE]
+"\u025F" => "j"
+
+# Ê  [LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK]
+"\u0284" => "j"
+
+# Ê  [LATIN SMALL LETTER J WITH CROSSED-TAIL]
+"\u029D" => "j"
+
+# â  [CIRCLED LATIN SMALL LETTER J]
+"\u24D9" => "j"
+
+# â±Œ  [LATIN SUBSCRIPT SMALL LETTER J]
+"\u2C7C" => "j"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER J]
+"\uFF4A" => "j"
+
+# â¥  [PARENTHESIZED LATIN SMALL LETTER J]
+"\u24A5" => "(j)"
+
+# Ä¶  [LATIN CAPITAL LETTER K WITH CEDILLA]
+"\u0136" => "K"
+
+# Æ  [LATIN CAPITAL LETTER K WITH HOOK]
+"\u0198" => "K"
+
+# Çš  [LATIN CAPITAL LETTER K WITH CARON]
+"\u01E8" => "K"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL K]
+"\u1D0B" => "K"
+
+# áž°  [LATIN CAPITAL LETTER K WITH ACUTE]
+"\u1E30" => "K"
+
+# áž²  [LATIN CAPITAL LETTER K WITH DOT BELOW]
+"\u1E32" => "K"
+
+# ážŽ  [LATIN CAPITAL LETTER K WITH LINE BELOW]
+"\u1E34" => "K"
+
+# â  [CIRCLED LATIN CAPITAL LETTER K]
+"\u24C0" => "K"
+
+# â±©  [LATIN CAPITAL LETTER K WITH DESCENDER]
+"\u2C69" => "K"
+
+# ê  [LATIN CAPITAL LETTER K WITH STROKE]
+"\uA740" => "K"
+
+# ê  [LATIN CAPITAL LETTER K WITH DIAGONAL STROKE]
+"\uA742" => "K"
+
+# ê  [LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE]
+"\uA744" => "K"
+
+# ïŒ«  [FULLWIDTH LATIN CAPITAL LETTER K]
+"\uFF2B" => "K"
+
+# Ä·  [LATIN SMALL LETTER K WITH CEDILLA]
+"\u0137" => "k"
+
+# Æ  [LATIN SMALL LETTER K WITH HOOK]
+"\u0199" => "k"
+
+# Ç©  [LATIN SMALL LETTER K WITH CARON]
+"\u01E9" => "k"
+
+# Ê  [LATIN SMALL LETTER TURNED K]
+"\u029E" => "k"
+
+# á¶  [LATIN SMALL LETTER K WITH PALATAL HOOK]
+"\u1D84" => "k"
+
+# áž±  [LATIN SMALL LETTER K WITH ACUTE]
+"\u1E31" => "k"
+
+# áž³  [LATIN SMALL LETTER K WITH DOT BELOW]
+"\u1E33" => "k"
+
+# ážµ  [LATIN SMALL LETTER K WITH LINE BELOW]
+"\u1E35" => "k"
+
+# â  [CIRCLED LATIN SMALL LETTER K]
+"\u24DA" => "k"
+
+# â±ª  [LATIN SMALL LETTER K WITH DESCENDER]
+"\u2C6A" => "k"
+
+# ê  [LATIN SMALL LETTER K WITH STROKE]
+"\uA741" => "k"
+
+# ê  [LATIN SMALL LETTER K WITH DIAGONAL STROKE]
+"\uA743" => "k"
+
+# ê
+  [LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE]
+"\uA745" => "k"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER K]
+"\uFF4B" => "k"
+
+# âŠ  [PARENTHESIZED LATIN SMALL LETTER K]
+"\u24A6" => "(k)"
+
+# Ä¹  [LATIN CAPITAL LETTER L WITH ACUTE]
+"\u0139" => "L"
+
+# Ä»  [LATIN CAPITAL LETTER L WITH CEDILLA]
+"\u013B" => "L"
+
+# Äœ  [LATIN CAPITAL LETTER L WITH CARON]
+"\u013D" => "L"
+
+# Ä¿  [LATIN CAPITAL LETTER L WITH MIDDLE DOT]
+"\u013F" => "L"
+
+# Å  [LATIN CAPITAL LETTER L WITH STROKE]
+"\u0141" => "L"
+
+# Èœ  [LATIN CAPITAL LETTER L WITH BAR]
+"\u023D" => "L"
+
+# Ê  [LATIN LETTER SMALL CAPITAL L]
+"\u029F" => "L"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL L WITH STROKE]
+"\u1D0C" => "L"
+
+# áž¶  [LATIN CAPITAL LETTER L WITH DOT BELOW]
+"\u1E36" => "L"
+
+# ážž  [LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON]
+"\u1E38" => "L"
+
+# ážº  [LATIN CAPITAL LETTER L WITH LINE BELOW]
+"\u1E3A" => "L"
+
+# ážŒ  [LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW]
+"\u1E3C" => "L"
+
+# â  [CIRCLED LATIN CAPITAL LETTER L]
+"\u24C1" => "L"
+
+# â±   [LATIN CAPITAL LETTER L WITH DOUBLE BAR]
+"\u2C60" => "L"
+
+# â±¢  [LATIN CAPITAL LETTER L WITH MIDDLE TILDE]
+"\u2C62" => "L"
+
+# ê  [LATIN CAPITAL LETTER BROKEN L]
+"\uA746" => "L"
+
+# ê  [LATIN CAPITAL LETTER L WITH HIGH STROKE]
+"\uA748" => "L"
+
+# ê  [LATIN CAPITAL LETTER TURNED L]
+"\uA780" => "L"
+
+# ïŒ¬  [FULLWIDTH LATIN CAPITAL LETTER L]
+"\uFF2C" => "L"
+
+# Äº  [LATIN SMALL LETTER L WITH ACUTE]
+"\u013A" => "l"
+
+# ÄŒ  [LATIN SMALL LETTER L WITH CEDILLA]
+"\u013C" => "l"
+
+# ÄŸ  [LATIN SMALL LETTER L WITH CARON]
+"\u013E" => "l"
+
+# Å  [LATIN SMALL LETTER L WITH MIDDLE DOT]
+"\u0140" => "l"
+
+# Å  [LATIN SMALL LETTER L WITH STROKE]
+"\u0142" => "l"
+
+# Æ  [LATIN SMALL LETTER L WITH BAR]
+"\u019A" => "l"
+
+# ÈŽ  [LATIN SMALL LETTER L WITH CURL]
+"\u0234" => "l"
+
+# É«  [LATIN SMALL LETTER L WITH MIDDLE TILDE]
+"\u026B" => "l"
+
+# É¬  [LATIN SMALL LETTER L WITH BELT]
+"\u026C" => "l"
+
+# É­  [LATIN SMALL LETTER L WITH RETROFLEX HOOK]
+"\u026D" => "l"
+
+# á¶
+  [LATIN SMALL LETTER L WITH PALATAL HOOK]
+"\u1D85" => "l"
+
+# áž·  [LATIN SMALL LETTER L WITH DOT BELOW]
+"\u1E37" => "l"
+
+# áž¹  [LATIN SMALL LETTER L WITH DOT BELOW AND MACRON]
+"\u1E39" => "l"
+
+# áž»  [LATIN SMALL LETTER L WITH LINE BELOW]
+"\u1E3B" => "l"
+
+# ážœ  [LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW]
+"\u1E3D" => "l"
+
+# â  [CIRCLED LATIN SMALL LETTER L]
+"\u24DB" => "l"
+
+# â±¡  [LATIN SMALL LETTER L WITH DOUBLE BAR]
+"\u2C61" => "l"
+
+# ê  [LATIN SMALL LETTER BROKEN L]
+"\uA747" => "l"
+
+# ê  [LATIN SMALL LETTER L WITH HIGH STROKE]
+"\uA749" => "l"
+
+# ê  [LATIN SMALL LETTER TURNED L]
+"\uA781" => "l"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER L]
+"\uFF4C" => "l"
+
+# Ç  [LATIN CAPITAL LETTER LJ]
+"\u01C7" => "LJ"
+
+# á»º  [LATIN CAPITAL LETTER MIDDLE-WELSH LL]
+"\u1EFA" => "LL"
+
+# Ç  [LATIN CAPITAL LETTER L WITH SMALL LETTER J]
+"\u01C8" => "Lj"
+
+# â§  [PARENTHESIZED LATIN SMALL LETTER L]
+"\u24A7" => "(l)"
+
+# Ç  [LATIN SMALL LETTER LJ]
+"\u01C9" => "lj"
+
+# á»»  [LATIN SMALL LETTER MIDDLE-WELSH LL]
+"\u1EFB" => "ll"
+
+# Êª  [LATIN SMALL LETTER LS DIGRAPH]
+"\u02AA" => "ls"
+
+# Ê«  [LATIN SMALL LETTER LZ DIGRAPH]
+"\u02AB" => "lz"
+
+# Æ  [LATIN CAPITAL LETTER TURNED M]
+"\u019C" => "M"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL M]
+"\u1D0D" => "M"
+
+# ážŸ  [LATIN CAPITAL LETTER M WITH ACUTE]
+"\u1E3E" => "M"
+
+# á¹  [LATIN CAPITAL LETTER M WITH DOT ABOVE]
+"\u1E40" => "M"
+
+# á¹  [LATIN CAPITAL LETTER M WITH DOT BELOW]
+"\u1E42" => "M"
+
+# â  [CIRCLED LATIN CAPITAL LETTER M]
+"\u24C2" => "M"
+
+# â±®  [LATIN CAPITAL LETTER M WITH HOOK]
+"\u2C6E" => "M"
+
+# êœ  [LATIN EPIGRAPHIC LETTER INVERTED M]
+"\uA7FD" => "M"
+
+# ê¿  [LATIN EPIGRAPHIC LETTER ARCHAIC M]
+"\uA7FF" => "M"
+
+# ïŒ­  [FULLWIDTH LATIN CAPITAL LETTER M]
+"\uFF2D" => "M"
+
+# É¯  [LATIN SMALL LETTER TURNED M]
+"\u026F" => "m"
+
+# É°  [LATIN SMALL LETTER TURNED M WITH LONG LEG]
+"\u0270" => "m"
+
+# É±  [LATIN SMALL LETTER M WITH HOOK]
+"\u0271" => "m"
+
+# áµ¯  [LATIN SMALL LETTER M WITH MIDDLE TILDE]
+"\u1D6F" => "m"
+
+# á¶  [LATIN SMALL LETTER M WITH PALATAL HOOK]
+"\u1D86" => "m"
+
+# áž¿  [LATIN SMALL LETTER M WITH ACUTE]
+"\u1E3F" => "m"
+
+# á¹  [LATIN SMALL LETTER M WITH DOT ABOVE]
+"\u1E41" => "m"
+
+# á¹  [LATIN SMALL LETTER M WITH DOT BELOW]
+"\u1E43" => "m"
+
+# â  [CIRCLED LATIN SMALL LETTER M]
+"\u24DC" => "m"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER M]
+"\uFF4D" => "m"
+
+# âš  [PARENTHESIZED LATIN SMALL LETTER M]
+"\u24A8" => "(m)"
+
+# Ã  [LATIN CAPITAL LETTER N WITH TILDE]
+"\u00D1" => "N"
+
+# Å  [LATIN CAPITAL LETTER N WITH ACUTE]
+"\u0143" => "N"
+
+# Å
+  [LATIN CAPITAL LETTER N WITH CEDILLA]
+"\u0145" => "N"
+
+# Å  [LATIN CAPITAL LETTER N WITH CARON]
+"\u0147" => "N"
+
+# Å  http://en.wikipedia.org/wiki/Eng_(letter)  [LATIN CAPITAL LETTER ENG]
+"\u014A" => "N"
+
+# Æ  [LATIN CAPITAL LETTER N WITH LEFT HOOK]
+"\u019D" => "N"
+
+# Çž  [LATIN CAPITAL LETTER N WITH GRAVE]
+"\u01F8" => "N"
+
+# È   [LATIN CAPITAL LETTER N WITH LONG RIGHT LEG]
+"\u0220" => "N"
+
+# ÉŽ  [LATIN LETTER SMALL CAPITAL N]
+"\u0274" => "N"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL REVERSED N]
+"\u1D0E" => "N"
+
+# á¹  [LATIN CAPITAL LETTER N WITH DOT ABOVE]
+"\u1E44" => "N"
+
+# á¹  [LATIN CAPITAL LETTER N WITH DOT BELOW]
+"\u1E46" => "N"
+
+# á¹  [LATIN CAPITAL LETTER N WITH LINE BELOW]
+"\u1E48" => "N"
+
+# á¹  [LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW]
+"\u1E4A" => "N"
+
+# â  [CIRCLED LATIN CAPITAL LETTER N]
+"\u24C3" => "N"
+
+# ïŒ®  [FULLWIDTH LATIN CAPITAL LETTER N]
+"\uFF2E" => "N"
+
+# Ã±  [LATIN SMALL LETTER N WITH TILDE]
+"\u00F1" => "n"
+
+# Å  [LATIN SMALL LETTER N WITH ACUTE]
+"\u0144" => "n"
+
+# Å  [LATIN SMALL LETTER N WITH CEDILLA]
+"\u0146" => "n"
+
+# Å  [LATIN SMALL LETTER N WITH CARON]
+"\u0148" => "n"
+
+# Å  [LATIN SMALL LETTER N PRECEDED BY APOSTROPHE]
+"\u0149" => "n"
+
+# Å  http://en.wikipedia.org/wiki/Eng_(letter)  [LATIN SMALL LETTER ENG]
+"\u014B" => "n"
+
+# Æ  [LATIN SMALL LETTER N WITH LONG RIGHT LEG]
+"\u019E" => "n"
+
+# Ç¹  [LATIN SMALL LETTER N WITH GRAVE]
+"\u01F9" => "n"
+
+# Èµ  [LATIN SMALL LETTER N WITH CURL]
+"\u0235" => "n"
+
+# É²  [LATIN SMALL LETTER N WITH LEFT HOOK]
+"\u0272" => "n"
+
+# É³  [LATIN SMALL LETTER N WITH RETROFLEX HOOK]
+"\u0273" => "n"
+
+# áµ°  [LATIN SMALL LETTER N WITH MIDDLE TILDE]
+"\u1D70" => "n"
+
+# á¶  [LATIN SMALL LETTER N WITH PALATAL HOOK]
+"\u1D87" => "n"
+
+# á¹
+  [LATIN SMALL LETTER N WITH DOT ABOVE]
+"\u1E45" => "n"
+
+# á¹  [LATIN SMALL LETTER N WITH DOT BELOW]
+"\u1E47" => "n"
+
+# á¹  [LATIN SMALL LETTER N WITH LINE BELOW]
+"\u1E49" => "n"
+
+# á¹  [LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW]
+"\u1E4B" => "n"
+
+# â¿  [SUPERSCRIPT LATIN SMALL LETTER N]
+"\u207F" => "n"
+
+# â  [CIRCLED LATIN SMALL LETTER N]
+"\u24DD" => "n"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER N]
+"\uFF4E" => "n"
+
+# Ç  [LATIN CAPITAL LETTER NJ]
+"\u01CA" => "NJ"
+
+# Ç  [LATIN CAPITAL LETTER N WITH SMALL LETTER J]
+"\u01CB" => "Nj"
+
+# â©  [PARENTHESIZED LATIN SMALL LETTER N]
+"\u24A9" => "(n)"
+
+# Ç  [LATIN SMALL LETTER NJ]
+"\u01CC" => "nj"
+
+# Ã  [LATIN CAPITAL LETTER O WITH GRAVE]
+"\u00D2" => "O"
+
+# Ã  [LATIN CAPITAL LETTER O WITH ACUTE]
+"\u00D3" => "O"
+
+# Ã  [LATIN CAPITAL LETTER O WITH CIRCUMFLEX]
+"\u00D4" => "O"
+
+# Ã  [LATIN CAPITAL LETTER O WITH TILDE]
+"\u00D5" => "O"
+
+# Ã  [LATIN CAPITAL LETTER O WITH DIAERESIS]
+"\u00D6" => "O"
+
+# Ã  [LATIN CAPITAL LETTER O WITH STROKE]
+"\u00D8" => "O"
+
+# Å  [LATIN CAPITAL LETTER O WITH MACRON]
+"\u014C" => "O"
+
+# Å  [LATIN CAPITAL LETTER O WITH BREVE]
+"\u014E" => "O"
+
+# Å  [LATIN CAPITAL LETTER O WITH DOUBLE ACUTE]
+"\u0150" => "O"
+
+# Æ  [LATIN CAPITAL LETTER OPEN O]
+"\u0186" => "O"
+
+# Æ  [LATIN CAPITAL LETTER O WITH MIDDLE TILDE]
+"\u019F" => "O"
+
+# Æ   [LATIN CAPITAL LETTER O WITH HORN]
+"\u01A0" => "O"
+
+# Ç  [LATIN CAPITAL LETTER O WITH CARON]
+"\u01D1" => "O"
+
+# Çª  [LATIN CAPITAL LETTER O WITH OGONEK]
+"\u01EA" => "O"
+
+# Ç¬  [LATIN CAPITAL LETTER O WITH OGONEK AND MACRON]
+"\u01EC" => "O"
+
+# ÇŸ  [LATIN CAPITAL LETTER O WITH STROKE AND ACUTE]
+"\u01FE" => "O"
+
+# È  [LATIN CAPITAL LETTER O WITH DOUBLE GRAVE]
+"\u020C" => "O"
+
+# È  [LATIN CAPITAL LETTER O WITH INVERTED BREVE]
+"\u020E" => "O"
+
+# Èª  [LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON]
+"\u022A" => "O"
+
+# È¬  [LATIN CAPITAL LETTER O WITH TILDE AND MACRON]
+"\u022C" => "O"
+
+# È®  [LATIN CAPITAL LETTER O WITH DOT ABOVE]
+"\u022E" => "O"
+
+# È°  [LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON]
+"\u0230" => "O"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL O]
+"\u1D0F" => "O"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL OPEN O]
+"\u1D10" => "O"
+
+# á¹  [LATIN CAPITAL LETTER O WITH TILDE AND ACUTE]
+"\u1E4C" => "O"
+
+# á¹  [LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS]
+"\u1E4E" => "O"
+
+# á¹  [LATIN CAPITAL LETTER O WITH MACRON AND GRAVE]
+"\u1E50" => "O"
+
+# á¹  [LATIN CAPITAL LETTER O WITH MACRON AND ACUTE]
+"\u1E52" => "O"
+
+# á»  [LATIN CAPITAL LETTER O WITH DOT BELOW]
+"\u1ECC" => "O"
+
+# á»  [LATIN CAPITAL LETTER O WITH HOOK ABOVE]
+"\u1ECE" => "O"
+
+# á»  [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE]
+"\u1ED0" => "O"
+
+# á»  [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE]
+"\u1ED2" => "O"
+
+# á»  [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE]
+"\u1ED4" => "O"
+
+# á»  [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE]
+"\u1ED6" => "O"
+
+# á»  [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW]
+"\u1ED8" => "O"
+
+# á»  [LATIN CAPITAL LETTER O WITH HORN AND ACUTE]
+"\u1EDA" => "O"
+
+# á»  [LATIN CAPITAL LETTER O WITH HORN AND GRAVE]
+"\u1EDC" => "O"
+
+# á»  [LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE]
+"\u1EDE" => "O"
+
+# á»   [LATIN CAPITAL LETTER O WITH HORN AND TILDE]
+"\u1EE0" => "O"
+
+# á»¢  [LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW]
+"\u1EE2" => "O"
+
+# â  [CIRCLED LATIN CAPITAL LETTER O]
+"\u24C4" => "O"
+
+# ê  [LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY]
+"\uA74A" => "O"
+
+# ê  [LATIN CAPITAL LETTER O WITH LOOP]
+"\uA74C" => "O"
+
+# ïŒ¯  [FULLWIDTH LATIN CAPITAL LETTER O]
+"\uFF2F" => "O"
+
+# Ã²  [LATIN SMALL LETTER O WITH GRAVE]
+"\u00F2" => "o"
+
+# Ã³  [LATIN SMALL LETTER O WITH ACUTE]
+"\u00F3" => "o"
+
+# ÃŽ  [LATIN SMALL LETTER O WITH CIRCUMFLEX]
+"\u00F4" => "o"
+
+# Ãµ  [LATIN SMALL LETTER O WITH TILDE]
+"\u00F5" => "o"
+
+# Ã¶  [LATIN SMALL LETTER O WITH DIAERESIS]
+"\u00F6" => "o"
+
+# Ãž  [LATIN SMALL LETTER O WITH STROKE]
+"\u00F8" => "o"
+
+# Å  [LATIN SMALL LETTER O WITH MACRON]
+"\u014D" => "o"
+
+# Å  [LATIN SMALL LETTER O WITH BREVE]
+"\u014F" => "o"
+
+# Å  [LATIN SMALL LETTER O WITH DOUBLE ACUTE]
+"\u0151" => "o"
+
+# Æ¡  [LATIN SMALL LETTER O WITH HORN]
+"\u01A1" => "o"
+
+# Ç  [LATIN SMALL LETTER O WITH CARON]
+"\u01D2" => "o"
+
+# Ç«  [LATIN SMALL LETTER O WITH OGONEK]
+"\u01EB" => "o"
+
+# Ç­  [LATIN SMALL LETTER O WITH OGONEK AND MACRON]
+"\u01ED" => "o"
+
+# Ç¿  [LATIN SMALL LETTER O WITH STROKE AND ACUTE]
+"\u01FF" => "o"
+
+# È  [LATIN SMALL LETTER O WITH DOUBLE GRAVE]
+"\u020D" => "o"
+
+# È  [LATIN SMALL LETTER O WITH INVERTED BREVE]
+"\u020F" => "o"
+
+# È«  [LATIN SMALL LETTER O WITH DIAERESIS AND MACRON]
+"\u022B" => "o"
+
+# È­  [LATIN SMALL LETTER O WITH TILDE AND MACRON]
+"\u022D" => "o"
+
+# È¯  [LATIN SMALL LETTER O WITH DOT ABOVE]
+"\u022F" => "o"
+
+# È±  [LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON]
+"\u0231" => "o"
+
+# É  [LATIN SMALL LETTER OPEN O]
+"\u0254" => "o"
+
+# Éµ  [LATIN SMALL LETTER BARRED O]
+"\u0275" => "o"
+
+# áŽ  [LATIN SMALL LETTER TOP HALF O]
+"\u1D16" => "o"
+
+# áŽ  [LATIN SMALL LETTER BOTTOM HALF O]
+"\u1D17" => "o"
+
+# á¶  [LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK]
+"\u1D97" => "o"
+
+# á¹  [LATIN SMALL LETTER O WITH TILDE AND ACUTE]
+"\u1E4D" => "o"
+
+# á¹  [LATIN SMALL LETTER O WITH TILDE AND DIAERESIS]
+"\u1E4F" => "o"
+
+# á¹  [LATIN SMALL LETTER O WITH MACRON AND GRAVE]
+"\u1E51" => "o"
+
+# á¹  [LATIN SMALL LETTER O WITH MACRON AND ACUTE]
+"\u1E53" => "o"
+
+# á»  [LATIN SMALL LETTER O WITH DOT BELOW]
+"\u1ECD" => "o"
+
+# á»  [LATIN SMALL LETTER O WITH HOOK ABOVE]
+"\u1ECF" => "o"
+
+# á»  [LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE]
+"\u1ED1" => "o"
+
+# á»  [LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE]
+"\u1ED3" => "o"
+
+# á»  [LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE]
+"\u1ED5" => "o"
+
+# á»  [LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE]
+"\u1ED7" => "o"
+
+# á»  [LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW]
+"\u1ED9" => "o"
+
+# á»  [LATIN SMALL LETTER O WITH HORN AND ACUTE]
+"\u1EDB" => "o"
+
+# á»  [LATIN SMALL LETTER O WITH HORN AND GRAVE]
+"\u1EDD" => "o"
+
+# á»  [LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE]
+"\u1EDF" => "o"
+
+# á»¡  [LATIN SMALL LETTER O WITH HORN AND TILDE]
+"\u1EE1" => "o"
+
+# á»£  [LATIN SMALL LETTER O WITH HORN AND DOT BELOW]
+"\u1EE3" => "o"
+
+# â  [LATIN SUBSCRIPT SMALL LETTER O]
+"\u2092" => "o"
+
+# â  [CIRCLED LATIN SMALL LETTER O]
+"\u24DE" => "o"
+
+# â±º  [LATIN SMALL LETTER O WITH LOW RING INSIDE]
+"\u2C7A" => "o"
+
+# ê  [LATIN SMALL LETTER O WITH LONG STROKE OVERLAY]
+"\uA74B" => "o"
+
+# ê  [LATIN SMALL LETTER O WITH LOOP]
+"\uA74D" => "o"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER O]
+"\uFF4F" => "o"
+
+# Å  [LATIN CAPITAL LIGATURE OE]
+"\u0152" => "OE"
+
+# É¶  [LATIN LETTER SMALL CAPITAL OE]
+"\u0276" => "OE"
+
+# ê  [LATIN CAPITAL LETTER OO]
+"\uA74E" => "OO"
+
+# È¢  http://en.wikipedia.org/wiki/OU  [LATIN CAPITAL LETTER OU]
+"\u0222" => "OU"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL OU]
+"\u1D15" => "OU"
+
+# âª  [PARENTHESIZED LATIN SMALL LETTER O]
+"\u24AA" => "(o)"
+
+# Å  [LATIN SMALL LIGATURE OE]
+"\u0153" => "oe"
+
+# áŽ  [LATIN SMALL LETTER TURNED OE]
+"\u1D14" => "oe"
+
+# ê  [LATIN SMALL LETTER OO]
+"\uA74F" => "oo"
+
+# È£  http://en.wikipedia.org/wiki/OU  [LATIN SMALL LETTER OU]
+"\u0223" => "ou"
+
+# Æ€  [LATIN CAPITAL LETTER P WITH HOOK]
+"\u01A4" => "P"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL P]
+"\u1D18" => "P"
+
+# á¹  [LATIN CAPITAL LETTER P WITH ACUTE]
+"\u1E54" => "P"
+
+# á¹  [LATIN CAPITAL LETTER P WITH DOT ABOVE]
+"\u1E56" => "P"
+
+# â
+  [CIRCLED LATIN CAPITAL LETTER P]
+"\u24C5" => "P"
+
+# â±£  [LATIN CAPITAL LETTER P WITH STROKE]
+"\u2C63" => "P"
+
+# ê  [LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER]
+"\uA750" => "P"
+
+# ê  [LATIN CAPITAL LETTER P WITH FLOURISH]
+"\uA752" => "P"
+
+# ê  [LATIN CAPITAL LETTER P WITH SQUIRREL TAIL]
+"\uA754" => "P"
+
+# ïŒ°  [FULLWIDTH LATIN CAPITAL LETTER P]
+"\uFF30" => "P"
+
+# Æ¥  [LATIN SMALL LETTER P WITH HOOK]
+"\u01A5" => "p"
+
+# áµ±  [LATIN SMALL LETTER P WITH MIDDLE TILDE]
+"\u1D71" => "p"
+
+# áµœ  [LATIN SMALL LETTER P WITH STROKE]
+"\u1D7D" => "p"
+
+# á¶  [LATIN SMALL LETTER P WITH PALATAL HOOK]
+"\u1D88" => "p"
+
+# á¹  [LATIN SMALL LETTER P WITH ACUTE]
+"\u1E55" => "p"
+
+# á¹  [LATIN SMALL LETTER P WITH DOT ABOVE]
+"\u1E57" => "p"
+
+# â  [CIRCLED LATIN SMALL LETTER P]
+"\u24DF" => "p"
+
+# ê  [LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER]
+"\uA751" => "p"
+
+# ê  [LATIN SMALL LETTER P WITH FLOURISH]
+"\uA753" => "p"
+
+# ê  [LATIN SMALL LETTER P WITH SQUIRREL TAIL]
+"\uA755" => "p"
+
+# êŒ  [LATIN EPIGRAPHIC LETTER REVERSED P]
+"\uA7FC" => "p"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER P]
+"\uFF50" => "p"
+
+# â«  [PARENTHESIZED LATIN SMALL LETTER P]
+"\u24AB" => "(p)"
+
+# É  [LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL]
+"\u024A" => "Q"
+
+# â  [CIRCLED LATIN CAPITAL LETTER Q]
+"\u24C6" => "Q"
+
+# ê  [LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER]
+"\uA756" => "Q"
+
+# ê  [LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE]
+"\uA758" => "Q"
+
+# ïŒ±  [FULLWIDTH LATIN CAPITAL LETTER Q]
+"\uFF31" => "Q"
+
+# Äž  http://en.wikipedia.org/wiki/Kra_(letter)  [LATIN SMALL LETTER KRA]
+"\u0138" => "q"
+
+# É  [LATIN SMALL LETTER Q WITH HOOK TAIL]
+"\u024B" => "q"
+
+# Ê   [LATIN SMALL LETTER Q WITH HOOK]
+"\u02A0" => "q"
+
+# â   [CIRCLED LATIN SMALL LETTER Q]
+"\u24E0" => "q"
+
+# ê  [LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER]
+"\uA757" => "q"
+
+# ê  [LATIN SMALL LETTER Q WITH DIAGONAL STROKE]
+"\uA759" => "q"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER Q]
+"\uFF51" => "q"
+
+# â¬  [PARENTHESIZED LATIN SMALL LETTER Q]
+"\u24AC" => "(q)"
+
+# È¹  [LATIN SMALL LETTER QP DIGRAPH]
+"\u0239" => "qp"
+
+# Å  [LATIN CAPITAL LETTER R WITH ACUTE]
+"\u0154" => "R"
+
+# Å  [LATIN CAPITAL LETTER R WITH CEDILLA]
+"\u0156" => "R"
+
+# Å  [LATIN CAPITAL LETTER R WITH CARON]
+"\u0158" => "R"
+
+# È  [LATIN CAPITAL LETTER R WITH DOUBLE GRAVE]
+"\u0210" => "R"
+
+# È  [LATIN CAPITAL LETTER R WITH INVERTED BREVE]
+"\u0212" => "R"
+
+# É  [LATIN CAPITAL LETTER R WITH STROKE]
+"\u024C" => "R"
+
+# Ê  [LATIN LETTER SMALL CAPITAL R]
+"\u0280" => "R"
+
+# Ê  [LATIN LETTER SMALL CAPITAL INVERTED R]
+"\u0281" => "R"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL REVERSED R]
+"\u1D19" => "R"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL TURNED R]
+"\u1D1A" => "R"
+
+# á¹  [LATIN CAPITAL LETTER R WITH DOT ABOVE]
+"\u1E58" => "R"
+
+# á¹  [LATIN CAPITAL LETTER R WITH DOT BELOW]
+"\u1E5A" => "R"
+
+# á¹  [LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON]
+"\u1E5C" => "R"
+
+# á¹  [LATIN CAPITAL LETTER R WITH LINE BELOW]
+"\u1E5E" => "R"
+
+# â  [CIRCLED LATIN CAPITAL LETTER R]
+"\u24C7" => "R"
+
+# â±€  [LATIN CAPITAL LETTER R WITH TAIL]
+"\u2C64" => "R"
+
+# ê  [LATIN CAPITAL LETTER R ROTUNDA]
+"\uA75A" => "R"
+
+# ê  [LATIN CAPITAL LETTER INSULAR R]
+"\uA782" => "R"
+
+# ïŒ²  [FULLWIDTH LATIN CAPITAL LETTER R]
+"\uFF32" => "R"
+
+# Å  [LATIN SMALL LETTER R WITH ACUTE]
+"\u0155" => "r"
+
+# Å  [LATIN SMALL LETTER R WITH CEDILLA]
+"\u0157" => "r"
+
+# Å  [LATIN SMALL LETTER R WITH CARON]
+"\u0159" => "r"
+
+# È  [LATIN SMALL LETTER R WITH DOUBLE GRAVE]
+"\u0211" => "r"
+
+# È  [LATIN SMALL LETTER R WITH INVERTED BREVE]
+"\u0213" => "r"
+
+# É  [LATIN SMALL LETTER R WITH STROKE]
+"\u024D" => "r"
+
+# ÉŒ  [LATIN SMALL LETTER R WITH LONG LEG]
+"\u027C" => "r"
+
+# Éœ  [LATIN SMALL LETTER R WITH TAIL]
+"\u027D" => "r"
+
+# ÉŸ  [LATIN SMALL LETTER R WITH FISHHOOK]
+"\u027E" => "r"
+
+# É¿  [LATIN SMALL LETTER REVERSED R WITH FISHHOOK]
+"\u027F" => "r"
+
+# áµ£  [LATIN SUBSCRIPT SMALL LETTER R]
+"\u1D63" => "r"
+
+# áµ²  [LATIN SMALL LETTER R WITH MIDDLE TILDE]
+"\u1D72" => "r"
+
+# áµ³  [LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE]
+"\u1D73" => "r"
+
+# á¶  [LATIN SMALL LETTER R WITH PALATAL HOOK]
+"\u1D89" => "r"
+
+# á¹  [LATIN SMALL LETTER R WITH DOT ABOVE]
+"\u1E59" => "r"
+
+# á¹  [LATIN SMALL LETTER R WITH DOT BELOW]
+"\u1E5B" => "r"
+
+# á¹  [LATIN SMALL LETTER R WITH DOT BELOW AND MACRON]
+"\u1E5D" => "r"
+
+# á¹  [LATIN SMALL LETTER R WITH LINE BELOW]
+"\u1E5F" => "r"
+
+# â¡  [CIRCLED LATIN SMALL LETTER R]
+"\u24E1" => "r"
+
+# ê  [LATIN SMALL LETTER R ROTUNDA]
+"\uA75B" => "r"
+
+# ê  [LATIN SMALL LETTER INSULAR R]
+"\uA783" => "r"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER R]
+"\uFF52" => "r"
+
+# â­  [PARENTHESIZED LATIN SMALL LETTER R]
+"\u24AD" => "(r)"
+
+# Å  [LATIN CAPITAL LETTER S WITH ACUTE]
+"\u015A" => "S"
+
+# Å  [LATIN CAPITAL LETTER S WITH CIRCUMFLEX]
+"\u015C" => "S"
+
+# Å  [LATIN CAPITAL LETTER S WITH CEDILLA]
+"\u015E" => "S"
+
+# Å   [LATIN CAPITAL LETTER S WITH CARON]
+"\u0160" => "S"
+
+# È  [LATIN CAPITAL LETTER S WITH COMMA BELOW]
+"\u0218" => "S"
+
+# á¹   [LATIN CAPITAL LETTER S WITH DOT ABOVE]
+"\u1E60" => "S"
+
+# á¹¢  [LATIN CAPITAL LETTER S WITH DOT BELOW]
+"\u1E62" => "S"
+
+# á¹€  [LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE]
+"\u1E64" => "S"
+
+# á¹Š  [LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE]
+"\u1E66" => "S"
+
+# á¹š  [LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE]
+"\u1E68" => "S"
+
+# â  [CIRCLED LATIN CAPITAL LETTER S]
+"\u24C8" => "S"
+
+# ê±  [LATIN LETTER SMALL CAPITAL S]
+"\uA731" => "S"
+
+# ê
+  [LATIN SMALL LETTER INSULAR S]
+"\uA785" => "S"
+
+# ïŒ³  [FULLWIDTH LATIN CAPITAL LETTER S]
+"\uFF33" => "S"
+
+# Å  [LATIN SMALL LETTER S WITH ACUTE]
+"\u015B" => "s"
+
+# Å  [LATIN SMALL LETTER S WITH CIRCUMFLEX]
+"\u015D" => "s"
+
+# Å  [LATIN SMALL LETTER S WITH CEDILLA]
+"\u015F" => "s"
+
+# Å¡  [LATIN SMALL LETTER S WITH CARON]
+"\u0161" => "s"
+
+# Å¿  http://en.wikipedia.org/wiki/Long_S  [LATIN SMALL LETTER LONG S]
+"\u017F" => "s"
+
+# È  [LATIN SMALL LETTER S WITH COMMA BELOW]
+"\u0219" => "s"
+
+# È¿  [LATIN SMALL LETTER S WITH SWASH TAIL]
+"\u023F" => "s"
+
+# Ê  [LATIN SMALL LETTER S WITH HOOK]
+"\u0282" => "s"
+
+# áµŽ  [LATIN SMALL LETTER S WITH MIDDLE TILDE]
+"\u1D74" => "s"
+
+# á¶  [LATIN SMALL LETTER S WITH PALATAL HOOK]
+"\u1D8A" => "s"
+
+# á¹¡  [LATIN SMALL LETTER S WITH DOT ABOVE]
+"\u1E61" => "s"
+
+# á¹£  [LATIN SMALL LETTER S WITH DOT BELOW]
+"\u1E63" => "s"
+
+# á¹¥  [LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE]
+"\u1E65" => "s"
+
+# á¹§  [LATIN SMALL LETTER S WITH CARON AND DOT ABOVE]
+"\u1E67" => "s"
+
+# á¹©  [LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE]
+"\u1E69" => "s"
+
+# áº  [LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE]
+"\u1E9C" => "s"
+
+# áº  [LATIN SMALL LETTER LONG S WITH HIGH STROKE]
+"\u1E9D" => "s"
+
+# â¢  [CIRCLED LATIN SMALL LETTER S]
+"\u24E2" => "s"
+
+# ê  [LATIN CAPITAL LETTER INSULAR S]
+"\uA784" => "s"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER S]
+"\uFF53" => "s"
+
+# áº  [LATIN CAPITAL LETTER SHARP S]
+"\u1E9E" => "SS"
+
+# â®  [PARENTHESIZED LATIN SMALL LETTER S]
+"\u24AE" => "(s)"
+
+# Ã  [LATIN SMALL LETTER SHARP S]
+"\u00DF" => "ss"
+
+# ï¬  [LATIN SMALL LIGATURE ST]
+"\uFB06" => "st"
+
+# Å¢  [LATIN CAPITAL LETTER T WITH CEDILLA]
+"\u0162" => "T"
+
+# Å€  [LATIN CAPITAL LETTER T WITH CARON]
+"\u0164" => "T"
+
+# ÅŠ  [LATIN CAPITAL LETTER T WITH STROKE]
+"\u0166" => "T"
+
+# Æ¬  [LATIN CAPITAL LETTER T WITH HOOK]
+"\u01AC" => "T"
+
+# Æ®  [LATIN CAPITAL LETTER T WITH RETROFLEX HOOK]
+"\u01AE" => "T"
+
+# È  [LATIN CAPITAL LETTER T WITH COMMA BELOW]
+"\u021A" => "T"
+
+# ÈŸ  [LATIN CAPITAL LETTER T WITH DIAGONAL STROKE]
+"\u023E" => "T"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL T]
+"\u1D1B" => "T"
+
+# á¹ª  [LATIN CAPITAL LETTER T WITH DOT ABOVE]
+"\u1E6A" => "T"
+
+# á¹¬  [LATIN CAPITAL LETTER T WITH DOT BELOW]
+"\u1E6C" => "T"
+
+# á¹®  [LATIN CAPITAL LETTER T WITH LINE BELOW]
+"\u1E6E" => "T"
+
+# á¹°  [LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW]
+"\u1E70" => "T"
+
+# â  [CIRCLED LATIN CAPITAL LETTER T]
+"\u24C9" => "T"
+
+# ê  [LATIN CAPITAL LETTER INSULAR T]
+"\uA786" => "T"
+
+# ïŒŽ  [FULLWIDTH LATIN CAPITAL LETTER T]
+"\uFF34" => "T"
+
+# Å£  [LATIN SMALL LETTER T WITH CEDILLA]
+"\u0163" => "t"
+
+# Å¥  [LATIN SMALL LETTER T WITH CARON]
+"\u0165" => "t"
+
+# Å§  [LATIN SMALL LETTER T WITH STROKE]
+"\u0167" => "t"
+
+# Æ«  [LATIN SMALL LETTER T WITH PALATAL HOOK]
+"\u01AB" => "t"
+
+# Æ­  [LATIN SMALL LETTER T WITH HOOK]
+"\u01AD" => "t"
+
+# È  [LATIN SMALL LETTER T WITH COMMA BELOW]
+"\u021B" => "t"
+
+# È¶  [LATIN SMALL LETTER T WITH CURL]
+"\u0236" => "t"
+
+# Ê  [LATIN SMALL LETTER TURNED T]
+"\u0287" => "t"
+
+# Ê  [LATIN SMALL LETTER T WITH RETROFLEX HOOK]
+"\u0288" => "t"
+
+# áµµ  [LATIN SMALL LETTER T WITH MIDDLE TILDE]
+"\u1D75" => "t"
+
+# á¹«  [LATIN SMALL LETTER T WITH DOT ABOVE]
+"\u1E6B" => "t"
+
+# á¹­  [LATIN SMALL LETTER T WITH DOT BELOW]
+"\u1E6D" => "t"
+
+# á¹¯  [LATIN SMALL LETTER T WITH LINE BELOW]
+"\u1E6F" => "t"
+
+# á¹±  [LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW]
+"\u1E71" => "t"
+
+# áº  [LATIN SMALL LETTER T WITH DIAERESIS]
+"\u1E97" => "t"
+
+# â£  [CIRCLED LATIN SMALL LETTER T]
+"\u24E3" => "t"
+
+# â±Š  [LATIN SMALL LETTER T WITH DIAGONAL STROKE]
+"\u2C66" => "t"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER T]
+"\uFF54" => "t"
+
+# Ã  [LATIN CAPITAL LETTER THORN]
+"\u00DE" => "TH"
+
+# êŠ  [LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER]
+"\uA766" => "TH"
+
+# êš  [LATIN CAPITAL LETTER TZ]
+"\uA728" => "TZ"
+
+# â¯  [PARENTHESIZED LATIN SMALL LETTER T]
+"\u24AF" => "(t)"
+
+# Êš  [LATIN SMALL LETTER TC DIGRAPH WITH CURL]
+"\u02A8" => "tc"
+
+# ÃŸ  [LATIN SMALL LETTER THORN]
+"\u00FE" => "th"
+
+# áµº  [LATIN SMALL LETTER TH WITH STRIKETHROUGH]
+"\u1D7A" => "th"
+
+# ê§  [LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER]
+"\uA767" => "th"
+
+# ÊŠ  [LATIN SMALL LETTER TS DIGRAPH]
+"\u02A6" => "ts"
+
+# ê©  [LATIN SMALL LETTER TZ]
+"\uA729" => "tz"
+
+# Ã  [LATIN CAPITAL LETTER U WITH GRAVE]
+"\u00D9" => "U"
+
+# Ã  [LATIN CAPITAL LETTER U WITH ACUTE]
+"\u00DA" => "U"
+
+# Ã  [LATIN CAPITAL LETTER U WITH CIRCUMFLEX]
+"\u00DB" => "U"
+
+# Ã  [LATIN CAPITAL LETTER U WITH DIAERESIS]
+"\u00DC" => "U"
+
+# Åš  [LATIN CAPITAL LETTER U WITH TILDE]
+"\u0168" => "U"
+
+# Åª  [LATIN CAPITAL LETTER U WITH MACRON]
+"\u016A" => "U"
+
+# Å¬  [LATIN CAPITAL LETTER U WITH BREVE]
+"\u016C" => "U"
+
+# Å®  [LATIN CAPITAL LETTER U WITH RING ABOVE]
+"\u016E" => "U"
+
+# Å°  [LATIN CAPITAL LETTER U WITH DOUBLE ACUTE]
+"\u0170" => "U"
+
+# Å²  [LATIN CAPITAL LETTER U WITH OGONEK]
+"\u0172" => "U"
+
+# Æ¯  [LATIN CAPITAL LETTER U WITH HORN]
+"\u01AF" => "U"
+
+# Ç  [LATIN CAPITAL LETTER U WITH CARON]
+"\u01D3" => "U"
+
+# Ç  [LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON]
+"\u01D5" => "U"
+
+# Ç  [LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE]
+"\u01D7" => "U"
+
+# Ç  [LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON]
+"\u01D9" => "U"
+
+# Ç  [LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE]
+"\u01DB" => "U"
+
+# È  [LATIN CAPITAL LETTER U WITH DOUBLE GRAVE]
+"\u0214" => "U"
+
+# È  [LATIN CAPITAL LETTER U WITH INVERTED BREVE]
+"\u0216" => "U"
+
+# É  [LATIN CAPITAL LETTER U BAR]
+"\u0244" => "U"
+
+# áŽ  [LATIN LETTER SMALL CAPITAL U]
+"\u1D1C" => "U"
+
+# áµŸ  [LATIN SMALL CAPITAL LETTER U WITH STROKE]
+"\u1D7E" => "U"
+
+# á¹²  [LATIN CAPITAL LETTER U WITH DIAERESIS BELOW]
+"\u1E72" => "U"
+
+# á¹Ž  [LATIN CAPITAL LETTER U WITH TILDE BELOW]
+"\u1E74" => "U"
+
+# á¹¶  [LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW]
+"\u1E76" => "U"
+
+# á¹ž  [LATIN CAPITAL LETTER U WITH TILDE AND ACUTE]
+"\u1E78" => "U"
+
+# á¹º  [LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS]
+"\u1E7A" => "U"
+
+# á»€  [LATIN CAPITAL LETTER U WITH DOT BELOW]
+"\u1EE4" => "U"
+
+# á»Š  [LATIN CAPITAL LETTER U WITH HOOK ABOVE]
+"\u1EE6" => "U"
+
+# á»š  [LATIN CAPITAL LETTER U WITH HORN AND ACUTE]
+"\u1EE8" => "U"
+
+# á»ª  [LATIN CAPITAL LETTER U WITH HORN AND GRAVE]
+"\u1EEA" => "U"
+
+# á»¬  [LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE]
+"\u1EEC" => "U"
+
+# á»®  [LATIN CAPITAL LETTER U WITH HORN AND TILDE]
+"\u1EEE" => "U"
+
+# á»°  [LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW]
+"\u1EF0" => "U"
+
+# â  [CIRCLED LATIN CAPITAL LETTER U]
+"\u24CA" => "U"
+
+# ïŒµ  [FULLWIDTH LATIN CAPITAL LETTER U]
+"\uFF35" => "U"
+
+# Ã¹  [LATIN SMALL LETTER U WITH GRAVE]
+"\u00F9" => "u"
+
+# Ãº  [LATIN SMALL LETTER U WITH ACUTE]
+"\u00FA" => "u"
+
+# Ã»  [LATIN SMALL LETTER U WITH CIRCUMFLEX]
+"\u00FB" => "u"
+
+# ÃŒ  [LATIN SMALL LETTER U WITH DIAERESIS]
+"\u00FC" => "u"
+
+# Å©  [LATIN SMALL LETTER U WITH TILDE]
+"\u0169" => "u"
+
+# Å«  [LATIN SMALL LETTER U WITH MACRON]
+"\u016B" => "u"
+
+# Å­  [LATIN SMALL LETTER U WITH BREVE]
+"\u016D" => "u"
+
+# Å¯  [LATIN SMALL LETTER U WITH RING ABOVE]
+"\u016F" => "u"
+
+# Å±  [LATIN SMALL LETTER U WITH DOUBLE ACUTE]
+"\u0171" => "u"
+
+# Å³  [LATIN SMALL LETTER U WITH OGONEK]
+"\u0173" => "u"
+
+# Æ°  [LATIN SMALL LETTER U WITH HORN]
+"\u01B0" => "u"
+
+# Ç  [LATIN SMALL LETTER U WITH CARON]
+"\u01D4" => "u"
+
+# Ç  [LATIN SMALL LETTER U WITH DIAERESIS AND MACRON]
+"\u01D6" => "u"
+
+# Ç  [LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE]
+"\u01D8" => "u"
+
+# Ç  [LATIN SMALL LETTER U WITH DIAERESIS AND CARON]
+"\u01DA" => "u"
+
+# Ç  [LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE]
+"\u01DC" => "u"
+
+# È  [LATIN SMALL LETTER U WITH DOUBLE GRAVE]
+"\u0215" => "u"
+
+# È  [LATIN SMALL LETTER U WITH INVERTED BREVE]
+"\u0217" => "u"
+
+# Ê  [LATIN SMALL LETTER U BAR]
+"\u0289" => "u"
+
+# áµ€  [LATIN SUBSCRIPT SMALL LETTER U]
+"\u1D64" => "u"
+
+# á¶  [LATIN SMALL LETTER U WITH RETROFLEX HOOK]
+"\u1D99" => "u"
+
+# á¹³  [LATIN SMALL LETTER U WITH DIAERESIS BELOW]
+"\u1E73" => "u"
+
+# á¹µ  [LATIN SMALL LETTER U WITH TILDE BELOW]
+"\u1E75" => "u"
+
+# á¹·  [LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW]
+"\u1E77" => "u"
+
+# á¹¹  [LATIN SMALL LETTER U WITH TILDE AND ACUTE]
+"\u1E79" => "u"
+
+# á¹»  [LATIN SMALL LETTER U WITH MACRON AND DIAERESIS]
+"\u1E7B" => "u"
+
+# á»¥  [LATIN SMALL LETTER U WITH DOT BELOW]
+"\u1EE5" => "u"
+
+# á»§  [LATIN SMALL LETTER U WITH HOOK ABOVE]
+"\u1EE7" => "u"
+
+# á»©  [LATIN SMALL LETTER U WITH HORN AND ACUTE]
+"\u1EE9" => "u"
+
+# á»«  [LATIN SMALL LETTER U WITH HORN AND GRAVE]
+"\u1EEB" => "u"
+
+# á»­  [LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE]
+"\u1EED" => "u"
+
+# á»¯  [LATIN SMALL LETTER U WITH HORN AND TILDE]
+"\u1EEF" => "u"
+
+# á»±  [LATIN SMALL LETTER U WITH HORN AND DOT BELOW]
+"\u1EF1" => "u"
+
+# â€  [CIRCLED LATIN SMALL LETTER U]
+"\u24E4" => "u"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER U]
+"\uFF55" => "u"
+
+# â°  [PARENTHESIZED LATIN SMALL LETTER U]
+"\u24B0" => "(u)"
+
+# áµ«  [LATIN SMALL LETTER UE]
+"\u1D6B" => "ue"
+
+# Æ²  [LATIN CAPITAL LETTER V WITH HOOK]
+"\u01B2" => "V"
+
+# É
+  [LATIN CAPITAL LETTER TURNED V]
+"\u0245" => "V"
+
+# áŽ   [LATIN LETTER SMALL CAPITAL V]
+"\u1D20" => "V"
+
+# á¹Œ  [LATIN CAPITAL LETTER V WITH TILDE]
+"\u1E7C" => "V"
+
+# á¹Ÿ  [LATIN CAPITAL LETTER V WITH DOT BELOW]
+"\u1E7E" => "V"
+
+# á»Œ  [LATIN CAPITAL LETTER MIDDLE-WELSH V]
+"\u1EFC" => "V"
+
+# â  [CIRCLED LATIN CAPITAL LETTER V]
+"\u24CB" => "V"
+
+# ê  [LATIN CAPITAL LETTER V WITH DIAGONAL STROKE]
+"\uA75E" => "V"
+
+# êš  [LATIN CAPITAL LETTER VEND]
+"\uA768" => "V"
+
+# ïŒ¶  [FULLWIDTH LATIN CAPITAL LETTER V]
+"\uFF36" => "V"
+
+# Ê  [LATIN SMALL LETTER V WITH HOOK]
+"\u028B" => "v"
+
+# Ê  [LATIN SMALL LETTER TURNED V]
+"\u028C" => "v"
+
+# áµ¥  [LATIN SUBSCRIPT SMALL LETTER V]
+"\u1D65" => "v"
+
+# á¶  [LATIN SMALL LETTER V WITH PALATAL HOOK]
+"\u1D8C" => "v"
+
+# á¹œ  [LATIN SMALL LETTER V WITH TILDE]
+"\u1E7D" => "v"
+
+# á¹¿  [LATIN SMALL LETTER V WITH DOT BELOW]
+"\u1E7F" => "v"
+
+# â¥  [CIRCLED LATIN SMALL LETTER V]
+"\u24E5" => "v"
+
+# â±±  [LATIN SMALL LETTER V WITH RIGHT HOOK]
+"\u2C71" => "v"
+
+# â±Ž  [LATIN SMALL LETTER V WITH CURL]
+"\u2C74" => "v"
+
+# ê  [LATIN SMALL LETTER V WITH DIAGONAL STROKE]
+"\uA75F" => "v"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER V]
+"\uFF56" => "v"
+
+# ê   [LATIN CAPITAL LETTER VY]
+"\uA760" => "VY"
+
+# â±  [PARENTHESIZED LATIN SMALL LETTER V]
+"\u24B1" => "(v)"
+
+# ê¡  [LATIN SMALL LETTER VY]
+"\uA761" => "vy"
+
+# ÅŽ  [LATIN CAPITAL LETTER W WITH CIRCUMFLEX]
+"\u0174" => "W"
+
+# Ç·  http://en.wikipedia.org/wiki/Wynn  [LATIN CAPITAL LETTER WYNN]
+"\u01F7" => "W"
+
+# áŽ¡  [LATIN LETTER SMALL CAPITAL W]
+"\u1D21" => "W"
+
+# áº  [LATIN CAPITAL LETTER W WITH GRAVE]
+"\u1E80" => "W"
+
+# áº  [LATIN CAPITAL LETTER W WITH ACUTE]
+"\u1E82" => "W"
+
+# áº  [LATIN CAPITAL LETTER W WITH DIAERESIS]
+"\u1E84" => "W"
+
+# áº  [LATIN CAPITAL LETTER W WITH DOT ABOVE]
+"\u1E86" => "W"
+
+# áº  [LATIN CAPITAL LETTER W WITH DOT BELOW]
+"\u1E88" => "W"
+
+# â  [CIRCLED LATIN CAPITAL LETTER W]
+"\u24CC" => "W"
+
+# â±²  [LATIN CAPITAL LETTER W WITH HOOK]
+"\u2C72" => "W"
+
+# ïŒ·  [FULLWIDTH LATIN CAPITAL LETTER W]
+"\uFF37" => "W"
+
+# Åµ  [LATIN SMALL LETTER W WITH CIRCUMFLEX]
+"\u0175" => "w"
+
+# Æ¿  http://en.wikipedia.org/wiki/Wynn  [LATIN LETTER WYNN]
+"\u01BF" => "w"
+
+# Ê  [LATIN SMALL LETTER TURNED W]
+"\u028D" => "w"
+
+# áº  [LATIN SMALL LETTER W WITH GRAVE]
+"\u1E81" => "w"
+
+# áº  [LATIN SMALL LETTER W WITH ACUTE]
+"\u1E83" => "w"
+
+# áº
+  [LATIN SMALL LETTER W WITH DIAERESIS]
+"\u1E85" => "w"
+
+# áº  [LATIN SMALL LETTER W WITH DOT ABOVE]
+"\u1E87" => "w"
+
+# áº  [LATIN SMALL LETTER W WITH DOT BELOW]
+"\u1E89" => "w"
+
+# áº  [LATIN SMALL LETTER W WITH RING ABOVE]
+"\u1E98" => "w"
+
+# âŠ  [CIRCLED LATIN SMALL LETTER W]
+"\u24E6" => "w"
+
+# â±³  [LATIN SMALL LETTER W WITH HOOK]
+"\u2C73" => "w"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER W]
+"\uFF57" => "w"
+
+# â²  [PARENTHESIZED LATIN SMALL LETTER W]
+"\u24B2" => "(w)"
+
+# áº  [LATIN CAPITAL LETTER X WITH DOT ABOVE]
+"\u1E8A" => "X"
+
+# áº  [LATIN CAPITAL LETTER X WITH DIAERESIS]
+"\u1E8C" => "X"
+
+# â  [CIRCLED LATIN CAPITAL LETTER X]
+"\u24CD" => "X"
+
+# ïŒž  [FULLWIDTH LATIN CAPITAL LETTER X]
+"\uFF38" => "X"
+
+# á¶  [LATIN SMALL LETTER X WITH PALATAL HOOK]
+"\u1D8D" => "x"
+
+# áº  [LATIN SMALL LETTER X WITH DOT ABOVE]
+"\u1E8B" => "x"
+
+# áº  [LATIN SMALL LETTER X WITH DIAERESIS]
+"\u1E8D" => "x"
+
+# â  [LATIN SUBSCRIPT SMALL LETTER X]
+"\u2093" => "x"
+
+# â§  [CIRCLED LATIN SMALL LETTER X]
+"\u24E7" => "x"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER X]
+"\uFF58" => "x"
+
+# â³  [PARENTHESIZED LATIN SMALL LETTER X]
+"\u24B3" => "(x)"
+
+# Ã  [LATIN CAPITAL LETTER Y WITH ACUTE]
+"\u00DD" => "Y"
+
+# Å¶  [LATIN CAPITAL LETTER Y WITH CIRCUMFLEX]
+"\u0176" => "Y"
+
+# Åž  [LATIN CAPITAL LETTER Y WITH DIAERESIS]
+"\u0178" => "Y"
+
+# Æ³  [LATIN CAPITAL LETTER Y WITH HOOK]
+"\u01B3" => "Y"
+
+# È²  [LATIN CAPITAL LETTER Y WITH MACRON]
+"\u0232" => "Y"
+
+# É  [LATIN CAPITAL LETTER Y WITH STROKE]
+"\u024E" => "Y"
+
+# Ê  [LATIN LETTER SMALL CAPITAL Y]
+"\u028F" => "Y"
+
+# áº  [LATIN CAPITAL LETTER Y WITH DOT ABOVE]
+"\u1E8E" => "Y"
+
+# á»²  [LATIN CAPITAL LETTER Y WITH GRAVE]
+"\u1EF2" => "Y"
+
+# á»Ž  [LATIN CAPITAL LETTER Y WITH DOT BELOW]
+"\u1EF4" => "Y"
+
+# á»¶  [LATIN CAPITAL LETTER Y WITH HOOK ABOVE]
+"\u1EF6" => "Y"
+
+# á»ž  [LATIN CAPITAL LETTER Y WITH TILDE]
+"\u1EF8" => "Y"
+
+# á»Ÿ  [LATIN CAPITAL LETTER Y WITH LOOP]
+"\u1EFE" => "Y"
+
+# â  [CIRCLED LATIN CAPITAL LETTER Y]
+"\u24CE" => "Y"
+
+# ïŒ¹  [FULLWIDTH LATIN CAPITAL LETTER Y]
+"\uFF39" => "Y"
+
+# Ãœ  [LATIN SMALL LETTER Y WITH ACUTE]
+"\u00FD" => "y"
+
+# Ã¿  [LATIN SMALL LETTER Y WITH DIAERESIS]
+"\u00FF" => "y"
+
+# Å·  [LATIN SMALL LETTER Y WITH CIRCUMFLEX]
+"\u0177" => "y"
+
+# ÆŽ  [LATIN SMALL LETTER Y WITH HOOK]
+"\u01B4" => "y"
+
+# È³  [LATIN SMALL LETTER Y WITH MACRON]
+"\u0233" => "y"
+
+# É  [LATIN SMALL LETTER Y WITH STROKE]
+"\u024F" => "y"
+
+# Ê  [LATIN SMALL LETTER TURNED Y]
+"\u028E" => "y"
+
+# áº  [LATIN SMALL LETTER Y WITH DOT ABOVE]
+"\u1E8F" => "y"
+
+# áº  [LATIN SMALL LETTER Y WITH RING ABOVE]
+"\u1E99" => "y"
+
+# á»³  [LATIN SMALL LETTER Y WITH GRAVE]
+"\u1EF3" => "y"
+
+# á»µ  [LATIN SMALL LETTER Y WITH DOT BELOW]
+"\u1EF5" => "y"
+
+# á»·  [LATIN SMALL LETTER Y WITH HOOK ABOVE]
+"\u1EF7" => "y"
+
+# á»¹  [LATIN SMALL LETTER Y WITH TILDE]
+"\u1EF9" => "y"
+
+# á»¿  [LATIN SMALL LETTER Y WITH LOOP]
+"\u1EFF" => "y"
+
+# âš  [CIRCLED LATIN SMALL LETTER Y]
+"\u24E8" => "y"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER Y]
+"\uFF59" => "y"
+
+# âŽ  [PARENTHESIZED LATIN SMALL LETTER Y]
+"\u24B4" => "(y)"
+
+# Å¹  [LATIN CAPITAL LETTER Z WITH ACUTE]
+"\u0179" => "Z"
+
+# Å»  [LATIN CAPITAL LETTER Z WITH DOT ABOVE]
+"\u017B" => "Z"
+
+# Åœ  [LATIN CAPITAL LETTER Z WITH CARON]
+"\u017D" => "Z"
+
+# Æµ  [LATIN CAPITAL LETTER Z WITH STROKE]
+"\u01B5" => "Z"
+
+# È  http://en.wikipedia.org/wiki/Yogh  [LATIN CAPITAL LETTER YOGH]
+"\u021C" => "Z"
+
+# È€  [LATIN CAPITAL LETTER Z WITH HOOK]
+"\u0224" => "Z"
+
+# áŽ¢  [LATIN LETTER SMALL CAPITAL Z]
+"\u1D22" => "Z"
+
+# áº  [LATIN CAPITAL LETTER Z WITH CIRCUMFLEX]
+"\u1E90" => "Z"
+
+# áº  [LATIN CAPITAL LETTER Z WITH DOT BELOW]
+"\u1E92" => "Z"
+
+# áº  [LATIN CAPITAL LETTER Z WITH LINE BELOW]
+"\u1E94" => "Z"
+
+# â  [CIRCLED LATIN CAPITAL LETTER Z]
+"\u24CF" => "Z"
+
+# â±«  [LATIN CAPITAL LETTER Z WITH DESCENDER]
+"\u2C6B" => "Z"
+
+# ê¢  [LATIN CAPITAL LETTER VISIGOTHIC Z]
+"\uA762" => "Z"
+
+# ïŒº  [FULLWIDTH LATIN CAPITAL LETTER Z]
+"\uFF3A" => "Z"
+
+# Åº  [LATIN SMALL LETTER Z WITH ACUTE]
+"\u017A" => "z"
+
+# ÅŒ  [LATIN SMALL LETTER Z WITH DOT ABOVE]
+"\u017C" => "z"
+
+# ÅŸ  [LATIN SMALL LETTER Z WITH CARON]
+"\u017E" => "z"
+
+# Æ¶  [LATIN SMALL LETTER Z WITH STROKE]
+"\u01B6" => "z"
+
+# È  http://en.wikipedia.org/wiki/Yogh  [LATIN SMALL LETTER YOGH]
+"\u021D" => "z"
+
+# È¥  [LATIN SMALL LETTER Z WITH HOOK]
+"\u0225" => "z"
+
+# É  [LATIN SMALL LETTER Z WITH SWASH TAIL]
+"\u0240" => "z"
+
+# Ê  [LATIN SMALL LETTER Z WITH RETROFLEX HOOK]
+"\u0290" => "z"
+
+# Ê  [LATIN SMALL LETTER Z WITH CURL]
+"\u0291" => "z"
+
+# áµ¶  [LATIN SMALL LETTER Z WITH MIDDLE TILDE]
+"\u1D76" => "z"
+
+# á¶  [LATIN SMALL LETTER Z WITH PALATAL HOOK]
+"\u1D8E" => "z"
+
+# áº  [LATIN SMALL LETTER Z WITH CIRCUMFLEX]
+"\u1E91" => "z"
+
+# áº  [LATIN SMALL LETTER Z WITH DOT BELOW]
+"\u1E93" => "z"
+
+# áº  [LATIN SMALL LETTER Z WITH LINE BELOW]
+"\u1E95" => "z"
+
+# â©  [CIRCLED LATIN SMALL LETTER Z]
+"\u24E9" => "z"
+
+# â±¬  [LATIN SMALL LETTER Z WITH DESCENDER]
+"\u2C6C" => "z"
+
+# ê£  [LATIN SMALL LETTER VISIGOTHIC Z]
+"\uA763" => "z"
+
+# ïœ  [FULLWIDTH LATIN SMALL LETTER Z]
+"\uFF5A" => "z"
+
+# âµ  [PARENTHESIZED LATIN SMALL LETTER Z]
+"\u24B5" => "(z)"
+
+# â°  [SUPERSCRIPT ZERO]
+"\u2070" => "0"
+
+# â  [SUBSCRIPT ZERO]
+"\u2080" => "0"
+
+# âª  [CIRCLED DIGIT ZERO]
+"\u24EA" => "0"
+
+# â¿  [NEGATIVE CIRCLED DIGIT ZERO]
+"\u24FF" => "0"
+
+# ïŒ  [FULLWIDTH DIGIT ZERO]
+"\uFF10" => "0"
+
+# Â¹  [SUPERSCRIPT ONE]
+"\u00B9" => "1"
+
+# â  [SUBSCRIPT ONE]
+"\u2081" => "1"
+
+# â   [CIRCLED DIGIT ONE]
+"\u2460" => "1"
+
+# âµ  [DOUBLE CIRCLED DIGIT ONE]
+"\u24F5" => "1"
+
+# â¶  [DINGBAT NEGATIVE CIRCLED DIGIT ONE]
+"\u2776" => "1"
+
+# â  [DINGBAT CIRCLED SANS-SERIF DIGIT ONE]
+"\u2780" => "1"
+
+# â  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE]
+"\u278A" => "1"
+
+# ïŒ  [FULLWIDTH DIGIT ONE]
+"\uFF11" => "1"
+
+# â  [DIGIT ONE FULL STOP]
+"\u2488" => "1."
+
+# âŽ  [PARENTHESIZED DIGIT ONE]
+"\u2474" => "(1)"
+
+# Â²  [SUPERSCRIPT TWO]
+"\u00B2" => "2"
+
+# â  [SUBSCRIPT TWO]
+"\u2082" => "2"
+
+# â¡  [CIRCLED DIGIT TWO]
+"\u2461" => "2"
+
+# â¶  [DOUBLE CIRCLED DIGIT TWO]
+"\u24F6" => "2"
+
+# â·  [DINGBAT NEGATIVE CIRCLED DIGIT TWO]
+"\u2777" => "2"
+
+# â  [DINGBAT CIRCLED SANS-SERIF DIGIT TWO]
+"\u2781" => "2"
+
+# â  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO]
+"\u278B" => "2"
+
+# ïŒ  [FULLWIDTH DIGIT TWO]
+"\uFF12" => "2"
+
+# â  [DIGIT TWO FULL STOP]
+"\u2489" => "2."
+
+# âµ  [PARENTHESIZED DIGIT TWO]
+"\u2475" => "(2)"
+
+# Â³  [SUPERSCRIPT THREE]
+"\u00B3" => "3"
+
+# â  [SUBSCRIPT THREE]
+"\u2083" => "3"
+
+# â¢  [CIRCLED DIGIT THREE]
+"\u2462" => "3"
+
+# â·  [DOUBLE CIRCLED DIGIT THREE]
+"\u24F7" => "3"
+
+# âž  [DINGBAT NEGATIVE CIRCLED DIGIT THREE]
+"\u2778" => "3"
+
+# â  [DINGBAT CIRCLED SANS-SERIF DIGIT THREE]
+"\u2782" => "3"
+
+# â  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE]
+"\u278C" => "3"
+
+# ïŒ  [FULLWIDTH DIGIT THREE]
+"\uFF13" => "3"
+
+# â  [DIGIT THREE FULL STOP]
+"\u248A" => "3."
+
+# â¶  [PARENTHESIZED DIGIT THREE]
+"\u2476" => "(3)"
+
+# âŽ  [SUPERSCRIPT FOUR]
+"\u2074" => "4"
+
+# â  [SUBSCRIPT FOUR]
+"\u2084" => "4"
+
+# â£  [CIRCLED DIGIT FOUR]
+"\u2463" => "4"
+
+# âž  [DOUBLE CIRCLED DIGIT FOUR]
+"\u24F8" => "4"
+
+# â¹  [DINGBAT NEGATIVE CIRCLED DIGIT FOUR]
+"\u2779" => "4"
+
+# â  [DINGBAT CIRCLED SANS-SERIF DIGIT FOUR]
+"\u2783" => "4"
+
+# â  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR]
+"\u278D" => "4"
+
+# ïŒ  [FULLWIDTH DIGIT FOUR]
+"\uFF14" => "4"
+
+# â  [DIGIT FOUR FULL STOP]
+"\u248B" => "4."
+
+# â·  [PARENTHESIZED DIGIT FOUR]
+"\u2477" => "(4)"
+
+# âµ  [SUPERSCRIPT FIVE]
+"\u2075" => "5"
+
+# â
+  [SUBSCRIPT FIVE]
+"\u2085" => "5"
+
+# â€  [CIRCLED DIGIT FIVE]
+"\u2464" => "5"
+
+# â¹  [DOUBLE CIRCLED DIGIT FIVE]
+"\u24F9" => "5"
+
+# âº  [DINGBAT NEGATIVE CIRCLED DIGIT FIVE]
+"\u277A" => "5"
+
+# â  [DINGBAT CIRCLED SANS-SERIF DIGIT FIVE]
+"\u2784" => "5"
+
+# â  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE]
+"\u278E" => "5"
+
+# ïŒ  [FULLWIDTH DIGIT FIVE]
+"\uFF15" => "5"
+
+# â  [DIGIT FIVE FULL STOP]
+"\u248C" => "5."
+
+# âž  [PARENTHESIZED DIGIT FIVE]
+"\u2478" => "(5)"
+
+# â¶  [SUPERSCRIPT SIX]
+"\u2076" => "6"
+
+# â  [SUBSCRIPT SIX]
+"\u2086" => "6"
+
+# â¥  [CIRCLED DIGIT SIX]
+"\u2465" => "6"
+
+# âº  [DOUBLE CIRCLED DIGIT SIX]
+"\u24FA" => "6"
+
+# â»  [DINGBAT NEGATIVE CIRCLED DIGIT SIX]
+"\u277B" => "6"
+
+# â
+  [DINGBAT CIRCLED SANS-SERIF DIGIT SIX]
+"\u2785" => "6"
+
+# â  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX]
+"\u278F" => "6"
+
+# ïŒ  [FULLWIDTH DIGIT SIX]
+"\uFF16" => "6"
+
+# â  [DIGIT SIX FULL STOP]
+"\u248D" => "6."
+
+# â¹  [PARENTHESIZED DIGIT SIX]
+"\u2479" => "(6)"
+
+# â·  [SUPERSCRIPT SEVEN]
+"\u2077" => "7"
+
+# â  [SUBSCRIPT SEVEN]
+"\u2087" => "7"
+
+# âŠ  [CIRCLED DIGIT SEVEN]
+"\u2466" => "7"
+
+# â»  [DOUBLE CIRCLED DIGIT SEVEN]
+"\u24FB" => "7"
+
+# âŒ  [DINGBAT NEGATIVE CIRCLED DIGIT SEVEN]
+"\u277C" => "7"
+
+# â  [DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN]
+"\u2786" => "7"
+
+# â  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN]
+"\u2790" => "7"
+
+# ïŒ  [FULLWIDTH DIGIT SEVEN]
+"\uFF17" => "7"
+
+# â  [DIGIT SEVEN FULL STOP]
+"\u248E" => "7."
+
+# âº  [PARENTHESIZED DIGIT SEVEN]
+"\u247A" => "(7)"
+
+# âž  [SUPERSCRIPT EIGHT]
+"\u2078" => "8"
+
+# â  [SUBSCRIPT EIGHT]
+"\u2088" => "8"
+
+# â§  [CIRCLED DIGIT EIGHT]
+"\u2467" => "8"
+
+# âŒ  [DOUBLE CIRCLED DIGIT EIGHT]
+"\u24FC" => "8"
+
+# âœ  [DINGBAT NEGATIVE CIRCLED DIGIT EIGHT]
+"\u277D" => "8"
+
+# â  [DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT]
+"\u2787" => "8"
+
+# â  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT]
+"\u2791" => "8"
+
+# ïŒ  [FULLWIDTH DIGIT EIGHT]
+"\uFF18" => "8"
+
+# â  [DIGIT EIGHT FULL STOP]
+"\u248F" => "8."
+
+# â»  [PARENTHESIZED DIGIT EIGHT]
+"\u247B" => "(8)"
+
+# â¹  [SUPERSCRIPT NINE]
+"\u2079" => "9"
+
+# â  [SUBSCRIPT NINE]
+"\u2089" => "9"
+
+# âš  [CIRCLED DIGIT NINE]
+"\u2468" => "9"
+
+# âœ  [DOUBLE CIRCLED DIGIT NINE]
+"\u24FD" => "9"
+
+# âŸ  [DINGBAT NEGATIVE CIRCLED DIGIT NINE]
+"\u277E" => "9"
+
+# â  [DINGBAT CIRCLED SANS-SERIF DIGIT NINE]
+"\u2788" => "9"
+
+# â  [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE]
+"\u2792" => "9"
+
+# ïŒ  [FULLWIDTH DIGIT NINE]
+"\uFF19" => "9"
+
+# â  [DIGIT NINE FULL STOP]
+"\u2490" => "9."
+
+# âŒ  [PARENTHESIZED DIGIT NINE]
+"\u247C" => "(9)"
+
+# â©  [CIRCLED NUMBER TEN]
+"\u2469" => "10"
+
+# âŸ  [DOUBLE CIRCLED NUMBER TEN]
+"\u24FE" => "10"
+
+# â¿  [DINGBAT NEGATIVE CIRCLED NUMBER TEN]
+"\u277F" => "10"
+
+# â  [DINGBAT CIRCLED SANS-SERIF NUMBER TEN]
+"\u2789" => "10"
+
+# â  [DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN]
+"\u2793" => "10"
+
+# â  [NUMBER TEN FULL STOP]
+"\u2491" => "10."
+
+# âœ  [PARENTHESIZED NUMBER TEN]
+"\u247D" => "(10)"
+
+# âª  [CIRCLED NUMBER ELEVEN]
+"\u246A" => "11"
+
+# â«  [NEGATIVE CIRCLED NUMBER ELEVEN]
+"\u24EB" => "11"
+
+# â  [NUMBER ELEVEN FULL STOP]
+"\u2492" => "11."
+
+# âŸ  [PARENTHESIZED NUMBER ELEVEN]
+"\u247E" => "(11)"
+
+# â«  [CIRCLED NUMBER TWELVE]
+"\u246B" => "12"
+
+# â¬  [NEGATIVE CIRCLED NUMBER TWELVE]
+"\u24EC" => "12"
+
+# â  [NUMBER TWELVE FULL STOP]
+"\u2493" => "12."
+
+# â¿  [PARENTHESIZED NUMBER TWELVE]
+"\u247F" => "(12)"
+
+# â¬  [CIRCLED NUMBER THIRTEEN]
+"\u246C" => "13"
+
+# â­  [NEGATIVE CIRCLED NUMBER THIRTEEN]
+"\u24ED" => "13"
+
+# â  [NUMBER THIRTEEN FULL STOP]
+"\u2494" => "13."
+
+# â  [PARENTHESIZED NUMBER THIRTEEN]
+"\u2480" => "(13)"
+
+# â­  [CIRCLED NUMBER FOURTEEN]
+"\u246D" => "14"
+
+# â®  [NEGATIVE CIRCLED NUMBER FOURTEEN]
+"\u24EE" => "14"
+
+# â  [NUMBER FOURTEEN FULL STOP]
+"\u2495" => "14."
+
+# â  [PARENTHESIZED NUMBER FOURTEEN]
+"\u2481" => "(14)"
+
+# â®  [CIRCLED NUMBER FIFTEEN]
+"\u246E" => "15"
+
+# â¯  [NEGATIVE CIRCLED NUMBER FIFTEEN]
+"\u24EF" => "15"
+
+# â  [NUMBER FIFTEEN FULL STOP]
+"\u2496" => "15."
+
+# â  [PARENTHESIZED NUMBER FIFTEEN]
+"\u2482" => "(15)"
+
+# â¯  [CIRCLED NUMBER SIXTEEN]
+"\u246F" => "16"
+
+# â°  [NEGATIVE CIRCLED NUMBER SIXTEEN]
+"\u24F0" => "16"
+
+# â  [NUMBER SIXTEEN FULL STOP]
+"\u2497" => "16."
+
+# â  [PARENTHESIZED NUMBER SIXTEEN]
+"\u2483" => "(16)"
+
+# â°  [CIRCLED NUMBER SEVENTEEN]
+"\u2470" => "17"
+
+# â±  [NEGATIVE CIRCLED NUMBER SEVENTEEN]
+"\u24F1" => "17"
+
+# â  [NUMBER SEVENTEEN FULL STOP]
+"\u2498" => "17."
+
+# â  [PARENTHESIZED NUMBER SEVENTEEN]
+"\u2484" => "(17)"
+
+# â±  [CIRCLED NUMBER EIGHTEEN]
+"\u2471" => "18"
+
+# â²  [NEGATIVE CIRCLED NUMBER EIGHTEEN]
+"\u24F2" => "18"
+
+# â  [NUMBER EIGHTEEN FULL STOP]
+"\u2499" => "18."
+
+# â
+  [PARENTHESIZED NUMBER EIGHTEEN]
+"\u2485" => "(18)"
+
+# â²  [CIRCLED NUMBER NINETEEN]
+"\u2472" => "19"
+
+# â³  [NEGATIVE CIRCLED NUMBER NINETEEN]
+"\u24F3" => "19"
+
+# â  [NUMBER NINETEEN FULL STOP]
+"\u249A" => "19."
+
+# â  [PARENTHESIZED NUMBER NINETEEN]
+"\u2486" => "(19)"
+
+# â³  [CIRCLED NUMBER TWENTY]
+"\u2473" => "20"
+
+# âŽ  [NEGATIVE CIRCLED NUMBER TWENTY]
+"\u24F4" => "20"
+
+# â  [NUMBER TWENTY FULL STOP]
+"\u249B" => "20."
+
+# â  [PARENTHESIZED NUMBER TWENTY]
+"\u2487" => "(20)"
+
+# Â«  [LEFT-POINTING DOUBLE ANGLE QUOTATION MARK]
+"\u00AB" => "\""
+
+# Â»  [RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK]
+"\u00BB" => "\""
+
+# â  [LEFT DOUBLE QUOTATION MARK]
+"\u201C" => "\""
+
+# â  [RIGHT DOUBLE QUOTATION MARK]
+"\u201D" => "\""
+
+# â  [DOUBLE LOW-9 QUOTATION MARK]
+"\u201E" => "\""
+
+# â³  [DOUBLE PRIME]
+"\u2033" => "\""
+
+# â¶  [REVERSED DOUBLE PRIME]
+"\u2036" => "\""
+
+# â  [HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT]
+"\u275D" => "\""
+
+# â  [HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT]
+"\u275E" => "\""
+
+# â®  [HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT]
+"\u276E" => "\""
+
+# â¯  [HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT]
+"\u276F" => "\""
+
+# ïŒ  [FULLWIDTH QUOTATION MARK]
+"\uFF02" => "\""
+
+# â  [LEFT SINGLE QUOTATION MARK]
+"\u2018" => "\'"
+
+# â  [RIGHT SINGLE QUOTATION MARK]
+"\u2019" => "\'"
+
+# â  [SINGLE LOW-9 QUOTATION MARK]
+"\u201A" => "\'"
+
+# â  [SINGLE HIGH-REVERSED-9 QUOTATION MARK]
+"\u201B" => "\'"
+
+# â²  [PRIME]
+"\u2032" => "\'"
+
+# âµ  [REVERSED PRIME]
+"\u2035" => "\'"
+
+# â¹  [SINGLE LEFT-POINTING ANGLE QUOTATION MARK]
+"\u2039" => "\'"
+
+# âº  [SINGLE RIGHT-POINTING ANGLE QUOTATION MARK]
+"\u203A" => "\'"
+
+# â  [HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT]
+"\u275B" => "\'"
+
+# â  [HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT]
+"\u275C" => "\'"
+
+# ïŒ  [FULLWIDTH APOSTROPHE]
+"\uFF07" => "\'"
+
+# â  [HYPHEN]
+"\u2010" => "-"
+
+# â  [NON-BREAKING HYPHEN]
+"\u2011" => "-"
+
+# â  [FIGURE DASH]
+"\u2012" => "-"
+
+# â  [EN DASH]
+"\u2013" => "-"
+
+# â  [EM DASH]
+"\u2014" => "-"
+
+# â»  [SUPERSCRIPT MINUS]
+"\u207B" => "-"
+
+# â  [SUBSCRIPT MINUS]
+"\u208B" => "-"
+
+# ïŒ  [FULLWIDTH HYPHEN-MINUS]
+"\uFF0D" => "-"
+
+# â
+  [LEFT SQUARE BRACKET WITH QUILL]
+"\u2045" => "["
+
+# â²  [LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT]
+"\u2772" => "["
+
+# ïŒ»  [FULLWIDTH LEFT SQUARE BRACKET]
+"\uFF3B" => "["
+
+# â  [RIGHT SQUARE BRACKET WITH QUILL]
+"\u2046" => "]"
+
+# â³  [LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT]
+"\u2773" => "]"
+
+# ïŒœ  [FULLWIDTH RIGHT SQUARE BRACKET]
+"\uFF3D" => "]"
+
+# âœ  [SUPERSCRIPT LEFT PARENTHESIS]
+"\u207D" => "("
+
+# â  [SUBSCRIPT LEFT PARENTHESIS]
+"\u208D" => "("
+
+# âš  [MEDIUM LEFT PARENTHESIS ORNAMENT]
+"\u2768" => "("
+
+# âª  [MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT]
+"\u276A" => "("
+
+# ïŒ  [FULLWIDTH LEFT PARENTHESIS]
+"\uFF08" => "("
+
+# âžš  [LEFT DOUBLE PARENTHESIS]
+"\u2E28" => "(("
+
+# âŸ  [SUPERSCRIPT RIGHT PARENTHESIS]
+"\u207E" => ")"
+
+# â  [SUBSCRIPT RIGHT PARENTHESIS]
+"\u208E" => ")"
+
+# â©  [MEDIUM RIGHT PARENTHESIS ORNAMENT]
+"\u2769" => ")"
+
+# â«  [MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT]
+"\u276B" => ")"
+
+# ïŒ  [FULLWIDTH RIGHT PARENTHESIS]
+"\uFF09" => ")"
+
+# âž©  [RIGHT DOUBLE PARENTHESIS]
+"\u2E29" => "))"
+
+# â¬  [MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT]
+"\u276C" => "<"
+
+# â°  [HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT]
+"\u2770" => "<"
+
+# ïŒ  [FULLWIDTH LESS-THAN SIGN]
+"\uFF1C" => "<"
+
+# â­  [MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT]
+"\u276D" => ">"
+
+# â±  [HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT]
+"\u2771" => ">"
+
+# ïŒ  [FULLWIDTH GREATER-THAN SIGN]
+"\uFF1E" => ">"
+
+# âŽ  [MEDIUM LEFT CURLY BRACKET ORNAMENT]
+"\u2774" => "{"
+
+# ïœ  [FULLWIDTH LEFT CURLY BRACKET]
+"\uFF5B" => "{"
+
+# âµ  [MEDIUM RIGHT CURLY BRACKET ORNAMENT]
+"\u2775" => "}"
+
+# ïœ  [FULLWIDTH RIGHT CURLY BRACKET]
+"\uFF5D" => "}"
+
+# âº  [SUPERSCRIPT PLUS SIGN]
+"\u207A" => "+"
+
+# â  [SUBSCRIPT PLUS SIGN]
+"\u208A" => "+"
+
+# ïŒ  [FULLWIDTH PLUS SIGN]
+"\uFF0B" => "+"
+
+# âŒ  [SUPERSCRIPT EQUALS SIGN]
+"\u207C" => "="
+
+# â  [SUBSCRIPT EQUALS SIGN]
+"\u208C" => "="
+
+# ïŒ  [FULLWIDTH EQUALS SIGN]
+"\uFF1D" => "="
+
+# ïŒ  [FULLWIDTH EXCLAMATION MARK]
+"\uFF01" => "!"
+
+# âŒ  [DOUBLE EXCLAMATION MARK]
+"\u203C" => "!!"
+
+# â  [EXCLAMATION QUESTION MARK]
+"\u2049" => "!?"
+
+# ïŒ  [FULLWIDTH NUMBER SIGN]
+"\uFF03" => "#"
+
+# ïŒ  [FULLWIDTH DOLLAR SIGN]
+"\uFF04" => "$"
+
+# â  [COMMERCIAL MINUS SIGN]
+"\u2052" => "%"
+
+# ïŒ
+  [FULLWIDTH PERCENT SIGN]
+"\uFF05" => "%"
+
+# ïŒ  [FULLWIDTH AMPERSAND]
+"\uFF06" => "&"
+
+# â  [LOW ASTERISK]
+"\u204E" => "*"
+
+# ïŒ  [FULLWIDTH ASTERISK]
+"\uFF0A" => "*"
+
+# ïŒ  [FULLWIDTH COMMA]
+"\uFF0C" => ","
+
+# ïŒ  [FULLWIDTH FULL STOP]
+"\uFF0E" => "."
+
+# â  [FRACTION SLASH]
+"\u2044" => "/"
+
+# ïŒ  [FULLWIDTH SOLIDUS]
+"\uFF0F" => "/"
+
+# ïŒ  [FULLWIDTH COLON]
+"\uFF1A" => ":"
+
+# â  [REVERSED SEMICOLON]
+"\u204F" => ";"
+
+# ïŒ  [FULLWIDTH SEMICOLON]
+"\uFF1B" => ";"
+
+# ïŒ  [FULLWIDTH QUESTION MARK]
+"\uFF1F" => "?"
+
+# â  [DOUBLE QUESTION MARK]
+"\u2047" => "??"
+
+# â  [QUESTION EXCLAMATION MARK]
+"\u2048" => "?!"
+
+# ïŒ   [FULLWIDTH COMMERCIAL AT]
+"\uFF20" => "@"
+
+# ïŒŒ  [FULLWIDTH REVERSE SOLIDUS]
+"\uFF3C" => "\\"
+
+# âž  [CARET]
+"\u2038" => "^"
+
+# ïŒŸ  [FULLWIDTH CIRCUMFLEX ACCENT]
+"\uFF3E" => "^"
+
+# ïŒ¿  [FULLWIDTH LOW LINE]
+"\uFF3F" => "_"
+
+# â  [SWUNG DASH]
+"\u2053" => "~"
+
+# ïœ  [FULLWIDTH TILDE]
+"\uFF5E" => "~"
+
+################################################################
+# Below is the Perl script used to generate the above mappings #
+# from ASCIIFoldingFilter.java:                                #
+################################################################
+#
+# #!/usr/bin/perl
+#
+# use warnings;
+# use strict;
+# 
+# my @source_chars = ();
+# my @source_char_descriptions = ();
+# my $target = '';
+# 
+# while (<>) {
+#   if (/case\s+'(\\u[A-F0-9]+)':\s*\/\/\s*(.*)/i) {
+#     push @source_chars, $1;
+#	  push @source_char_descriptions, $2;
+#	  next;
+#   }
+#   if (/output\[[^\]]+\]\s*=\s*'(\\'|\\\\|.)'/) {
+#     $target .= $1;
+#     next;
+#   }
+#   if (/break;/) {
+#     $target = "\\\"" if ($target eq '"');
+#     for my $source_char_num (0..$#source_chars) {
+#	    print "# $source_char_descriptions[$source_char_num]\n";
+#	    print "\"$source_chars[$source_char_num]\" => \"$target\"\n\n";
+#	  }
+#	  @source_chars = ();
+#	  @source_char_descriptions = ();
+#	  $target = '';
+#   }
+# }
Index: gs3-extensions/solr/trunk/src/etc/conf/mapping-ISOLatin1Accent.txt
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/mapping-ISOLatin1Accent.txt	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/mapping-ISOLatin1Accent.txt	(revision 24446)
@@ -0,0 +1,248 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Syntax:
+#   "source" => "target"
+#     "source".length() > 0 (source cannot be empty.)
+#     "target".length() >= 0 (target can be empty.)
+
+# example:
+#   "Ã" => "A"
+#   "\u00C0" => "A"
+#   "\u00C0" => "\u0041"
+#   "Ã" => "ss"
+#   "\t" => " "
+#   "\n" => ""
+
+# Ã => A
+"\u00C0" => "A"
+
+# Ã => A
+"\u00C1" => "A"
+
+# Ã => A
+"\u00C2" => "A"
+
+# Ã => A
+"\u00C3" => "A"
+
+# Ã => A
+"\u00C4" => "A"
+
+# Ã
+ => A
+"\u00C5" => "A"
+
+# Ã => AE
+"\u00C6" => "AE"
+
+# Ã => C
+"\u00C7" => "C"
+
+# Ã => E
+"\u00C8" => "E"
+
+# Ã => E
+"\u00C9" => "E"
+
+# Ã => E
+"\u00CA" => "E"
+
+# Ã => E
+"\u00CB" => "E"
+
+# Ã => I
+"\u00CC" => "I"
+
+# Ã => I
+"\u00CD" => "I"
+
+# Ã => I
+"\u00CE" => "I"
+
+# Ã => I
+"\u00CF" => "I"
+
+# Ä² => IJ
+"\u0132" => "IJ"
+
+# Ã => D
+"\u00D0" => "D"
+
+# Ã => N
+"\u00D1" => "N"
+
+# Ã => O
+"\u00D2" => "O"
+
+# Ã => O
+"\u00D3" => "O"
+
+# Ã => O
+"\u00D4" => "O"
+
+# Ã => O
+"\u00D5" => "O"
+
+# Ã => O
+"\u00D6" => "O"
+
+# Ã => O
+"\u00D8" => "O"
+
+# Å => OE
+"\u0152" => "OE"
+
+# Ã
+"\u00DE" => "TH"
+
+# Ã => U
+"\u00D9" => "U"
+
+# Ã => U
+"\u00DA" => "U"
+
+# Ã => U
+"\u00DB" => "U"
+
+# Ã => U
+"\u00DC" => "U"
+
+# Ã => Y
+"\u00DD" => "Y"
+
+# Åž => Y
+"\u0178" => "Y"
+
+# Ã  => a
+"\u00E0" => "a"
+
+# Ã¡ => a
+"\u00E1" => "a"
+
+# Ã¢ => a
+"\u00E2" => "a"
+
+# Ã£ => a
+"\u00E3" => "a"
+
+# Ã€ => a
+"\u00E4" => "a"
+
+# Ã¥ => a
+"\u00E5" => "a"
+
+# ÃŠ => ae
+"\u00E6" => "ae"
+
+# Ã§ => c
+"\u00E7" => "c"
+
+# Ãš => e
+"\u00E8" => "e"
+
+# Ã© => e
+"\u00E9" => "e"
+
+# Ãª => e
+"\u00EA" => "e"
+
+# Ã« => e
+"\u00EB" => "e"
+
+# Ã¬ => i
+"\u00EC" => "i"
+
+# Ã­ => i
+"\u00ED" => "i"
+
+# Ã® => i
+"\u00EE" => "i"
+
+# Ã¯ => i
+"\u00EF" => "i"
+
+# Ä³ => ij
+"\u0133" => "ij"
+
+# Ã° => d
+"\u00F0" => "d"
+
+# Ã± => n
+"\u00F1" => "n"
+
+# Ã² => o
+"\u00F2" => "o"
+
+# Ã³ => o
+"\u00F3" => "o"
+
+# ÃŽ => o
+"\u00F4" => "o"
+
+# Ãµ => o
+"\u00F5" => "o"
+
+# Ã¶ => o
+"\u00F6" => "o"
+
+# Ãž => o
+"\u00F8" => "o"
+
+# Å => oe
+"\u0153" => "oe"
+
+# Ã => ss
+"\u00DF" => "ss"
+
+# ÃŸ => th
+"\u00FE" => "th"
+
+# Ã¹ => u
+"\u00F9" => "u"
+
+# Ãº => u
+"\u00FA" => "u"
+
+# Ã» => u
+"\u00FB" => "u"
+
+# ÃŒ => u
+"\u00FC" => "u"
+
+# Ãœ => y
+"\u00FD" => "y"
+
+# Ã¿ => y
+"\u00FF" => "y"
+
+# ï¬ => ff
+"\uFB00" => "ff"
+
+# ï¬ => fi
+"\uFB01" => "fi"
+
+# ï¬ => fl
+"\uFB02" => "fl"
+
+# ï¬ => ffi
+"\uFB03" => "ffi"
+
+# ï¬ => ffl
+"\uFB04" => "ffl"
+
+# ï¬
+ => ft
+"\uFB05" => "ft"
+
+# ï¬ => st
+"\uFB06" => "st"
Index: gs3-extensions/solr/trunk/src/etc/conf/protwords.txt
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/protwords.txt	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/protwords.txt	(revision 24446)
@@ -0,0 +1,21 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#-----------------------------------------------------------------------
+# Use a protected word file to protect against the stemmer reducing two
+# unrelated words to the same base word.
+
+# Some non-words that normally won't be encountered,
+# just to test that they won't be stemmed.
+dontstems
+zwhacky
+
Index: gs3-extensions/solr/trunk/src/etc/conf/protwords.txt.in
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/protwords.txt.in	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/protwords.txt.in	(revision 24446)
@@ -0,0 +1,21 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#-----------------------------------------------------------------------
+# Use a protected word file to protect against the stemmer reducing two
+# unrelated words to the same base word.
+
+# Some non-words that normally won't be encountered,
+# just to test that they won't be stemmed.
+dontstems
+zwhacky
+
Index: gs3-extensions/solr/trunk/src/etc/conf/schema.xml
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/schema.xml	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/schema.xml	(revision 24446)
@@ -0,0 +1,649 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!--  
+ This is the Solr schema file. This file should be named "schema.xml" and
+ should be in the conf directory under the solr home
+ (i.e. ./solr/conf/schema.xml by default) 
+ or located where the classloader for the Solr webapp can find it.
+
+ This example schema is the recommended starting point for users.
+ It should be kept correct and concise, usable out-of-the-box.
+
+ For more information, on how to customize this file, please see
+ http://wiki.apache.org/solr/SchemaXml
+
+ PERFORMANCE NOTE: this schema includes many optional features and should not
+ be used for benchmarking.  To improve performance one could
+  - set stored="false" for all fields possible (esp large fields) when you
+    only need to search on the field but don't need to return the original
+    value.
+  - set indexed="false" if you don't need to search on the field, but only
+    return the field as a result of searching on other indexed fields.
+  - remove all unneeded copyField statements
+  - for best index size and searching performance, set "index" to false
+    for all general text fields, use copyField to copy them to the
+    catchall "text" field, and use that for searching.
+  - For maximum indexing performance, use the StreamingUpdateSolrServer
+    java client.
+  - Remember to run the JVM in server mode, and use a higher logging level
+    that avoids logging every request
+-->
+
+<schema name="example" version="1.4">
+  <!-- attribute "name" is the name of this schema and is only used for display purposes.
+       Applications should change this to reflect the nature of the search collection.
+       version="1.4" is Solr's version number for the schema syntax and semantics.  It should
+       not normally be changed by applications.
+       1.0: multiValued attribute did not exist, all fields are multiValued by nature
+       1.1: multiValued attribute introduced, false by default 
+       1.2: omitTermFreqAndPositions attribute introduced, true by default except for text fields.
+       1.3: removed optional field compress feature
+       1.4: default auto-phrase (QueryParser feature) to off
+     -->
+
+  <types>
+    <!-- field type definitions. The "name" attribute is
+       just a label to be used by field definitions.  The "class"
+       attribute and any other attributes determine the real
+       behavior of the fieldType.
+         Class names starting with "solr" refer to java classes in the
+       org.apache.solr.analysis package.
+    -->
+
+    <!-- The StrField type is not analyzed, but indexed/stored verbatim. -->
+    <fieldType name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
+
+    <!-- boolean type: "true" or "false" -->
+    <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true" omitNorms="true"/>
+    <!--Binary data type. The data should be sent/retrieved in as Base64 encoded Strings -->
+    <fieldtype name="binary" class="solr.BinaryField"/>
+
+    <!-- The optional sortMissingLast and sortMissingFirst attributes are
+         currently supported on types that are sorted internally as strings.
+	       This includes "string","boolean","sint","slong","sfloat","sdouble","pdate"
+       - If sortMissingLast="true", then a sort on this field will cause documents
+         without the field to come after documents with the field,
+         regardless of the requested sort order (asc or desc).
+       - If sortMissingFirst="true", then a sort on this field will cause documents
+         without the field to come before documents with the field,
+         regardless of the requested sort order.
+       - If sortMissingLast="false" and sortMissingFirst="false" (the default),
+         then default lucene sorting will be used which places docs without the
+         field first in an ascending sort and last in a descending sort.
+    -->    
+
+    <!--
+      Default numeric field types. For faster range queries, consider the tint/tfloat/tlong/tdouble types.
+    -->
+    <fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+
+    <!--
+     Numeric field types that index each value at various levels of precision
+     to accelerate range queries when the number of values between the range
+     endpoints is large. See the javadoc for NumericRangeQuery for internal
+     implementation details.
+
+     Smaller precisionStep values (specified in bits) will lead to more tokens
+     indexed per value, slightly larger index size, and faster range queries.
+     A precisionStep of 0 disables indexing at different precision levels.
+    -->
+    <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
+
+    <!-- The format for this date field is of the form 1995-12-31T23:59:59Z, and
+         is a more restricted form of the canonical representation of dateTime
+         http://www.w3.org/TR/xmlschema-2/#dateTime    
+         The trailing "Z" designates UTC time and is mandatory.
+         Optional fractional seconds are allowed: 1995-12-31T23:59:59.999Z
+         All other components are mandatory.
+
+         Expressions can also be used to denote calculations that should be
+         performed relative to "NOW" to determine the value, ie...
+
+               NOW/HOUR
+                  ... Round to the start of the current hour
+               NOW-1DAY
+                  ... Exactly 1 day prior to now
+               NOW/DAY+6MONTHS+3DAYS
+                  ... 6 months and 3 days in the future from the start of
+                      the current day
+                      
+         Consult the DateField javadocs for more information.
+
+         Note: For faster range queries, consider the tdate type
+      -->
+    <fieldType name="date" class="solr.TrieDateField" omitNorms="true" precisionStep="0" positionIncrementGap="0"/>
+
+    <!-- A Trie based date field for faster date range queries and date faceting. -->
+    <fieldType name="tdate" class="solr.TrieDateField" omitNorms="true" precisionStep="6" positionIncrementGap="0"/>
+
+
+    <!--
+      Note:
+      These should only be used for compatibility with existing indexes (created with older Solr versions)
+      or if "sortMissingFirst" or "sortMissingLast" functionality is needed. Use Trie based fields instead.
+
+      Plain numeric field types that store and index the text
+      value verbatim (and hence don't support range queries, since the
+      lexicographic ordering isn't equal to the numeric ordering)
+    -->
+    <fieldType name="pint" class="solr.IntField" omitNorms="true"/>
+    <fieldType name="plong" class="solr.LongField" omitNorms="true"/>
+    <fieldType name="pfloat" class="solr.FloatField" omitNorms="true"/>
+    <fieldType name="pdouble" class="solr.DoubleField" omitNorms="true"/>
+    <fieldType name="pdate" class="solr.DateField" sortMissingLast="true" omitNorms="true"/>
+
+
+    <!--
+      Note:
+      These should only be used for compatibility with existing indexes (created with older Solr versions)
+      or if "sortMissingFirst" or "sortMissingLast" functionality is needed. Use Trie based fields instead.
+
+      Numeric field types that manipulate the value into
+      a string value that isn't human-readable in its internal form,
+      but with a lexicographic ordering the same as the numeric ordering,
+      so that range queries work correctly.
+    -->
+    <fieldType name="sint" class="solr.SortableIntField" sortMissingLast="true" omitNorms="true"/>
+    <fieldType name="slong" class="solr.SortableLongField" sortMissingLast="true" omitNorms="true"/>
+    <fieldType name="sfloat" class="solr.SortableFloatField" sortMissingLast="true" omitNorms="true"/>
+    <fieldType name="sdouble" class="solr.SortableDoubleField" sortMissingLast="true" omitNorms="true"/>
+
+
+    <!-- The "RandomSortField" is not used to store or search any
+         data.  You can declare fields of this type it in your schema
+         to generate pseudo-random orderings of your docs for sorting 
+         purposes.  The ordering is generated based on the field name 
+         and the version of the index, As long as the index version
+         remains unchanged, and the same field name is reused,
+         the ordering of the docs will be consistent.  
+         If you want different psuedo-random orderings of documents,
+         for the same version of the index, use a dynamicField and
+         change the name
+     -->
+    <fieldType name="random" class="solr.RandomSortField" indexed="true" />
+
+    <!-- solr.TextField allows the specification of custom text analyzers
+         specified as a tokenizer and a list of token filters. Different
+         analyzers may be specified for indexing and querying.
+
+         The optional positionIncrementGap puts space between multiple fields of
+         this type on the same document, with the purpose of preventing false phrase
+         matching across fields.
+
+         For more info on customizing your analyzer chain, please see
+         http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters
+     -->
+
+    <!-- One can also specify an existing Analyzer class that has a
+         default constructor via the class attribute on the analyzer element
+    <fieldType name="text_greek" class="solr.TextField">
+      <analyzer class="org.apache.lucene.analysis.el.GreekAnalyzer"/>
+    </fieldType>
+    -->
+
+    <!-- A text field that only splits on whitespace for exact matching of words -->
+    <fieldType name="text_ws" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A general text field that has reasonable, generic
+         cross-language defaults: it tokenizes with StandardTokenizer,
+	 removes stop words from case-insensitive "stopwords.txt"
+	 (empty by default), and down cases.  At query time only, it
+	 also applies synonyms. -->
+    <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        -->
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A text field with defaults appropriate for English: it
+         tokenizes with StandardTokenizer, removes English stop words
+         (stopwords_en.txt), down cases, protects words from protwords.txt, and
+         finally applies Porter's stemming.  The query time analyzer
+         also applies synonyms from synonyms.txt. -->
+    <fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        -->
+        <!-- Case insensitive stop word removal.
+          add enablePositionIncrements=true in both the index and query
+          analyzers to leave a 'gap' for more accurate phrase queries.
+        -->
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.LowerCaseFilterFactory"/>
+	<filter class="solr.EnglishPossessiveFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+	<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+	-->
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.LowerCaseFilterFactory"/>
+	<filter class="solr.EnglishPossessiveFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+	<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+	-->
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A text field with defaults appropriate for English, plus
+	 aggressive word-splitting and autophrase features enabled.
+	 This field is just like text_en, except it adds
+	 WordDelimiterFilter to enable splitting and matching of
+	 words on case-change, alpha numeric boundaries, and
+	 non-alphanumeric chars.  This means certain compound word
+	 cases will work, for example query "wi fi" will match
+	 document "WiFi" or "wi-fi".  However, other cases will still
+	 not match, for example if the query is "wifi" and the
+	 document is "wi fi" or if the query is "wi-fi" and the
+	 document is "wifi".
+        -->
+    <fieldType name="text_en_splitting" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
+      <analyzer type="index">
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        -->
+        <!-- Case insensitive stop word removal.
+          add enablePositionIncrements=true in both the index and query
+          analyzers to leave a 'gap' for more accurate phrase queries.
+        -->
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Less flexible matching, but less false matches.  Probably not ideal for product names,
+         but may be good for SKUs.  Can insert dashes in the wrong place and still match. -->
+    <fieldType name="text_en_splitting_tight" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="false"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords_en.txt"/>
+        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="0" generateNumberParts="0" catenateWords="1" catenateNumbers="1" catenateAll="0"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+        <!-- this filter can remove any duplicate tokens that appear at the same position - sometimes
+             possible with WordDelimiterFilter in conjuncton with stemming. -->
+        <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Just like text_general except it reverses the characters of
+	 each token, to enable more efficient leading wildcard queries. -->
+    <fieldType name="text_general_rev" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.ReversedWildcardFilterFactory" withOriginal="true"
+           maxPosAsterisk="3" maxPosQuestion="2" maxFractionAsterisk="0.33"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- charFilter + WhitespaceTokenizer  -->
+    <!--
+    <fieldType name="text_char_norm" class="solr.TextField" positionIncrementGap="100" >
+      <analyzer>
+        <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ISOLatin1Accent.txt"/>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+      </analyzer>
+    </fieldType>
+    -->
+
+    <!-- This is an example of using the KeywordTokenizer along
+         With various TokenFilterFactories to produce a sortable field
+         that does not include some properties of the source text
+      -->
+    <fieldType name="alphaOnlySort" class="solr.TextField" sortMissingLast="true" omitNorms="true">
+      <analyzer>
+        <!-- KeywordTokenizer does no actual tokenizing, so the entire
+             input string is preserved as a single token
+          -->
+        <tokenizer class="solr.KeywordTokenizerFactory"/>
+        <!-- The LowerCase TokenFilter does what you expect, which can be
+             when you want your sorting to be case insensitive
+          -->
+        <filter class="solr.LowerCaseFilterFactory" />
+        <!-- The TrimFilter removes any leading or trailing whitespace -->
+        <filter class="solr.TrimFilterFactory" />
+        <!-- The PatternReplaceFilter gives you the flexibility to use
+             Java Regular expression to replace any sequence of characters
+             matching a pattern with an arbitrary replacement string, 
+             which may include back references to portions of the original
+             string matched by the pattern.
+             
+             See the Java Regular Expression documentation for more
+             information on pattern and replacement string syntax.
+             
+             http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/package-summary.html
+          -->
+        <filter class="solr.PatternReplaceFilterFactory"
+                pattern="([^a-z])" replacement="" replace="all"
+        />
+      </analyzer>
+    </fieldType>
+    
+    <fieldtype name="phonetic" stored="false" indexed="true" class="solr.TextField" >
+      <analyzer>
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.DoubleMetaphoneFilterFactory" inject="false"/>
+      </analyzer>
+    </fieldtype>
+
+    <fieldtype name="payloads" stored="false" indexed="true" class="solr.TextField" >
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <!--
+        The DelimitedPayloadTokenFilter can put payloads on tokens... for example,
+        a token of "foo|1.4"  would be indexed as "foo" with a payload of 1.4f
+        Attributes of the DelimitedPayloadTokenFilterFactory : 
+         "delimiter" - a one character delimiter. Default is | (pipe)
+	 "encoder" - how to encode the following value into a playload
+	    float -> org.apache.lucene.analysis.payloads.FloatEncoder,
+	    integer -> o.a.l.a.p.IntegerEncoder
+	    identity -> o.a.l.a.p.IdentityEncoder
+            Fully Qualified class name implementing PayloadEncoder, Encoder must have a no arg constructor.
+         -->
+        <filter class="solr.DelimitedPayloadTokenFilterFactory" encoder="float"/>
+      </analyzer>
+    </fieldtype>
+
+    <!-- lowercases the entire field value, keeping it as a single token.  -->
+    <fieldType name="lowercase" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.KeywordTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory" />
+      </analyzer>
+    </fieldType>
+
+    <fieldType name="text_path" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.PathHierarchyTokenizerFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- since fields of this type are by default not stored or indexed,
+         any data added to them will be ignored outright.  --> 
+    <fieldtype name="ignored" stored="false" indexed="false" multiValued="true" class="solr.StrField" />
+
+    <!-- This point type indexes the coordinates as separate fields (subFields)
+      If subFieldType is defined, it references a type, and a dynamic field
+      definition is created matching *___<typename>.  Alternately, if 
+      subFieldSuffix is defined, that is used to create the subFields.
+      Example: if subFieldType="double", then the coordinates would be
+        indexed in fields myloc_0___double,myloc_1___double.
+      Example: if subFieldSuffix="_d" then the coordinates would be indexed
+        in fields myloc_0_d,myloc_1_d
+      The subFields are an implementation detail of the fieldType, and end
+      users normally should not need to know about them.
+     -->
+    <fieldType name="point" class="solr.PointType" dimension="2" subFieldSuffix="_d"/>
+
+    <!-- A specialized field for geospatial search. If indexed, this fieldType must not be multivalued. -->
+    <fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
+
+   <!--
+    A Geohash is a compact representation of a latitude longitude pair in a single field.
+    See http://wiki.apache.org/solr/SpatialSearch
+   -->
+    <fieldtype name="geohash" class="solr.GeoHashField"/>
+ </types>
+
+
+ <fields>
+   <!-- Valid attributes for fields:
+     name: mandatory - the name for the field
+     type: mandatory - the name of a previously defined type from the 
+       <types> section
+     indexed: true if this field should be indexed (searchable or sortable)
+     stored: true if this field should be retrievable
+     multiValued: true if this field may contain multiple values per document
+     omitNorms: (expert) set to true to omit the norms associated with
+       this field (this disables length normalization and index-time
+       boosting for the field, and saves some memory).  Only full-text
+       fields or fields that need an index-time boost need norms.
+     termVectors: [false] set to true to store the term vector for a
+       given field.
+       When using MoreLikeThis, fields used for similarity should be
+       stored for best performance.
+     termPositions: Store position information with the term vector.  
+       This will increase storage costs.
+     termOffsets: Store offset information with the term vector. This 
+       will increase storage costs.
+     default: a value that should be used if no value is specified
+       when adding a document.
+   -->
+
+   <field name="id" type="string" indexed="true" stored="true" required="true" /> 
+   <field name="docOID" type="string" indexed="true" stored="true" required="true" /> 
+   <field name="sku" type="text_en_splitting_tight" indexed="true" stored="true" omitNorms="true"/>
+   <field name="name" type="text_general" indexed="true" stored="true"/>
+   <field name="alphaNameSort" type="alphaOnlySort" indexed="true" stored="false"/>
+   <field name="manu" type="text_general" indexed="true" stored="true" omitNorms="true"/>
+   <field name="cat" type="string" indexed="true" stored="true" multiValued="true"/>
+   <field name="features" type="text_general" indexed="true" stored="true" multiValued="true"/>
+   <field name="includes" type="text_general" indexed="true" stored="true" termVectors="true" termPositions="true" termOffsets="true" />
+
+   <field name="weight" type="float" indexed="true" stored="true"/>
+   <field name="price"  type="float" indexed="true" stored="true"/>
+   <field name="popularity" type="int" indexed="true" stored="true" />
+   <field name="inStock" type="boolean" indexed="true" stored="true" />
+
+   <!--
+   The following store examples are used to demonstrate the various ways one might _CHOOSE_ to
+    implement spatial.  It is highly unlikely that you would ever have ALL of these fields defined.
+    -->
+   <field name="store" type="location" indexed="true" stored="true"/>
+
+   <!-- Common metadata fields, named specifically to match up with
+     SolrCell metadata when parsing rich documents such as Word, PDF.
+     Some fields are multiValued only because Tika currently may return
+     multiple values for them.
+   -->
+   <field name="title" type="text_general" indexed="true" stored="true" multiValued="true"/>
+   <field name="subject" type="text_general" indexed="true" stored="true"/>
+   <field name="description" type="text_general" indexed="true" stored="true"/>
+   <field name="comments" type="text_general" indexed="true" stored="true"/>
+   <field name="author" type="text_general" indexed="true" stored="true"/>
+   <field name="keywords" type="text_general" indexed="true" stored="true"/>
+   <field name="category" type="text_general" indexed="true" stored="true"/>
+   <field name="content_type" type="string" indexed="true" stored="true" multiValued="true"/>
+   <field name="last_modified" type="date" indexed="true" stored="true"/>
+   <field name="links" type="string" indexed="true" stored="true" multiValued="true"/>
+
+
+   <!-- catchall field, containing all other searchable text fields (implemented
+        via copyField further on in this schema  -->
+   <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
+
+   <!-- catchall text field that indexes tokens both normally and in reverse for efficient
+        leading wildcard queries. -->
+   <field name="text_rev" type="text_general_rev" indexed="true" stored="false" multiValued="true"/>
+
+   <!-- non-tokenized version of manufacturer to make it easier to sort or group
+        results by manufacturer.  copied from "manu" via copyField -->
+   <field name="manu_exact" type="string" indexed="true" stored="false"/>
+
+   <field name="payloads" type="payloads" indexed="true" stored="true"/>
+
+   <!-- Uncommenting the following will create a "timestamp" field using
+        a default value of "NOW" to indicate when each document was indexed.
+     -->
+   <!--
+   <field name="timestamp" type="date" indexed="true" stored="true" default="NOW" multiValued="false"/>
+     -->
+   
+
+   <!-- Dynamic field definitions.  If a field name is not found, dynamicFields
+        will be used if the name matches any of the patterns.
+        RESTRICTION: the glob-like pattern in the name attribute must have
+        a "*" only at the start or the end.
+        EXAMPLE:  name="*_i" will match any field ending in _i (like myid_i, z_i)
+        Longer patterns will be matched first.  if equal size patterns
+        both match, the first appearing in the schema will be used.  -->
+   <dynamicField name="*_i"  type="int"    indexed="true"  stored="true"/>
+   <dynamicField name="*_s"  type="string"  indexed="true"  stored="true"/>
+   <dynamicField name="*_l"  type="long"   indexed="true"  stored="true"/>
+   <dynamicField name="*_t"  type="text_general"    indexed="true"  stored="true"/>
+   <dynamicField name="*_txt" type="text_general"    indexed="true"  stored="true" multiValued="true"/>
+   <dynamicField name="*_b"  type="boolean" indexed="true"  stored="true"/>
+   <dynamicField name="*_f"  type="float"  indexed="true"  stored="true"/>
+   <dynamicField name="*_d"  type="double" indexed="true"  stored="true"/>
+
+   <!-- Type used to index the lat and lon components for the "location" FieldType -->
+   <dynamicField name="*_coordinate"  type="tdouble" indexed="true"  stored="false"/>
+
+   <dynamicField name="*_dt" type="date"    indexed="true"  stored="true"/>
+   <dynamicField name="*_p"  type="location" indexed="true" stored="true"/>
+
+   <!-- some trie-coded dynamic fields for faster range queries -->
+   <dynamicField name="*_ti" type="tint"    indexed="true"  stored="true"/>
+   <dynamicField name="*_tl" type="tlong"   indexed="true"  stored="true"/>
+   <dynamicField name="*_tf" type="tfloat"  indexed="true"  stored="true"/>
+   <dynamicField name="*_td" type="tdouble" indexed="true"  stored="true"/>
+   <dynamicField name="*_tdt" type="tdate"  indexed="true"  stored="true"/>
+
+   <dynamicField name="*_pi"  type="pint"    indexed="true"  stored="true"/>
+
+   <dynamicField name="ignored_*" type="ignored" multiValued="true"/>
+   <dynamicField name="attr_*" type="text_general" indexed="true" stored="true" multiValued="true"/>
+
+   <dynamicField name="random_*" type="random" />
+
+   <!-- uncomment the following to ignore any fields that don't already match an existing 
+        field name or dynamic field, rather than reporting them as an error. 
+        alternately, change the type="ignored" to some other type e.g. "text" if you want 
+        unknown fields indexed and/or stored by default --> 
+   <!--dynamicField name="*" type="ignored" multiValued="true" /-->
+   
+ </fields>
+
+ <!-- Field to use to determine and enforce document uniqueness. 
+      Unless this field is marked with required="false", it will be a required field
+   -->
+ <uniqueKey>docOID</uniqueKey>
+
+ <!-- field for the QueryParser to use when an explicit fieldname is absent -->
+ <defaultSearchField>text</defaultSearchField>
+
+ <!-- SolrQueryParser configuration: defaultOperator="AND|OR" -->
+ <solrQueryParser defaultOperator="OR"/>
+
+  <!-- copyField commands copy one field to another at the time a document
+        is added to the index.  It's used either to index the same field differently,
+        or to add multiple fields to the same field for easier/faster searching.  -->
+
+   <copyField source="cat" dest="text"/>
+   <copyField source="name" dest="text"/>
+   <copyField source="manu" dest="text"/>
+   <copyField source="features" dest="text"/>
+   <copyField source="includes" dest="text"/>
+   <copyField source="manu" dest="manu_exact"/>
+	
+   <!-- Above, multiple source fields are copied to the [text] field. 
+	  Another way to map multiple source fields to the same 
+	  destination field is to use the dynamic field syntax. 
+	  copyField also supports a maxChars to copy setting.  -->
+	   
+   <!-- <copyField source="*_t" dest="text" maxChars="3000"/> -->
+
+   <!-- copy name to alphaNameSort, a field designed for sorting by name -->
+   <!-- <copyField source="name" dest="alphaNameSort"/> -->
+ 
+
+ <!-- Similarity is the scoring routine for each document vs. a query.
+      A custom similarity may be specified here, but the default is fine
+      for most applications.  -->
+ <!-- <similarity class="org.apache.lucene.search.DefaultSimilarity"/> -->
+ <!-- ... OR ...
+      Specify a SimilarityFactory class name implementation
+      allowing parameters to be used.
+ -->
+ <!--
+ <similarity class="com.example.solr.CustomSimilarityFactory">
+   <str name="paramkey">param value</str>
+ </similarity>
+ -->
+
+
+</schema>
Index: gs3-extensions/solr/trunk/src/etc/conf/schema.xml.in
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/schema.xml.in	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/schema.xml.in	(revision 24446)
@@ -0,0 +1,657 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!--  
+ This is the Solr schema file. This file should be named "schema.xml" and
+ should be in the conf directory under the solr home
+ (i.e. ./solr/conf/schema.xml by default) 
+ or located where the classloader for the Solr webapp can find it.
+
+ This example schema is the recommended starting point for users.
+ It should be kept correct and concise, usable out-of-the-box.
+
+ For more information, on how to customize this file, please see
+ http://wiki.apache.org/solr/SchemaXml
+
+ PERFORMANCE NOTE: this schema includes many optional features and should not
+ be used for benchmarking.  To improve performance one could
+  - set stored="false" for all fields possible (esp large fields) when you
+    only need to search on the field but don't need to return the original
+    value.
+  - set indexed="false" if you don't need to search on the field, but only
+    return the field as a result of searching on other indexed fields.
+  - remove all unneeded copyField statements
+  - for best index size and searching performance, set "index" to false
+    for all general text fields, use copyField to copy them to the
+    catchall "text" field, and use that for searching.
+  - For maximum indexing performance, use the StreamingUpdateSolrServer
+    java client.
+  - Remember to run the JVM in server mode, and use a higher logging level
+    that avoids logging every request
+-->
+
+<schema name="example" version="1.4">
+  <!-- attribute "name" is the name of this schema and is only used for display purposes.
+       Applications should change this to reflect the nature of the search collection.
+       version="1.4" is Solr's version number for the schema syntax and semantics.  It should
+       not normally be changed by applications.
+       1.0: multiValued attribute did not exist, all fields are multiValued by nature
+       1.1: multiValued attribute introduced, false by default 
+       1.2: omitTermFreqAndPositions attribute introduced, true by default except for text fields.
+       1.3: removed optional field compress feature
+       1.4: default auto-phrase (QueryParser feature) to off
+     -->
+
+  <types>
+    <!-- field type definitions. The "name" attribute is
+       just a label to be used by field definitions.  The "class"
+       attribute and any other attributes determine the real
+       behavior of the fieldType.
+         Class names starting with "solr" refer to java classes in the
+       org.apache.solr.analysis package.
+    -->
+
+    <!-- The StrField type is not analyzed, but indexed/stored verbatim. -->
+    <fieldType name="string" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
+
+    <!-- boolean type: "true" or "false" -->
+    <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true" omitNorms="true"/>
+    <!--Binary data type. The data should be sent/retrieved in as Base64 encoded Strings -->
+    <fieldtype name="binary" class="solr.BinaryField"/>
+
+    <!-- The optional sortMissingLast and sortMissingFirst attributes are
+         currently supported on types that are sorted internally as strings.
+	       This includes "string","boolean","sint","slong","sfloat","sdouble","pdate"
+       - If sortMissingLast="true", then a sort on this field will cause documents
+         without the field to come after documents with the field,
+         regardless of the requested sort order (asc or desc).
+       - If sortMissingFirst="true", then a sort on this field will cause documents
+         without the field to come before documents with the field,
+         regardless of the requested sort order.
+       - If sortMissingLast="false" and sortMissingFirst="false" (the default),
+         then default lucene sorting will be used which places docs without the
+         field first in an ascending sort and last in a descending sort.
+    -->    
+
+    <!--
+      Default numeric field types. For faster range queries, consider the tint/tfloat/tlong/tdouble types.
+    -->
+    <fieldType name="int" class="solr.TrieIntField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="long" class="solr.TrieLongField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" omitNorms="true" positionIncrementGap="0"/>
+
+    <!--
+     Numeric field types that index each value at various levels of precision
+     to accelerate range queries when the number of values between the range
+     endpoints is large. See the javadoc for NumericRangeQuery for internal
+     implementation details.
+
+     Smaller precisionStep values (specified in bits) will lead to more tokens
+     indexed per value, slightly larger index size, and faster range queries.
+     A precisionStep of 0 disables indexing at different precision levels.
+    -->
+    <fieldType name="tint" class="solr.TrieIntField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
+    <fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" omitNorms="true" positionIncrementGap="0"/>
+
+    <!-- The format for this date field is of the form 1995-12-31T23:59:59Z, and
+         is a more restricted form of the canonical representation of dateTime
+         http://www.w3.org/TR/xmlschema-2/#dateTime    
+         The trailing "Z" designates UTC time and is mandatory.
+         Optional fractional seconds are allowed: 1995-12-31T23:59:59.999Z
+         All other components are mandatory.
+
+         Expressions can also be used to denote calculations that should be
+         performed relative to "NOW" to determine the value, ie...
+
+               NOW/HOUR
+                  ... Round to the start of the current hour
+               NOW-1DAY
+                  ... Exactly 1 day prior to now
+               NOW/DAY+6MONTHS+3DAYS
+                  ... 6 months and 3 days in the future from the start of
+                      the current day
+                      
+         Consult the DateField javadocs for more information.
+
+         Note: For faster range queries, consider the tdate type
+      -->
+    <fieldType name="date" class="solr.TrieDateField" omitNorms="true" precisionStep="0" positionIncrementGap="0"/>
+
+    <!-- A Trie based date field for faster date range queries and date faceting. -->
+    <fieldType name="tdate" class="solr.TrieDateField" omitNorms="true" precisionStep="6" positionIncrementGap="0"/>
+
+
+    <!--
+      Note:
+      These should only be used for compatibility with existing indexes (created with older Solr versions)
+      or if "sortMissingFirst" or "sortMissingLast" functionality is needed. Use Trie based fields instead.
+
+      Plain numeric field types that store and index the text
+      value verbatim (and hence don't support range queries, since the
+      lexicographic ordering isn't equal to the numeric ordering)
+    -->
+    <fieldType name="pint" class="solr.IntField" omitNorms="true"/>
+    <fieldType name="plong" class="solr.LongField" omitNorms="true"/>
+    <fieldType name="pfloat" class="solr.FloatField" omitNorms="true"/>
+    <fieldType name="pdouble" class="solr.DoubleField" omitNorms="true"/>
+    <fieldType name="pdate" class="solr.DateField" sortMissingLast="true" omitNorms="true"/>
+
+
+    <!--
+      Note:
+      These should only be used for compatibility with existing indexes (created with older Solr versions)
+      or if "sortMissingFirst" or "sortMissingLast" functionality is needed. Use Trie based fields instead.
+
+      Numeric field types that manipulate the value into
+      a string value that isn't human-readable in its internal form,
+      but with a lexicographic ordering the same as the numeric ordering,
+      so that range queries work correctly.
+    -->
+    <fieldType name="sint" class="solr.SortableIntField" sortMissingLast="true" omitNorms="true"/>
+    <fieldType name="slong" class="solr.SortableLongField" sortMissingLast="true" omitNorms="true"/>
+    <fieldType name="sfloat" class="solr.SortableFloatField" sortMissingLast="true" omitNorms="true"/>
+    <fieldType name="sdouble" class="solr.SortableDoubleField" sortMissingLast="true" omitNorms="true"/>
+
+
+    <!-- The "RandomSortField" is not used to store or search any
+         data.  You can declare fields of this type it in your schema
+         to generate pseudo-random orderings of your docs for sorting 
+         purposes.  The ordering is generated based on the field name 
+         and the version of the index, As long as the index version
+         remains unchanged, and the same field name is reused,
+         the ordering of the docs will be consistent.  
+         If you want different psuedo-random orderings of documents,
+         for the same version of the index, use a dynamicField and
+         change the name
+     -->
+    <fieldType name="random" class="solr.RandomSortField" indexed="true" />
+
+    <!-- solr.TextField allows the specification of custom text analyzers
+         specified as a tokenizer and a list of token filters. Different
+         analyzers may be specified for indexing and querying.
+
+         The optional positionIncrementGap puts space between multiple fields of
+         this type on the same document, with the purpose of preventing false phrase
+         matching across fields.
+
+         For more info on customizing your analyzer chain, please see
+         http://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters
+     -->
+
+    <!-- One can also specify an existing Analyzer class that has a
+         default constructor via the class attribute on the analyzer element
+    <fieldType name="text_greek" class="solr.TextField">
+      <analyzer class="org.apache.lucene.analysis.el.GreekAnalyzer"/>
+    </fieldType>
+    -->
+
+    <!-- A text field that only splits on whitespace for exact matching of words -->
+    <fieldType name="text_ws" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A general text field that has reasonable, generic
+         cross-language defaults: it tokenizes with StandardTokenizer,
+	 removes stop words from case-insensitive "stopwords.txt"
+	 (empty by default), and down cases.  At query time only, it
+	 also applies synonyms. -->
+    <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        -->
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A text field with defaults appropriate for English: it
+         tokenizes with StandardTokenizer, removes English stop words
+         (stopwords_en.txt), down cases, protects words from protwords.txt, and
+         finally applies Porter's stemming.  The query time analyzer
+         also applies synonyms from synonyms.txt. -->
+    <fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        -->
+        <!-- Case insensitive stop word removal.
+          add enablePositionIncrements=true in both the index and query
+          analyzers to leave a 'gap' for more accurate phrase queries.
+        -->
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.LowerCaseFilterFactory"/>
+	<filter class="solr.EnglishPossessiveFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+	<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+	-->
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.LowerCaseFilterFactory"/>
+	<filter class="solr.EnglishPossessiveFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+	<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+	-->
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- A text field with defaults appropriate for English, plus
+	 aggressive word-splitting and autophrase features enabled.
+	 This field is just like text_en, except it adds
+	 WordDelimiterFilter to enable splitting and matching of
+	 words on case-change, alpha numeric boundaries, and
+	 non-alphanumeric chars.  This means certain compound word
+	 cases will work, for example query "wi fi" will match
+	 document "WiFi" or "wi-fi".  However, other cases will still
+	 not match, for example if the query is "wifi" and the
+	 document is "wi fi" or if the query is "wi-fi" and the
+	 document is "wifi".
+        -->
+    <fieldType name="text_en_splitting" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
+      <analyzer type="index">
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <!-- in this example, we will only use synonyms at query time
+        <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/>
+        -->
+        <!-- Case insensitive stop word removal.
+          add enablePositionIncrements=true in both the index and query
+          analyzers to leave a 'gap' for more accurate phrase queries.
+        -->
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory"
+                ignoreCase="true"
+                words="stopwords_en.txt"
+                enablePositionIncrements="true"
+                />
+        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.PorterStemFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Less flexible matching, but less false matches.  Probably not ideal for product names,
+         but may be good for SKUs.  Can insert dashes in the wrong place and still match. -->
+    <fieldType name="text_en_splitting_tight" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="true">
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="false"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords_en.txt"/>
+        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="0" generateNumberParts="0" catenateWords="1" catenateNumbers="1" catenateAll="0"/>
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
+        <filter class="solr.EnglishMinimalStemFilterFactory"/>
+        <!-- this filter can remove any duplicate tokens that appear at the same position - sometimes
+             possible with WordDelimiterFilter in conjuncton with stemming. -->
+        <filter class="solr.RemoveDuplicatesTokenFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- Just like text_general except it reverses the characters of
+	 each token, to enable more efficient leading wildcard queries. -->
+    <fieldType name="text_general_rev" class="solr.TextField" positionIncrementGap="100">
+      <analyzer type="index">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <filter class="solr.LowerCaseFilterFactory"/>
+        <filter class="solr.ReversedWildcardFilterFactory" withOriginal="true"
+           maxPosAsterisk="3" maxPosQuestion="2" maxFractionAsterisk="0.33"/>
+      </analyzer>
+      <analyzer type="query">
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
+        <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt" enablePositionIncrements="true" />
+        <filter class="solr.LowerCaseFilterFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- charFilter + WhitespaceTokenizer  -->
+    <!--
+    <fieldType name="text_char_norm" class="solr.TextField" positionIncrementGap="100" >
+      <analyzer>
+        <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ISOLatin1Accent.txt"/>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+      </analyzer>
+    </fieldType>
+    -->
+
+    <!-- This is an example of using the KeywordTokenizer along
+         With various TokenFilterFactories to produce a sortable field
+         that does not include some properties of the source text
+      -->
+    <fieldType name="alphaOnlySort" class="solr.TextField" sortMissingLast="true" omitNorms="true">
+      <analyzer>
+        <!-- KeywordTokenizer does no actual tokenizing, so the entire
+             input string is preserved as a single token
+          -->
+        <tokenizer class="solr.KeywordTokenizerFactory"/>
+        <!-- The LowerCase TokenFilter does what you expect, which can be
+             when you want your sorting to be case insensitive
+          -->
+        <filter class="solr.LowerCaseFilterFactory" />
+        <!-- The TrimFilter removes any leading or trailing whitespace -->
+        <filter class="solr.TrimFilterFactory" />
+        <!-- The PatternReplaceFilter gives you the flexibility to use
+             Java Regular expression to replace any sequence of characters
+             matching a pattern with an arbitrary replacement string, 
+             which may include back references to portions of the original
+             string matched by the pattern.
+             
+             See the Java Regular Expression documentation for more
+             information on pattern and replacement string syntax.
+             
+             http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/package-summary.html
+          -->
+        <filter class="solr.PatternReplaceFilterFactory"
+                pattern="([^a-z])" replacement="" replace="all"
+        />
+      </analyzer>
+    </fieldType>
+    
+    <fieldtype name="phonetic" stored="false" indexed="true" class="solr.TextField" >
+      <analyzer>
+        <tokenizer class="solr.StandardTokenizerFactory"/>
+        <filter class="solr.DoubleMetaphoneFilterFactory" inject="false"/>
+      </analyzer>
+    </fieldtype>
+
+    <fieldtype name="payloads" stored="false" indexed="true" class="solr.TextField" >
+      <analyzer>
+        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
+        <!--
+        The DelimitedPayloadTokenFilter can put payloads on tokens... for example,
+        a token of "foo|1.4"  would be indexed as "foo" with a payload of 1.4f
+        Attributes of the DelimitedPayloadTokenFilterFactory : 
+         "delimiter" - a one character delimiter. Default is | (pipe)
+	 "encoder" - how to encode the following value into a playload
+	    float -> org.apache.lucene.analysis.payloads.FloatEncoder,
+	    integer -> o.a.l.a.p.IntegerEncoder
+	    identity -> o.a.l.a.p.IdentityEncoder
+            Fully Qualified class name implementing PayloadEncoder, Encoder must have a no arg constructor.
+         -->
+        <filter class="solr.DelimitedPayloadTokenFilterFactory" encoder="float"/>
+      </analyzer>
+    </fieldtype>
+
+    <!-- lowercases the entire field value, keeping it as a single token.  -->
+    <fieldType name="lowercase" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.KeywordTokenizerFactory"/>
+        <filter class="solr.LowerCaseFilterFactory" />
+      </analyzer>
+    </fieldType>
+
+    <fieldType name="text_path" class="solr.TextField" positionIncrementGap="100">
+      <analyzer>
+        <tokenizer class="solr.PathHierarchyTokenizerFactory"/>
+      </analyzer>
+    </fieldType>
+
+    <!-- since fields of this type are by default not stored or indexed,
+         any data added to them will be ignored outright.  --> 
+    <fieldtype name="ignored" stored="false" indexed="false" multiValued="true" class="solr.StrField" />
+
+    <!-- This point type indexes the coordinates as separate fields (subFields)
+      If subFieldType is defined, it references a type, and a dynamic field
+      definition is created matching *___<typename>.  Alternately, if 
+      subFieldSuffix is defined, that is used to create the subFields.
+      Example: if subFieldType="double", then the coordinates would be
+        indexed in fields myloc_0___double,myloc_1___double.
+      Example: if subFieldSuffix="_d" then the coordinates would be indexed
+        in fields myloc_0_d,myloc_1_d
+      The subFields are an implementation detail of the fieldType, and end
+      users normally should not need to know about them.
+     -->
+    <fieldType name="point" class="solr.PointType" dimension="2" subFieldSuffix="_d"/>
+
+    <!-- A specialized field for geospatial search. If indexed, this fieldType must not be multivalued. -->
+    <fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
+
+   <!--
+    A Geohash is a compact representation of a latitude longitude pair in a single field.
+    See http://wiki.apache.org/solr/SpatialSearch
+   -->
+    <fieldtype name="geohash" class="solr.GeoHashField"/>
+ </types>
+
+
+ <fields>
+   <!-- Valid attributes for fields:
+     name: mandatory - the name for the field
+     type: mandatory - the name of a previously defined type from the 
+       <types> section
+     indexed: true if this field should be indexed (searchable or sortable)
+     stored: true if this field should be retrievable
+     multiValued: true if this field may contain multiple values per document
+     omitNorms: (expert) set to true to omit the norms associated with
+       this field (this disables length normalization and index-time
+       boosting for the field, and saves some memory).  Only full-text
+       fields or fields that need an index-time boost need norms.
+     termVectors: [false] set to true to store the term vector for a
+       given field.
+       When using MoreLikeThis, fields used for similarity should be
+       stored for best performance.
+     termPositions: Store position information with the term vector.  
+       This will increase storage costs.
+     termOffsets: Store offset information with the term vector. This 
+       will increase storage costs.
+     default: a value that should be used if no value is specified
+       when adding a document.
+   -->
+
+   <field name="docOID" type="string" indexed="true" stored="true" required="true" /> 
+
+   <!-- ##GREENSTONE-FIELDS## -->
+
+<!--
+   <field name="sku" type="text_en_splitting_tight" indexed="true" stored="true" omitNorms="true"/>
+   <field name="name" type="text_general" indexed="true" stored="true"/>
+   <field name="alphaNameSort" type="alphaOnlySort" indexed="true" stored="false"/>
+   <field name="manu" type="text_general" indexed="true" stored="true" omitNorms="true"/>
+   <field name="cat" type="string" indexed="true" stored="true" multiValued="true"/>
+   <field name="features" type="text_general" indexed="true" stored="true" multiValued="true"/>
+   <field name="includes" type="text_general" indexed="true" stored="true" termVectors="true" termPositions="true" termOffsets="true" />
+
+   <field name="weight" type="float" indexed="true" stored="true"/>
+   <field name="price"  type="float" indexed="true" stored="true"/>
+   <field name="popularity" type="int" indexed="true" stored="true" />
+   <field name="inStock" type="boolean" indexed="true" stored="true" />
+-->
+
+   <!--
+   The following store examples are used to demonstrate the various ways one might _CHOOSE_ to
+    implement spatial.  It is highly unlikely that you would ever have ALL of these fields defined.
+    -->
+   <field name="store" type="location" indexed="true" stored="true"/>
+
+   <!-- Common metadata fields, named specifically to match up with
+     SolrCell metadata when parsing rich documents such as Word, PDF.
+     Some fields are multiValued only because Tika currently may return
+     multiple values for them.
+   -->
+<!--
+   <field name="title" type="text_general" indexed="true" stored="true" multiValued="true"/>
+   <field name="subject" type="text_general" indexed="true" stored="true"/>
+   <field name="description" type="text_general" indexed="true" stored="true"/>
+   <field name="comments" type="text_general" indexed="true" stored="true"/>
+   <field name="author" type="text_general" indexed="true" stored="true"/>
+   <field name="keywords" type="text_general" indexed="true" stored="true"/>
+   <field name="category" type="text_general" indexed="true" stored="true"/>
+   <field name="content_type" type="string" indexed="true" stored="true" multiValued="true"/>
+   <field name="last_modified" type="date" indexed="true" stored="true"/>
+   <field name="links" type="string" indexed="true" stored="true" multiValued="true"/>
+-->
+
+
+   <!-- catchall field, containing all other searchable text fields (implemented
+        via copyField further on in this schema  -->
+   <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
+
+   <!-- catchall text field that indexes tokens both normally and in reverse for efficient
+        leading wildcard queries. -->
+   <field name="text_rev" type="text_general_rev" indexed="true" stored="false" multiValued="true"/>
+
+   <!-- non-tokenized version of manufacturer to make it easier to sort or group
+        results by manufacturer.  copied from "manu" via copyField -->
+   <field name="manu_exact" type="string" indexed="true" stored="false"/>
+
+   <field name="payloads" type="payloads" indexed="true" stored="true"/>
+
+   <!-- Uncommenting the following will create a "timestamp" field using
+        a default value of "NOW" to indicate when each document was indexed.
+     -->
+   <!--
+   <field name="timestamp" type="date" indexed="true" stored="true" default="NOW" multiValued="false"/>
+     -->
+   
+
+   <!-- Dynamic field definitions.  If a field name is not found, dynamicFields
+        will be used if the name matches any of the patterns.
+        RESTRICTION: the glob-like pattern in the name attribute must have
+        a "*" only at the start or the end.
+        EXAMPLE:  name="*_i" will match any field ending in _i (like myid_i, z_i)
+        Longer patterns will be matched first.  if equal size patterns
+        both match, the first appearing in the schema will be used.  -->
+   <dynamicField name="*_i"  type="int"    indexed="true"  stored="true"/>
+   <dynamicField name="*_s"  type="string"  indexed="true"  stored="true"/>
+   <dynamicField name="*_l"  type="long"   indexed="true"  stored="true"/>
+   <dynamicField name="*_t"  type="text_general"    indexed="true"  stored="true"/>
+   <dynamicField name="*_txt" type="text_general"    indexed="true"  stored="true" multiValued="true"/>
+   <dynamicField name="*_b"  type="boolean" indexed="true"  stored="true"/>
+   <dynamicField name="*_f"  type="float"  indexed="true"  stored="true"/>
+   <dynamicField name="*_d"  type="double" indexed="true"  stored="true"/>
+
+   <!-- Type used to index the lat and lon components for the "location" FieldType -->
+   <dynamicField name="*_coordinate"  type="tdouble" indexed="true"  stored="false"/>
+
+   <dynamicField name="*_dt" type="date"    indexed="true"  stored="true"/>
+   <dynamicField name="*_p"  type="location" indexed="true" stored="true"/>
+
+   <!-- some trie-coded dynamic fields for faster range queries -->
+   <dynamicField name="*_ti" type="tint"    indexed="true"  stored="true"/>
+   <dynamicField name="*_tl" type="tlong"   indexed="true"  stored="true"/>
+   <dynamicField name="*_tf" type="tfloat"  indexed="true"  stored="true"/>
+   <dynamicField name="*_td" type="tdouble" indexed="true"  stored="true"/>
+   <dynamicField name="*_tdt" type="tdate"  indexed="true"  stored="true"/>
+
+   <dynamicField name="*_pi"  type="pint"    indexed="true"  stored="true"/>
+
+   <dynamicField name="ignored_*" type="ignored" multiValued="true"/>
+   <dynamicField name="attr_*" type="text_general" indexed="true" stored="true" multiValued="true"/>
+
+   <dynamicField name="random_*" type="random" />
+
+   <!-- uncomment the following to ignore any fields that don't already match an existing 
+        field name or dynamic field, rather than reporting them as an error. 
+        alternately, change the type="ignored" to some other type e.g. "text" if you want 
+        unknown fields indexed and/or stored by default --> 
+   <!--dynamicField name="*" type="ignored" multiValued="true" /-->
+   
+ </fields>
+
+ <!-- Field to use to determine and enforce document uniqueness. 
+      Unless this field is marked with required="false", it will be a required field
+   -->
+ <uniqueKey>docOID</uniqueKey>
+
+ <!-- field for the QueryParser to use when an explicit fieldname is absent -->
+ <defaultSearchField>text</defaultSearchField>
+
+ <!-- SolrQueryParser configuration: defaultOperator="AND|OR" -->
+ <solrQueryParser defaultOperator="OR"/>
+
+  <!-- copyField commands copy one field to another at the time a document
+        is added to the index.  It's used either to index the same field differently,
+        or to add multiple fields to the same field for easier/faster searching.  -->
+
+<!--
+   <copyField source="cat" dest="text"/>
+   <copyField source="name" dest="text"/>
+   <copyField source="manu" dest="text"/>
+   <copyField source="features" dest="text"/>
+   <copyField source="includes" dest="text"/>
+   <copyField source="manu" dest="manu_exact"/>
+-->
+	
+   <!-- Above, multiple source fields are copied to the [text] field. 
+	  Another way to map multiple source fields to the same 
+	  destination field is to use the dynamic field syntax. 
+	  copyField also supports a maxChars to copy setting.  -->
+	   
+   <!-- <copyField source="*_t" dest="text" maxChars="3000"/> -->
+
+   <!-- copy name to alphaNameSort, a field designed for sorting by name -->
+   <!-- <copyField source="name" dest="alphaNameSort"/> -->
+ 
+
+ <!-- Similarity is the scoring routine for each document vs. a query.
+      A custom similarity may be specified here, but the default is fine
+      for most applications.  -->
+ <!-- <similarity class="org.apache.lucene.search.DefaultSimilarity"/> -->
+ <!-- ... OR ...
+      Specify a SimilarityFactory class name implementation
+      allowing parameters to be used.
+ -->
+ <!--
+ <similarity class="com.example.solr.CustomSimilarityFactory">
+   <str name="paramkey">param value</str>
+ </similarity>
+ -->
+
+
+</schema>
Index: gs3-extensions/solr/trunk/src/etc/conf/scripts.conf
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/scripts.conf	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/scripts.conf	(revision 24446)
@@ -0,0 +1,24 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+user=
+solr_hostname=localhost
+solr_port=8983
+rsyncd_port=18983
+data_dir=
+webapp_name=solr
+master_host=
+master_data_dir=
+master_status_dir=
Index: gs3-extensions/solr/trunk/src/etc/conf/solrconfig.xml
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/solrconfig.xml	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/solrconfig.xml	(revision 24446)
@@ -0,0 +1,1528 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- 
+     For more details about configurations options that may appear in
+     this file, see http://wiki.apache.org/solr/SolrConfigXml. 
+-->
+<config>
+  <!-- In all configuration below, a prefix of "solr." for class names
+       is an alias that causes solr to search appropriate packages,
+       including org.apache.solr.(search|update|request|core|analysis)
+
+       You may also specify a fully qualified Java classname if you
+       have your own custom plugins.
+    -->
+
+  <!-- Set this to 'false' if you want solr to continue working after
+       it has encountered an severe configuration error.  In a
+       production environment, you may want solr to keep working even
+       if one handler is mis-configured.
+
+       You may also set this to false using by setting the system
+       property:
+
+         -Dsolr.abortOnConfigurationError=false
+    -->
+  <abortOnConfigurationError>${solr.abortOnConfigurationError:true}</abortOnConfigurationError>
+  
+  <!-- Controls what version of Lucene various components of Solr
+       adhere to.  Generally, you want to use the latest version to
+       get all bug fixes and improvements. It is highly recommended
+       that you fully re-index after changing this setting as it can
+       affect both how text is indexed and queried.
+    -->
+  <luceneMatchVersion>LUCENE_33</luceneMatchVersion>
+
+  <!-- lib directives can be used to instruct Solr to load an Jars
+       identified and use them to resolve any "plugins" specified in
+       your solrconfig.xml or schema.xml (ie: Analyzers, Request
+       Handlers, etc...).
+
+       All directories and paths are resolved relative to the
+       instanceDir.
+
+       If a "./lib" directory exists in your instanceDir, all files
+       found in it are included as if you had used the following
+       syntax...
+       
+              <lib dir="./lib" />
+    -->
+  <!-- A dir option by itself adds any files found in the directory to
+       the classpath, this is useful for including all jars in a
+       directory.
+    -->
+  <lib dir="../../contrib/extraction/lib" />
+  <!-- When a regex is specified in addition to a directory, only the
+       files in that directory which completely match the regex
+       (anchored on both ends) will be included.
+    -->
+  <lib dir="../../dist/" regex="apache-solr-cell-\d.*\.jar" />
+  <lib dir="../../dist/" regex="apache-solr-clustering-\d.*\.jar" />
+  <lib dir="../../dist/" regex="apache-solr-dataimporthandler-\d.*\.jar" />
+
+  <!-- If a dir option (with or without a regex) is used and nothing
+       is found that matches, it will be ignored
+    -->
+  <lib dir="../../contrib/clustering/lib/" />
+  <lib dir="/total/crap/dir/ignored" /> 
+  <!-- an exact path can be used to specify a specific file.  This
+       will cause a serious error to be logged if it can't be loaded.
+    -->
+  <!--
+  <lib path="../a-jar-that-does-not-exist.jar" /> 
+  -->
+  
+  <!-- Data Directory
+
+       Used to specify an alternate directory to hold all index data
+       other than the default ./data under the Solr home.  If
+       replication is in use, this should match the replication
+       configuration.
+    -->
+  <dataDir>${solr.data.dir:}</dataDir>
+
+
+  <!-- The DirectoryFactory to use for indexes.
+       
+       solr.StandardDirectoryFactory, the default, is filesystem
+       based.  solr.RAMDirectoryFactory is memory based, not
+       persistent, and doesn't work with replication.
+    -->
+  <directoryFactory name="DirectoryFactory" 
+                    class="${solr.directoryFactory:solr.StandardDirectoryFactory}"/>
+
+
+  <!-- Index Defaults
+
+       Values here affect all index writers and act as a default
+       unless overridden.
+
+       WARNING: See also the <mainIndex> section below for parameters
+       that overfor Solr's main Lucene index.
+    -->
+  <indexDefaults>
+
+    <useCompoundFile>false</useCompoundFile>
+
+    <mergeFactor>10</mergeFactor>
+    <!-- Sets the amount of RAM that may be used by Lucene indexing
+         for buffering added documents and deletions before they are
+         flushed to the Directory.  -->
+    <ramBufferSizeMB>32</ramBufferSizeMB>
+    <!-- If both ramBufferSizeMB and maxBufferedDocs is set, then
+         Lucene will flush based on whichever limit is hit first.  
+      -->
+    <!-- <maxBufferedDocs>1000</maxBufferedDocs> -->
+
+    <maxFieldLength>10000</maxFieldLength>
+    <writeLockTimeout>1000</writeLockTimeout>
+    <commitLockTimeout>10000</commitLockTimeout>
+
+    <!-- Expert: Merge Policy 
+
+         The Merge Policy in Lucene controls how merging is handled by
+         Lucene.  The default in Solr 3.3 is TieredMergePolicy.
+         
+         The default in 2.3 was the LogByteSizeMergePolicy,
+         previous versions used LogDocMergePolicy.
+         
+         LogByteSizeMergePolicy chooses segments to merge based on
+         their size.  The Lucene 2.2 default, LogDocMergePolicy chose
+         when to merge based on number of documents
+         
+         Other implementations of MergePolicy must have a no-argument
+         constructor
+      -->
+    <!--
+       <mergePolicy class="org.apache.lucene.index.TieredMergePolicy"/>
+       -->
+
+    <!-- Expert: Merge Scheduler
+
+         The Merge Scheduler in Lucene controls how merges are
+         performed.  The ConcurrentMergeScheduler (Lucene 2.3 default)
+         can perform merges in the background using separate threads.
+         The SerialMergeScheduler (Lucene 2.2 default) does not.
+     -->
+    <!-- 
+       <mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"/>
+       -->
+	  
+    <!-- LockFactory 
+
+         This option specifies which Lucene LockFactory implementation
+         to use.
+      
+         single = SingleInstanceLockFactory - suggested for a
+                  read-only index or when there is no possibility of
+                  another process trying to modify the index.
+         native = NativeFSLockFactory - uses OS native file locking.
+                  Do not use when multiple solr webapps in the same
+                  JVM are attempting to share a single index.
+         simple = SimpleFSLockFactory  - uses a plain file for locking
+
+         (For backwards compatibility with Solr 1.2, 'simple' is the
+         default if not specified.)
+
+         More details on the nuances of each LockFactory...
+         http://wiki.apache.org/lucene-java/AvailableLockFactories
+    -->
+    <lockType>native</lockType>
+
+    <!-- Expert: Controls how often Lucene loads terms into memory
+         Default is 128 and is likely good for most everyone.
+      -->
+    <!-- <termIndexInterval>256</termIndexInterval> -->
+  </indexDefaults>
+
+  <!-- Main Index
+
+       Values here override the values in the <indexDefaults> section
+       for the main on disk index.
+    -->
+  <mainIndex>
+
+    <useCompoundFile>false</useCompoundFile>
+    <ramBufferSizeMB>32</ramBufferSizeMB>
+    <mergeFactor>10</mergeFactor>
+
+    <!-- Unlock On Startup
+
+         If true, unlock any held write or commit locks on startup.
+         This defeats the locking mechanism that allows multiple
+         processes to safely access a lucene index, and should be used
+         with care.
+
+         This is not needed if lock type is 'none' or 'single'
+     -->
+    <unlockOnStartup>false</unlockOnStartup>
+    
+    <!-- If true, IndexReaders will be reopened (often more efficient)
+         instead of closed and then opened.
+      -->
+    <reopenReaders>true</reopenReaders>
+
+    <!-- Commit Deletion Policy
+
+         Custom deletion policies can specified here. The class must
+         implement org.apache.lucene.index.IndexDeletionPolicy.
+
+         http://lucene.apache.org/java/2_9_1/api/all/org/apache/lucene/index/IndexDeletionPolicy.html
+
+         The standard Solr IndexDeletionPolicy implementation supports
+         deleting index commit points on number of commits, age of
+         commit point and optimized status.
+         
+         The latest commit point should always be preserved regardless
+         of the criteria.
+    -->
+    <deletionPolicy class="solr.SolrDeletionPolicy">
+      <!-- The number of commit points to be kept -->
+      <str name="maxCommitsToKeep">1</str>
+      <!-- The number of optimized commit points to be kept -->
+      <str name="maxOptimizedCommitsToKeep">0</str>
+      <!--
+          Delete all commit points once they have reached the given age.
+          Supports DateMathParser syntax e.g.
+        -->
+      <!--
+         <str name="maxCommitAge">30MINUTES</str>
+         <str name="maxCommitAge">1DAY</str>
+      -->
+    </deletionPolicy>
+
+    <!-- Lucene Infostream
+       
+         To aid in advanced debugging, Lucene provides an "InfoStream"
+         of detailed information when indexing.
+
+         Setting The value to true will instruct the underlying Lucene
+         IndexWriter to write its debugging info the specified file
+      -->
+     <infoStream file="INFOSTREAM.txt">false</infoStream> 
+
+  </mainIndex>
+
+  <!-- JMX
+       
+       This example enables JMX if and only if an existing MBeanServer
+       is found, use this if you want to configure JMX through JVM
+       parameters. Remove this to disable exposing Solr configuration
+       and statistics to JMX.
+
+       For more details see http://wiki.apache.org/solr/SolrJmx
+    -->
+  <jmx />
+  <!-- If you want to connect to a particular server, specify the
+       agentId 
+    -->
+  <!-- <jmx agentId="myAgent" /> -->
+  <!-- If you want to start a new MBeanServer, specify the serviceUrl -->
+  <!-- <jmx serviceUrl="service:jmx:rmi:///jndi/rmi://localhost:9999/solr"/>
+    -->
+
+  <!-- The default high-performance update handler -->
+  <updateHandler class="solr.DirectUpdateHandler2">
+
+    <!-- AutoCommit
+
+         Perform a <commit/> automatically under certain conditions.
+         Instead of enabling autoCommit, consider using "commitWithin"
+         when adding documents. 
+
+         http://wiki.apache.org/solr/UpdateXmlMessages
+
+         maxDocs - Maximum number of documents to add since the last
+                   commit before automatically triggering a new commit.
+
+         maxTime - Maximum amount of time that is allowed to pass
+                   since a document was added before automaticly
+                   triggering a new commit. 
+      -->
+    <!--
+       <autoCommit> 
+         <maxDocs>10000</maxDocs>
+         <maxTime>1000</maxTime> 
+       </autoCommit>
+      -->
+
+    <!-- Update Related Event Listeners
+         
+         Various IndexWriter related events can trigger Listeners to
+         take actions.
+
+         postCommit - fired after every commit or optimize command
+         postOptimize - fired after every optimize command
+      -->
+    <!-- The RunExecutableListener executes an external command from a
+         hook such as postCommit or postOptimize.
+         
+         exe - the name of the executable to run
+         dir - dir to use as the current working directory. (default=".")
+         wait - the calling thread waits until the executable returns. 
+                (default="true")
+         args - the arguments to pass to the program.  (default is none)
+         env - environment variables to set.  (default is none)
+      -->
+    <!-- This example shows how RunExecutableListener could be used
+         with the script based replication...
+         http://wiki.apache.org/solr/CollectionDistribution
+      -->
+    <!--
+       <listener event="postCommit" class="solr.RunExecutableListener">
+         <str name="exe">solr/bin/snapshooter</str>
+         <str name="dir">.</str>
+         <bool name="wait">true</bool>
+         <arr name="args"> <str>arg1</str> <str>arg2</str> </arr>
+         <arr name="env"> <str>MYVAR=val1</str> </arr>
+       </listener>
+      -->
+  </updateHandler>
+  
+  <!-- IndexReaderFactory
+
+       Use the following format to specify a custom IndexReaderFactory,
+       which allows for alternate IndexReader implementations.
+
+       ** Experimental Feature **
+
+       Please note - Using a custom IndexReaderFactory may prevent
+       certain other features from working. The API to
+       IndexReaderFactory may change without warning or may even be
+       removed from future releases if the problems cannot be
+       resolved.
+
+
+       ** Features that may not work with custom IndexReaderFactory **
+
+       The ReplicationHandler assumes a disk-resident index. Using a
+       custom IndexReader implementation may cause incompatibility
+       with ReplicationHandler and may cause replication to not work
+       correctly. See SOLR-1366 for details.
+
+    -->
+  <!--
+  <indexReaderFactory name="IndexReaderFactory" class="package.class">
+    <str name="someArg">Some Value</str>
+  </indexReaderFactory >
+  -->
+  <!-- By explicitly declaring the Factory, the termIndexDivisor can
+       be specified.
+    -->
+  <!--
+     <indexReaderFactory name="IndexReaderFactory" 
+                         class="solr.StandardIndexReaderFactory">
+       <int name="setTermIndexDivisor">12</int>
+     </indexReaderFactory >
+    -->
+
+
+  <query>
+    <!-- Max Boolean Clauses
+
+         Maximum number of clauses in each BooleanQuery,  an exception
+         is thrown if exceeded.
+
+         ** WARNING **
+         
+         This option actually modifies a global Lucene property that
+         will affect all SolrCores.  If multiple solrconfig.xml files
+         disagree on this property, the value at any given moment will
+         be based on the last SolrCore to be initialized.
+         
+      -->
+    <maxBooleanClauses>1024</maxBooleanClauses>
+
+
+    <!-- Solr Internal Query Caches
+
+         There are two implementations of cache available for Solr,
+         LRUCache, based on a synchronized LinkedHashMap, and
+         FastLRUCache, based on a ConcurrentHashMap.  
+
+         FastLRUCache has faster gets and slower puts in single
+         threaded operation and thus is generally faster than LRUCache
+         when the hit ratio of the cache is high (> 75%), and may be
+         faster under other scenarios on multi-cpu systems.
+    -->
+
+    <!-- Filter Cache
+
+         Cache used by SolrIndexSearcher for filters (DocSets),
+         unordered sets of *all* documents that match a query.  When a
+         new searcher is opened, its caches may be prepopulated or
+         "autowarmed" using data from caches in the old searcher.
+         autowarmCount is the number of items to prepopulate.  For
+         LRUCache, the autowarmed items will be the most recently
+         accessed items.
+
+         Parameters:
+           class - the SolrCache implementation LRUCache or
+               (LRUCache or FastLRUCache)
+           size - the maximum number of entries in the cache
+           initialSize - the initial capacity (number of entries) of
+               the cache.  (see java.util.HashMap)
+           autowarmCount - the number of entries to prepopulate from
+               and old cache.  
+      -->
+    <filterCache class="solr.FastLRUCache"
+                 size="512"
+                 initialSize="512"
+                 autowarmCount="0"/>
+
+    <!-- Query Result Cache
+         
+         Caches results of searches - ordered lists of document ids
+         (DocList) based on a query, a sort, and the range of documents requested.  
+      -->
+    <queryResultCache class="solr.LRUCache"
+                     size="512"
+                     initialSize="512"
+                     autowarmCount="0"/>
+   
+    <!-- Document Cache
+
+         Caches Lucene Document objects (the stored fields for each
+         document).  Since Lucene internal document ids are transient,
+         this cache will not be autowarmed.  
+      -->
+    <documentCache class="solr.LRUCache"
+                   size="512"
+                   initialSize="512"
+                   autowarmCount="0"/>
+    
+    <!-- Field Value Cache
+         
+         Cache used to hold field values that are quickly accessible
+         by document id.  The fieldValueCache is created by default
+         even if not configured here.
+      -->
+    <!--
+       <fieldValueCache class="solr.FastLRUCache"
+                        size="512"
+                        autowarmCount="128"
+                        showItems="32" />
+      -->
+
+    <!-- Custom Cache
+
+         Example of a generic cache.  These caches may be accessed by
+         name through SolrIndexSearcher.getCache(),cacheLookup(), and
+         cacheInsert().  The purpose is to enable easy caching of
+         user/application level data.  The regenerator argument should
+         be specified as an implementation of solr.CacheRegenerator 
+         if autowarming is desired.  
+      -->
+    <!--
+       <cache name="myUserCache"
+              class="solr.LRUCache"
+              size="4096"
+              initialSize="1024"
+              autowarmCount="1024"
+              regenerator="com.mycompany.MyRegenerator"
+              />
+      -->
+
+
+    <!-- Lazy Field Loading
+
+         If true, stored fields that are not requested will be loaded
+         lazily.  This can result in a significant speed improvement
+         if the usual case is to not load all stored fields,
+         especially if the skipped fields are large compressed text
+         fields.
+    -->
+    <enableLazyFieldLoading>true</enableLazyFieldLoading>
+
+   <!-- Use Filter For Sorted Query
+
+        A possible optimization that attempts to use a filter to
+        satisfy a search.  If the requested sort does not include
+        score, then the filterCache will be checked for a filter
+        matching the query. If found, the filter will be used as the
+        source of document ids, and then the sort will be applied to
+        that.
+
+        For most situations, this will not be useful unless you
+        frequently get the same search repeatedly with different sort
+        options, and none of them ever use "score"
+     -->
+   <!--
+      <useFilterForSortedQuery>true</useFilterForSortedQuery>
+     -->
+
+   <!-- Result Window Size
+
+        An optimization for use with the queryResultCache.  When a search
+        is requested, a superset of the requested number of document ids
+        are collected.  For example, if a search for a particular query
+        requests matching documents 10 through 19, and queryWindowSize is 50,
+        then documents 0 through 49 will be collected and cached.  Any further
+        requests in that range can be satisfied via the cache.  
+     -->
+   <queryResultWindowSize>20</queryResultWindowSize>
+
+   <!-- Maximum number of documents to cache for any entry in the
+        queryResultCache. 
+     -->
+   <queryResultMaxDocsCached>200</queryResultMaxDocsCached>
+
+   <!-- Query Related Event Listeners
+
+        Various IndexSearcher related events can trigger Listeners to
+        take actions.
+
+        newSearcher - fired whenever a new searcher is being prepared
+        and there is a current searcher handling requests (aka
+        registered).  It can be used to prime certain caches to
+        prevent long request times for certain requests.
+
+        firstSearcher - fired whenever a new searcher is being
+        prepared but there is no current registered searcher to handle
+        requests or to gain autowarming data from.
+
+        
+     -->
+    <!-- QuerySenderListener takes an array of NamedList and executes a
+         local query request for each NamedList in sequence. 
+      -->
+    <listener event="newSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <!--
+           <lst><str name="q">solr</str><str name="sort">price asc</str></lst>
+           <lst><str name="q">rocks</str><str name="sort">weight asc</str></lst>
+          -->
+      </arr>
+    </listener>
+    <listener event="firstSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <lst>
+          <str name="q">static firstSearcher warming in solrconfig.xml</str>
+        </lst>
+      </arr>
+    </listener>
+
+    <!-- Use Cold Searcher
+
+         If a search request comes in and there is no current
+         registered searcher, then immediately register the still
+         warming searcher and use it.  If "false" then all requests
+         will block until the first searcher is done warming.
+      -->
+    <useColdSearcher>false</useColdSearcher>
+
+    <!-- Max Warming Searchers
+         
+         Maximum number of searchers that may be warming in the
+         background concurrently.  An error is returned if this limit
+         is exceeded.
+
+         Recommend values of 1-2 for read-only slaves, higher for
+         masters w/o cache warming.
+      -->
+    <maxWarmingSearchers>2</maxWarmingSearchers>
+
+  </query>
+
+
+  <!-- Request Dispatcher
+
+       This section contains instructions for how the SolrDispatchFilter
+       should behave when processing requests for this SolrCore.
+
+       handleSelect affects the behavior of requests such as /select?qt=XXX
+
+       handleSelect="true" will cause the SolrDispatchFilter to process
+       the request and will result in consistent error handling and
+       formatting for all types of requests.
+
+       handleSelect="false" will cause the SolrDispatchFilter to
+       ignore "/select" requests and fallback to using the legacy
+       SolrServlet and it's Solr 1.1 style error formatting
+    -->
+  <requestDispatcher handleSelect="true" >
+    <!-- Request Parsing
+
+         These settings indicate how Solr Requests may be parsed, and
+         what restrictions may be placed on the ContentStreams from
+         those requests
+
+         enableRemoteStreaming - enables use of the stream.file
+         and stream.url parameters for specifying remote streams.
+
+         multipartUploadLimitInKB - specifies the max size of
+         Multipart File Uploads that Solr will allow in a Request.
+         
+         *** WARNING ***
+         The settings below authorize Solr to fetch remote files, You
+         should make sure your system has some authentication before
+         using enableRemoteStreaming="true"
+
+      --> 
+    <requestParsers enableRemoteStreaming="true" 
+                    multipartUploadLimitInKB="2048000" />
+
+    <!-- HTTP Caching
+
+         Set HTTP caching related parameters (for proxy caches and clients).
+
+         The options below instruct Solr not to output any HTTP Caching
+         related headers
+      -->
+    <httpCaching never304="true" />
+    <!-- If you include a <cacheControl> directive, it will be used to
+         generate a Cache-Control header (as well as an Expires header
+         if the value contains "max-age=")
+         
+         By default, no Cache-Control header is generated.
+         
+         You can use the <cacheControl> option even if you have set
+         never304="true"
+      -->
+    <!--
+       <httpCaching never304="true" >
+         <cacheControl>max-age=30, public</cacheControl> 
+       </httpCaching>
+      -->
+    <!-- To enable Solr to respond with automatically generated HTTP
+         Caching headers, and to response to Cache Validation requests
+         correctly, set the value of never304="false"
+         
+         This will cause Solr to generate Last-Modified and ETag
+         headers based on the properties of the Index.
+
+         The following options can also be specified to affect the
+         values of these headers...
+
+         lastModFrom - the default value is "openTime" which means the
+         Last-Modified value (and validation against If-Modified-Since
+         requests) will all be relative to when the current Searcher
+         was opened.  You can change it to lastModFrom="dirLastMod" if
+         you want the value to exactly correspond to when the physical
+         index was last modified.
+
+         etagSeed="..." is an option you can change to force the ETag
+         header (and validation against If-None-Match requests) to be
+         different even if the index has not changed (ie: when making
+         significant changes to your config file)
+
+         (lastModifiedFrom and etagSeed are both ignored if you use
+         the never304="true" option)
+      -->
+    <!--
+       <httpCaching lastModifiedFrom="openTime"
+                    etagSeed="Solr">
+         <cacheControl>max-age=30, public</cacheControl> 
+       </httpCaching>
+      -->
+  </requestDispatcher>
+
+  <!-- Request Handlers 
+
+       http://wiki.apache.org/solr/SolrRequestHandler
+
+       incoming queries will be dispatched to the correct handler
+       based on the path or the qt (query type) param.
+
+       Names starting with a '/' are accessed with the a path equal to
+       the registered name.  Names without a leading '/' are accessed
+       with: http://host/app/[core/]select?qt=name
+
+       If a /select request is processed with out a qt param
+       specified, the requestHandler that declares default="true" will
+       be used.
+       
+       If a Request Handler is declared with startup="lazy", then it will
+       not be initialized until the first request that uses it.
+
+    -->
+  <!-- SearchHandler
+
+       http://wiki.apache.org/solr/SearchHandler
+
+       For processing Search Queries, the primary Request Handler
+       provided with Solr is "SearchHandler" It delegates to a sequent
+       of SearchComponents (see below) and supports distributed
+       queries across multiple shards
+    -->
+  <requestHandler name="search" class="solr.SearchHandler" default="true">
+    <!-- default values for query parameters can be specified, these
+         will be overridden by parameters in the request
+      -->
+     <lst name="defaults">
+       <str name="echoParams">explicit</str>
+       <int name="rows">10</int>
+     </lst>
+    <!-- In addition to defaults, "appends" params can be specified
+         to identify values which should be appended to the list of
+         multi-val params from the query (or the existing "defaults").
+      -->
+    <!-- In this example, the param "fq=instock:true" would be appended to
+         any query time fq params the user may specify, as a mechanism for
+         partitioning the index, independent of any user selected filtering
+         that may also be desired (perhaps as a result of faceted searching).
+
+         NOTE: there is *absolutely* nothing a client can do to prevent these
+         "appends" values from being used, so don't use this mechanism
+         unless you are sure you always want it.
+      -->
+    <!--
+       <lst name="appends">
+         <str name="fq">inStock:true</str>
+       </lst>
+      -->
+    <!-- "invariants" are a way of letting the Solr maintainer lock down
+         the options available to Solr clients.  Any params values
+         specified here are used regardless of what values may be specified
+         in either the query, the "defaults", or the "appends" params.
+
+         In this example, the facet.field and facet.query params would
+         be fixed, limiting the facets clients can use.  Faceting is
+         not turned on by default - but if the client does specify
+         facet=true in the request, these are the only facets they
+         will be able to see counts for; regardless of what other
+         facet.field or facet.query params they may specify.
+
+         NOTE: there is *absolutely* nothing a client can do to prevent these
+         "invariants" values from being used, so don't use this mechanism
+         unless you are sure you always want it.
+      -->
+    <!--
+       <lst name="invariants">
+         <str name="facet.field">cat</str>
+         <str name="facet.field">manu_exact</str>
+         <str name="facet.query">price:[* TO 500]</str>
+         <str name="facet.query">price:[500 TO *]</str>
+       </lst>
+      -->
+    <!-- If the default list of SearchComponents is not desired, that
+         list can either be overridden completely, or components can be
+         prepended or appended to the default list.  (see below)
+      -->
+    <!--
+       <arr name="components">
+         <str>nameOfCustomComponent1</str>
+         <str>nameOfCustomComponent2</str>
+       </arr>
+      -->
+    </requestHandler>
+
+  <!-- A Robust Example
+
+       This example SearchHandler declaration shows off usage of the
+       SearchHandler with many defaults declared
+
+       Note that multiple instances of the same Request Handler
+       (SearchHandler) can be registered multiple times with different
+       names (and different init parameters)
+    -->
+  <requestHandler name="/browse" class="solr.SearchHandler">
+     <lst name="defaults">
+       <str name="echoParams">explicit</str>
+
+       <!-- VelocityResponseWriter settings -->
+       <str name="wt">velocity</str>
+
+       <str name="v.template">browse</str>
+       <str name="v.layout">layout</str>
+       <str name="title">Solritas</str>
+
+       <str name="defType">edismax</str>
+       <str name="q.alt">*:*</str>
+       <str name="rows">10</str>
+       <str name="fl">*,score</str>
+       <str name="mlt.qf">
+         text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
+       </str>
+       <str name="mlt.fl">text,features,name,sku,id,manu,cat</str>
+       <int name="mlt.count">3</int>
+
+       <str name="qf">
+          text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
+       </str>
+
+       <str name="facet">on</str>
+       <str name="facet.field">cat</str>
+       <str name="facet.field">manu_exact</str>
+       <str name="facet.query">ipod</str>
+       <str name="facet.query">GB</str>
+       <str name="facet.mincount">1</str>
+       <str name="facet.pivot">cat,inStock</str>
+       <str name="facet.range">price</str>
+       <int name="f.price.facet.range.start">0</int>
+       <int name="f.price.facet.range.end">600</int>
+       <int name="f.price.facet.range.gap">50</int>
+       <str name="f.price.facet.range.other">after</str>
+       <str name="facet.range">manufacturedate_dt</str>
+       <str name="f.manufacturedate_dt.facet.range.start">NOW/YEAR-10YEARS</str>
+       <str name="f.manufacturedate_dt.facet.range.end">NOW</str>
+       <str name="f.manufacturedate_dt.facet.range.gap">+1YEAR</str>
+       <str name="f.manufacturedate_dt.facet.range.other">before</str>
+       <str name="f.manufacturedate_dt.facet.range.other">after</str>
+
+
+       <!-- Highlighting defaults -->
+       <str name="hl">on</str>
+       <str name="hl.fl">text features name</str>
+       <str name="f.name.hl.fragsize">0</str>
+       <str name="f.name.hl.alternateField">name</str>
+     </lst>
+     <arr name="last-components">
+       <str>spellcheck</str>
+     </arr>
+     <!--
+     <str name="url-scheme">httpx</str>
+     -->
+  </requestHandler>
+
+  <!-- XML Update Request Handler.  
+       
+       http://wiki.apache.org/solr/UpdateXmlMessages
+
+       The canonical Request Handler for Modifying the Index through
+       commands specified using XML.
+
+       Note: Since solr1.1 requestHandlers requires a valid content
+       type header if posted in the body. For example, curl now
+       requires: -H 'Content-type:text/xml; charset=utf-8'
+    -->
+  <requestHandler name="/update" 
+                  class="solr.XmlUpdateRequestHandler">
+    <!-- See below for information on defining 
+         updateRequestProcessorChains that can be used by name 
+         on each Update Request
+      -->
+    <!--
+       <lst name="defaults">
+         <str name="update.chain">dedupe</str>
+       </lst>
+       -->
+    </requestHandler>
+  <!-- Binary Update Request Handler
+       http://wiki.apache.org/solr/javabin
+    -->
+  <requestHandler name="/update/javabin" 
+                  class="solr.BinaryUpdateRequestHandler" />
+
+  <!-- CSV Update Request Handler
+       http://wiki.apache.org/solr/UpdateCSV
+    -->
+  <requestHandler name="/update/csv" 
+                  class="solr.CSVRequestHandler" 
+                  startup="lazy" />
+
+  <!-- JSON Update Request Handler
+       http://wiki.apache.org/solr/UpdateJSON
+    -->
+  <requestHandler name="/update/json" 
+                  class="solr.JsonUpdateRequestHandler" 
+                  startup="lazy" />
+
+  <!-- Solr Cell Update Request Handler
+
+       http://wiki.apache.org/solr/ExtractingRequestHandler 
+
+    -->
+  <requestHandler name="/update/extract" 
+                  startup="lazy"
+                  class="solr.extraction.ExtractingRequestHandler" >
+    <lst name="defaults">
+      <!-- All the main content goes into "text"... if you need to return
+           the extracted text or do highlighting, use a stored field. -->
+      <str name="fmap.content">text</str>
+      <str name="lowernames">true</str>
+      <str name="uprefix">ignored_</str>
+
+      <!-- capture link hrefs but ignore div attributes -->
+      <str name="captureAttr">true</str>
+      <str name="fmap.a">links</str>
+      <str name="fmap.div">ignored_</str>
+    </lst>
+  </requestHandler>
+
+  <!-- Field Analysis Request Handler
+
+       RequestHandler that provides much the same functionality as
+       analysis.jsp. Provides the ability to specify multiple field
+       types and field names in the same request and outputs
+       index-time and query-time analysis for each of them.
+
+       Request parameters are:
+       analysis.fieldname - field name whose analyzers are to be used
+
+       analysis.fieldtype - field type whose analyzers are to be used
+       analysis.fieldvalue - text for index-time analysis
+       q (or analysis.q) - text for query time analysis
+       analysis.showmatch (true|false) - When set to true and when
+           query analysis is performed, the produced tokens of the
+           field value analysis will be marked as "matched" for every
+           token that is produces by the query analysis
+   -->
+  <requestHandler name="/analysis/field" 
+                  startup="lazy"
+                  class="solr.FieldAnalysisRequestHandler" />
+
+
+  <!-- Document Analysis Handler
+
+       http://wiki.apache.org/solr/AnalysisRequestHandler
+
+       An analysis handler that provides a breakdown of the analysis
+       process of provided docuemnts. This handler expects a (single)
+       content stream with the following format:
+
+       <docs>
+         <doc>
+           <field name="id">1</field>
+           <field name="name">The Name</field>
+           <field name="text">The Text Value</field>
+         </doc>
+         <doc>...</doc>
+         <doc>...</doc>
+         ...
+       </docs>
+
+    Note: Each document must contain a field which serves as the
+    unique key. This key is used in the returned response to associate
+    an analysis breakdown to the analyzed document.
+
+    Like the FieldAnalysisRequestHandler, this handler also supports
+    query analysis by sending either an "analysis.query" or "q"
+    request parameter that holds the query text to be analyzed. It
+    also supports the "analysis.showmatch" parameter which when set to
+    true, all field tokens that match the query tokens will be marked
+    as a "match". 
+  -->
+  <requestHandler name="/analysis/document" 
+                  class="solr.DocumentAnalysisRequestHandler" 
+                  startup="lazy" />
+
+  <!-- Admin Handlers
+
+       Admin Handlers - This will register all the standard admin
+       RequestHandlers.  
+    -->
+  <requestHandler name="/admin/" 
+                  class="solr.admin.AdminHandlers" />
+  <!-- This single handler is equivalent to the following... -->
+  <!--
+     <requestHandler name="/admin/luke"       class="solr.admin.LukeRequestHandler" />
+     <requestHandler name="/admin/system"     class="solr.admin.SystemInfoHandler" />
+     <requestHandler name="/admin/plugins"    class="solr.admin.PluginInfoHandler" />
+     <requestHandler name="/admin/threads"    class="solr.admin.ThreadDumpHandler" />
+     <requestHandler name="/admin/properties" class="solr.admin.PropertiesRequestHandler" />
+     <requestHandler name="/admin/file"       class="solr.admin.ShowFileRequestHandler" >
+    -->
+  <!-- If you wish to hide files under ${solr.home}/conf, explicitly
+       register the ShowFileRequestHandler using: 
+    -->
+  <!--
+     <requestHandler name="/admin/file" 
+                     class="solr.admin.ShowFileRequestHandler" >
+       <lst name="invariants">
+         <str name="hidden">synonyms.txt</str> 
+         <str name="hidden">anotherfile.txt</str> 
+       </lst>
+     </requestHandler>
+    -->
+
+  <!-- ping/healthcheck -->
+  <requestHandler name="/admin/ping" class="solr.PingRequestHandler">
+    <lst name="defaults">
+      <str name="qt">search</str>
+      <str name="q">solrpingquery</str>
+      <str name="echoParams">all</str>
+    </lst>
+  </requestHandler>
+
+  <!-- Echo the request contents back to the client -->
+  <requestHandler name="/debug/dump" class="solr.DumpRequestHandler" >
+    <lst name="defaults">
+     <str name="echoParams">explicit</str> 
+     <str name="echoHandler">true</str>
+    </lst>
+  </requestHandler>
+  
+  <!-- Solr Replication
+
+       The SolrReplicationHandler supports replicating indexes from a
+       "master" used for indexing and "salves" used for queries.
+
+       http://wiki.apache.org/solr/SolrReplication 
+
+       In the example below, remove the <lst name="master"> section if
+       this is just a slave and remove  the <lst name="slave"> section
+       if this is just a master.
+    -->
+  <!--
+     <requestHandler name="/replication" class="solr.ReplicationHandler" >
+       <lst name="master">
+         <str name="replicateAfter">commit</str>
+         <str name="replicateAfter">startup</str>
+         <str name="confFiles">schema.xml,stopwords.txt</str>
+       </lst>
+       <lst name="slave">
+         <str name="masterUrl">http://localhost:8983/solr/replication</str>
+         <str name="pollInterval">00:00:60</str>
+       </lst>
+     </requestHandler>
+    -->
+
+  <!-- Search Components
+
+       Search components are registered to SolrCore and used by 
+       instances of SearchHandler (which can access them by name)
+       
+       By default, the following components are available:
+       
+       <searchComponent name="query"     class="solr.QueryComponent" />
+       <searchComponent name="facet"     class="solr.FacetComponent" />
+       <searchComponent name="mlt"       class="solr.MoreLikeThisComponent" />
+       <searchComponent name="highlight" class="solr.HighlightComponent" />
+       <searchComponent name="stats"     class="solr.StatsComponent" />
+       <searchComponent name="debug"     class="solr.DebugComponent" />
+   
+       Default configuration in a requestHandler would look like:
+
+       <arr name="components">
+         <str>query</str>
+         <str>facet</str>
+         <str>mlt</str>
+         <str>highlight</str>
+         <str>stats</str>
+         <str>debug</str>
+       </arr>
+
+       If you register a searchComponent to one of the standard names, 
+       that will be used instead of the default.
+
+       To insert components before or after the 'standard' components, use:
+    
+       <arr name="first-components">
+         <str>myFirstComponentName</str>
+       </arr>
+    
+       <arr name="last-components">
+         <str>myLastComponentName</str>
+       </arr>
+
+       NOTE: The component registered with the name "debug" will
+       always be executed after the "last-components" 
+       
+     -->
+
+   <!-- Spell Check
+
+        The spell check component can return a list of alternative spelling
+        suggestions.  
+
+        http://wiki.apache.org/solr/SpellCheckComponent
+     -->
+  <searchComponent name="spellcheck" class="solr.SpellCheckComponent">
+
+    <str name="queryAnalyzerFieldType">textSpell</str>
+
+    <!-- Multiple "Spell Checkers" can be declared and used by this
+         component
+      -->
+
+    <!-- a spellchecker built from a field of the main index, and
+         written to disk
+      -->
+    <lst name="spellchecker">
+      <str name="name">default</str>
+      <str name="field">name</str>
+      <str name="spellcheckIndexDir">spellchecker</str>
+      <!-- uncomment this to require terms to occur in 1% of the documents in order to be included in the dictionary
+      	<float name="thresholdTokenFrequency">.01</float>
+      -->
+    </lst>
+
+    <!-- a spellchecker that uses a different distance measure -->
+    <!--
+       <lst name="spellchecker">
+         <str name="name">jarowinkler</str>
+         <str name="field">spell</str>
+         <str name="distanceMeasure">
+           org.apache.lucene.search.spell.JaroWinklerDistance
+         </str>
+         <str name="spellcheckIndexDir">spellcheckerJaro</str>
+       </lst>
+     -->
+
+    <!-- a spellchecker that use an alternate comparator 
+
+         comparatorClass be one of:
+          1. score (default)
+          2. freq (Frequency first, then score)
+          3. A fully qualified class name
+      -->
+    <!--
+       <lst name="spellchecker">
+         <str name="name">freq</str>
+         <str name="field">lowerfilt</str>
+         <str name="spellcheckIndexDir">spellcheckerFreq</str>
+         <str name="comparatorClass">freq</str>
+         <str name="buildOnCommit">true</str>
+      -->
+
+    <!-- A spellchecker that reads the list of words from a file -->
+    <!--
+       <lst name="spellchecker">
+         <str name="classname">solr.FileBasedSpellChecker</str>
+         <str name="name">file</str>
+         <str name="sourceLocation">spellings.txt</str>
+         <str name="characterEncoding">UTF-8</str>
+         <str name="spellcheckIndexDir">spellcheckerFile</str>
+       </lst>
+      -->
+  </searchComponent>
+
+  <!-- A request handler for demonstrating the spellcheck component.  
+
+       NOTE: This is purely as an example.  The whole purpose of the
+       SpellCheckComponent is to hook it into the request handler that
+       handles your normal user queries so that a separate request is
+       not needed to get suggestions.
+
+       IN OTHER WORDS, THERE IS REALLY GOOD CHANCE THE SETUP BELOW IS
+       NOT WHAT YOU WANT FOR YOUR PRODUCTION SYSTEM!
+       
+       See http://wiki.apache.org/solr/SpellCheckComponent for details
+       on the request parameters.
+    -->
+  <requestHandler name="/spell" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <str name="spellcheck.onlyMorePopular">false</str>
+      <str name="spellcheck.extendedResults">false</str>
+      <str name="spellcheck.count">1</str>
+    </lst>
+    <arr name="last-components">
+      <str>spellcheck</str>
+    </arr>
+  </requestHandler>
+
+  <!-- Term Vector Component
+
+       http://wiki.apache.org/solr/TermVectorComponent
+    -->
+  <searchComponent name="tvComponent" class="solr.TermVectorComponent"/>
+
+  <!-- A request handler for demonstrating the term vector component
+
+       This is purely as an example.
+
+       In reality you will likely want to add the component to your 
+       already specified request handlers. 
+    -->
+  <requestHandler name="tvrh" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <bool name="tv">true</bool>
+    </lst>
+    <arr name="last-components">
+      <str>tvComponent</str>
+    </arr>
+  </requestHandler>
+
+  <!-- Clustering Component
+
+       http://wiki.apache.org/solr/ClusteringComponent
+
+       This relies on third party jars which are notincluded in the
+       release.  To use this component (and the "/clustering" handler)
+       Those jars will need to be downloaded, and you'll need to set
+       the solr.cluster.enabled system property when running solr...
+
+          java -Dsolr.clustering.enabled=true -jar start.jar
+    -->
+  <searchComponent name="clustering" 
+                   enable="${solr.clustering.enabled:false}"
+                   class="solr.clustering.ClusteringComponent" >
+    <!-- Declare an engine -->
+    <lst name="engine">
+      <!-- The name, only one can be named "default" -->
+      <str name="name">default</str>
+
+      <!-- Class name of Carrot2 clustering algorithm. 
+           
+           Currently available algorithms are:
+           
+           * org.carrot2.clustering.lingo.LingoClusteringAlgorithm
+           * org.carrot2.clustering.stc.STCClusteringAlgorithm
+           * org.carrot2.clustering.kmeans.BisectingKMeansClusteringAlgorithm
+           
+           See http://project.carrot2.org/algorithms.html for the
+           algorithm's characteristics.
+        -->
+      <str name="carrot.algorithm">org.carrot2.clustering.lingo.LingoClusteringAlgorithm</str>
+
+      <!-- Overriding values for Carrot2 default algorithm attributes.
+
+           For a description of all available attributes, see:
+           http://download.carrot2.org/stable/manual/#chapter.components.
+           Use attribute key as name attribute of str elements
+           below. These can be further overridden for individual
+           requests by specifying attribute key as request parameter
+           name and attribute value as parameter value.
+        -->
+      <str name="LingoClusteringAlgorithm.desiredClusterCountBase">20</str>
+      
+      <!-- Location of Carrot2 lexical resources.
+
+           A directory from which to load Carrot2-specific stop words
+           and stop labels. Absolute or relative to Solr config directory.
+           If a specific resource (e.g. stopwords.en) is present in the
+           specified dir, it will completely override the corresponding
+           default one that ships with Carrot2.
+
+           For an overview of Carrot2 lexical resources, see:
+           http://download.carrot2.org/head/manual/#chapter.lexical-resources
+        -->
+      <str name="carrot.lexicalResourcesDir">clustering/carrot2</str>
+
+      <!-- The language to assume for the documents.
+           
+           For a list of allowed values, see:
+           http://download.carrot2.org/stable/manual/#section.attribute.lingo.MultilingualClustering.defaultLanguage
+       -->
+      <str name="MultilingualClustering.defaultLanguage">ENGLISH</str>
+    </lst>
+    <lst name="engine">
+      <str name="name">stc</str>
+      <str name="carrot.algorithm">org.carrot2.clustering.stc.STCClusteringAlgorithm</str>
+    </lst>
+  </searchComponent>
+
+  <!-- A request handler for demonstrating the clustering component
+
+       This is purely as an example.
+
+       In reality you will likely want to add the component to your 
+       already specified request handlers. 
+    -->
+  <requestHandler name="/clustering"
+                  startup="lazy"
+                  enable="${solr.clustering.enabled:false}"
+                  class="solr.SearchHandler">
+    <lst name="defaults">
+      <bool name="clustering">true</bool>
+      <str name="clustering.engine">default</str>
+      <bool name="clustering.results">true</bool>
+      <!-- The title field -->
+      <str name="carrot.title">name</str>
+      <str name="carrot.url">id</str>
+      <!-- The field to cluster on -->
+       <str name="carrot.snippet">features</str>
+       <!-- produce summaries -->
+       <bool name="carrot.produceSummary">true</bool>
+       <!-- the maximum number of labels per cluster -->
+       <!--<int name="carrot.numDescriptions">5</int>-->
+       <!-- produce sub clusters -->
+       <bool name="carrot.outputSubClusters">false</bool>
+       
+       <str name="defType">edismax</str>
+       <str name="qf">
+          text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
+       </str>
+       <str name="q.alt">*:*</str>
+       <str name="rows">10</str>
+       <str name="fl">*,score</str>
+    </lst>     
+    <arr name="last-components">
+      <str>clustering</str>
+    </arr>
+  </requestHandler>
+  
+  <!-- Terms Component
+
+       http://wiki.apache.org/solr/TermsComponent
+
+       A component to return terms and document frequency of those
+       terms
+    -->
+  <searchComponent name="terms" class="solr.TermsComponent"/>
+
+  <!-- A request handler for demonstrating the terms component -->
+  <requestHandler name="/terms" class="solr.SearchHandler" startup="lazy">
+     <lst name="defaults">
+      <bool name="terms">true</bool>
+    </lst>     
+    <arr name="components">
+      <str>terms</str>
+    </arr>
+  </requestHandler>
+
+
+  <!-- Query Elevation Component
+
+       http://wiki.apache.org/solr/QueryElevationComponent
+
+       a search component that enables you to configure the top
+       results for a given query regardless of the normal lucene
+       scoring.
+    -->
+  <searchComponent name="elevator" class="solr.QueryElevationComponent" >
+    <!-- pick a fieldType to analyze queries -->
+    <str name="queryFieldType">string</str>
+    <str name="config-file">elevate.xml</str>
+  </searchComponent>
+
+  <!-- A request handler for demonstrating the elevator component -->
+  <requestHandler name="/elevate" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+    </lst>
+    <arr name="last-components">
+      <str>elevator</str>
+    </arr>
+  </requestHandler>
+
+  <!-- Highlighting Component
+
+       http://wiki.apache.org/solr/HighlightingParameters
+    -->
+  <searchComponent class="solr.HighlightComponent" name="highlight">
+    <highlighting>
+      <!-- Configure the standard fragmenter -->
+      <!-- This could most likely be commented out in the "default" case -->
+      <fragmenter name="gap" 
+                  default="true"
+                  class="solr.highlight.GapFragmenter">
+        <lst name="defaults">
+          <int name="hl.fragsize">100</int>
+        </lst>
+      </fragmenter>
+
+      <!-- A regular-expression-based fragmenter 
+           (for sentence extraction) 
+        -->
+      <fragmenter name="regex" 
+                  class="solr.highlight.RegexFragmenter">
+        <lst name="defaults">
+          <!-- slightly smaller fragsizes work better because of slop -->
+          <int name="hl.fragsize">70</int>
+          <!-- allow 50% slop on fragment sizes -->
+          <float name="hl.regex.slop">0.5</float>
+          <!-- a basic sentence pattern -->
+          <str name="hl.regex.pattern">[-\w ,/\n\&quot;&apos;]{20,200}</str>
+        </lst>
+      </fragmenter>
+
+      <!-- Configure the standard formatter -->
+      <formatter name="html" 
+                 default="true"
+                 class="solr.highlight.HtmlFormatter">
+        <lst name="defaults">
+          <str name="hl.simple.pre"><![CDATA[<em>]]></str>
+          <str name="hl.simple.post"><![CDATA[</em>]]></str>
+        </lst>
+      </formatter>
+
+      <!-- Configure the standard encoder -->
+      <encoder name="html" 
+               class="solr.highlight.HtmlEncoder" />
+
+      <!-- Configure the standard fragListBuilder -->
+      <fragListBuilder name="simple" 
+                       default="true"
+                       class="solr.highlight.SimpleFragListBuilder"/>
+
+      <!-- Configure the single fragListBuilder -->
+      <fragListBuilder name="single" 
+                       class="solr.highlight.SingleFragListBuilder"/>
+
+      <!-- default tag FragmentsBuilder -->
+      <fragmentsBuilder name="default" 
+                        default="true"
+                        class="solr.highlight.ScoreOrderFragmentsBuilder">
+        <!-- 
+        <lst name="defaults">
+          <str name="hl.multiValuedSeparatorChar">/</str>
+        </lst>
+        -->
+      </fragmentsBuilder>
+
+      <!-- multi-colored tag FragmentsBuilder -->
+      <fragmentsBuilder name="colored" 
+                        class="solr.highlight.ScoreOrderFragmentsBuilder">
+        <lst name="defaults">
+          <str name="hl.tag.pre"><![CDATA[
+               <b style="background:yellow">,<b style="background:lawgreen">,
+               <b style="background:aquamarine">,<b style="background:magenta">,
+               <b style="background:palegreen">,<b style="background:coral">,
+               <b style="background:wheat">,<b style="background:khaki">,
+               <b style="background:lime">,<b style="background:deepskyblue">]]></str>
+          <str name="hl.tag.post"><![CDATA[</b>]]></str>
+        </lst>
+      </fragmentsBuilder>
+    </highlighting>
+  </searchComponent>
+
+  <!-- Update Processors
+
+       Chains of Update Processor Factories for dealing with Update
+       Requests can be declared, and then used by name in Update
+       Request Processors
+
+       http://wiki.apache.org/solr/UpdateRequestProcessor
+
+    --> 
+  <!-- Deduplication
+
+       An example dedup update processor that creates the "id" field
+       on the fly based on the hash code of some other fields.  This
+       example has overwriteDupes set to false since we are using the
+       id field as the signatureField and Solr will maintain
+       uniqueness based on that anyway.  
+       
+    -->
+  <!--
+     <updateRequestProcessorChain name="dedupe">
+       <processor class="solr.processor.SignatureUpdateProcessorFactory">
+         <bool name="enabled">true</bool>
+         <str name="signatureField">id</str>
+         <bool name="overwriteDupes">false</bool>
+         <str name="fields">name,features,cat</str>
+         <str name="signatureClass">solr.processor.Lookup3Signature</str>
+       </processor>
+       <processor class="solr.LogUpdateProcessorFactory" />
+       <processor class="solr.RunUpdateProcessorFactory" />
+     </updateRequestProcessorChain>
+    -->
+
+  <!-- Response Writers
+
+       http://wiki.apache.org/solr/QueryResponseWriter
+
+       Request responses will be written using the writer specified by
+       the 'wt' request parameter matching the name of a registered
+       writer.
+
+       The "default" writer is the default and will be used if 'wt' is
+       not specified in the request.
+    -->
+  <!-- The following response writers are implicitly configured unless
+       overridden...
+    -->
+  <!--
+     <queryResponseWriter name="xml" 
+                          default="true"
+                          class="solr.XMLResponseWriter" />
+     <queryResponseWriter name="json" class="solr.JSONResponseWriter"/>
+     <queryResponseWriter name="python" class="solr.PythonResponseWriter"/>
+     <queryResponseWriter name="ruby" class="solr.RubyResponseWriter"/>
+     <queryResponseWriter name="php" class="solr.PHPResponseWriter"/>
+     <queryResponseWriter name="phps" class="solr.PHPSerializedResponseWriter"/>
+     <queryResponseWriter name="velocity" class="solr.VelocityResponseWriter"/>
+     <queryResponseWriter name="csv" class="solr.CSVResponseWriter"/>
+    -->
+  <!--
+     Custom response writers can be declared as needed...
+    -->
+  <!--
+     <queryResponseWriter name="custom" class="com.example.MyResponseWriter"/>
+    -->
+
+  <!-- XSLT response writer transforms the XML output by any xslt file found
+       in Solr's conf/xslt directory.  Changes to xslt files are checked for
+       every xsltCacheLifetimeSeconds.  
+    -->
+  <queryResponseWriter name="xslt" class="solr.XSLTResponseWriter">
+    <int name="xsltCacheLifetimeSeconds">5</int>
+  </queryResponseWriter>
+
+  <!-- Query Parsers
+
+       http://wiki.apache.org/solr/SolrQuerySyntax
+
+       Multiple QParserPlugins can be registered by name, and then
+       used in either the "defType" param for the QueryComponent (used
+       by SearchHandler) or in LocalParams
+    -->
+  <!-- example of registering a query parser -->
+  <!--
+     <queryParser name="myparser" class="com.mycompany.MyQParserPlugin"/>
+    -->
+
+  <!-- Function Parsers
+
+       http://wiki.apache.org/solr/FunctionQuery
+
+       Multiple ValueSourceParsers can be registered by name, and then
+       used as function names when using the "func" QParser.
+    -->
+  <!-- example of registering a custom function parser  -->
+  <!--
+     <valueSourceParser name="myfunc" 
+                        class="com.mycompany.MyValueSourceParser" />
+    -->
+
+  <!-- Legacy config for the admin interface -->
+  <admin>
+    <defaultQuery>*:*</defaultQuery>
+
+    <!-- configure a healthcheck file for servers behind a
+         loadbalancer 
+      -->
+    <!--
+       <healthcheck type="file">server-enabled</healthcheck>
+      -->
+  </admin>
+
+</config>
Index: gs3-extensions/solr/trunk/src/etc/conf/solrconfig.xml.in
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/solrconfig.xml.in	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/solrconfig.xml.in	(revision 24446)
@@ -0,0 +1,1533 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- 
+     For more details about configurations options that may appear in
+     this file, see http://wiki.apache.org/solr/SolrConfigXml. 
+-->
+<config>
+  <!-- In all configuration below, a prefix of "solr." for class names
+       is an alias that causes solr to search appropriate packages,
+       including org.apache.solr.(search|update|request|core|analysis)
+
+       You may also specify a fully qualified Java classname if you
+       have your own custom plugins.
+    -->
+
+  <!-- Set this to 'false' if you want solr to continue working after
+       it has encountered an severe configuration error.  In a
+       production environment, you may want solr to keep working even
+       if one handler is mis-configured.
+
+       You may also set this to false using by setting the system
+       property:
+
+         -Dsolr.abortOnConfigurationError=false
+    -->
+  <abortOnConfigurationError>${solr.abortOnConfigurationError:true}</abortOnConfigurationError>
+  
+  <!-- Controls what version of Lucene various components of Solr
+       adhere to.  Generally, you want to use the latest version to
+       get all bug fixes and improvements. It is highly recommended
+       that you fully re-index after changing this setting as it can
+       affect both how text is indexed and queried.
+    -->
+  <luceneMatchVersion>LUCENE_33</luceneMatchVersion>
+
+  <!-- lib directives can be used to instruct Solr to load an Jars
+       identified and use them to resolve any "plugins" specified in
+       your solrconfig.xml or schema.xml (ie: Analyzers, Request
+       Handlers, etc...).
+
+       All directories and paths are resolved relative to the
+       instanceDir.
+
+       If a "./lib" directory exists in your instanceDir, all files
+       found in it are included as if you had used the following
+       syntax...
+       
+              <lib dir="./lib" />
+    -->
+  <!-- A dir option by itself adds any files found in the directory to
+       the classpath, this is useful for including all jars in a
+       directory.
+    -->
+  <lib dir="../../contrib/extraction/lib" />
+  <!-- When a regex is specified in addition to a directory, only the
+       files in that directory which completely match the regex
+       (anchored on both ends) will be included.
+    -->
+  <lib dir="../../dist/" regex="apache-solr-cell-\d.*\.jar" />
+  <lib dir="../../dist/" regex="apache-solr-clustering-\d.*\.jar" />
+  <lib dir="../../dist/" regex="apache-solr-dataimporthandler-\d.*\.jar" />
+
+  <!-- If a dir option (with or without a regex) is used and nothing
+       is found that matches, it will be ignored
+    -->
+  <lib dir="../../contrib/clustering/lib/" />
+  <lib dir="/total/crap/dir/ignored" /> 
+  <!-- an exact path can be used to specify a specific file.  This
+       will cause a serious error to be logged if it can't be loaded.
+    -->
+  <!--
+  <lib path="../a-jar-that-does-not-exist.jar" /> 
+  -->
+  
+  <!-- Data Directory
+
+       Used to specify an alternate directory to hold all index data
+       other than the default ./data under the Solr home.  If
+       replication is in use, this should match the replication
+       configuration.
+    -->
+  <dataDir>${solr.data.dir:}</dataDir>
+
+
+  <!-- The DirectoryFactory to use for indexes.
+       
+       solr.StandardDirectoryFactory, the default, is filesystem
+       based.  solr.RAMDirectoryFactory is memory based, not
+       persistent, and doesn't work with replication.
+    -->
+  <directoryFactory name="DirectoryFactory" 
+                    class="${solr.directoryFactory:solr.StandardDirectoryFactory}"/>
+
+
+  <!-- Index Defaults
+
+       Values here affect all index writers and act as a default
+       unless overridden.
+
+       WARNING: See also the <mainIndex> section below for parameters
+       that overfor Solr's main Lucene index.
+    -->
+  <indexDefaults>
+
+    <useCompoundFile>false</useCompoundFile>
+
+    <mergeFactor>10</mergeFactor>
+    <!-- Sets the amount of RAM that may be used by Lucene indexing
+         for buffering added documents and deletions before they are
+         flushed to the Directory.  -->
+    <ramBufferSizeMB>32</ramBufferSizeMB>
+    <!-- If both ramBufferSizeMB and maxBufferedDocs is set, then
+         Lucene will flush based on whichever limit is hit first.  
+      -->
+    <!-- <maxBufferedDocs>1000</maxBufferedDocs> -->
+
+    <maxFieldLength>10000</maxFieldLength>
+    <writeLockTimeout>1000</writeLockTimeout>
+    <commitLockTimeout>10000</commitLockTimeout>
+
+    <!-- Expert: Merge Policy 
+
+         The Merge Policy in Lucene controls how merging is handled by
+         Lucene.  The default in Solr 3.3 is TieredMergePolicy.
+         
+         The default in 2.3 was the LogByteSizeMergePolicy,
+         previous versions used LogDocMergePolicy.
+         
+         LogByteSizeMergePolicy chooses segments to merge based on
+         their size.  The Lucene 2.2 default, LogDocMergePolicy chose
+         when to merge based on number of documents
+         
+         Other implementations of MergePolicy must have a no-argument
+         constructor
+      -->
+    <!--
+       <mergePolicy class="org.apache.lucene.index.TieredMergePolicy"/>
+       -->
+
+    <!-- Expert: Merge Scheduler
+
+         The Merge Scheduler in Lucene controls how merges are
+         performed.  The ConcurrentMergeScheduler (Lucene 2.3 default)
+         can perform merges in the background using separate threads.
+         The SerialMergeScheduler (Lucene 2.2 default) does not.
+     -->
+    <!-- 
+       <mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"/>
+       -->
+	  
+    <!-- LockFactory 
+
+         This option specifies which Lucene LockFactory implementation
+         to use.
+      
+         single = SingleInstanceLockFactory - suggested for a
+                  read-only index or when there is no possibility of
+                  another process trying to modify the index.
+         native = NativeFSLockFactory - uses OS native file locking.
+                  Do not use when multiple solr webapps in the same
+                  JVM are attempting to share a single index.
+         simple = SimpleFSLockFactory  - uses a plain file for locking
+
+         (For backwards compatibility with Solr 1.2, 'simple' is the
+         default if not specified.)
+
+         More details on the nuances of each LockFactory...
+         http://wiki.apache.org/lucene-java/AvailableLockFactories
+    -->
+    <lockType>native</lockType>
+
+    <!-- Expert: Controls how often Lucene loads terms into memory
+         Default is 128 and is likely good for most everyone.
+      -->
+    <!-- <termIndexInterval>256</termIndexInterval> -->
+  </indexDefaults>
+
+  <!-- Main Index
+
+       Values here override the values in the <indexDefaults> section
+       for the main on disk index.
+    -->
+  <mainIndex>
+
+    <useCompoundFile>false</useCompoundFile>
+    <ramBufferSizeMB>32</ramBufferSizeMB>
+    <mergeFactor>10</mergeFactor>
+
+    <!-- Unlock On Startup
+
+         If true, unlock any held write or commit locks on startup.
+         This defeats the locking mechanism that allows multiple
+         processes to safely access a lucene index, and should be used
+         with care.
+
+         This is not needed if lock type is 'none' or 'single'
+     -->
+    <unlockOnStartup>false</unlockOnStartup>
+    
+    <!-- If true, IndexReaders will be reopened (often more efficient)
+         instead of closed and then opened.
+      -->
+    <reopenReaders>true</reopenReaders>
+
+    <!-- Commit Deletion Policy
+
+         Custom deletion policies can specified here. The class must
+         implement org.apache.lucene.index.IndexDeletionPolicy.
+
+         http://lucene.apache.org/java/2_9_1/api/all/org/apache/lucene/index/IndexDeletionPolicy.html
+
+         The standard Solr IndexDeletionPolicy implementation supports
+         deleting index commit points on number of commits, age of
+         commit point and optimized status.
+         
+         The latest commit point should always be preserved regardless
+         of the criteria.
+    -->
+    <deletionPolicy class="solr.SolrDeletionPolicy">
+      <!-- The number of commit points to be kept -->
+      <str name="maxCommitsToKeep">1</str>
+      <!-- The number of optimized commit points to be kept -->
+      <str name="maxOptimizedCommitsToKeep">0</str>
+      <!--
+          Delete all commit points once they have reached the given age.
+          Supports DateMathParser syntax e.g.
+        -->
+      <!--
+         <str name="maxCommitAge">30MINUTES</str>
+         <str name="maxCommitAge">1DAY</str>
+      -->
+    </deletionPolicy>
+
+    <!-- Lucene Infostream
+       
+         To aid in advanced debugging, Lucene provides an "InfoStream"
+         of detailed information when indexing.
+
+         Setting The value to true will instruct the underlying Lucene
+         IndexWriter to write its debugging info the specified file
+      -->
+     <infoStream file="INFOSTREAM.txt">false</infoStream> 
+
+  </mainIndex>
+
+  <!-- JMX
+       
+       This example enables JMX if and only if an existing MBeanServer
+       is found, use this if you want to configure JMX through JVM
+       parameters. Remove this to disable exposing Solr configuration
+       and statistics to JMX.
+
+       For more details see http://wiki.apache.org/solr/SolrJmx
+    -->
+  <jmx />
+  <!-- If you want to connect to a particular server, specify the
+       agentId 
+    -->
+  <!-- <jmx agentId="myAgent" /> -->
+  <!-- If you want to start a new MBeanServer, specify the serviceUrl -->
+  <!-- <jmx serviceUrl="service:jmx:rmi:///jndi/rmi://localhost:9999/solr"/>
+    -->
+
+  <!-- The default high-performance update handler -->
+  <updateHandler class="solr.DirectUpdateHandler2">
+
+    <!-- AutoCommit
+
+         Perform a <commit/> automatically under certain conditions.
+         Instead of enabling autoCommit, consider using "commitWithin"
+         when adding documents. 
+
+         http://wiki.apache.org/solr/UpdateXmlMessages
+
+         maxDocs - Maximum number of documents to add since the last
+                   commit before automatically triggering a new commit.
+
+         maxTime - Maximum amount of time that is allowed to pass
+                   since a document was added before automaticly
+                   triggering a new commit. 
+      -->
+    <!--
+       <autoCommit> 
+         <maxDocs>10000</maxDocs>
+         <maxTime>1000</maxTime> 
+       </autoCommit>
+      -->
+
+    <!-- Update Related Event Listeners
+         
+         Various IndexWriter related events can trigger Listeners to
+         take actions.
+
+         postCommit - fired after every commit or optimize command
+         postOptimize - fired after every optimize command
+      -->
+    <!-- The RunExecutableListener executes an external command from a
+         hook such as postCommit or postOptimize.
+         
+         exe - the name of the executable to run
+         dir - dir to use as the current working directory. (default=".")
+         wait - the calling thread waits until the executable returns. 
+                (default="true")
+         args - the arguments to pass to the program.  (default is none)
+         env - environment variables to set.  (default is none)
+      -->
+    <!-- This example shows how RunExecutableListener could be used
+         with the script based replication...
+         http://wiki.apache.org/solr/CollectionDistribution
+      -->
+    <!--
+       <listener event="postCommit" class="solr.RunExecutableListener">
+         <str name="exe">solr/bin/snapshooter</str>
+         <str name="dir">.</str>
+         <bool name="wait">true</bool>
+         <arr name="args"> <str>arg1</str> <str>arg2</str> </arr>
+         <arr name="env"> <str>MYVAR=val1</str> </arr>
+       </listener>
+      -->
+  </updateHandler>
+  
+  <!-- IndexReaderFactory
+
+       Use the following format to specify a custom IndexReaderFactory,
+       which allows for alternate IndexReader implementations.
+
+       ** Experimental Feature **
+
+       Please note - Using a custom IndexReaderFactory may prevent
+       certain other features from working. The API to
+       IndexReaderFactory may change without warning or may even be
+       removed from future releases if the problems cannot be
+       resolved.
+
+
+       ** Features that may not work with custom IndexReaderFactory **
+
+       The ReplicationHandler assumes a disk-resident index. Using a
+       custom IndexReader implementation may cause incompatibility
+       with ReplicationHandler and may cause replication to not work
+       correctly. See SOLR-1366 for details.
+
+    -->
+  <!--
+  <indexReaderFactory name="IndexReaderFactory" class="package.class">
+    <str name="someArg">Some Value</str>
+  </indexReaderFactory >
+  -->
+  <!-- By explicitly declaring the Factory, the termIndexDivisor can
+       be specified.
+    -->
+  <!--
+     <indexReaderFactory name="IndexReaderFactory" 
+                         class="solr.StandardIndexReaderFactory">
+       <int name="setTermIndexDivisor">12</int>
+     </indexReaderFactory >
+    -->
+
+
+  <query>
+    <!-- Max Boolean Clauses
+
+         Maximum number of clauses in each BooleanQuery,  an exception
+         is thrown if exceeded.
+
+         ** WARNING **
+         
+         This option actually modifies a global Lucene property that
+         will affect all SolrCores.  If multiple solrconfig.xml files
+         disagree on this property, the value at any given moment will
+         be based on the last SolrCore to be initialized.
+         
+      -->
+    <maxBooleanClauses>1024</maxBooleanClauses>
+
+
+    <!-- Solr Internal Query Caches
+
+         There are two implementations of cache available for Solr,
+         LRUCache, based on a synchronized LinkedHashMap, and
+         FastLRUCache, based on a ConcurrentHashMap.  
+
+         FastLRUCache has faster gets and slower puts in single
+         threaded operation and thus is generally faster than LRUCache
+         when the hit ratio of the cache is high (> 75%), and may be
+         faster under other scenarios on multi-cpu systems.
+    -->
+
+    <!-- Filter Cache
+
+         Cache used by SolrIndexSearcher for filters (DocSets),
+         unordered sets of *all* documents that match a query.  When a
+         new searcher is opened, its caches may be prepopulated or
+         "autowarmed" using data from caches in the old searcher.
+         autowarmCount is the number of items to prepopulate.  For
+         LRUCache, the autowarmed items will be the most recently
+         accessed items.
+
+         Parameters:
+           class - the SolrCache implementation LRUCache or
+               (LRUCache or FastLRUCache)
+           size - the maximum number of entries in the cache
+           initialSize - the initial capacity (number of entries) of
+               the cache.  (see java.util.HashMap)
+           autowarmCount - the number of entries to prepopulate from
+               and old cache.  
+      -->
+    <filterCache class="solr.FastLRUCache"
+                 size="512"
+                 initialSize="512"
+                 autowarmCount="0"/>
+
+    <!-- Query Result Cache
+         
+         Caches results of searches - ordered lists of document ids
+         (DocList) based on a query, a sort, and the range of documents requested.  
+      -->
+    <queryResultCache class="solr.LRUCache"
+                     size="512"
+                     initialSize="512"
+                     autowarmCount="0"/>
+   
+    <!-- Document Cache
+
+         Caches Lucene Document objects (the stored fields for each
+         document).  Since Lucene internal document ids are transient,
+         this cache will not be autowarmed.  
+      -->
+    <documentCache class="solr.LRUCache"
+                   size="512"
+                   initialSize="512"
+                   autowarmCount="0"/>
+    
+    <!-- Field Value Cache
+         
+         Cache used to hold field values that are quickly accessible
+         by document id.  The fieldValueCache is created by default
+         even if not configured here.
+      -->
+    <!--
+       <fieldValueCache class="solr.FastLRUCache"
+                        size="512"
+                        autowarmCount="128"
+                        showItems="32" />
+      -->
+
+    <!-- Custom Cache
+
+         Example of a generic cache.  These caches may be accessed by
+         name through SolrIndexSearcher.getCache(),cacheLookup(), and
+         cacheInsert().  The purpose is to enable easy caching of
+         user/application level data.  The regenerator argument should
+         be specified as an implementation of solr.CacheRegenerator 
+         if autowarming is desired.  
+      -->
+    <!--
+       <cache name="myUserCache"
+              class="solr.LRUCache"
+              size="4096"
+              initialSize="1024"
+              autowarmCount="1024"
+              regenerator="com.mycompany.MyRegenerator"
+              />
+      -->
+
+
+    <!-- Lazy Field Loading
+
+         If true, stored fields that are not requested will be loaded
+         lazily.  This can result in a significant speed improvement
+         if the usual case is to not load all stored fields,
+         especially if the skipped fields are large compressed text
+         fields.
+    -->
+    <enableLazyFieldLoading>true</enableLazyFieldLoading>
+
+   <!-- Use Filter For Sorted Query
+
+        A possible optimization that attempts to use a filter to
+        satisfy a search.  If the requested sort does not include
+        score, then the filterCache will be checked for a filter
+        matching the query. If found, the filter will be used as the
+        source of document ids, and then the sort will be applied to
+        that.
+
+        For most situations, this will not be useful unless you
+        frequently get the same search repeatedly with different sort
+        options, and none of them ever use "score"
+     -->
+   <!--
+      <useFilterForSortedQuery>true</useFilterForSortedQuery>
+     -->
+
+   <!-- Result Window Size
+
+        An optimization for use with the queryResultCache.  When a search
+        is requested, a superset of the requested number of document ids
+        are collected.  For example, if a search for a particular query
+        requests matching documents 10 through 19, and queryWindowSize is 50,
+        then documents 0 through 49 will be collected and cached.  Any further
+        requests in that range can be satisfied via the cache.  
+     -->
+   <queryResultWindowSize>20</queryResultWindowSize>
+
+   <!-- Maximum number of documents to cache for any entry in the
+        queryResultCache. 
+     -->
+   <queryResultMaxDocsCached>200</queryResultMaxDocsCached>
+
+   <!-- Query Related Event Listeners
+
+        Various IndexSearcher related events can trigger Listeners to
+        take actions.
+
+        newSearcher - fired whenever a new searcher is being prepared
+        and there is a current searcher handling requests (aka
+        registered).  It can be used to prime certain caches to
+        prevent long request times for certain requests.
+
+        firstSearcher - fired whenever a new searcher is being
+        prepared but there is no current registered searcher to handle
+        requests or to gain autowarming data from.
+
+        
+     -->
+    <!-- QuerySenderListener takes an array of NamedList and executes a
+         local query request for each NamedList in sequence. 
+      -->
+    <listener event="newSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <!--
+           <lst><str name="q">solr</str><str name="sort">price asc</str></lst>
+           <lst><str name="q">rocks</str><str name="sort">weight asc</str></lst>
+          -->
+      </arr>
+    </listener>
+    <listener event="firstSearcher" class="solr.QuerySenderListener">
+      <arr name="queries">
+        <lst>
+          <str name="q">static firstSearcher warming in solrconfig.xml</str>
+        </lst>
+      </arr>
+    </listener>
+
+    <!-- Use Cold Searcher
+
+         If a search request comes in and there is no current
+         registered searcher, then immediately register the still
+         warming searcher and use it.  If "false" then all requests
+         will block until the first searcher is done warming.
+      -->
+    <useColdSearcher>false</useColdSearcher>
+
+    <!-- Max Warming Searchers
+         
+         Maximum number of searchers that may be warming in the
+         background concurrently.  An error is returned if this limit
+         is exceeded.
+
+         Recommend values of 1-2 for read-only slaves, higher for
+         masters w/o cache warming.
+      -->
+    <maxWarmingSearchers>2</maxWarmingSearchers>
+
+  </query>
+
+
+  <!-- Request Dispatcher
+
+       This section contains instructions for how the SolrDispatchFilter
+       should behave when processing requests for this SolrCore.
+
+       handleSelect affects the behavior of requests such as /select?qt=XXX
+
+       handleSelect="true" will cause the SolrDispatchFilter to process
+       the request and will result in consistent error handling and
+       formatting for all types of requests.
+
+       handleSelect="false" will cause the SolrDispatchFilter to
+       ignore "/select" requests and fallback to using the legacy
+       SolrServlet and it's Solr 1.1 style error formatting
+    -->
+  <requestDispatcher handleSelect="true" >
+    <!-- Request Parsing
+
+         These settings indicate how Solr Requests may be parsed, and
+         what restrictions may be placed on the ContentStreams from
+         those requests
+
+         enableRemoteStreaming - enables use of the stream.file
+         and stream.url parameters for specifying remote streams.
+
+         multipartUploadLimitInKB - specifies the max size of
+         Multipart File Uploads that Solr will allow in a Request.
+         
+         *** WARNING ***
+         The settings below authorize Solr to fetch remote files, You
+         should make sure your system has some authentication before
+         using enableRemoteStreaming="true"
+
+      --> 
+    <requestParsers enableRemoteStreaming="true" 
+                    multipartUploadLimitInKB="2048000" />
+
+    <!-- HTTP Caching
+
+         Set HTTP caching related parameters (for proxy caches and clients).
+
+         The options below instruct Solr not to output any HTTP Caching
+         related headers
+      -->
+    <httpCaching never304="true" />
+    <!-- If you include a <cacheControl> directive, it will be used to
+         generate a Cache-Control header (as well as an Expires header
+         if the value contains "max-age=")
+         
+         By default, no Cache-Control header is generated.
+         
+         You can use the <cacheControl> option even if you have set
+         never304="true"
+      -->
+    <!--
+       <httpCaching never304="true" >
+         <cacheControl>max-age=30, public</cacheControl> 
+       </httpCaching>
+      -->
+    <!-- To enable Solr to respond with automatically generated HTTP
+         Caching headers, and to response to Cache Validation requests
+         correctly, set the value of never304="false"
+         
+         This will cause Solr to generate Last-Modified and ETag
+         headers based on the properties of the Index.
+
+         The following options can also be specified to affect the
+         values of these headers...
+
+         lastModFrom - the default value is "openTime" which means the
+         Last-Modified value (and validation against If-Modified-Since
+         requests) will all be relative to when the current Searcher
+         was opened.  You can change it to lastModFrom="dirLastMod" if
+         you want the value to exactly correspond to when the physical
+         index was last modified.
+
+         etagSeed="..." is an option you can change to force the ETag
+         header (and validation against If-None-Match requests) to be
+         different even if the index has not changed (ie: when making
+         significant changes to your config file)
+
+         (lastModifiedFrom and etagSeed are both ignored if you use
+         the never304="true" option)
+      -->
+    <!--
+       <httpCaching lastModifiedFrom="openTime"
+                    etagSeed="Solr">
+         <cacheControl>max-age=30, public</cacheControl> 
+       </httpCaching>
+      -->
+  </requestDispatcher>
+
+  <!-- Request Handlers 
+
+       http://wiki.apache.org/solr/SolrRequestHandler
+
+       incoming queries will be dispatched to the correct handler
+       based on the path or the qt (query type) param.
+
+       Names starting with a '/' are accessed with the a path equal to
+       the registered name.  Names without a leading '/' are accessed
+       with: http://host/app/[core/]select?qt=name
+
+       If a /select request is processed with out a qt param
+       specified, the requestHandler that declares default="true" will
+       be used.
+       
+       If a Request Handler is declared with startup="lazy", then it will
+       not be initialized until the first request that uses it.
+
+    -->
+  <!-- SearchHandler
+
+       http://wiki.apache.org/solr/SearchHandler
+
+       For processing Search Queries, the primary Request Handler
+       provided with Solr is "SearchHandler" It delegates to a sequent
+       of SearchComponents (see below) and supports distributed
+       queries across multiple shards
+    -->
+  <requestHandler name="search" class="solr.SearchHandler" default="true">
+    <!-- default values for query parameters can be specified, these
+         will be overridden by parameters in the request
+      -->
+     <lst name="defaults">
+       <str name="echoParams">explicit</str>
+       <int name="rows">10</int>
+     </lst>
+    <!-- In addition to defaults, "appends" params can be specified
+         to identify values which should be appended to the list of
+         multi-val params from the query (or the existing "defaults").
+      -->
+    <!-- In this example, the param "fq=instock:true" would be appended to
+         any query time fq params the user may specify, as a mechanism for
+         partitioning the index, independent of any user selected filtering
+         that may also be desired (perhaps as a result of faceted searching).
+
+         NOTE: there is *absolutely* nothing a client can do to prevent these
+         "appends" values from being used, so don't use this mechanism
+         unless you are sure you always want it.
+      -->
+    <!--
+       <lst name="appends">
+         <str name="fq">inStock:true</str>
+       </lst>
+      -->
+    <!-- "invariants" are a way of letting the Solr maintainer lock down
+         the options available to Solr clients.  Any params values
+         specified here are used regardless of what values may be specified
+         in either the query, the "defaults", or the "appends" params.
+
+         In this example, the facet.field and facet.query params would
+         be fixed, limiting the facets clients can use.  Faceting is
+         not turned on by default - but if the client does specify
+         facet=true in the request, these are the only facets they
+         will be able to see counts for; regardless of what other
+         facet.field or facet.query params they may specify.
+
+         NOTE: there is *absolutely* nothing a client can do to prevent these
+         "invariants" values from being used, so don't use this mechanism
+         unless you are sure you always want it.
+      -->
+    <!--
+       <lst name="invariants">
+         <str name="facet.field">cat</str>
+         <str name="facet.field">manu_exact</str>
+         <str name="facet.query">price:[* TO 500]</str>
+         <str name="facet.query">price:[500 TO *]</str>
+       </lst>
+      -->
+    <!-- If the default list of SearchComponents is not desired, that
+         list can either be overridden completely, or components can be
+         prepended or appended to the default list.  (see below)
+      -->
+    <!--
+       <arr name="components">
+         <str>nameOfCustomComponent1</str>
+         <str>nameOfCustomComponent2</str>
+       </arr>
+      -->
+    </requestHandler>
+
+  <!-- A Robust Example
+
+       This example SearchHandler declaration shows off usage of the
+       SearchHandler with many defaults declared
+
+       Note that multiple instances of the same Request Handler
+       (SearchHandler) can be registered multiple times with different
+       names (and different init parameters)
+    -->
+  <requestHandler name="/browse" class="solr.SearchHandler">
+     <lst name="defaults">
+       <str name="echoParams">explicit</str>
+
+       <!-- VelocityResponseWriter settings -->
+       <str name="wt">velocity</str>
+
+       <str name="v.template">browse</str>
+       <str name="v.layout">layout</str>
+       <str name="title">Solritas</str>
+
+       <str name="defType">edismax</str>
+       <str name="q.alt">*:*</str>
+       <str name="rows">10</str>
+       <str name="fl">*,score</str>
+       <str name="mlt.qf">
+         text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
+       </str>
+       <str name="mlt.fl">text,features,name,sku,id,manu,cat</str>
+       <int name="mlt.count">3</int>
+
+       <str name="qf">
+          text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
+       </str>
+
+       <str name="facet">on</str>
+       <str name="facet.field">cat</str>
+       <str name="facet.field">manu_exact</str>
+       <str name="facet.query">ipod</str>
+       <str name="facet.query">GB</str>
+       <str name="facet.mincount">1</str>
+       <str name="facet.pivot">cat,inStock</str>
+       <str name="facet.range">price</str>
+       <int name="f.price.facet.range.start">0</int>
+       <int name="f.price.facet.range.end">600</int>
+       <int name="f.price.facet.range.gap">50</int>
+       <str name="f.price.facet.range.other">after</str>
+       <str name="facet.range">manufacturedate_dt</str>
+       <str name="f.manufacturedate_dt.facet.range.start">NOW/YEAR-10YEARS</str>
+       <str name="f.manufacturedate_dt.facet.range.end">NOW</str>
+       <str name="f.manufacturedate_dt.facet.range.gap">+1YEAR</str>
+       <str name="f.manufacturedate_dt.facet.range.other">before</str>
+       <str name="f.manufacturedate_dt.facet.range.other">after</str>
+
+
+       <!-- Highlighting defaults -->
+       <str name="hl">on</str>
+       <str name="hl.fl">text features name</str>
+       <str name="f.name.hl.fragsize">0</str>
+       <str name="f.name.hl.alternateField">name</str>
+     </lst>
+     <arr name="last-components">
+       <str>spellcheck</str>
+     </arr>
+     <!--
+     <str name="url-scheme">httpx</str>
+     -->
+  </requestHandler>
+
+  <!-- XML Update Request Handler.  
+       
+       http://wiki.apache.org/solr/UpdateXmlMessages
+
+       The canonical Request Handler for Modifying the Index through
+       commands specified using XML.
+
+       Note: Since solr1.1 requestHandlers requires a valid content
+       type header if posted in the body. For example, curl now
+       requires: -H 'Content-type:text/xml; charset=utf-8'
+    -->
+  <requestHandler name="/update" 
+                  class="solr.XmlUpdateRequestHandler">
+    <!-- See below for information on defining 
+         updateRequestProcessorChains that can be used by name 
+         on each Update Request
+      -->
+    <!--
+       <lst name="defaults">
+         <str name="update.chain">dedupe</str>
+       </lst>
+       -->
+    </requestHandler>
+  <!-- Binary Update Request Handler
+       http://wiki.apache.org/solr/javabin
+    -->
+  <requestHandler name="/update/javabin" 
+                  class="solr.BinaryUpdateRequestHandler" />
+
+  <!-- CSV Update Request Handler
+       http://wiki.apache.org/solr/UpdateCSV
+    -->
+  <requestHandler name="/update/csv" 
+                  class="solr.CSVRequestHandler" 
+                  startup="lazy" />
+
+  <!-- JSON Update Request Handler
+       http://wiki.apache.org/solr/UpdateJSON
+    -->
+  <requestHandler name="/update/json" 
+                  class="solr.JsonUpdateRequestHandler" 
+                  startup="lazy" />
+
+  <!-- Solr Cell Update Request Handler
+
+       http://wiki.apache.org/solr/ExtractingRequestHandler 
+
+    -->
+  <requestHandler name="/update/extract" 
+                  startup="lazy"
+                  class="solr.extraction.ExtractingRequestHandler" >
+    <lst name="defaults">
+      <!-- All the main content goes into "text"... if you need to return
+           the extracted text or do highlighting, use a stored field. -->
+      <str name="fmap.content">text</str>
+      <str name="lowernames">true</str>
+      <str name="uprefix">ignored_</str>
+
+      <!-- capture link hrefs but ignore div attributes -->
+      <str name="captureAttr">true</str>
+      <str name="fmap.a">links</str>
+      <str name="fmap.div">ignored_</str>
+    </lst>
+  </requestHandler>
+
+  <!-- Field Analysis Request Handler
+
+       RequestHandler that provides much the same functionality as
+       analysis.jsp. Provides the ability to specify multiple field
+       types and field names in the same request and outputs
+       index-time and query-time analysis for each of them.
+
+       Request parameters are:
+       analysis.fieldname - field name whose analyzers are to be used
+
+       analysis.fieldtype - field type whose analyzers are to be used
+       analysis.fieldvalue - text for index-time analysis
+       q (or analysis.q) - text for query time analysis
+       analysis.showmatch (true|false) - When set to true and when
+           query analysis is performed, the produced tokens of the
+           field value analysis will be marked as "matched" for every
+           token that is produces by the query analysis
+   -->
+  <requestHandler name="/analysis/field" 
+                  startup="lazy"
+                  class="solr.FieldAnalysisRequestHandler" />
+
+
+  <!-- Document Analysis Handler
+
+       http://wiki.apache.org/solr/AnalysisRequestHandler
+
+       An analysis handler that provides a breakdown of the analysis
+       process of provided docuemnts. This handler expects a (single)
+       content stream with the following format:
+
+       <docs>
+         <doc>
+           <field name="id">1</field>
+           <field name="name">The Name</field>
+           <field name="text">The Text Value</field>
+         </doc>
+         <doc>...</doc>
+         <doc>...</doc>
+         ...
+       </docs>
+
+    Note: Each document must contain a field which serves as the
+    unique key. This key is used in the returned response to associate
+    an analysis breakdown to the analyzed document.
+
+    Like the FieldAnalysisRequestHandler, this handler also supports
+    query analysis by sending either an "analysis.query" or "q"
+    request parameter that holds the query text to be analyzed. It
+    also supports the "analysis.showmatch" parameter which when set to
+    true, all field tokens that match the query tokens will be marked
+    as a "match". 
+  -->
+  <requestHandler name="/analysis/document" 
+                  class="solr.DocumentAnalysisRequestHandler" 
+                  startup="lazy" />
+
+  <!-- Admin Handlers
+
+       Admin Handlers - This will register all the standard admin
+       RequestHandlers.  
+    -->
+  <requestHandler name="/admin/" 
+                  class="solr.admin.AdminHandlers" />
+  <!-- This single handler is equivalent to the following... -->
+  <!--
+     <requestHandler name="/admin/luke"       class="solr.admin.LukeRequestHandler" />
+     <requestHandler name="/admin/system"     class="solr.admin.SystemInfoHandler" />
+     <requestHandler name="/admin/plugins"    class="solr.admin.PluginInfoHandler" />
+     <requestHandler name="/admin/threads"    class="solr.admin.ThreadDumpHandler" />
+     <requestHandler name="/admin/properties" class="solr.admin.PropertiesRequestHandler" />
+     <requestHandler name="/admin/file"       class="solr.admin.ShowFileRequestHandler" >
+    -->
+  <!-- If you wish to hide files under ${solr.home}/conf, explicitly
+       register the ShowFileRequestHandler using: 
+    -->
+  <!--
+     <requestHandler name="/admin/file" 
+                     class="solr.admin.ShowFileRequestHandler" >
+       <lst name="invariants">
+         <str name="hidden">synonyms.txt</str> 
+         <str name="hidden">anotherfile.txt</str> 
+       </lst>
+     </requestHandler>
+    -->
+
+  <!-- ping/healthcheck -->
+  <requestHandler name="/admin/ping" class="solr.PingRequestHandler">
+    <lst name="defaults">
+      <str name="qt">search</str>
+      <str name="q">solrpingquery</str>
+      <str name="echoParams">all</str>
+    </lst>
+  </requestHandler>
+
+  <!-- Echo the request contents back to the client -->
+  <requestHandler name="/debug/dump" class="solr.DumpRequestHandler" >
+    <lst name="defaults">
+     <str name="echoParams">explicit</str> 
+     <str name="echoHandler">true</str>
+    </lst>
+  </requestHandler>
+  
+  <!-- Solr Replication
+
+       The SolrReplicationHandler supports replicating indexes from a
+       "master" used for indexing and "salves" used for queries.
+
+       http://wiki.apache.org/solr/SolrReplication 
+
+       In the example below, remove the <lst name="master"> section if
+       this is just a slave and remove  the <lst name="slave"> section
+       if this is just a master.
+    -->
+  <!--
+     <requestHandler name="/replication" class="solr.ReplicationHandler" >
+       <lst name="master">
+         <str name="replicateAfter">commit</str>
+         <str name="replicateAfter">startup</str>
+         <str name="confFiles">schema.xml,stopwords.txt</str>
+       </lst>
+       <lst name="slave">
+         <str name="masterUrl">http://localhost:8983/solr/replication</str>
+         <str name="pollInterval">00:00:60</str>
+       </lst>
+     </requestHandler>
+    -->
+
+  <!-- Search Components
+
+       Search components are registered to SolrCore and used by 
+       instances of SearchHandler (which can access them by name)
+       
+       By default, the following components are available:
+       
+       <searchComponent name="query"     class="solr.QueryComponent" />
+       <searchComponent name="facet"     class="solr.FacetComponent" />
+       <searchComponent name="mlt"       class="solr.MoreLikeThisComponent" />
+       <searchComponent name="highlight" class="solr.HighlightComponent" />
+       <searchComponent name="stats"     class="solr.StatsComponent" />
+       <searchComponent name="debug"     class="solr.DebugComponent" />
+   
+       Default configuration in a requestHandler would look like:
+
+       <arr name="components">
+         <str>query</str>
+         <str>facet</str>
+         <str>mlt</str>
+         <str>highlight</str>
+         <str>stats</str>
+         <str>debug</str>
+       </arr>
+
+       If you register a searchComponent to one of the standard names, 
+       that will be used instead of the default.
+
+       To insert components before or after the 'standard' components, use:
+    
+       <arr name="first-components">
+         <str>myFirstComponentName</str>
+       </arr>
+    
+       <arr name="last-components">
+         <str>myLastComponentName</str>
+       </arr>
+
+       NOTE: The component registered with the name "debug" will
+       always be executed after the "last-components" 
+       
+     -->
+
+   <!-- Spell Check
+
+        The spell check component can return a list of alternative spelling
+        suggestions.  
+
+        http://wiki.apache.org/solr/SpellCheckComponent
+     -->
+  <searchComponent name="spellcheck" class="solr.SpellCheckComponent">
+
+    <str name="queryAnalyzerFieldType">textSpell</str>
+
+    <!-- Multiple "Spell Checkers" can be declared and used by this
+         component
+      -->
+
+    <!-- a spellchecker built from a field of the main index, and
+         written to disk
+      -->
+    <lst name="spellchecker">
+      <str name="name">default</str>
+      <str name="field">name</str>
+      <str name="spellcheckIndexDir">spellchecker</str>
+      <!-- uncomment this to require terms to occur in 1% of the documents in order to be included in the dictionary
+      	<float name="thresholdTokenFrequency">.01</float>
+      -->
+    </lst>
+
+    <!-- a spellchecker that uses a different distance measure -->
+    <!--
+       <lst name="spellchecker">
+         <str name="name">jarowinkler</str>
+         <str name="field">spell</str>
+         <str name="distanceMeasure">
+           org.apache.lucene.search.spell.JaroWinklerDistance
+         </str>
+         <str name="spellcheckIndexDir">spellcheckerJaro</str>
+       </lst>
+     -->
+
+    <!-- a spellchecker that use an alternate comparator 
+
+         comparatorClass be one of:
+          1. score (default)
+          2. freq (Frequency first, then score)
+          3. A fully qualified class name
+      -->
+    <!--
+       <lst name="spellchecker">
+         <str name="name">freq</str>
+         <str name="field">lowerfilt</str>
+         <str name="spellcheckIndexDir">spellcheckerFreq</str>
+         <str name="comparatorClass">freq</str>
+         <str name="buildOnCommit">true</str>
+      -->
+
+    <!-- A spellchecker that reads the list of words from a file -->
+    <!--
+       <lst name="spellchecker">
+         <str name="classname">solr.FileBasedSpellChecker</str>
+         <str name="name">file</str>
+         <str name="sourceLocation">spellings.txt</str>
+         <str name="characterEncoding">UTF-8</str>
+         <str name="spellcheckIndexDir">spellcheckerFile</str>
+       </lst>
+      -->
+  </searchComponent>
+
+  <!-- A request handler for demonstrating the spellcheck component.  
+
+       NOTE: This is purely as an example.  The whole purpose of the
+       SpellCheckComponent is to hook it into the request handler that
+       handles your normal user queries so that a separate request is
+       not needed to get suggestions.
+
+       IN OTHER WORDS, THERE IS REALLY GOOD CHANCE THE SETUP BELOW IS
+       NOT WHAT YOU WANT FOR YOUR PRODUCTION SYSTEM!
+       
+       See http://wiki.apache.org/solr/SpellCheckComponent for details
+       on the request parameters.
+    -->
+  <requestHandler name="/spell" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <str name="spellcheck.onlyMorePopular">false</str>
+      <str name="spellcheck.extendedResults">false</str>
+      <str name="spellcheck.count">1</str>
+    </lst>
+    <arr name="last-components">
+      <str>spellcheck</str>
+    </arr>
+  </requestHandler>
+
+  <!-- Term Vector Component
+
+       http://wiki.apache.org/solr/TermVectorComponent
+    -->
+  <searchComponent name="tvComponent" class="solr.TermVectorComponent"/>
+
+  <!-- A request handler for demonstrating the term vector component
+
+       This is purely as an example.
+
+       In reality you will likely want to add the component to your 
+       already specified request handlers. 
+    -->
+  <requestHandler name="tvrh" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <bool name="tv">true</bool>
+    </lst>
+    <arr name="last-components">
+      <str>tvComponent</str>
+    </arr>
+  </requestHandler>
+
+  <!-- Clustering Component
+
+       http://wiki.apache.org/solr/ClusteringComponent
+
+       This relies on third party jars which are notincluded in the
+       release.  To use this component (and the "/clustering" handler)
+       Those jars will need to be downloaded, and you'll need to set
+       the solr.cluster.enabled system property when running solr...
+
+          java -Dsolr.clustering.enabled=true -jar start.jar
+    -->
+  <searchComponent name="clustering" 
+                   enable="${solr.clustering.enabled:false}"
+                   class="solr.clustering.ClusteringComponent" >
+    <!-- Declare an engine -->
+    <lst name="engine">
+      <!-- The name, only one can be named "default" -->
+      <str name="name">default</str>
+
+      <!-- Class name of Carrot2 clustering algorithm. 
+           
+           Currently available algorithms are:
+           
+           * org.carrot2.clustering.lingo.LingoClusteringAlgorithm
+           * org.carrot2.clustering.stc.STCClusteringAlgorithm
+           * org.carrot2.clustering.kmeans.BisectingKMeansClusteringAlgorithm
+           
+           See http://project.carrot2.org/algorithms.html for the
+           algorithm's characteristics.
+        -->
+      <str name="carrot.algorithm">org.carrot2.clustering.lingo.LingoClusteringAlgorithm</str>
+
+      <!-- Overriding values for Carrot2 default algorithm attributes.
+
+           For a description of all available attributes, see:
+           http://download.carrot2.org/stable/manual/#chapter.components.
+           Use attribute key as name attribute of str elements
+           below. These can be further overridden for individual
+           requests by specifying attribute key as request parameter
+           name and attribute value as parameter value.
+        -->
+      <str name="LingoClusteringAlgorithm.desiredClusterCountBase">20</str>
+      
+      <!-- Location of Carrot2 lexical resources.
+
+           A directory from which to load Carrot2-specific stop words
+           and stop labels. Absolute or relative to Solr config directory.
+           If a specific resource (e.g. stopwords.en) is present in the
+           specified dir, it will completely override the corresponding
+           default one that ships with Carrot2.
+
+           For an overview of Carrot2 lexical resources, see:
+           http://download.carrot2.org/head/manual/#chapter.lexical-resources
+        -->
+      <str name="carrot.lexicalResourcesDir">clustering/carrot2</str>
+
+      <!-- The language to assume for the documents.
+           
+           For a list of allowed values, see:
+           http://download.carrot2.org/stable/manual/#section.attribute.lingo.MultilingualClustering.defaultLanguage
+       -->
+      <str name="MultilingualClustering.defaultLanguage">ENGLISH</str>
+    </lst>
+    <lst name="engine">
+      <str name="name">stc</str>
+      <str name="carrot.algorithm">org.carrot2.clustering.stc.STCClusteringAlgorithm</str>
+    </lst>
+  </searchComponent>
+
+  <!-- A request handler for demonstrating the clustering component
+
+       This is purely as an example.
+
+       In reality you will likely want to add the component to your 
+       already specified request handlers. 
+    -->
+  <requestHandler name="/clustering"
+                  startup="lazy"
+                  enable="${solr.clustering.enabled:false}"
+                  class="solr.SearchHandler">
+    <lst name="defaults">
+      <bool name="clustering">true</bool>
+      <str name="clustering.engine">default</str>
+      <bool name="clustering.results">true</bool>
+      <!-- The title field -->
+      <str name="carrot.title">name</str>
+      <str name="carrot.url">id</str>
+      <!-- The field to cluster on -->
+       <str name="carrot.snippet">features</str>
+       <!-- produce summaries -->
+       <bool name="carrot.produceSummary">true</bool>
+       <!-- the maximum number of labels per cluster -->
+       <!--<int name="carrot.numDescriptions">5</int>-->
+       <!-- produce sub clusters -->
+       <bool name="carrot.outputSubClusters">false</bool>
+       
+       <str name="defType">edismax</str>
+       <str name="qf">
+          text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4
+       </str>
+       <str name="q.alt">*:*</str>
+       <str name="rows">10</str>
+       <str name="fl">*,score</str>
+    </lst>     
+    <arr name="last-components">
+      <str>clustering</str>
+    </arr>
+  </requestHandler>
+  
+  <!-- Terms Component
+
+       http://wiki.apache.org/solr/TermsComponent
+
+       A component to return terms and document frequency of those
+       terms
+    -->
+  <searchComponent name="terms" class="solr.TermsComponent"/>
+
+  <!-- A request handler for demonstrating the terms component -->
+  <requestHandler name="/terms" class="solr.SearchHandler" startup="lazy">
+     <lst name="defaults">
+      <bool name="terms">true</bool>
+    </lst>     
+    <arr name="components">
+      <str>terms</str>
+    </arr>
+  </requestHandler>
+
+
+  <!-- Query Elevation Component
+
+       http://wiki.apache.org/solr/QueryElevationComponent
+
+       a search component that enables you to configure the top
+       results for a given query regardless of the normal lucene
+       scoring.
+    -->
+<!--
+  <searchComponent name="elevator" class="solr.QueryElevationComponent" >
+-->
+    <!-- pick a fieldType to analyze queries -->
+
+<!--
+    <str name="queryFieldType">string</str>
+    <str name="config-file">elevate.xml</str>
+  </searchComponent>
+-->
+  <!-- A request handler for demonstrating the elevator component -->
+<!--
+  <requestHandler name="/elevate" class="solr.SearchHandler" startup="lazy">
+    <lst name="defaults">
+      <str name="echoParams">explicit</str>
+    </lst>
+    <arr name="last-components">
+      <str>elevator</str>
+    </arr>
+  </requestHandler>
+-->
+  <!-- Highlighting Component
+
+       http://wiki.apache.org/solr/HighlightingParameters
+    -->
+  <searchComponent class="solr.HighlightComponent" name="highlight">
+    <highlighting>
+      <!-- Configure the standard fragmenter -->
+      <!-- This could most likely be commented out in the "default" case -->
+      <fragmenter name="gap" 
+                  default="true"
+                  class="solr.highlight.GapFragmenter">
+        <lst name="defaults">
+          <int name="hl.fragsize">100</int>
+        </lst>
+      </fragmenter>
+
+      <!-- A regular-expression-based fragmenter 
+           (for sentence extraction) 
+        -->
+      <fragmenter name="regex" 
+                  class="solr.highlight.RegexFragmenter">
+        <lst name="defaults">
+          <!-- slightly smaller fragsizes work better because of slop -->
+          <int name="hl.fragsize">70</int>
+          <!-- allow 50% slop on fragment sizes -->
+          <float name="hl.regex.slop">0.5</float>
+          <!-- a basic sentence pattern -->
+          <str name="hl.regex.pattern">[-\w ,/\n\&quot;&apos;]{20,200}</str>
+        </lst>
+      </fragmenter>
+
+      <!-- Configure the standard formatter -->
+      <formatter name="html" 
+                 default="true"
+                 class="solr.highlight.HtmlFormatter">
+        <lst name="defaults">
+          <str name="hl.simple.pre"><![CDATA[<em>]]></str>
+          <str name="hl.simple.post"><![CDATA[</em>]]></str>
+        </lst>
+      </formatter>
+
+      <!-- Configure the standard encoder -->
+      <encoder name="html" 
+               class="solr.highlight.HtmlEncoder" />
+
+      <!-- Configure the standard fragListBuilder -->
+      <fragListBuilder name="simple" 
+                       default="true"
+                       class="solr.highlight.SimpleFragListBuilder"/>
+
+      <!-- Configure the single fragListBuilder -->
+      <fragListBuilder name="single" 
+                       class="solr.highlight.SingleFragListBuilder"/>
+
+      <!-- default tag FragmentsBuilder -->
+      <fragmentsBuilder name="default" 
+                        default="true"
+                        class="solr.highlight.ScoreOrderFragmentsBuilder">
+        <!-- 
+        <lst name="defaults">
+          <str name="hl.multiValuedSeparatorChar">/</str>
+        </lst>
+        -->
+      </fragmentsBuilder>
+
+      <!-- multi-colored tag FragmentsBuilder -->
+      <fragmentsBuilder name="colored" 
+                        class="solr.highlight.ScoreOrderFragmentsBuilder">
+        <lst name="defaults">
+          <str name="hl.tag.pre"><![CDATA[
+               <b style="background:yellow">,<b style="background:lawgreen">,
+               <b style="background:aquamarine">,<b style="background:magenta">,
+               <b style="background:palegreen">,<b style="background:coral">,
+               <b style="background:wheat">,<b style="background:khaki">,
+               <b style="background:lime">,<b style="background:deepskyblue">]]></str>
+          <str name="hl.tag.post"><![CDATA[</b>]]></str>
+        </lst>
+      </fragmentsBuilder>
+    </highlighting>
+  </searchComponent>
+
+  <!-- Update Processors
+
+       Chains of Update Processor Factories for dealing with Update
+       Requests can be declared, and then used by name in Update
+       Request Processors
+
+       http://wiki.apache.org/solr/UpdateRequestProcessor
+
+    --> 
+  <!-- Deduplication
+
+       An example dedup update processor that creates the "id" field
+       on the fly based on the hash code of some other fields.  This
+       example has overwriteDupes set to false since we are using the
+       id field as the signatureField and Solr will maintain
+       uniqueness based on that anyway.  
+       
+    -->
+  <!--
+     <updateRequestProcessorChain name="dedupe">
+       <processor class="solr.processor.SignatureUpdateProcessorFactory">
+         <bool name="enabled">true</bool>
+         <str name="signatureField">id</str>
+         <bool name="overwriteDupes">false</bool>
+         <str name="fields">name,features,cat</str>
+         <str name="signatureClass">solr.processor.Lookup3Signature</str>
+       </processor>
+       <processor class="solr.LogUpdateProcessorFactory" />
+       <processor class="solr.RunUpdateProcessorFactory" />
+     </updateRequestProcessorChain>
+    -->
+
+  <!-- Response Writers
+
+       http://wiki.apache.org/solr/QueryResponseWriter
+
+       Request responses will be written using the writer specified by
+       the 'wt' request parameter matching the name of a registered
+       writer.
+
+       The "default" writer is the default and will be used if 'wt' is
+       not specified in the request.
+    -->
+  <!-- The following response writers are implicitly configured unless
+       overridden...
+    -->
+  <!--
+     <queryResponseWriter name="xml" 
+                          default="true"
+                          class="solr.XMLResponseWriter" />
+     <queryResponseWriter name="json" class="solr.JSONResponseWriter"/>
+     <queryResponseWriter name="python" class="solr.PythonResponseWriter"/>
+     <queryResponseWriter name="ruby" class="solr.RubyResponseWriter"/>
+     <queryResponseWriter name="php" class="solr.PHPResponseWriter"/>
+     <queryResponseWriter name="phps" class="solr.PHPSerializedResponseWriter"/>
+     <queryResponseWriter name="velocity" class="solr.VelocityResponseWriter"/>
+     <queryResponseWriter name="csv" class="solr.CSVResponseWriter"/>
+    -->
+  <!--
+     Custom response writers can be declared as needed...
+    -->
+  <!--
+     <queryResponseWriter name="custom" class="com.example.MyResponseWriter"/>
+    -->
+
+  <!-- XSLT response writer transforms the XML output by any xslt file found
+       in Solr's conf/xslt directory.  Changes to xslt files are checked for
+       every xsltCacheLifetimeSeconds.  
+    -->
+  <queryResponseWriter name="xslt" class="solr.XSLTResponseWriter">
+    <int name="xsltCacheLifetimeSeconds">5</int>
+  </queryResponseWriter>
+
+  <!-- Query Parsers
+
+       http://wiki.apache.org/solr/SolrQuerySyntax
+
+       Multiple QParserPlugins can be registered by name, and then
+       used in either the "defType" param for the QueryComponent (used
+       by SearchHandler) or in LocalParams
+    -->
+  <!-- example of registering a query parser -->
+  <!--
+     <queryParser name="myparser" class="com.mycompany.MyQParserPlugin"/>
+    -->
+
+  <!-- Function Parsers
+
+       http://wiki.apache.org/solr/FunctionQuery
+
+       Multiple ValueSourceParsers can be registered by name, and then
+       used as function names when using the "func" QParser.
+    -->
+  <!-- example of registering a custom function parser  -->
+  <!--
+     <valueSourceParser name="myfunc" 
+                        class="com.mycompany.MyValueSourceParser" />
+    -->
+
+  <!-- Legacy config for the admin interface -->
+  <admin>
+    <defaultQuery>*:*</defaultQuery>
+
+    <!-- configure a healthcheck file for servers behind a
+         loadbalancer 
+      -->
+    <!--
+       <healthcheck type="file">server-enabled</healthcheck>
+      -->
+  </admin>
+
+</config>
Index: gs3-extensions/solr/trunk/src/etc/conf/spellings.txt
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/spellings.txt	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/spellings.txt	(revision 24446)
@@ -0,0 +1,2 @@
+pizza
+history
Index: gs3-extensions/solr/trunk/src/etc/conf/stopwords.txt
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/stopwords.txt	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/stopwords.txt	(revision 24446)
@@ -0,0 +1,14 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
Index: gs3-extensions/solr/trunk/src/etc/conf/stopwords.txt.in
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/stopwords.txt.in	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/stopwords.txt.in	(revision 24446)
@@ -0,0 +1,14 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
Index: gs3-extensions/solr/trunk/src/etc/conf/stopwords_en.txt
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/stopwords_en.txt	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/stopwords_en.txt	(revision 24446)
@@ -0,0 +1,54 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# a couple of test stopwords to test that the words are really being
+# configured from this file:
+stopworda
+stopwordb
+
+# Standard english stop words taken from Lucene's StopAnalyzer
+a
+an
+and
+are
+as
+at
+be
+but
+by
+for
+if
+in
+into
+is
+it
+no
+not
+of
+on
+or
+such
+that
+the
+their
+then
+there
+these
+they
+this
+to
+was
+will
+with
Index: gs3-extensions/solr/trunk/src/etc/conf/stopwords_en.txt.in
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/stopwords_en.txt.in	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/stopwords_en.txt.in	(revision 24446)
@@ -0,0 +1,54 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# a couple of test stopwords to test that the words are really being
+# configured from this file:
+stopworda
+stopwordb
+
+# Standard english stop words taken from Lucene's StopAnalyzer
+a
+an
+and
+are
+as
+at
+be
+but
+by
+for
+if
+in
+into
+is
+it
+no
+not
+of
+on
+or
+such
+that
+the
+their
+then
+there
+these
+they
+this
+to
+was
+will
+with
Index: gs3-extensions/solr/trunk/src/etc/conf/synonyms.txt
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/synonyms.txt	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/synonyms.txt	(revision 24446)
@@ -0,0 +1,29 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#-----------------------------------------------------------------------
+#some test synonym mappings unlikely to appear in real input text
+aaafoo => aaabar
+bbbfoo => bbbfoo bbbbar
+cccfoo => cccbar cccbaz
+fooaaa,baraaa,bazaaa
+
+# Some synonym groups specific to this example
+GB,gib,gigabyte,gigabytes
+MB,mib,megabyte,megabytes
+Television, Televisions, TV, TVs
+#notice we use "gib" instead of "GiB" so any WordDelimiterFilter coming
+#after us won't split it into two words.
+
+# Synonym mappings can be used for spelling correction too
+pixima => pixma
+
Index: gs3-extensions/solr/trunk/src/etc/conf/synonyms.txt.in
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/synonyms.txt.in	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/synonyms.txt.in	(revision 24446)
@@ -0,0 +1,29 @@
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#-----------------------------------------------------------------------
+#some test synonym mappings unlikely to appear in real input text
+aaafoo => aaabar
+bbbfoo => bbbfoo bbbbar
+cccfoo => cccbar cccbaz
+fooaaa,baraaa,bazaaa
+
+# Some synonym groups specific to this example
+GB,gib,gigabyte,gigabytes
+MB,mib,megabyte,megabytes
+Television, Televisions, TV, TVs
+#notice we use "gib" instead of "GiB" so any WordDelimiterFilter coming
+#after us won't split it into two words.
+
+# Synonym mappings can be used for spelling correction too
+pixima => pixma
+
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/VM_global_library.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/VM_global_library.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/VM_global_library.vm	(revision 24446)
@@ -0,0 +1,184 @@
+
+#macro(param $key)$request.params.get($key)#end
+
+#macro(url_for_solr)/solr#if($request.core.name != "")/$request.core.name#end#end
+#macro(url_for_home)#url_for_solr/browse#end
+
+#macro(q)&q=$!{esc.url($params.get('q'))}#end
+
+#macro(fqs $p)#foreach($fq in $p)#if($velocityCount>1)&#{end}fq=$esc.url($fq)#end#end
+
+#macro(debug)#if($request.params.get('debugQuery'))&debugQuery=true#end#end
+
+#macro(boostPrice)#if($request.params.get('bf') == 'price')&bf=price#end#end        
+
+#macro(annotate)#if($request.params.get('annotateBrowse'))&annotateBrowse=true#end#end
+
+#macro(annTitle $msg)#if($annotate == true)title="$msg"#end#end
+
+#macro(spatial)#if($request.params.get('sfield'))&sfield=store#end#if($request.params.get('pt'))&pt=$request.params.get('pt')#end#if($request.params.get('d'))&d=$request.params.get('d')#end#end
+
+#macro(qOpts)#set($queryOpts = $request.params.get("queryOpts"))#if($queryOpts && $queryOpts != "")&queryOpts=$queryOpts#end#end
+
+#macro(lensNoQ)?#if($request.params.getParams('fq') and $list.size($request.params.getParams('fq')) > 0)&#fqs($request.params.getParams('fq'))#end#debug#boostPrice#annotate#spatial#qOpts#end
+#macro(lens)#lensNoQ#q#end
+        
+
+#macro(url_for_lens)#{url_for_home}#lens#end
+
+#macro(url_for_start $start)#url_for_home#lens&start=$start#end
+
+#macro(url_for_filters $p)#url_for_home?#q#boostPrice#spatial#qOpts#if($list.size($p) > 0)&#fqs($p)#end#debug#end
+
+#macro(url_for_nested_facet_query $field)#url_for_home#lens&fq=$esc.url($field)#end
+
+## TODO: convert to use {!raw f=$field}$value (with escaping of course)
+#macro(url_for_facet_filter $field $value)#url_for_home#lens&fq=$esc.url($field):%22$esc.url($value)%22#end
+
+#macro(url_for_facet_date_filter $field $value)#url_for_home#lens&fq=$esc.url($field):$esc.url($value)#end
+
+#macro(url_for_facet_range_filter $field $value)#url_for_home#lens&fq=$esc.url($field):$esc.url($value)#end
+
+
+#macro(link_to_previous_page $text)
+  #if($page.current_page_number > 1)
+    #set($prev_start = $page.start - $page.results_per_page)
+    <a class="prev-page" href="#url_for_start($prev_start)">$text</a>
+  #end
+#end
+
+#macro(link_to_next_page $text)
+  #if($page.current_page_number < $page.page_count)
+    #set($next_start = $page.start + $page.results_per_page)
+    <a class="next-page" href="#url_for_start($next_start)">$text</a>
+  #end
+#end
+
+#macro(link_to_page $page_number $text)
+  #if($page_number == $page.current_page_number)
+    $text
+  #else
+    #if($page_number <= $page.page_count)
+      #set($page_start = $page_number * $page.results_per_page - $page.results_per_page)
+      <a class="page" href="#url_for_start($page_start)">$text</a>
+    #end
+  #end
+#end
+
+#macro(display_facet_query $field, $display, $fieldName)
+  #if($field.size() > 0)
+  <span class="facet-field">$display</span>
+    <ul>
+    #foreach ($facet in $field)
+      #if ($facet.value > 0)
+        #set($facetURL = "#url_for_nested_facet_query($facet.key)")
+        #if ($facetURL != '')
+          <li><a href="$facetURL">$facet.key</a> ($facet.value)</li>
+        #end
+      #end
+    #end
+    </ul>
+  #end      
+#end
+
+#macro(display_facet_range_date $field, $display, $fieldName)
+  <span class="facet-field">$display</span>
+    ##Note: even if mincount is 1, you can still get a '0' before & after
+    ##Note: We assume facet.range.include='lower'
+    <ul>
+    #if ($field.before && $field.before > 0)
+      #set($value = "[* TO " + $date.format("yyyy-MM-dd'T'HH:mm:ss'Z'", $field.start) + "-1MILLIS]")
+      #set($facetURL = "#url_for_facet_date_filter($fieldName, $value)")
+      <li><a href="$facetURL">Before</a> ($field.before)</li>
+    #end
+    #foreach ($facet in $field.counts)
+      #set($theDate = $date.toDate("yyyy-MM-dd'T'HH:mm:ss'Z'", $facet.key))
+      #set($value = '["' + $facet.key + '" TO "' + $facet.key + $field.gap + '-1MILLIS"]')
+
+      #set($facetURL = "#url_for_facet_date_filter($fieldName, $value)")
+      #if ($facetURL != '')
+          <li><a href="$facetURL">$date.format('MMM yyyy', $theDate)</a> ($facet.value)</li>
+      #end
+    #end
+    #if ($field.after && $field.after > 0)
+      #set($value = "[" + $date.format("yyyy-MM-dd'T'HH:mm:ss'Z'", $field.after) + " TO *]")
+      #set($facetURL = "#url_for_facet_date_filter($fieldName, $value)")
+      <li><a href="$facetURL">After</a> ($field.after)</li>
+    #end
+    </ul>
+#end
+        
+
+
+#macro(display_facet_range $field, $display, $fieldName, $start, $end, $gap, $before, $after)
+  <span class="facet-field">$display</span>
+    <ul>
+    #if($before && $before != "")
+      #set($value = "[* TO " + $start + "]")
+      #set($facetURL = "#url_for_facet_range_filter($fieldName, $value)")
+      <li><a href="$facetURL">Less than $start</a> ($before)</li>
+    #end
+    #foreach ($facet in $field)
+      #set($rangeEnd = $math.add($facet.key, $gap))
+      #set($value = "[" + $facet.key + " TO " + $rangeEnd + "]")
+      #set($facetURL = "#url_for_facet_range_filter($fieldName, $value)")
+      #if ($facetURL != '')
+        <li><a href="$facetURL">$facet.key</a> ($facet.value)</li>
+      #end
+    #end
+    #if($end && $end != "")
+      #set($value = "[" + $end + " TO *]")
+      #set($facetURL = "#url_for_facet_range_filter($fieldName, $value)")
+      <li><a href="$facetURL">More than $math.toNumber($end)</a> ($after)</li>
+    #end
+    </ul>
+#end
+
+##   <lst name="facet_pivot">
+##     <arr name="cat,inStock">
+##       <lst>
+##         <str name="field">cat</str>
+##         <str name="value">electronics</str>
+##         <int name="count">17</int>
+##         <arr name="pivot">
+##           <lst>
+##             <str name="field">inStock</str>
+##             <str name="value">true</str>
+##             <int name="count">13</int>
+##           </lst>
+##           <lst>
+##           <str name="field">inStock</str>
+##             <str name="value">false</str>
+##             <int name="count">4</int>
+##           </lst>
+##         </arr>
+##       </lst>
+
+## $pivots is a list of facet_pivot
+#macro(display_facet_pivot $pivots, $display)
+  #if($pivots.size() > 0)
+  <span class="facet-field">$display</span>
+    <ul>
+      #foreach ($pivot in $pivots)
+        #foreach ($entry in $pivot.value)
+          <a href="#url_for_facet_filter($entry.field, $entry.value)">$entry.field::$entry.value</a> ($entry.count)
+          <ul>
+            #foreach($nest in $entry.pivot)
+              <a href="#url_for_facet_filter($entry.field, $entry.value)&fq=$esc.url($nest.field):%22$esc.url($nest.value)%22">$nest.field::$nest.value</a> ($nest.count)
+            #end
+          </ul>
+        #end
+      #end
+    </ul>
+  #end
+#end
+
+#macro(field $f)
+  #if($response.response.highlighting.get($docId).get($f).get(0))
+    $!response.response.highlighting.get($docId).get($f).get(0)
+  #else
+    #foreach($v in $doc.getFieldValues($f))
+      $v
+    #end
+  #end
+#end  
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/browse.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/browse.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/browse.vm	(revision 24446)
@@ -0,0 +1,45 @@
+#set($searcher=$request.searcher)
+#set($params=$request.params)
+#set($clusters = $response.response.clusters)
+#set($mltResults = $response.response.get("moreLikeThis"))
+#set($annotate = $params.get("annotateBrowse"))
+#parse('query.vm')
+#if($response.response.spellcheck.suggestions and $response.response.spellcheck.suggestions.size() > 0)
+  Did you mean <a href="#url_for_home?q=$esc.url($response.response.spellcheck.suggestions.collation)#if($list.size($request.params.getParams('fq')) > 0)&#fqs($request.params.getParams('fq'))#end#debug">$response.response.spellcheck.suggestions.collation</a>?
+#end
+
+<div class="navigators">
+  #parse("facets.vm")
+</div>
+
+<div class="pagination">
+  #if($response.response.get('grouped'))
+    <span><span class="results-found">$response.response.get('grouped').size() group(s)</span> found in ${response.responseHeader.QTime} ms</span>
+  #else<span><span class="results-found">$page.results_found</span> results found in ${response.responseHeader.QTime} ms</span>
+  Page <span class="page-num">$page.current_page_number</span> of <span
+        class="page-count">$page.page_count</span>#end
+</div>
+
+<div class="results">
+  #if($response.response.get('grouped'))
+    #foreach($grouping in $response.response.get('grouped'))
+      #parse("hitGrouped.vm")
+    #end
+  #else
+    #foreach($doc in $response.results)
+      #parse("hit.vm")
+    #end
+  #end
+</div>
+
+<div class="pagination">
+  #if($response.response.get('grouped'))
+  #else
+  #link_to_previous_page("previous")
+  <span class="results-found">$page.results_found</span> results found.
+  Page <span class="page-num">$page.current_page_number</span> of <span
+        class="page-count">$page.page_count</span>
+  #link_to_next_page("next")
+  #end
+  <br/>
+</div>
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/cluster.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/cluster.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/cluster.vm	(revision 24446)
@@ -0,0 +1,26 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<h2 #annTitle("Clusters generated by Carrot2 using the /clustering RequestHandler")>Clusters</h2>
+<div id="clusters">
+  Run Solr with java -Dsolr.clustering.enabled=true -jar start.jar to see results
+</div>
+<script type="text/javascript">
+
+  $('#clusters').load("#url_for_solr/clustering#lens",
+    {'wt':'velocity', 'v.template':"clusterResults"});
+</script>
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/clusterResults.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/clusterResults.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/clusterResults.vm	(revision 24446)
@@ -0,0 +1,29 @@
+#foreach ($clusters in $response.response.clusters)
+    #set($labels = $clusters.get('labels'))
+    #set($docs = $clusters.get('docs'))
+    <!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<h3>#foreach ($label in $labels)$label#if( $foreach.hasNext ),#end#end</h3>
+        <ol>
+        #foreach ($cluDoc in $docs)
+          <li><a href="#url_for_home?q=id:$cluDoc">$cluDoc</a></li>
+        #end
+        </ol>
+        
+    
+#end
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/doc.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/doc.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/doc.vm	(revision 24446)
@@ -0,0 +1,42 @@
+<div class="result-title"><b>#field('name')</b><span class="mlt">#if($params.getBool('mlt', false) == false)<a href="#lensNoQ&q=id:$docId&mlt=true">More Like This</a>#end</span></div>
+##do we have a physical store for this product
+#set($store = $doc.getFieldValue('store'))
+#if($store)<div class="map"><img src="http://maps.google.com/maps/api/staticmap?&zoom=12&size=150x80&maptype=roadmap&markers=$doc.getFieldValue('store')&sensor=false" /><div><small><a target="_map" href="http://maps.google.com/?q=$store&amp;source=embed">Larger Map</a></small></div></div>#end
+<div>Price: $!number.currency($doc.getFieldValue('price'))</div>
+<div>Features: #field('features')</div>
+<div>In Stock: #field('inStock')</div>
+<div class="mlt">
+  #set($mlt = $mltResults.get($docId))
+  #set($mltOn = $params.getBool('mlt'))
+  #if($mltOn == true)<div class="field-name">Similar Items</div>#end
+  #if ($mltOn && $mlt && $mlt.size() > 0)
+  <ul>
+    #foreach($mltHit in $mlt)
+      #set($mltId = $mltHit.getFieldValue('id'))
+      <li><div><a href="#url_for_home?q=id:$mltId">$mltId</a></div><div><span class="field-name">Name:</span> $mltHit.getFieldValue('name')</div>
+        <div><span class="field-name">Price:</span> $!number.currency($mltHit.getFieldValue('price')) <span class="field-name">In Stock:</span> $mltHit.getFieldValue('inStock')</div>
+
+      </li>
+    #end
+  </ul>
+  #elseif($mltOn && $mlt.size() == 0)
+    <div>No Similar Items Found</div>
+  #end
+</div>
+#if($params.getBool("debugQuery",false))
+  <a href="#" onclick='jQuery(this).siblings("pre").toggle(); return false;'>toggle explain</a>
+  <pre style="display:none">$response.getExplainMap().get($doc.getFirstValue('id'))</pre>
+  <a href="#" onclick='jQuery(this).siblings("pre2").toggle(); return false;'>toggle all fields</a>
+  <pre2 style="display:none">
+  #foreach($fieldname in $doc.fieldNames)
+     <br>
+       <span class="field-name">$fieldname :</span>
+       <span>
+       #foreach($value in $doc.getFieldValues($fieldname))
+         $value
+       #end
+       </span>
+  #end
+   </br>
+  </pre2>
+#end
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/facet_fields.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/facet_fields.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/facet_fields.vm	(revision 24446)
@@ -0,0 +1,12 @@
+#if($response.facetFields)
+    <h2 #annTitle("Facets generated by adding &facet.field= to the request")>Field Facets</h2>
+    #foreach($field in $response.facetFields)
+      <span class="facet-field">$field.name</span>
+
+      <ul>
+        #foreach($facet in $field.values)
+            <li><a href="#url_for_facet_filter($field.name, $facet.name)">$facet.name</a> ($facet.count)</li>
+        #end
+      </ul>
+    #end
+  #end
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/facet_queries.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/facet_queries.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/facet_queries.vm	(revision 24446)
@@ -0,0 +1,3 @@
+#set($field = $response.response.facet_counts.facet_queries)
+<h2 #annTitle("Facets generated by adding &facet.query= to the request")>Query Facets</h2>        
+#display_facet_query($field, "", "")
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/facet_ranges.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/facet_ranges.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/facet_ranges.vm	(revision 24446)
@@ -0,0 +1,30 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<h2 #annTitle("Facets generated by adding &facet.range= to the request")>Range Facets</h2>
+#set($field = $response.response.facet_counts.facet_ranges.price.counts)
+#set($start = $response.response.facet_counts.facet_ranges.price.start)
+#set($end = $response.response.facet_counts.facet_ranges.price.end)
+#set($gap = $response.response.facet_counts.facet_ranges.price.gap)
+#set($before = $response.response.facet_counts.facet_ranges.price.before)
+#set($after = $response.response.facet_counts.facet_ranges.price.after)
+##TODO: Make this display the "range", not just the lower value
+##TODO: Have a generic way to deal with ranges
+#display_facet_range($field, "Price (in $)", "price", $start, $end, $gap, $before, $after)
+
+#set($field = $response.response.facet_counts.facet_ranges.manufacturedate_dt)
+#display_facet_range_date($field, "Manufacture Date", "manufacturedate_dt")
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/facets.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/facets.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/facets.vm	(revision 24446)
@@ -0,0 +1,7 @@
+#parse('facet_fields.vm')  
+#parse('facet_queries.vm')
+#parse('facet_ranges.vm')
+#parse('cluster.vm')        
+
+
+
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/footer.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/footer.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/footer.vm	(revision 24446)
@@ -0,0 +1,17 @@
+<hr/>
+<div>
+  <span>Options:</span>
+  #if($request.params.get('debugQuery'))
+  <a href="#url_for_home?#q#if($list.size($request.params.getParams('fq')) > 0)&#fqs($request.params.getParams('fq'))#end">disable debug</a>
+  #else
+  <a href="#url_for_lens&debugQuery=true&fl=*,score">enable debug</a>
+  #end
+  #if($annotate)
+  <a href="#url_for_home?#q#if($list.size($request.params.getParams('fq')) > 0)&#fqs($request.params.getParams('fq'))#end#boostPrice">disable annotation</a>
+  #else
+  <a href="#url_for_lens&annotateBrowse=true">enable annotation</a>
+  #end
+  <a #annTitle("Click to switch to an XML response: &wt=xml") href="#url_for_lens&wt=xml#if($request.params.get('debugQuery'))&debugQuery=true#end">XML</a></div>
+<div>Generated by <a href="http://wiki.apache.org/solr/VelocityResponseWriter">VelocityResponseWriter</a></div>
+<div><span>Documentation: </span> <a href="http://lucene.apache.org/solr">Solr Home Page</a>, <a href="http://wiki.apache.org/solr">Solr Wiki</a></div>
+<div>Disclaimer: The locations displayed in this demonstration are purely fictional.  It is more than likely that no store with the items listed actually exists at that location!</div>        
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/head.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/head.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/head.vm	(revision 24446)
@@ -0,0 +1,45 @@
+
+    ## An example of using an arbitrary request parameter
+    <!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<title>#param('title')</title>
+    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
+
+<script type="text/javascript" src="#{url_for_solr}/admin/jquery-1.4.3.min.js"></script>
+  <link rel="stylesheet" type="text/css" href="#{url_for_solr}/admin/file?file=/velocity/main.css&contentType=text/css"/>
+  <link rel="stylesheet" href="#{url_for_solr}/admin/file?file=/velocity/jquery.autocomplete.css&contentType=text/css" type="text/css" />
+  <script type="text/javascript" src="#{url_for_solr}/admin/file?file=/velocity/jquery.autocomplete.js&contentType=text/javascript"></script>
+
+
+    <script>
+    $(document).ready(function(){
+      $("\#q").autocomplete('#{url_for_solr}/terms', {  ## backslash escaped #q as that is a macro defined in VM_global_library.vm
+           extraParams:{
+             'terms.prefix': function() { return $("\#q").val();},
+             'terms.sort': 'count',
+             'terms.fl': 'name',
+             'wt': 'velocity',
+             'v.template': 'suggest'
+           }
+         }
+      );
+
+      // http://localhost:8983/solr/terms?terms.fl=name&terms.prefix=i&terms.sort=count
+    });
+
+    </script>
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/header.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/header.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/header.vm	(revision 24446)
@@ -0,0 +1,3 @@
+<div id="head">
+  <span ><a href="#url_for_home#if($request.params.get('debugQuery'))?debugQuery=true#end"><img src="#{url_for_solr}/admin/solr_small.png" id="logo"/></a></span>
+</div>
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/hit.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/hit.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/hit.vm	(revision 24446)
@@ -0,0 +1,5 @@
+#set($docId = $doc.getFieldValue('id'))
+
+<div class="result-document">
+  #parse("doc.vm")
+</div>
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/jquery.autocomplete.css
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/jquery.autocomplete.css	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/jquery.autocomplete.css	(revision 24446)
@@ -0,0 +1,48 @@
+.ac_results {
+	padding: 0px;
+	border: 1px solid black;
+	background-color: white;
+	overflow: hidden;
+	z-index: 99999;
+}
+
+.ac_results ul {
+	width: 100%;
+	list-style-position: outside;
+	list-style: none;
+	padding: 0;
+	margin: 0;
+}
+
+.ac_results li {
+	margin: 0px;
+	padding: 2px 5px;
+	cursor: default;
+	display: block;
+	/* 
+	if width will be 100% horizontal scrollbar will apear 
+	when scroll mode will be used
+	*/
+	/*width: 100%;*/
+	font: menu;
+	font-size: 12px;
+	/* 
+	it is very important, if line-height not setted or setted 
+	in relative units scroll will be broken in firefox
+	*/
+	line-height: 16px;
+	overflow: hidden;
+}
+
+.ac_loading {
+	background: white url('indicator.gif') right center no-repeat;
+}
+
+.ac_odd {
+	background-color: #eee;
+}
+
+.ac_over {
+	background-color: #0A246A;
+	color: white;
+}
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/jquery.autocomplete.js
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/jquery.autocomplete.js	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/jquery.autocomplete.js	(revision 24446)
@@ -0,0 +1,762 @@
+/*
+ * Autocomplete - jQuery plugin 1.1pre
+ *
+ * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, JÃ¶rn Zaefferer
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   http://www.gnu.org/licenses/gpl.html
+ *
+ * Revision: $Id: jquery.autocomplete.js 5785 2008-07-12 10:37:33Z joern.zaefferer $
+ *
+ */
+
+;(function($) {
+	
+$.fn.extend({
+	autocomplete: function(urlOrData, options) {
+		var isUrl = typeof urlOrData == "string";
+		options = $.extend({}, $.Autocompleter.defaults, {
+			url: isUrl ? urlOrData : null,
+			data: isUrl ? null : urlOrData,
+			delay: isUrl ? $.Autocompleter.defaults.delay : 10,
+			max: options && !options.scroll ? 10 : 150
+		}, options);
+		
+		// if highlight is set to false, replace it with a do-nothing function
+		options.highlight = options.highlight || function(value) { return value; };
+		
+		// if the formatMatch option is not specified, then use formatItem for backwards compatibility
+		options.formatMatch = options.formatMatch || options.formatItem;
+		
+		return this.each(function() {
+			new $.Autocompleter(this, options);
+		});
+	},
+	result: function(handler) {
+		return this.bind("result", handler);
+	},
+	search: function(handler) {
+		return this.trigger("search", [handler]);
+	},
+	flushCache: function() {
+		return this.trigger("flushCache");
+	},
+	setOptions: function(options){
+		return this.trigger("setOptions", [options]);
+	},
+	unautocomplete: function() {
+		return this.trigger("unautocomplete");
+	}
+});
+
+$.Autocompleter = function(input, options) {
+
+	var KEY = {
+		UP: 38,
+		DOWN: 40,
+		DEL: 46,
+		TAB: 9,
+		RETURN: 13,
+		ESC: 27,
+		COMMA: 188,
+		PAGEUP: 33,
+		PAGEDOWN: 34,
+		BACKSPACE: 8
+	};
+
+	// Create $ object for input element
+	var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass);
+
+	var timeout;
+	var previousValue = "";
+	var cache = $.Autocompleter.Cache(options);
+	var hasFocus = 0;
+	var lastKeyPressCode;
+	var config = {
+		mouseDownOnSelect: false
+	};
+	var select = $.Autocompleter.Select(options, input, selectCurrent, config);
+	
+	var blockSubmit;
+	
+	// prevent form submit in opera when selecting with return key
+	$.browser.opera && $(input.form).bind("submit.autocomplete", function() {
+		if (blockSubmit) {
+			blockSubmit = false;
+			return false;
+		}
+	});
+	
+	// only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all
+	$input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
+		// track last key pressed
+		lastKeyPressCode = event.keyCode;
+		switch(event.keyCode) {
+		
+			case KEY.UP:
+				event.preventDefault();
+				if ( select.visible() ) {
+					select.prev();
+				} else {
+					onChange(0, true);
+				}
+				break;
+				
+			case KEY.DOWN:
+				event.preventDefault();
+				if ( select.visible() ) {
+					select.next();
+				} else {
+					onChange(0, true);
+				}
+				break;
+				
+			case KEY.PAGEUP:
+				event.preventDefault();
+				if ( select.visible() ) {
+					select.pageUp();
+				} else {
+					onChange(0, true);
+				}
+				break;
+				
+			case KEY.PAGEDOWN:
+				event.preventDefault();
+				if ( select.visible() ) {
+					select.pageDown();
+				} else {
+					onChange(0, true);
+				}
+				break;
+			
+			// matches also semicolon
+			case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
+			case KEY.TAB:
+			case KEY.RETURN:
+				if( selectCurrent() ) {
+					// stop default to prevent a form submit, Opera needs special handling
+					event.preventDefault();
+					blockSubmit = true;
+					return false;
+				}
+				break;
+				
+			case KEY.ESC:
+				select.hide();
+				break;
+				
+			default:
+				clearTimeout(timeout);
+				timeout = setTimeout(onChange, options.delay);
+				break;
+		}
+	}).focus(function(){
+		// track whether the field has focus, we shouldn't process any
+		// results if the field no longer has focus
+		hasFocus++;
+	}).blur(function() {
+		hasFocus = 0;
+		if (!config.mouseDownOnSelect) {
+			hideResults();
+		}
+	}).click(function() {
+		// show select when clicking in a focused field
+		if ( hasFocus++ > 1 && !select.visible() ) {
+			onChange(0, true);
+		}
+	}).bind("search", function() {
+		// TODO why not just specifying both arguments?
+		var fn = (arguments.length > 1) ? arguments[1] : null;
+		function findValueCallback(q, data) {
+			var result;
+			if( data && data.length ) {
+				for (var i=0; i < data.length; i++) {
+					if( data[i].result.toLowerCase() == q.toLowerCase() ) {
+						result = data[i];
+						break;
+					}
+				}
+			}
+			if( typeof fn == "function" ) fn(result);
+			else $input.trigger("result", result && [result.data, result.value]);
+		}
+		$.each(trimWords($input.val()), function(i, value) {
+			request(value, findValueCallback, findValueCallback);
+		});
+	}).bind("flushCache", function() {
+		cache.flush();
+	}).bind("setOptions", function() {
+		$.extend(options, arguments[1]);
+		// if we've updated the data, repopulate
+		if ( "data" in arguments[1] )
+			cache.populate();
+	}).bind("unautocomplete", function() {
+		select.unbind();
+		$input.unbind();
+		$(input.form).unbind(".autocomplete");
+	});
+	
+	
+	function selectCurrent() {
+		var selected = select.selected();
+		if( !selected )
+			return false;
+		
+		var v = selected.result;
+		previousValue = v;
+		
+		if ( options.multiple ) {
+			var words = trimWords($input.val());
+			if ( words.length > 1 ) {
+				v = words.slice(0, words.length - 1).join( options.multipleSeparator ) + options.multipleSeparator + v;
+			}
+			v += options.multipleSeparator;
+		}
+		
+		$input.val(v);
+		hideResultsNow();
+		$input.trigger("result", [selected.data, selected.value]);
+		return true;
+	}
+	
+	function onChange(crap, skipPrevCheck) {
+		if( lastKeyPressCode == KEY.DEL ) {
+			select.hide();
+			return;
+		}
+		
+		var currentValue = $input.val();
+		
+		if ( !skipPrevCheck && currentValue == previousValue )
+			return;
+		
+		previousValue = currentValue;
+		
+		currentValue = lastWord(currentValue);
+		if ( currentValue.length >= options.minChars) {
+			$input.addClass(options.loadingClass);
+			if (!options.matchCase)
+				currentValue = currentValue.toLowerCase();
+			request(currentValue, receiveData, hideResultsNow);
+		} else {
+			stopLoading();
+			select.hide();
+		}
+	};
+	
+	function trimWords(value) {
+		if ( !value ) {
+			return [""];
+		}
+		var words = value.split( options.multipleSeparator );
+		var result = [];
+		$.each(words, function(i, value) {
+			if ( $.trim(value) )
+				result[i] = $.trim(value);
+		});
+		return result;
+	}
+	
+	function lastWord(value) {
+		if ( !options.multiple )
+			return value;
+		var words = trimWords(value);
+		return words[words.length - 1];
+	}
+	
+	// fills in the input box w/the first match (assumed to be the best match)
+	// q: the term entered
+	// sValue: the first matching result
+	function autoFill(q, sValue){
+		// autofill in the complete box w/the first match as long as the user hasn't entered in more data
+		// if the last user key pressed was backspace, don't autofill
+		if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) {
+			// fill in the value (keep the case the user has typed)
+			$input.val($input.val() + sValue.substring(lastWord(previousValue).length));
+			// select the portion of the value not typed by the user (so the next character will erase)
+			$.Autocompleter.Selection(input, previousValue.length, previousValue.length + sValue.length);
+		}
+	};
+
+	function hideResults() {
+		clearTimeout(timeout);
+		timeout = setTimeout(hideResultsNow, 200);
+	};
+
+	function hideResultsNow() {
+		var wasVisible = select.visible();
+		select.hide();
+		clearTimeout(timeout);
+		stopLoading();
+		if (options.mustMatch) {
+			// call search and run callback
+			$input.search(
+				function (result){
+					// if no value found, clear the input box
+					if( !result ) {
+						if (options.multiple) {
+							var words = trimWords($input.val()).slice(0, -1);
+							$input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") );
+						}
+						else
+							$input.val( "" );
+					}
+				}
+			);
+		}
+		if (wasVisible)
+			// position cursor at end of input field
+			$.Autocompleter.Selection(input, input.value.length, input.value.length);
+	};
+
+	function receiveData(q, data) {
+		if ( data && data.length && hasFocus ) {
+			stopLoading();
+			select.display(data, q);
+			autoFill(q, data[0].value);
+			select.show();
+		} else {
+			hideResultsNow();
+		}
+	};
+
+	function request(term, success, failure) {
+		if (!options.matchCase)
+			term = term.toLowerCase();
+		var data = cache.load(term);
+		// recieve the cached data
+		if (data && data.length) {
+			success(term, data);
+		// if an AJAX url has been supplied, try loading the data now
+		} else if( (typeof options.url == "string") && (options.url.length > 0) ){
+			
+			var extraParams = {
+				timestamp: +new Date()
+			};
+			$.each(options.extraParams, function(key, param) {
+				extraParams[key] = typeof param == "function" ? param() : param;
+			});
+			
+			$.ajax({
+				// try to leverage ajaxQueue plugin to abort previous requests
+				mode: "abort",
+				// limit abortion to this input
+				port: "autocomplete" + input.name,
+				dataType: options.dataType,
+				url: options.url,
+				data: $.extend({
+					q: lastWord(term),
+					limit: options.max
+				}, extraParams),
+				success: function(data) {
+					var parsed = options.parse && options.parse(data) || parse(data);
+					cache.add(term, parsed);
+					success(term, parsed);
+				}
+			});
+		} else {
+			// if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match
+			select.emptyList();
+			failure(term);
+		}
+	};
+	
+	function parse(data) {
+		var parsed = [];
+		var rows = data.split("\n");
+		for (var i=0; i < rows.length; i++) {
+			var row = $.trim(rows[i]);
+			if (row) {
+				row = row.split("|");
+				parsed[parsed.length] = {
+					data: row,
+					value: row[0],
+					result: options.formatResult && options.formatResult(row, row[0]) || row[0]
+				};
+			}
+		}
+		return parsed;
+	};
+
+	function stopLoading() {
+		$input.removeClass(options.loadingClass);
+	};
+
+};
+
+$.Autocompleter.defaults = {
+	inputClass: "ac_input",
+	resultsClass: "ac_results",
+	loadingClass: "ac_loading",
+	minChars: 1,
+	delay: 400,
+	matchCase: false,
+	matchSubset: true,
+	matchContains: false,
+	cacheLength: 10,
+	max: 100,
+	mustMatch: false,
+	extraParams: {},
+	selectFirst: true,
+	formatItem: function(row) { return row[0]; },
+	formatMatch: null,
+	autoFill: false,
+	width: 0,
+	multiple: false,
+	multipleSeparator: ", ",
+	highlight: function(value, term) {
+		return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
+	},
+    scroll: true,
+    scrollHeight: 180
+};
+
+$.Autocompleter.Cache = function(options) {
+
+	var data = {};
+	var length = 0;
+	
+	function matchSubset(s, sub) {
+		if (!options.matchCase) 
+			s = s.toLowerCase();
+		var i = s.indexOf(sub);
+		if (options.matchContains == "word"){
+			i = s.toLowerCase().search("\\b" + sub.toLowerCase());
+		}
+		if (i == -1) return false;
+		return i == 0 || options.matchContains;
+	};
+	
+	function add(q, value) {
+		if (length > options.cacheLength){
+			flush();
+		}
+		if (!data[q]){ 
+			length++;
+		}
+		data[q] = value;
+	}
+	
+	function populate(){
+		if( !options.data ) return false;
+		// track the matches
+		var stMatchSets = {},
+			nullData = 0;
+
+		// no url was specified, we need to adjust the cache length to make sure it fits the local data store
+		if( !options.url ) options.cacheLength = 1;
+		
+		// track all options for minChars = 0
+		stMatchSets[""] = [];
+		
+		// loop through the array and create a lookup structure
+		for ( var i = 0, ol = options.data.length; i < ol; i++ ) {
+			var rawValue = options.data[i];
+			// if rawValue is a string, make an array otherwise just reference the array
+			rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue;
+			
+			var value = options.formatMatch(rawValue, i+1, options.data.length);
+			if ( value === false )
+				continue;
+				
+			var firstChar = value.charAt(0).toLowerCase();
+			// if no lookup array for this character exists, look it up now
+			if( !stMatchSets[firstChar] ) 
+				stMatchSets[firstChar] = [];
+
+			// if the match is a string
+			var row = {
+				value: value,
+				data: rawValue,
+				result: options.formatResult && options.formatResult(rawValue) || value
+			};
+			
+			// push the current match into the set list
+			stMatchSets[firstChar].push(row);
+
+			// keep track of minChars zero items
+			if ( nullData++ < options.max ) {
+				stMatchSets[""].push(row);
+			}
+		};
+
+		// add the data items to the cache
+		$.each(stMatchSets, function(i, value) {
+			// increase the cache size
+			options.cacheLength++;
+			// add to the cache
+			add(i, value);
+		});
+	}
+	
+	// populate any existing data
+	setTimeout(populate, 25);
+	
+	function flush(){
+		data = {};
+		length = 0;
+	}
+	
+	return {
+		flush: flush,
+		add: add,
+		populate: populate,
+		load: function(q) {
+			if (!options.cacheLength || !length)
+				return null;
+			/* 
+			 * if dealing w/local data and matchContains than we must make sure
+			 * to loop through all the data collections looking for matches
+			 */
+			if( !options.url && options.matchContains ){
+				// track all matches
+				var csub = [];
+				// loop through all the data grids for matches
+				for( var k in data ){
+					// don't search through the stMatchSets[""] (minChars: 0) cache
+					// this prevents duplicates
+					if( k.length > 0 ){
+						var c = data[k];
+						$.each(c, function(i, x) {
+							// if we've got a match, add it to the array
+							if (matchSubset(x.value, q)) {
+								csub.push(x);
+							}
+						});
+					}
+				}				
+				return csub;
+			} else 
+			// if the exact item exists, use it
+			if (data[q]){
+				return data[q];
+			} else
+			if (options.matchSubset) {
+				for (var i = q.length - 1; i >= options.minChars; i--) {
+					var c = data[q.substr(0, i)];
+					if (c) {
+						var csub = [];
+						$.each(c, function(i, x) {
+							if (matchSubset(x.value, q)) {
+								csub[csub.length] = x;
+							}
+						});
+						return csub;
+					}
+				}
+			}
+			return null;
+		}
+	};
+};
+
+$.Autocompleter.Select = function (options, input, select, config) {
+	var CLASSES = {
+		ACTIVE: "ac_over"
+	};
+	
+	var listItems,
+		active = -1,
+		data,
+		term = "",
+		needsInit = true,
+		element,
+		list;
+	
+	// Create results
+	function init() {
+		if (!needsInit)
+			return;
+		element = $("<div/>")
+		.hide()
+		.addClass(options.resultsClass)
+		.css("position", "absolute")
+		.appendTo(document.body);
+	
+		list = $("<ul/>").appendTo(element).mouseover( function(event) {
+			if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') {
+	            active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event));
+			    $(target(event)).addClass(CLASSES.ACTIVE);            
+	        }
+		}).click(function(event) {
+			$(target(event)).addClass(CLASSES.ACTIVE);
+			select();
+			// TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus
+			input.focus();
+			return false;
+		}).mousedown(function() {
+			config.mouseDownOnSelect = true;
+		}).mouseup(function() {
+			config.mouseDownOnSelect = false;
+		});
+		
+		if( options.width > 0 )
+			element.css("width", options.width);
+			
+		needsInit = false;
+	} 
+	
+	function target(event) {
+		var element = event.target;
+		while(element && element.tagName != "LI")
+			element = element.parentNode;
+		// more fun with IE, sometimes event.target is empty, just ignore it then
+		if(!element)
+			return [];
+		return element;
+	}
+
+	function moveSelect(step) {
+		listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE);
+		movePosition(step);
+        var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE);
+        if(options.scroll) {
+            var offset = 0;
+            listItems.slice(0, active).each(function() {
+				offset += this.offsetHeight;
+			});
+            if((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) {
+                list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight());
+            } else if(offset < list.scrollTop()) {
+                list.scrollTop(offset);
+            }
+        }
+	};
+	
+	function movePosition(step) {
+		active += step;
+		if (active < 0) {
+			active = listItems.size() - 1;
+		} else if (active >= listItems.size()) {
+			active = 0;
+		}
+	}
+	
+	function limitNumberOfItems(available) {
+		return options.max && options.max < available
+			? options.max
+			: available;
+	}
+	
+	function fillList() {
+		list.empty();
+		var max = limitNumberOfItems(data.length);
+		for (var i=0; i < max; i++) {
+			if (!data[i])
+				continue;
+			var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term);
+			if ( formatted === false )
+				continue;
+			var li = $("<li/>").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
+			$.data(li, "ac_data", data[i]);
+		}
+		listItems = list.find("li");
+		if ( options.selectFirst ) {
+			listItems.slice(0, 1).addClass(CLASSES.ACTIVE);
+			active = 0;
+		}
+		// apply bgiframe if available
+		if ( $.fn.bgiframe )
+			list.bgiframe();
+	}
+	
+	return {
+		display: function(d, q) {
+			init();
+			data = d;
+			term = q;
+			fillList();
+		},
+		next: function() {
+			moveSelect(1);
+		},
+		prev: function() {
+			moveSelect(-1);
+		},
+		pageUp: function() {
+			if (active != 0 && active - 8 < 0) {
+				moveSelect( -active );
+			} else {
+				moveSelect(-8);
+			}
+		},
+		pageDown: function() {
+			if (active != listItems.size() - 1 && active + 8 > listItems.size()) {
+				moveSelect( listItems.size() - 1 - active );
+			} else {
+				moveSelect(8);
+			}
+		},
+		hide: function() {
+			element && element.hide();
+			listItems && listItems.removeClass(CLASSES.ACTIVE);
+			active = -1;
+		},
+		visible : function() {
+			return element && element.is(":visible");
+		},
+		current: function() {
+			return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]);
+		},
+		show: function() {
+			var offset = $(input).offset();
+			element.css({
+				width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(),
+				top: offset.top + input.offsetHeight,
+				left: offset.left
+			}).show();
+            if(options.scroll) {
+                list.scrollTop(0);
+                list.css({
+					maxHeight: options.scrollHeight,
+					overflow: 'auto'
+				});
+				
+                if($.browser.msie && typeof document.body.style.maxHeight === "undefined") {
+					var listHeight = 0;
+					listItems.each(function() {
+						listHeight += this.offsetHeight;
+					});
+					var scrollbarsVisible = listHeight > options.scrollHeight;
+                    list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight );
+					if (!scrollbarsVisible) {
+						// IE doesn't recalculate width when scrollbar disappears
+						listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) );
+					}
+                }
+                
+            }
+		},
+		selected: function() {
+			var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE);
+			return selected && selected.length && $.data(selected[0], "ac_data");
+		},
+		emptyList: function (){
+			list && list.empty();
+		},
+		unbind: function() {
+			element && element.remove();
+		}
+	};
+};
+
+$.Autocompleter.Selection = function(field, start, end) {
+	if( field.createTextRange ){
+		var selRange = field.createTextRange();
+		selRange.collapse(true);
+		selRange.moveStart("character", start);
+		selRange.moveEnd("character", end);
+		selRange.select();
+	} else if( field.setSelectionRange ){
+		field.setSelectionRange(start, end);
+	} else {
+		if( field.selectionStart ){
+			field.selectionStart = start;
+			field.selectionEnd = end;
+		}
+	}
+	field.focus();
+};
+
+})(jQuery);
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/layout.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/layout.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/layout.vm	(revision 24446)
@@ -0,0 +1,20 @@
+<html>
+<head>
+  #parse("head.vm")
+</head>
+  <body>
+    <div id="admin"><a href="#url_for_solr/admin">Solr Admin</a></div>
+    <div id="header">
+      #parse("header.vm")
+    </div>
+    <div id="tabs">
+      #parse("tabs.vm")
+    </div>
+    <div id="content">
+      $content
+    </div>
+    <div id="footer">
+      #parse("footer.vm")
+    </div>
+  </body>
+</html>
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/main.css
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/main.css	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/main.css	(revision 24446)
@@ -0,0 +1,184 @@
+#admin{
+  text-align: right;
+  vertical-align: top; 
+}
+
+#head{
+  width: 100%;
+}
+.array-field {
+  border: 2px solid #474747;
+  background: #FFE9D8;
+  padding: 5px;
+  margin: 5px;
+}
+
+.array-field-list li {
+  list-style: circle;
+  margin-left: 20px;
+}
+
+body {
+  font-family: Helvetica, Arial, sans-serif;
+  font-size: 10pt;
+}
+
+a {
+  color: #43a4b1;
+}
+
+.navigators {
+  float: left;
+  margin: 5px;
+  margin-top: 0px;
+  width: 185px;
+  padding: 5px;
+  top: -20px;
+  position: relative;  
+}
+
+.navigators h2 {
+  background: #FEC293;
+  border: 1px solid #ce9d77;
+  padding: 5px;
+}
+
+.navigators ul {
+  list-style: none;
+  margin: 0;
+  margin-bottom: 5px;
+  margin-top: 5px;
+  padding-left: 10px;
+}
+
+.navigators ul li {
+  color: #999;
+  padding: 2px;
+  text-transform: capitalize;
+}
+
+
+
+.facet-field {
+  font-weight: bold;
+}
+
+.highlight {
+  color: white;
+  background-color: gray;
+  border: 1px black solid;
+}
+
+.highlight-box {
+  margin-left: 15px;
+}
+
+.field-name {
+  font-weight: bold;
+}
+
+.highlighted-facet-field {
+  background: white;
+}
+
+.constraints {
+  margin-top: 10px;
+}
+
+#query-form{
+  width: 80%;
+}
+
+
+
+.query-box, .constraints {
+  padding: 5px;
+  margin: 5px;
+  font-weight: normal;
+  font-size: 24px;
+  letter-spacing: 0.08em;
+}
+
+.query-box #q {
+  margin-left: 8px;
+  width: 60%;
+  height: 50px;
+  border: 1px solid #999;
+  font-size: 1em;
+  padding: 0.4em;
+}
+
+.query-box {
+  
+}
+
+.query-boost {
+  
+  top: 10px;
+  left: 50px;
+  position: relative;
+  font-size: 0.8em;
+}
+
+.query-box .inputs{
+  left: 180px;
+  position: relative;
+  
+}
+
+#logo {
+  margin: 10px;
+  border-style: none;
+}
+
+.pagination {
+  padding-left: 33%;
+  background: #eee;
+  margin: 5px;
+  margin-left: 210px;
+  padding-top: 5px;
+  padding-bottom: 5px;
+}
+
+.result-document {
+  border: 1px solid #999;
+  padding: 5px;
+  margin: 5px;
+  margin-left: 210px;
+  margin-bottom: 15px;
+}
+
+.result-document div{
+  padding: 5px;
+}
+
+.result-title{
+  width:60%;
+}
+
+.mlt{
+  
+}
+
+.map{
+  float: right;
+  position: relative;
+  top: -25px;  
+}
+
+.result-document:nth-child(2n+1) {
+  background-color: #eee;
+}
+
+
+.selected-facet-field {
+  font-weight: bold;
+}
+
+li.show {
+  list-style: disc;
+}
+
+.group-value{
+  font-weight: bold;
+}
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/query.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/query.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/query.vm	(revision 24446)
@@ -0,0 +1,56 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<div class="query-box">
+  <form id="query-form" action="#{url_for_home}" method="GET">
+    <div class="inputs">
+      <span #annTitle("Add the query using the &q= parameter")>Find: <input type="text" id="q" name="q" value="$!esc.html($params.get('q'))"/> <input type="submit" id="querySubmit"/> <input type="reset"/></span>
+      <div class="query-boost"><span #annTitle("Add the boost function &bf=price to the query")><input type="checkbox" name="bf" value="price" #if($request.params.get('bf') == 'price')checked="true"#end>Boost by Price</input></span>
+      #parse("querySpatial.vm")
+      </div>
+  </div>
+
+    #if($request.params.get('debugQuery'))
+      <input type="hidden" name="debugQuery" value="true"/>
+    #end
+    #if($annotate == true)
+      <input type="hidden" name="annotateBrowse" value="true"/>
+    #end
+    #foreach($fq in $request.params.getParams('fq'))
+      #if ($fq != "{!bbox}")
+        <input type="hidden" name="fq" id="allFQs" value="$esc.html($fq)"/>
+      #end
+    #end
+    <div class="constraints" #annTitle("Lists out the &fq filters.  Click to remove.")>
+      #foreach($fq in $params.getParams('fq'))
+        #set($previous_fq_count=$velocityCount - 1)
+        #if($fq != '')
+        &gt; <a style="{text-decoration: line-through;}" href="#url_for_filters($request.params.getParams('fq').subList(0,$previous_fq_count))">$fq</a>
+        #end
+      #end
+    </div>
+     #if($request.params.get('debugQuery'))
+        <a href="#" onclick='jQuery(this).siblings("pre").toggle(); return false;'>toggle parsed query</a>
+        <pre style="display:none">$response.response.debug.parsedquery</pre>
+      #end
+      #set($queryOpts = $request.params.get("queryOpts"))
+      #if($queryOpts && $queryOpts != "")
+        <input type="hidden" name="queryOpts" value="$queryOpts"/>
+      #end
+  </form>
+
+</div>
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/querySpatial.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/querySpatial.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/querySpatial.vm	(revision 24446)
@@ -0,0 +1,40 @@
+#set($queryOpts = $params.get("queryOpts"))
+#if($queryOpts == "spatial")
+<div>
+        #set($loc = $request.params.get('pt'))
+        #set($dist = $request.params.get('d', "10"))
+        <label #annTitle("Add the &pt parameter")>Location Filter:
+          <select id="pt" name="pt">
+            <option value="none"
+            #if($loc == '')selected="true"#end>No Filter</option>
+            <option value="45.17614,-93.87341"
+            #if($loc == '45.17614,-93.87341')selected="true"#end>Buffalo, MN</option>
+            <option value="37.7752,-100.0232"
+            #if($loc == '37.7752,-100.0232')selected="true"#end>Dodge City, KS</option>
+            <option value="35.0752,-97.032"
+            #if($loc == '35.0752,-97.032')selected="true"#end>Oklahoma City, OK</option>
+            <option value="37.7752,-122.4232"
+            #if($loc == '37.7752,-122.4232')selected="true"#end>San Francisco CA</option>
+          </select>
+  </label>
+  <span #annTitle("Add the &d parameter")>Distance (KM): <input id="d" name="d" type="text" size="6"
+                                                                value="#if($dist != '')${dist}#{else}10#end"/></span>
+<input type="hidden" name="sfield" value="store"/>
+<input type="hidden" id="spatialFQ" name="fq" value=""/>
+<input type="hidden" name="queryOpts" value="spatial"/>        
+</div>
+<script type="text/javascript">
+  $('#query-form').submit(function() {
+    if ($("#pt").val() != "none") {
+      $("#spatialFQ").val("{!bbox}");
+    }
+    $fqs = $("#allFQs").val();
+    $fqs = $fqs.replace("{!bbox}", "");
+    if ($fqs == ''){
+      $("#allFQs").remove();
+    }
+    $("#allFQs").val($fqs);
+    return true;
+    });
+</script>
+#end
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/suggest.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/suggest.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/suggest.vm	(revision 24446)
@@ -0,0 +1,3 @@
+#foreach($t in $response.response.terms.name)
+$t.key
+#end
Index: gs3-extensions/solr/trunk/src/etc/conf/velocity/tabs.vm
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/velocity/tabs.vm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/velocity/tabs.vm	(revision 24446)
@@ -0,0 +1,22 @@
+##TODO: Make some nice tabs here
+#set($queryOpts = $params.get("queryOpts"))
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<span #annTitle("Click the link to demonstrate various Solr capabilities")><span>Examples: </span><span class="tab">#if($queryOpts && $queryOpts != "")<a href="#url_for_home">Simple</a>#{else}Simple#end</span>
+<span class="tab">#if($queryOpts == "spatial")Spatial#else<a href="#url_for_home?&queryOpts=spatial">Spatial</a>#end</span>
+<hr/>        
Index: gs3-extensions/solr/trunk/src/etc/conf/xslt/example.xsl
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/xslt/example.xsl	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/xslt/example.xsl	(revision 24446)
@@ -0,0 +1,132 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<!-- 
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<!-- 
+  Simple transform of Solr query results to HTML
+ -->
+<xsl:stylesheet version='1.0'
+    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
+>
+
+  <xsl:output media-type="text/html" encoding="UTF-8"/> 
+  
+  <xsl:variable name="title" select="concat('Solr search results (',response/result/@numFound,' documents)')"/>
+  
+  <xsl:template match='/'>
+    <html>
+      <head>
+        <title><xsl:value-of select="$title"/></title>
+        <xsl:call-template name="css"/>
+      </head>
+      <body>
+        <h1><xsl:value-of select="$title"/></h1>
+        <div class="note">
+          This has been formatted by the sample "example.xsl" transform -
+          use your own XSLT to get a nicer page
+        </div>
+        <xsl:apply-templates select="response/result/doc"/>
+      </body>
+    </html>
+  </xsl:template>
+  
+  <xsl:template match="doc">
+    <xsl:variable name="pos" select="position()"/>
+    <div class="doc">
+      <table width="100%">
+        <xsl:apply-templates>
+          <xsl:with-param name="pos"><xsl:value-of select="$pos"/></xsl:with-param>
+        </xsl:apply-templates>
+      </table>
+    </div>
+  </xsl:template>
+
+  <xsl:template match="doc/*[@name='score']" priority="100">
+    <xsl:param name="pos"></xsl:param>
+    <tr>
+      <td class="name">
+        <xsl:value-of select="@name"/>
+      </td>
+      <td class="value">
+        <xsl:value-of select="."/>
+
+        <xsl:if test="boolean(//lst[@name='explain'])">
+          <xsl:element name="a">
+            <!-- can't allow whitespace here -->
+            <xsl:attribute name="href">javascript:toggle("<xsl:value-of select="concat('exp-',$pos)" />");</xsl:attribute>?</xsl:element>
+          <br/>
+          <xsl:element name="div">
+            <xsl:attribute name="class">exp</xsl:attribute>
+            <xsl:attribute name="id">
+              <xsl:value-of select="concat('exp-',$pos)" />
+            </xsl:attribute>
+            <xsl:value-of select="//lst[@name='explain']/str[position()=$pos]"/>
+          </xsl:element>
+        </xsl:if>
+      </td>
+    </tr>
+  </xsl:template>
+
+  <xsl:template match="doc/arr" priority="100">
+    <tr>
+      <td class="name">
+        <xsl:value-of select="@name"/>
+      </td>
+      <td class="value">
+        <ul>
+        <xsl:for-each select="*">
+          <li><xsl:value-of select="."/></li>
+        </xsl:for-each>
+        </ul>
+      </td>
+    </tr>
+  </xsl:template>
+
+
+  <xsl:template match="doc/*">
+    <tr>
+      <td class="name">
+        <xsl:value-of select="@name"/>
+      </td>
+      <td class="value">
+        <xsl:value-of select="."/>
+      </td>
+    </tr>
+  </xsl:template>
+
+  <xsl:template match="*"/>
+  
+  <xsl:template name="css">
+    <script>
+      function toggle(id) {
+        var obj = document.getElementById(id);
+        obj.style.display = (obj.style.display != 'block') ? 'block' : 'none';
+      }
+    </script>
+    <style type="text/css">
+      body { font-family: "Lucida Grande", sans-serif }
+      td.name { font-style: italic; font-size:80%; }
+      td { vertical-align: top; }
+      ul { margin: 0px; margin-left: 1em; padding: 0px; }
+      .note { font-size:80%; }
+      .doc { margin-top: 1em; border-top: solid grey 1px; }
+      .exp { display: none; font-family: monospace; white-space: pre; }
+    </style>
+  </xsl:template>
+
+</xsl:stylesheet>
Index: gs3-extensions/solr/trunk/src/etc/conf/xslt/example_atom.xsl
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/xslt/example_atom.xsl	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/xslt/example_atom.xsl	(revision 24446)
@@ -0,0 +1,67 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<!-- 
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<!-- 
+  Simple transform of Solr query results to Atom
+ -->
+
+<xsl:stylesheet version='1.0'
+    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
+
+  <xsl:output
+       method="xml"
+       encoding="utf-8"
+       media-type="application/xml"
+  />
+
+  <xsl:template match='/'>
+    <xsl:variable name="query" select="response/lst[@name='responseHeader']/lst[@name='params']/str[@name='q']"/>
+    <feed xmlns="http://www.w3.org/2005/Atom">
+      <title>Example Solr Atom 1.0 Feed</title>
+      <subtitle>
+       This has been formatted by the sample "example_atom.xsl" transform -
+       use your own XSLT to get a nicer Atom feed.
+      </subtitle>
+      <author>
+        <name>Apache Solr</name>
+        <email>solr-user@lucene.apache.org</email>
+      </author>
+      <link rel="self" type="application/atom+xml" 
+            href="http://localhost:8983/solr/q={$query}&amp;wt=xslt&amp;tr=atom.xsl"/>
+      <updated>
+        <xsl:value-of select="response/result/doc[position()=1]/date[@name='timestamp']"/>
+      </updated>
+      <id>tag:localhost,2007:example</id>
+      <xsl:apply-templates select="response/result/doc"/>
+    </feed>
+  </xsl:template>
+    
+  <!-- search results xslt -->
+  <xsl:template match="doc">
+    <xsl:variable name="id" select="str[@name='id']"/>
+    <entry>
+      <title><xsl:value-of select="str[@name='name']"/></title>
+      <link href="http://localhost:8983/solr/select?q={$id}"/>
+      <id>tag:localhost,2007:<xsl:value-of select="$id"/></id>
+      <summary><xsl:value-of select="arr[@name='features']"/></summary>
+      <updated><xsl:value-of select="date[@name='timestamp']"/></updated>
+    </entry>
+  </xsl:template>
+
+</xsl:stylesheet>
Index: gs3-extensions/solr/trunk/src/etc/conf/xslt/example_rss.xsl
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/xslt/example_rss.xsl	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/xslt/example_rss.xsl	(revision 24446)
@@ -0,0 +1,66 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<!-- 
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<!-- 
+  Simple transform of Solr query results to RSS
+ -->
+
+<xsl:stylesheet version='1.0'
+    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
+
+  <xsl:output
+       method="xml"
+       encoding="utf-8"
+       media-type="application/xml"
+  />
+  <xsl:template match='/'>
+    <rss version="2.0">
+       <channel>
+	 <title>Example Solr RSS 2.0 Feed</title>
+         <link>http://localhost:8983/solr</link>
+         <description>
+          This has been formatted by the sample "example_rss.xsl" transform -
+          use your own XSLT to get a nicer RSS feed.
+         </description>
+         <language>en-us</language>
+         <docs>http://localhost:8983/solr</docs>
+         <xsl:apply-templates select="response/result/doc"/>
+       </channel>
+    </rss>
+  </xsl:template>
+  
+  <!-- search results xslt -->
+  <xsl:template match="doc">
+    <xsl:variable name="id" select="str[@name='id']"/>
+    <xsl:variable name="timestamp" select="date[@name='timestamp']"/>
+    <item>
+      <title><xsl:value-of select="str[@name='name']"/></title>
+      <link>
+        http://localhost:8983/solr/select?q=id:<xsl:value-of select="$id"/>
+      </link>
+      <description>
+        <xsl:value-of select="arr[@name='features']"/>
+      </description>
+      <pubDate><xsl:value-of select="$timestamp"/></pubDate>
+      <guid>
+        http://localhost:8983/solr/select?q=id:<xsl:value-of select="$id"/>
+      </guid>
+    </item>
+  </xsl:template>
+</xsl:stylesheet>
Index: gs3-extensions/solr/trunk/src/etc/conf/xslt/luke.xsl
===================================================================
--- gs3-extensions/solr/trunk/src/etc/conf/xslt/luke.xsl	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/conf/xslt/luke.xsl	(revision 24446)
@@ -0,0 +1,337 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+    
+    http://www.apache.org/licenses/LICENSE-2.0
+    
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+
+<!-- 
+  Display the luke request handler with graphs
+ -->
+<xsl:stylesheet
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns="http://www.w3.org/1999/xhtml"
+    version="1.0"
+    >
+    <xsl:output
+        method="html"
+        encoding="UTF-8"
+        media-type="text/html"
+        doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+        doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+    />
+
+    <xsl:variable name="title">Solr Luke Request Handler Response</xsl:variable>
+
+    <xsl:template match="/">
+        <html xmlns="http://www.w3.org/1999/xhtml">
+            <head>
+                <link rel="stylesheet" type="text/css" href="solr-admin.css"/>
+                <link rel="icon" href="favicon.ico" type="image/ico"/>
+                <link rel="shortcut icon" href="favicon.ico" type="image/ico"/>
+                <title>
+                    <xsl:value-of select="$title"/>
+                </title>
+                <xsl:call-template name="css"/>
+
+            </head>
+            <body>
+                <h1>
+                    <xsl:value-of select="$title"/>
+                </h1>
+                <div class="doc">
+                    <ul>
+                        <xsl:if test="response/lst[@name='index']">
+                            <li>
+                                <a href="#index">Index Statistics</a>
+                            </li>
+                        </xsl:if>
+                        <xsl:if test="response/lst[@name='fields']">
+                            <li>
+                                <a href="#fields">Field Statistics</a>
+                                <ul>
+                                    <xsl:for-each select="response/lst[@name='fields']/lst">
+                                        <li>
+                                            <a href="#{@name}">
+                                                <xsl:value-of select="@name"/>
+                                            </a>
+                                        </li>
+                                    </xsl:for-each>
+                                </ul>
+                            </li>
+                        </xsl:if>
+                        <xsl:if test="response/lst[@name='doc']">
+                            <li>
+                                <a href="#doc">Document statistics</a>
+                            </li>
+                        </xsl:if>
+                    </ul>
+                </div>
+                <xsl:if test="response/lst[@name='index']">
+                    <h2><a name="index"/>Index Statistics</h2>
+                    <xsl:apply-templates select="response/lst[@name='index']"/>
+                </xsl:if>
+                <xsl:if test="response/lst[@name='fields']">
+                    <h2><a name="fields"/>Field Statistics</h2>
+                    <xsl:apply-templates select="response/lst[@name='fields']"/>
+                </xsl:if>
+                <xsl:if test="response/lst[@name='doc']">
+                    <h2><a name="doc"/>Document statistics</h2>
+                    <xsl:apply-templates select="response/lst[@name='doc']"/>
+                </xsl:if>
+            </body>
+        </html>
+    </xsl:template>
+
+    <xsl:template match="lst">
+        <xsl:if test="parent::lst">
+            <tr>
+                <td colspan="2">
+                    <div class="doc">
+                        <xsl:call-template name="list"/>
+                    </div>
+                </td>
+            </tr>
+        </xsl:if>
+        <xsl:if test="not(parent::lst)">
+            <div class="doc">
+                <xsl:call-template name="list"/>
+            </div>
+        </xsl:if>
+    </xsl:template>
+
+    <xsl:template name="list">
+        <xsl:if test="count(child::*)>0">
+            <table>
+                <thead>
+                    <tr>
+                        <th colspan="2">
+                            <p>
+                                <a name="{@name}"/>
+                            </p>
+                            <xsl:value-of select="@name"/>
+                        </th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <xsl:choose>
+                        <xsl:when
+                            test="@name='histogram'">
+                            <tr>
+                                <td colspan="2">
+                                    <xsl:call-template name="histogram"/>
+                                </td>
+                            </tr>
+                        </xsl:when>
+                        <xsl:otherwise>
+                            <xsl:apply-templates/>
+                        </xsl:otherwise>
+                    </xsl:choose>
+                </tbody>
+            </table>
+        </xsl:if>
+    </xsl:template>
+
+    <xsl:template name="histogram">
+        <div class="doc">
+            <xsl:call-template name="barchart">
+                <xsl:with-param name="max_bar_width">50</xsl:with-param>
+                <xsl:with-param name="iwidth">800</xsl:with-param>
+                <xsl:with-param name="iheight">160</xsl:with-param>
+                <xsl:with-param name="fill">blue</xsl:with-param>
+            </xsl:call-template>
+        </div>
+    </xsl:template>
+
+    <xsl:template name="barchart">
+        <xsl:param name="max_bar_width"/>
+        <xsl:param name="iwidth"/>
+        <xsl:param name="iheight"/>
+        <xsl:param name="fill"/>
+        <xsl:variable name="max">
+            <xsl:for-each select="int">
+                <xsl:sort data-type="number" order="descending"/>
+                <xsl:if test="position()=1">
+                    <xsl:value-of select="."/>
+                </xsl:if>
+            </xsl:for-each>
+        </xsl:variable>
+        <xsl:variable name="bars">
+           <xsl:value-of select="count(int)"/>
+        </xsl:variable>
+        <xsl:variable name="bar_width">
+           <xsl:choose>
+             <xsl:when test="$max_bar_width &lt; ($iwidth div $bars)">
+               <xsl:value-of select="$max_bar_width"/>
+             </xsl:when>
+             <xsl:otherwise>
+               <xsl:value-of select="$iwidth div $bars"/>
+             </xsl:otherwise>
+           </xsl:choose>
+        </xsl:variable>
+        <table class="histogram">
+           <tbody>
+              <tr>
+                <xsl:for-each select="int">
+                   <td>
+                 <xsl:value-of select="."/>
+                 <div class="histogram">
+                  <xsl:attribute name="style">background-color: <xsl:value-of select="$fill"/>; width: <xsl:value-of select="$bar_width"/>px; height: <xsl:value-of select="($iheight*number(.)) div $max"/>px;</xsl:attribute>
+                 </div>
+                   </td> 
+                </xsl:for-each>
+              </tr>
+              <tr>
+                <xsl:for-each select="int">
+                   <td>
+                       <xsl:value-of select="@name"/>
+                   </td>
+                </xsl:for-each>
+              </tr>
+           </tbody>
+        </table>
+    </xsl:template>
+
+    <xsl:template name="keyvalue">
+        <xsl:choose>
+            <xsl:when test="@name">
+                <tr>
+                    <td class="name">
+                        <xsl:value-of select="@name"/>
+                    </td>
+                    <td class="value">
+                        <xsl:value-of select="."/>
+                    </td>
+                </tr>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:value-of select="."/>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <xsl:template match="int|bool|long|float|double|uuid|date">
+        <xsl:call-template name="keyvalue"/>
+    </xsl:template>
+
+    <xsl:template match="arr">
+        <tr>
+            <td class="name">
+                <xsl:value-of select="@name"/>
+            </td>
+            <td class="value">
+                <ul>
+                    <xsl:for-each select="child::*">
+                        <li>
+                            <xsl:apply-templates/>
+                        </li>
+                    </xsl:for-each>
+                </ul>
+            </td>
+        </tr>
+    </xsl:template>
+
+    <xsl:template match="str">
+        <xsl:choose>
+            <xsl:when test="@name='schema' or @name='index' or @name='flags'">
+                <xsl:call-template name="schema"/>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:call-template name="keyvalue"/>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="schema">
+        <tr>
+            <td class="name">
+                <xsl:value-of select="@name"/>
+            </td>
+            <td class="value">
+                <xsl:if test="contains(.,'unstored')">
+                    <xsl:value-of select="."/>
+                </xsl:if>
+                <xsl:if test="not(contains(.,'unstored'))">
+                    <xsl:call-template name="infochar2string">
+                        <xsl:with-param name="charList">
+                            <xsl:value-of select="."/>
+                        </xsl:with-param>
+                    </xsl:call-template>
+                </xsl:if>
+            </td>
+        </tr>
+    </xsl:template>
+
+    <xsl:template name="infochar2string">
+        <xsl:param name="i">1</xsl:param>
+        <xsl:param name="charList"/>
+
+        <xsl:variable name="char">
+            <xsl:value-of select="substring($charList,$i,1)"/>
+        </xsl:variable>
+        <xsl:choose>
+            <xsl:when test="$char='I'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='I']"/> - </xsl:when>
+            <xsl:when test="$char='T'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='T']"/> - </xsl:when>
+            <xsl:when test="$char='S'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='S']"/> - </xsl:when>
+            <xsl:when test="$char='M'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='M']"/> - </xsl:when>
+            <xsl:when test="$char='V'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='V']"/> - </xsl:when>
+            <xsl:when test="$char='o'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='o']"/> - </xsl:when>
+            <xsl:when test="$char='p'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='p']"/> - </xsl:when>
+            <xsl:when test="$char='O'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='O']"/> - </xsl:when>
+            <xsl:when test="$char='L'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='L']"/> - </xsl:when>
+            <xsl:when test="$char='B'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='B']"/> - </xsl:when>
+            <xsl:when test="$char='C'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='C']"/> - </xsl:when>
+            <xsl:when test="$char='f'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='f']"/> - </xsl:when>
+            <xsl:when test="$char='l'">
+                <xsl:value-of select="/response/lst[@name='info']/lst/str[@name='l']"/> -
+            </xsl:when>
+        </xsl:choose>
+
+        <xsl:if test="not($i>=string-length($charList))">
+            <xsl:call-template name="infochar2string">
+                <xsl:with-param name="i">
+                    <xsl:value-of select="$i+1"/>
+                </xsl:with-param>
+                <xsl:with-param name="charList">
+                    <xsl:value-of select="$charList"/>
+                </xsl:with-param>
+            </xsl:call-template>
+        </xsl:if>
+    </xsl:template>
+    <xsl:template name="css">
+        <style type="text/css">
+            <![CDATA[
+            td.name {font-style: italic; font-size:80%; }
+            .doc { margin: 0.5em; border: solid grey 1px; }
+            .exp { display: none; font-family: monospace; white-space: pre; }
+            div.histogram { background: none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;}
+            table.histogram { width: auto; vertical-align: bottom; }
+            table.histogram td, table.histogram th { text-align: center; vertical-align: bottom; border-bottom: 1px solid #ff9933; width: auto; }
+            ]]>
+        </style>
+    </xsl:template>
+</xsl:stylesheet>
Index: gs3-extensions/solr/trunk/src/etc/jetty.xml
===================================================================
--- gs3-extensions/solr/trunk/src/etc/jetty.xml	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/jetty.xml	(revision 24446)
@@ -0,0 +1,227 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
+
+<!-- =============================================================== -->
+<!-- Configure the Jetty Server                                      -->
+<!--                                                                 -->
+<!-- Documentation of this file format can be found at:              -->
+<!-- http://docs.codehaus.org/display/JETTY/jetty.xml                -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+
+
+<Configure id="Server" class="org.mortbay.jetty.Server">
+
+    <!-- Increase the maximum POST size to 1 MB to be able to handle large shard requests -->
+    <Call class="java.lang.System" name="setProperty">
+      <Arg>org.mortbay.jetty.Request.maxFormContentSize</Arg>
+      <Arg>1000000</Arg>
+    </Call>
+
+    <!-- =========================================================== -->
+    <!-- Server Thread Pool                                          -->
+    <!-- =========================================================== -->
+    <Set name="ThreadPool">
+
+      <New class="org.mortbay.thread.QueuedThreadPool">
+        <Set name="minThreads">10</Set>
+        <Set name="maxThreads">10000</Set>
+        <Set name="lowThreads">20</Set>
+      </New>
+
+      <!-- Optional Java 5 bounded threadpool with job queue 
+      <New class="org.mortbay.thread.concurrent.ThreadPool">
+        <Set name="corePoolSize">50</Set>
+        <Set name="maximumPoolSize">50</Set>
+      </New>
+      -->
+    </Set>
+
+
+
+    <!-- =========================================================== -->
+    <!-- Set connectors                                              -->
+    <!-- =========================================================== -->
+    <!-- One of each type!                                           -->
+    <!-- =========================================================== -->
+
+    <!-- Use this connector for many frequently idle connections
+         and for threadless continuations.
+    -->    
+  <!--
+    <Call name="addConnector">
+      <Arg>
+          <New class="org.mortbay.jetty.nio.SelectChannelConnector">
+            <Set name="host"><SystemProperty name="jetty.host" /></Set>
+            <Set name="port"><SystemProperty name="jetty.port" default="8983"/></Set>
+            <Set name="maxIdleTime">30000</Set>
+            <Set name="Acceptors">2</Set>
+            <Set name="statsOn">false</Set>
+            <Set name="confidentialPort">8443</Set>
+	    <Set name="lowResourcesConnections">5000</Set>
+	    <Set name="lowResourcesMaxIdleTime">5000</Set>
+          </New>
+      </Arg>
+    </Call>
+  -->
+
+    <!-- This connector is currently being used for Solr because it
+          showed better performance than nio.SelectChannelConnector
+          for typical Solr requests.  -->
+    <Call name="addConnector">
+      <Arg>
+          <New class="org.mortbay.jetty.bio.SocketConnector">
+            <Set name="host"><SystemProperty name="jetty.host" /></Set>
+            <Set name="port"><SystemProperty name="jetty.port" default="8983"/></Set>
+            <Set name="maxIdleTime">50000</Set>
+            <Set name="lowResourceMaxIdleTime">1500</Set>
+            <Set name="statsOn">false</Set>
+          </New>
+      </Arg>
+    </Call>
+
+    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+    <!-- To add a HTTPS SSL listener                                     -->
+    <!-- see jetty-ssl.xml to add an ssl connector. use                  -->
+    <!-- java -jar start.jar etc/jetty.xml etc/jetty-ssl.xml             -->
+    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+    <!-- To allow Jetty to be started from xinetd                        -->
+    <!-- mixin jetty-xinetd.xml:                                         -->
+    <!--   java -jar start.jar etc/jetty.xml etc/jetty-xinetd.xml        -->
+    <!--                                                                 -->
+    <!-- See jetty-xinetd.xml for further instructions.                  -->
+    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+    
+    <!-- =========================================================== -->
+    <!-- Set up global session ID manager                            -->
+    <!-- =========================================================== -->
+    <!--
+    <Set name="sessionIdManager">
+      <New class="org.mortbay.jetty.servlet.HashSessionIdManager">
+        <Set name="workerName">node1</Set>
+      </New>
+    </Set>
+    -->
+
+    <!-- =========================================================== -->
+    <!-- Set handler Collection Structure                            --> 
+    <!-- =========================================================== -->
+    <Set name="handler">
+      <New id="Handlers" class="org.mortbay.jetty.handler.HandlerCollection">
+        <Set name="handlers">
+         <Array type="org.mortbay.jetty.Handler">
+           <Item>
+             <New id="Contexts" class="org.mortbay.jetty.handler.ContextHandlerCollection"/>
+           </Item>
+           <Item>
+             <New id="DefaultHandler" class="org.mortbay.jetty.handler.DefaultHandler"/>
+           </Item>
+           <Item>
+             <New id="RequestLog" class="org.mortbay.jetty.handler.RequestLogHandler"/>
+           </Item>
+         </Array>
+        </Set>
+      </New>
+    </Set>
+    
+    <!-- =========================================================== -->
+    <!-- Configure the context deployer                              -->
+    <!-- A context deployer will deploy contexts described in        -->
+    <!-- configuration files discovered in a directory.              -->
+    <!-- The configuration directory can be scanned for hot          -->
+    <!-- deployments at the configured scanInterval.                 -->
+    <!--                                                             -->
+    <!-- This deployer is configured to deploy contexts configured   -->
+    <!-- in the $JETTY_HOME/contexts directory                       -->
+    <!--                                                             -->
+    <!-- =========================================================== -->
+    <Call name="addLifeCycle">
+      <Arg>
+        <New class="org.mortbay.jetty.deployer.ContextDeployer">
+          <Set name="contexts"><Ref id="Contexts"/></Set>
+          <Set name="configurationDir"><SystemProperty name="jetty.home" default="."/>/contexts</Set>
+          <Set name="scanInterval">5</Set>
+        </New>
+      </Arg>
+    </Call>
+
+    <!-- =========================================================== -->
+    <!-- Configure the webapp deployer.                              -->
+    <!-- A webapp  deployer will deploy standard webapps discovered  -->
+    <!-- in a directory at startup, without the need for additional  -->
+    <!-- configuration files.    It does not support hot deploy or   -->
+    <!-- non standard contexts (see ContextDeployer above).          -->
+    <!--                                                             -->
+    <!-- This deployer is configured to deploy webapps from the      -->
+    <!-- $JETTY_HOME/webapps directory                               -->
+    <!--                                                             -->
+    <!-- Normally only one type of deployer need be used.            -->
+    <!--                                                             -->
+    <!-- =========================================================== -->
+    <Call name="addLifeCycle">
+      <Arg>
+        <New class="org.mortbay.jetty.deployer.WebAppDeployer">
+          <Set name="contexts"><Ref id="Contexts"/></Set>
+          <Set name="webAppDir"><SystemProperty name="jetty.home" default="."/>/webapps</Set>
+	  <Set name="parentLoaderPriority">false</Set>
+	  <Set name="extract">true</Set>
+	  <Set name="allowDuplicates">false</Set>
+          <Set name="defaultsDescriptor"><SystemProperty name="jetty.home" default="."/>/etc/webdefault.xml</Set>
+        </New>
+      </Arg>
+    </Call>
+
+    <!-- =========================================================== -->
+    <!-- Configure Authentication Realms                             -->
+    <!-- Realms may be configured for the entire server here, or     -->
+    <!-- they can be configured for a specific web app in a context  -->
+    <!-- configuration (see $(jetty.home)/contexts/test.xml for an   -->
+    <!-- example).                                                   -->
+    <!-- =========================================================== -->
+  <!--
+    <Set name="UserRealms">
+      <Array type="org.mortbay.jetty.security.UserRealm">
+        <Item>
+          <New class="org.mortbay.jetty.security.HashUserRealm">
+            <Set name="name">Test Realm</Set>
+            <Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set>
+            <Set name="refreshInterval">0</Set>
+          </New>
+        </Item>
+      </Array>
+    </Set>
+  -->
+
+    <!-- =========================================================== -->
+    <!-- Configure Request Log                                       -->
+    <!-- Request logs  may be configured for the entire server here, -->
+    <!-- or they can be configured for a specific web app in a       -->
+    <!-- contexts configuration (see $(jetty.home)/contexts/test.xml -->
+    <!-- for an example).                                            -->
+    <!-- =========================================================== -->
+  <!--
+    <Ref id="RequestLog">
+      <Set name="requestLog">
+        <New id="RequestLogImpl" class="org.mortbay.jetty.NCSARequestLog">
+          <Set name="filename"><SystemProperty name="jetty.logs" default="./logs"/>/yyyy_mm_dd.request.log</Set>
+          <Set name="filenameDateFormat">yyyy_MM_dd</Set>
+          <Set name="retainDays">90</Set>
+          <Set name="append">true</Set>
+          <Set name="extended">false</Set>
+          <Set name="logCookies">false</Set>
+          <Set name="LogTimeZone">GMT</Set>
+        </New>
+      </Set>
+    </Ref>
+  -->
+    <!-- =========================================================== -->
+    <!-- extra options                                               -->
+    <!-- =========================================================== -->
+    <Set name="stopAtShutdown">true</Set>
+    <Set name="sendServerVersion">false</Set>
+    <Set name="sendDateHeader">false</Set>
+    <Set name="gracefulShutdown">1000</Set>
+
+</Configure>
Index: gs3-extensions/solr/trunk/src/etc/solr.xml
===================================================================
--- gs3-extensions/solr/trunk/src/etc/solr.xml	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/solr.xml	(revision 24446)
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!--
+ All (relative) paths are relative to the installation path
+  
+  persistent: Save changes made via the API to this file
+  sharedLib: path to a lib directory that will be shared across all cores
+-->
+<solr persistent="false">
+
+  <!--
+  adminPath: RequestHandler path to manage cores.  
+    If 'null' (or absent), cores will not be manageable via request handler
+  -->
+  <cores adminPath="/admin/cores" defaultCoreName="collection1">
+    <core name="collection1" instanceDir=".">
+    </core>
+
+    <core name="demo-Doc" instanceDir="/research/code/greenstone2-svn/collect/demo/etc">
+      <property name="solr.data.dir" value="/research/code/greenstone2-svn/collect/demo/index/didx" />
+    </core>
+
+    <core name="demo-Sec" instanceDir="/research/code/greenstone2-svn/collect/demo/etc">
+      <property name="solr.data.dir" value="/research/code/greenstone2-svn/collect/demo/index/sidx" />
+    </core>
+
+  </cores>
+</solr>
Index: gs3-extensions/solr/trunk/src/etc/webdefault.xml
===================================================================
--- gs3-extensions/solr/trunk/src/etc/webdefault.xml	(revision 24446)
+++ gs3-extensions/solr/trunk/src/etc/webdefault.xml	(revision 24446)
@@ -0,0 +1,410 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!-- ===================================================================== -->
+<!-- This file contains the default descriptor for web applications.       -->
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<!-- The intent of this descriptor is to include jetty specific or common  -->
+<!-- configuration for all webapps.   If a context has a webdefault.xml    -->
+<!-- descriptor, it is applied before the contexts own web.xml file        -->
+<!--                                                                       -->
+<!-- A context may be assigned a default descriptor by:                    -->
+<!--  + Calling WebApplicationContext.setDefaultsDescriptor                -->
+<!--  + Passed an arg to addWebApplications                                -->
+<!--                                                                       -->
+<!-- This file is used both as the resource within the jetty.jar (which is -->
+<!-- used as the default if no explicit defaults descriptor is set) and it -->
+<!-- is copied to the etc directory of the Jetty distro and explicitly     -->
+<!-- by the jetty.xml file.                                                -->
+<!--                                                                       -->
+<!-- ===================================================================== -->
+<web-app 
+   xmlns="http://java.sun.com/xml/ns/javaee" 
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
+   metadata-complete="true"
+   version="2.5"> 
+
+  <description>
+    Default web.xml file.  
+    This file is applied to a Web application before it's own WEB_INF/web.xml file
+  </description>
+
+
+  <!-- ==================================================================== -->
+  <!-- Context params to control Session Cookies                            -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <!-- UNCOMMENT TO ACTIVATE
+  <context-param>
+    <param-name>org.mortbay.jetty.servlet.SessionDomain</param-name>
+    <param-value>127.0.0.1</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>org.mortbay.jetty.servlet.SessionPath</param-name>
+    <param-value>/</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>org.mortbay.jetty.servlet.MaxAge</param-name>
+    <param-value>-1</param-value>
+  </context-param>
+  -->
+
+  <context-param>
+    <param-name>org.mortbay.jetty.webapp.NoTLDJarPattern</param-name>
+    <param-value>start.jar|ant-.*\.jar|dojo-.*\.jar|jetty-.*\.jar|jsp-api-.*\.jar|junit-.*\.jar|servlet-api-.*\.jar|dnsns\.jar|rt\.jar|jsse\.jar|tools\.jar|sunpkcs11\.jar|sunjce_provider\.jar|xerces.*\.jar</param-value>
+  </context-param>
+            
+
+
+  <!-- ==================================================================== -->
+  <!-- The default servlet.                                                 -->
+  <!-- This servlet, normally mapped to /, provides the handling for static -->
+  <!-- content, OPTIONS and TRACE methods for the context.                  -->
+  <!-- The following initParameters are supported:                          -->
+  <!--                                                                      -->
+  <!--   acceptRanges     If true, range requests and responses are         -->
+  <!--                    supported                                         -->
+  <!--                                                                      -->
+  <!--   dirAllowed       If true, directory listings are returned if no    -->
+  <!--                    welcome file is found. Else 403 Forbidden.        -->
+  <!--                                                                      -->
+  <!--   welcomeServlets  If true, attempt to dispatch to welcome files     -->
+  <!--                    that are servlets, if no matching static          --> 
+  <!--                    resources can be found.                           -->
+  <!--                                                                      -->
+  <!--   redirectWelcome  If true, redirect welcome file requests           -->
+  <!--                    else use request dispatcher forwards              -->
+  <!--                                                                      -->
+  <!--   gzip             If set to true, then static content will be served--> 
+  <!--                    as gzip content encoded if a matching resource is -->
+  <!--                    found ending with ".gz"                           -->
+  <!--                                                                      -->
+  <!--   resoureBase      Can be set to replace the context resource base   -->
+  <!--                                                                      -->
+  <!--   relativeResourceBase                                               -->
+  <!--                    Set with a pathname relative to the base of the   -->
+  <!--                    servlet context root. Useful for only serving     -->
+  <!--                    static content from only specific subdirectories. -->
+  <!--                                                                      -->
+  <!--   useFileMappedBuffer                                                -->
+  <!--                    If set to true (the default), a  memory mapped    -->
+  <!--                    file buffer will be used to serve static content  -->
+  <!--                    when using an NIO connector. Setting this value   -->
+  <!--                    to false means that a direct buffer will be used  -->
+  <!--                    instead. If you are having trouble with Windows   -->
+  <!--                    file locking, set this to false.                  -->
+  <!--                                                                      -->
+  <!--  cacheControl      If set, all static content will have this value   -->
+  <!--                    set as the cache-control header.                  -->
+  <!--                                                                      -->
+  <!--  maxCacheSize      Maximum size of the static resource cache         -->
+  <!--                                                                      -->
+  <!--  maxCachedFileSize Maximum size of any single file in the cache      -->
+  <!--                                                                      -->
+  <!--  maxCachedFiles    Maximum number of files in the cache              -->
+  <!--                                                                      -->
+  <!--  cacheType         "nio", "bio" or "both" to determine the type(s)   -->
+  <!--                    of resource cache. A bio cached buffer may be used-->
+  <!--                    by nio but is not as efficient as a nio buffer.   -->
+  <!--                    An nio cached buffer may not be used by bio.      -->
+  <!--                                                                      -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <servlet>
+    <servlet-name>default</servlet-name>
+    <servlet-class>org.mortbay.jetty.servlet.DefaultServlet</servlet-class>
+    <init-param>
+      <param-name>acceptRanges</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <init-param>
+      <param-name>dirAllowed</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <init-param>
+      <param-name>welcomeServlets</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>redirectWelcome</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>maxCacheSize</param-name>
+      <param-value>256000000</param-value>
+    </init-param>
+    <init-param>
+      <param-name>maxCachedFileSize</param-name>
+      <param-value>10000000</param-value>
+    </init-param>
+    <init-param>
+      <param-name>maxCachedFiles</param-name>
+      <param-value>1000</param-value>
+    </init-param>
+    <init-param>
+      <param-name>cacheType</param-name>
+      <param-value>both</param-value>
+    </init-param>
+    <init-param>
+      <param-name>gzip</param-name>
+      <param-value>true</param-value>
+    </init-param>
+    <init-param>
+      <param-name>useFileMappedBuffer</param-name>
+      <param-value>true</param-value>
+    </init-param>  
+    <!--
+    <init-param>
+      <param-name>cacheControl</param-name>
+      <param-value>max-age=3600,public</param-value>
+    </init-param>
+    -->
+    <load-on-startup>0</load-on-startup>
+  </servlet> 
+
+  <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
+  
+
+  <!-- ==================================================================== -->
+  <!-- JSP Servlet                                                          -->
+  <!-- This is the jasper JSP servlet from the jakarta project              -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <!-- The JSP page compiler and execution servlet, which is the mechanism  -->
+  <!-- used by Glassfish to support JSP pages.  Traditionally, this servlet -->
+  <!-- is mapped to URL patterh "*.jsp".  This servlet supports the         -->
+  <!-- following initialization parameters (default values are in square    -->
+  <!-- brackets):                                                           -->
+  <!--                                                                      -->
+  <!--   checkInterval       If development is false and reloading is true, -->
+  <!--                       background compiles are enabled. checkInterval -->
+  <!--                       is the time in seconds between checks to see   -->
+  <!--                       if a JSP page needs to be recompiled. [300]    -->
+  <!--                                                                      -->
+  <!--   compiler            Which compiler Ant should use to compile JSP   -->
+  <!--                       pages.  See the Ant documenation for more      -->
+  <!--                       information. [javac]                           -->
+  <!--                                                                      -->
+  <!--   classdebuginfo      Should the class file be compiled with         -->
+  <!--                       debugging information?  [true]                 -->
+  <!--                                                                      -->
+  <!--   classpath           What class path should I use while compiling   -->
+  <!--                       generated servlets?  [Created dynamically      -->
+  <!--                       based on the current web application]          -->
+  <!--                       Set to ? to make the container explicitly set  -->
+  <!--                       this parameter.                                -->
+  <!--                                                                      -->
+  <!--   development         Is Jasper used in development mode (will check -->
+  <!--                       for JSP modification on every access)?  [true] -->
+  <!--                                                                      -->
+  <!--   enablePooling       Determines whether tag handler pooling is      -->
+  <!--                       enabled  [true]                                -->
+  <!--                                                                      -->
+  <!--   fork                Tell Ant to fork compiles of JSP pages so that -->
+  <!--                       a separate JVM is used for JSP page compiles   -->
+  <!--                       from the one Tomcat is running in. [true]      -->
+  <!--                                                                      -->
+  <!--   ieClassId           The class-id value to be sent to Internet      -->
+  <!--                       Explorer when using <jsp:plugin> tags.         -->
+  <!--                       [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93]   -->
+  <!--                                                                      -->
+  <!--   javaEncoding        Java file encoding to use for generating java  -->
+  <!--                       source files. [UTF-8]                          -->
+  <!--                                                                      -->
+  <!--   keepgenerated       Should we keep the generated Java source code  -->
+  <!--                       for each page instead of deleting it? [true]   -->
+  <!--                                                                      -->
+  <!--   logVerbosityLevel   The level of detailed messages to be produced  -->
+  <!--                       by this servlet.  Increasing levels cause the  -->
+  <!--                       generation of more messages.  Valid values are -->
+  <!--                       FATAL, ERROR, WARNING, INFORMATION, and DEBUG. -->
+  <!--                       [WARNING]                                      -->
+  <!--                                                                      -->
+  <!--   mappedfile          Should we generate static content with one     -->
+  <!--                       print statement per input line, to ease        -->
+  <!--                       debugging?  [false]                            -->
+  <!--                                                                      -->
+  <!--                                                                      -->
+  <!--   reloading           Should Jasper check for modified JSPs?  [true] -->
+  <!--                                                                      -->
+  <!--   suppressSmap        Should the generation of SMAP info for JSR45   -->
+  <!--                       debugging be suppressed?  [false]              -->
+  <!--                                                                      -->
+  <!--   dumpSmap            Should the SMAP info for JSR45 debugging be    -->
+  <!--                       dumped to a file? [false]                      -->
+  <!--                       False if suppressSmap is true                  -->
+  <!--                                                                      -->
+  <!--   scratchdir          What scratch directory should we use when      -->
+  <!--                       compiling JSP pages?  [default work directory  -->
+  <!--                       for the current web application]               -->
+  <!--                                                                      -->
+  <!--   tagpoolMaxSize      The maximum tag handler pool size  [5]         -->
+  <!--                                                                      -->
+  <!--   xpoweredBy          Determines whether X-Powered-By response       -->
+  <!--                       header is added by generated servlet  [false]  -->
+  <!--                                                                      -->
+  <!-- If you wish to use Jikes to compile JSP pages:                       -->
+  <!--   Set the init parameter "compiler" to "jikes".  Define              -->
+  <!--   the property "-Dbuild.compiler.emacs=true" when starting Jetty     -->
+  <!--   to cause Jikes to emit error messages in a format compatible with  -->
+  <!--   Jasper.                                                            -->
+  <!--   If you get an error reporting that jikes can't use UTF-8 encoding, -->
+  <!--   try setting the init parameter "javaEncoding" to "ISO-8859-1".     -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <servlet id="jsp">
+    <servlet-name>jsp</servlet-name>
+    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
+    <init-param>
+        <param-name>logVerbosityLevel</param-name>
+        <param-value>DEBUG</param-value>
+    </init-param>
+    <init-param>
+        <param-name>fork</param-name>
+        <param-value>false</param-value>
+    </init-param>
+    <init-param>
+        <param-name>xpoweredBy</param-name>
+        <param-value>false</param-value>
+    </init-param>
+    <!--  
+    <init-param>
+        <param-name>classpath</param-name>
+        <param-value>?</param-value>
+    </init-param>
+    -->
+    <load-on-startup>0</load-on-startup>
+  </servlet>
+
+  <servlet-mapping> 
+    <servlet-name>jsp</servlet-name> 
+    <url-pattern>*.jsp</url-pattern> 
+    <url-pattern>*.jspf</url-pattern>
+    <url-pattern>*.jspx</url-pattern>
+    <url-pattern>*.xsp</url-pattern>
+    <url-pattern>*.JSP</url-pattern> 
+    <url-pattern>*.JSPF</url-pattern>
+    <url-pattern>*.JSPX</url-pattern>
+    <url-pattern>*.XSP</url-pattern>
+  </servlet-mapping>
+  
+  <!-- ==================================================================== -->
+  <!-- Dynamic Servlet Invoker.                                             -->
+  <!-- This servlet invokes anonymous servlets that have not been defined   -->
+  <!-- in the web.xml or by other means. The first element of the pathInfo  -->
+  <!-- of a request passed to the envoker is treated as a servlet name for  -->
+  <!-- an existing servlet, or as a class name of a new servlet.            -->
+  <!-- This servlet is normally mapped to /servlet/*                        -->
+  <!-- This servlet support the following initParams:                       -->
+  <!--                                                                      -->
+  <!--  nonContextServlets       If false, the invoker can only load        -->
+  <!--                           servlets from the contexts classloader.    -->
+  <!--                           This is false by default and setting this  -->
+  <!--                           to true may have security implications.    -->
+  <!--                                                                      -->
+  <!--  verbose                  If true, log dynamic loads                 -->
+  <!--                                                                      -->
+  <!--  *                        All other parameters are copied to the     -->
+  <!--                           each dynamic servlet as init parameters    -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <!-- Uncomment for dynamic invocation
+  <servlet>
+    <servlet-name>invoker</servlet-name>
+    <servlet-class>org.mortbay.jetty.servlet.Invoker</servlet-class>
+    <init-param>
+      <param-name>verbose</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>nonContextServlets</param-name>
+      <param-value>false</param-value>
+    </init-param>
+    <init-param>
+      <param-name>dynamicParam</param-name>
+      <param-value>anyValue</param-value>
+    </init-param>
+    <load-on-startup>0</load-on-startup>
+  </servlet>
+
+  <servlet-mapping> <servlet-name>invoker</servlet-name> <url-pattern>/servlet/*</url-pattern> </servlet-mapping>
+  -->
+
+
+
+  <!-- ==================================================================== -->
+  <session-config>
+    <session-timeout>30</session-timeout>
+  </session-config>
+
+  <!-- ==================================================================== -->
+  <!-- Default MIME mappings                                                -->
+  <!-- The default MIME mappings are provided by the mime.properties        -->
+  <!-- resource in the org.mortbay.jetty.jar file.  Additional or modified  -->
+  <!-- mappings may be specified here                                       -->
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->
+  <!-- UNCOMMENT TO ACTIVATE
+  <mime-mapping>
+    <extension>mysuffix</extension>
+    <mime-type>mymime/type</mime-type>
+  </mime-mapping>
+  -->
+
+  <!-- ==================================================================== -->
+  <welcome-file-list>
+    <welcome-file>index.html</welcome-file>
+    <welcome-file>index.htm</welcome-file>
+    <welcome-file>index.jsp</welcome-file>
+  </welcome-file-list>
+
+  <!-- ==================================================================== -->
+  <locale-encoding-mapping-list>
+    <locale-encoding-mapping><locale>ar</locale><encoding>ISO-8859-6</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>be</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>bg</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>ca</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>cs</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>da</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>de</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>el</locale><encoding>ISO-8859-7</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>en</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>es</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>et</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>fi</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>fr</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>hr</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>hu</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>is</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>it</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>iw</locale><encoding>ISO-8859-8</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>ja</locale><encoding>Shift_JIS</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>ko</locale><encoding>EUC-KR</encoding></locale-encoding-mapping>     
+    <locale-encoding-mapping><locale>lt</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>lv</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>mk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>nl</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>no</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>pl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>pt</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>ro</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>ru</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>sh</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>sk</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>sl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>sq</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>sr</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>sv</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>tr</locale><encoding>ISO-8859-9</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>uk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>zh</locale><encoding>GB2312</encoding></locale-encoding-mapping>
+    <locale-encoding-mapping><locale>zh_TW</locale><encoding>Big5</encoding></locale-encoding-mapping>   
+  </locale-encoding-mapping-list>
+  
+  <security-constraint>
+    <web-resource-collection>
+      <web-resource-name>Disable TRACE</web-resource-name>
+      <url-pattern>/</url-pattern>
+      <http-method>TRACE</http-method>
+    </web-resource-collection>
+    <auth-constraint/>
+  </security-constraint>
+  
+</web-app>
+
Index: gs3-extensions/solr/trunk/src/lib/jetty-LICENSE.txt
===================================================================
--- gs3-extensions/solr/trunk/src/lib/jetty-LICENSE.txt	(revision 24446)
+++ gs3-extensions/solr/trunk/src/lib/jetty-LICENSE.txt	(revision 24446)
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
Index: gs3-extensions/solr/trunk/src/lib/jetty-NOTICE.txt
===================================================================
--- gs3-extensions/solr/trunk/src/lib/jetty-NOTICE.txt	(revision 24446)
+++ gs3-extensions/solr/trunk/src/lib/jetty-NOTICE.txt	(revision 24446)
@@ -0,0 +1,36 @@
+==============================================================
+ Jetty Web Container 
+ Copyright 1995-2009 Mort Bay Consulting Pty Ltd
+==============================================================
+
+The Jetty Web Container is Copyright Mort Bay Consulting Pty Ltd
+unless otherwise noted. It is licensed under the apache 2.0
+license.
+
+The javax.servlet package used by Jetty is copyright 
+Sun Microsystems, Inc and Apache Software Foundation. It is 
+distributed under the Common Development and Distribution License.
+You can obtain a copy of the license at 
+https://glassfish.dev.java.net/public/CDDLv1.0.html.
+
+The UnixCrypt.java code ~Implements the one way cryptography used by
+Unix systems for simple password protection.  Copyright 1996 Aki Yoshida,
+modified April 2001  by Iris Van den Broeke, Daniel Deville.
+Permission to use, copy, modify and distribute UnixCrypt 
+for non-commercial or commercial purposes and without fee is
+granted provided that the copyright notice appears in all copies.
+
+The default JSP implementation is provided by the Glassfish JSP engine
+from project Glassfish http://glassfish.dev.java.net.  Copyright 2005
+Sun Microsystems, Inc. and portions Copyright Apache Software Foundation.
+
+Some portions of the code are Copyright:
+  2006 Tim Vernum 
+  1999 Jason Gilbert.
+
+The jboss integration module contains some LGPL code.
+
+The win32 Java Service Wrapper (v3.2.3) is Copyright (c) 1999, 2006 
+Tanuki Software, Inc.  and 2001 Silver Egg Technology.  It is 
+covered by an open license which is viewable at
+http://svn.codehaus.org/jetty/jetty/branches/jetty-6.1/extras/win32service/LICENSE.txt
Index: gs3-extensions/solr/trunk/src/perllib/solrbuilder.pm
===================================================================
--- gs3-extensions/solr/trunk/src/perllib/solrbuilder.pm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/perllib/solrbuilder.pm	(revision 24446)
@@ -0,0 +1,585 @@
+###########################################################################
+#
+# solrbuilder.pm -- perl wrapper for building index with Solr
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+
+package solrbuilder;
+
+use strict; 
+no strict 'refs';
+
+use lucenebuilder;
+use Config; # for getting the perlpath in the recommended way
+
+sub BEGIN {
+    @solrbuilder::ISA = ('lucenebuilder');
+}
+
+
+sub new {
+    my $class = shift(@_);
+    my $self = new lucenebuilder (@_);
+    $self = bless $self, $class;
+
+    $self->{'buildtype'} = "solr";
+
+    my $solr_passes_script = "solr_passes.pl";
+
+    $self->{'solr_passes'} = "$solr_passes_script";
+    # Tack perl on the beginning to ensure execution
+    $self->{'solr_passes_exe'} = "\"$Config{perlpath}\" -S \"$solr_passes_script\"";
+    return $self;
+}
+
+
+sub default_buildproc {
+    my $self  = shift (@_);
+
+    return "solrbuildproc";
+}
+
+# This writes a nice version of the text docs
+#
+# Essentially the same as the lucenebuilder.pm version, only using solr_passes
+# => refactor and make better use of inheritence
+#
+sub compress_text
+{
+    my $self = shift (@_);
+    # do nothing if we don't want compressed text
+    return if $self->{'no_text'};
+
+    my ($textindex) = @_;
+
+    # workaround to avoid hard-coding "solr" check into buildcol.pl
+    $textindex =~ s/^section://; 
+
+    my $outhandle = $self->{'outhandle'};
+
+    # the text directory
+    my $text_dir = &util::filename_cat($self->{'build_dir'}, "text");
+    my $build_dir = &util::filename_cat($self->{'build_dir'},"");
+    &util::mk_all_dir ($text_dir);
+
+    my $osextra = "";
+    if ($ENV{'GSDLOS'} =~ /^windows$/i)
+    {
+	$text_dir =~ s@/@\\@g;
+    }
+    else
+    {
+	if ($outhandle ne "STDERR")
+	{
+	    # so solr_passes doesn't print to stderr if we redirect output
+	    $osextra .= " 2>/dev/null";
+	}
+    }
+
+    # Find the perl script to call to run solr
+    my $solr_passes = $self->{'solr_passes'};
+    my $solr_passes_exe = $self->{'solr_passes_exe'};
+
+    my $solr_passes_sections = "Doc";
+
+    my ($handle);
+
+    if ($self->{'debug'})
+    {
+	$handle = *STDOUT;
+    }
+    else
+    {
+	my $collection = $self->{'collection'};
+
+        print STDERR "Executable:    $solr_passes_exe\n";
+        print STDERR "Sections:      $solr_passes_sections\n";
+        print STDERR "Build Dir:     $build_dir\n";
+        print STDERR "Cmd:           $solr_passes_exe $collection text $solr_passes_sections \"$build_dir\" \"dummy\"   $osextra\n";
+	if (!open($handle, "| $solr_passes_exe $collection text $solr_passes_sections \"$build_dir\" \"dummy\"   $osextra"))
+	{
+	    print STDERR "<FatalError name='NoRunSolrPasses'/>\n</Stage>\n" if $self->{'gli'};
+	    die "solrbuilder::build_index - couldn't run $solr_passes_exe\n$!\n";
+	}
+    }
+
+    # stored text is always Doc and Sec levels    
+    my $levels = { 'document' => 1, 'section' => 1 };
+    # always do database at section level
+    my $db_level = "section"; 
+
+    # set up the document processr
+    $self->{'buildproc'}->set_output_handle ($handle);
+    $self->{'buildproc'}->set_mode ('text');
+    $self->{'buildproc'}->set_index ($textindex);
+    $self->{'buildproc'}->set_indexing_text (0);
+    #$self->{'buildproc'}->set_indexfieldmap ($self->{'indexfieldmap'});
+    $self->{'buildproc'}->set_levels ($levels);
+    $self->{'buildproc'}->set_db_level ($db_level);
+    $self->{'buildproc'}->reset();
+
+    &plugin::begin($self->{'pluginfo'}, $self->{'source_dir'},
+		   $self->{'buildproc'}, $self->{'maxdocs'});
+    &plugin::read ($self->{'pluginfo'}, $self->{'source_dir'},
+		   "", {}, {}, $self->{'buildproc'}, $self->{'maxdocs'}, 0, $self->{'gli'});
+    &plugin::end($self->{'pluginfo'});
+
+    close ($handle) unless $self->{'debug'};
+    $self->print_stats();
+
+    print STDERR "</Stage>\n" if $self->{'gli'};
+}
+
+#----
+
+
+
+sub filter_in_out_file
+{
+    my ($in_filename,$out_filename,$replace_rules) = @_;
+
+    if (open(SIN,"<$in_filename")) {
+
+	if (open(SOUT,">$out_filename")) {
+
+	    my $line;
+	    while (defined ($line=<SIN>)) {
+		chomp $line;
+
+		my $done_insert = 0;
+		foreach my $rule (@$replace_rules) {
+		    my $line_re = $rule->{'regexp'};
+		    my $insert  = $rule->{'insert'};
+
+		    if ($line =~ m/$line_re/) {
+			print SOUT $insert;
+			$done_insert = 1;
+			last;
+		    }
+		}
+		if (!$done_insert) {
+		    print SOUT "$line\n";;
+		}
+	    }
+
+	    close(SOUT);
+	}
+	else {
+	    print STDERR "Error: Failed to open $out_filename\n";
+	    print STDERR "       $!\n";
+	}
+
+	close(SIN);
+    }
+    else {
+	print STDERR "Error: Failed to open $in_filename\n";
+	print STDERR "       $!\n";
+    }
+
+}
+
+# Generate solr schema.xml file based on indexmapfield and other associated
+# config files 
+#
+# Unlike make_auxiliary_files(), this needs to be done up-front (rather
+# than at the end) so the data-types in schema.xml are correctly set up
+# prior to document content being pumped through solr_passes.pl
+
+
+sub premake_solr_auxiliary_files 
+{
+    my $self = shift (@_);
+    
+    # Replace the following marker: 
+    #
+    #   <!-- ##GREENSTONE-FIELDS## -->
+    #
+    # with lines of the form:
+    #
+    #   <field name="<field>" type="string" ... /> 
+    #
+    # for each <field> in 'indexfieldmap'
+  
+    my $schema_insert_xml = "";
+
+    foreach my $ifm (@{$self->{'build_cfg'}->{'indexfieldmap'}}) {
+
+	my ($field) = ($ifm =~ m/^.*->(.*)$/);
+
+	# Need special case for Long/Lat
+	# ... but for now treat everything as of type string
+
+	$schema_insert_xml .= "    "; # indent
+	$schema_insert_xml .= "<field name=\"$field\" ";
+	$schema_insert_xml .=   "type=\"string\" indexed=\"true\" ";
+	$schema_insert_xml .=   "stored=\"false\" multiValued=\"true\" />\n"; 
+    }
+
+    # just the one rule to date
+    my $insert_rules 
+	= [ { 'regexp' => "^\\s*<!--\\s*##GREENSTONE-FIELDS##\\s*-->\\s*\$",
+	      'insert' => $schema_insert_xml } ];
+        
+    my $solr_home = $ENV{'GEXT_SOLR'};
+    my $in_dirname = &util::filename_cat($solr_home,"etc","conf");
+    my $schema_in_filename = &util::filename_cat($in_dirname,"schema.xml.in");
+
+
+    my $collect_home = $ENV{'GSDLCOLLECTDIR'};
+    my $out_dirname = &util::filename_cat($collect_home,"etc","conf");
+    my $schema_out_filename = &util::filename_cat($out_dirname,"schema.xml");
+    
+    # make sure output conf directory exists
+    if (!-d $out_dirname) {
+	&util::mk_dir($out_dirname);
+    }
+
+    filter_in_out_file($schema_in_filename,$schema_out_filename,$insert_rules);
+
+    # now do the same for solrconfig.xml, stopwords, ...
+    # these are simpler, as they currently do not need any filtering
+
+    my @in_file_list = ( "solrconfig.xml", "stopwords.txt", "stopwords_en.txt",
+			 "synonyms.txt", "protwords.txt" );
+
+    foreach my $file ( @in_file_list ) {
+	my $in_filename = &util::filename_cat($in_dirname,$file.".in");
+	my $out_filename = &util::filename_cat($out_dirname,$file);
+	filter_in_out_file($in_filename,$out_filename,[]);
+    }
+}
+
+
+sub pre_build_indexes
+{
+    my $self = shift (@_);
+    my ($indexname) = @_;
+    my $outhandle = $self->{'outhandle'};
+
+    # read in build.cfg if in incremental mode???
+
+    my $indexes = [];
+    if (defined $indexname && $indexname =~ /\w/) {
+	push @$indexes, $indexname;
+    } else {
+	$indexes = $self->{'collect_cfg'}->{'indexes'};
+    }
+
+    # skip para-level check, as this is done in the main 'build_indexes' 
+    # routine
+
+    my $all_metadata_specified = 0; # has the user added a 'metadata' index?
+    my $allfields_index = 0;        # do we have an allfields index?
+
+    # Using a hashmap here would duplications, but while more space
+    # efficient, it's not entirely clear it would be more computationally
+    # efficient
+    my @all_fields = ();
+
+    foreach my $index (@$indexes) {
+	if ($self->want_built($index)) {
+
+	    # get the parameters for the output
+	    # split on : just in case there is subcoll and lang stuff
+	    my ($fields) = split (/:/, $index);
+
+	    foreach my $field (split (/;/, $fields)) {
+		if ($field eq "metadata") {
+		    $all_metadata_specified = 1;
+		}
+		else {
+		    push(@all_fields,$field);
+		}
+	    }
+	}
+    }
+
+    if ($all_metadata_specified) {
+
+	# (Unforunately) we need to process all the documents in the collection
+	# to figure out what the metadata_field_mapping is	    
+
+##	my $db_level = "section"; #always
+
+	# set up the document processr
+	$self->{'buildproc'}->set_output_handle (undef);
+	$self->{'buildproc'}->set_mode ('index_field_mapping');
+##	$self->{'buildproc'}->set_index ($index);
+##	$self->{'buildproc'}->set_indexing_text (0);
+	#$self->{'buildproc'}->set_indexfieldmap ($self->{'indexfieldmap'});
+##	$self->{'buildproc'}->set_levels ($levels);
+##	$self->{'buildproc'}->set_db_level ($db_level);
+	$self->{'buildproc'}->reset();
+	
+	&plugin::begin($self->{'pluginfo'}, $self->{'source_dir'},
+		       $self->{'buildproc'}, $self->{'maxdocs'});
+	&plugin::read ($self->{'pluginfo'}, $self->{'source_dir'},
+		       "", {}, {}, $self->{'buildproc'}, $self->{'maxdocs'}, 0, $self->{'gli'});
+	&plugin::end($self->{'pluginfo'});
+	
+##	close ($handle) unless $self->{'debug'};
+
+##	$self->print_stats();
+
+	# just make "delete" stop  ???
+    }
+
+    else {
+	# Field mapping solely dependent of entries in 'indexes'
+
+	# No need to explicitly handle "allfields" as create_shortname()
+	# will get a fix on it through it's static_indexfield_map
+
+	my $buildproc = $self->{'buildproc'};
+	
+	foreach my $field (@all_fields) {
+	    if (!defined $buildproc->{'indexfieldmap'}->{$field}) {
+		my $shortname = $buildproc->create_shortname($field);
+		$buildproc->{'indexfieldmap'}->{$field} = $shortname;
+		$buildproc->{'indexfieldmap'}->{$shortname} = 1;
+	    }
+	}
+    }
+
+    # write out solr 'schema.xml' (and related) file 
+    $self->make_final_field_list();
+    $self->premake_solr_auxiliary_files();
+
+    # if collect==core not already in solr.xml (check with STATUS)
+    # => use CREATE API to add to solr.xml
+    #
+    # else 
+    # => use RELOAD call to refresh fields now expressed in schema.xml
+
+}
+
+# Essentially the same as the lucenebuilder.pm version, only using solr_passes
+# => refactor and make better use of inheritence
+
+sub build_indexesXXXX {
+    my $self = shift (@_);
+    my ($indexname) = @_;
+    my $outhandle = $self->{'outhandle'};
+
+    $self->pre_build_indexes($indexname);
+
+    my $indexes = [];
+    if (defined $indexname && $indexname =~ /\w/) {
+	push @$indexes, $indexname;
+    } else {
+	$indexes = $self->{'collect_cfg'}->{'indexes'};
+    }
+
+    # have we got para index?
+    foreach my $level (keys %{$self->{'levels'}}) {
+	if ($level =~ /paragraph/) {
+	    print $outhandle "Warning: Paragraph level indexing not supported by Solr\n";
+	    last;
+	}
+    }
+    # create the mapping between the index descriptions
+    # and their directory names (includes subcolls and langs)
+    $self->{'index_mapping'} = $self->create_index_mapping ($indexes);
+
+    # build each of the indexes
+    foreach my $index (@$indexes) {
+	if ($self->want_built($index)) {
+
+	    my $idx = $self->{'index_mapping'}->{$index};
+	    foreach my $level (keys %{$self->{'levels'}}) {
+		next if $level =~ /paragraph/; # we don't do para indexing
+		my ($pindex) = $level =~ /^(.)/;
+		# should probably check that new name with level
+		# is unique ... but currently (with doc sec and para)
+		# each has unique first letter.
+		$self->{'index_mapping'}->{$index} = $pindex.$idx;
+
+		my $llevel = $mgppbuilder::level_map{$level};
+		print $outhandle "\n*** building index $index at level $llevel in subdirectory " .
+		    "$self->{'index_mapping'}->{$index}\n" if ($self->{'verbosity'} >= 1);
+		print STDERR "<Stage name='Index' source='$index' level=$llevel>\n" if $self->{'gli'};
+
+		$self->build_index($index,$llevel);
+	    }
+	    $self->{'index_mapping'}->{$index} = $idx;
+
+	} else {
+	    print $outhandle "\n*** ignoring index $index\n" if ($self->{'verbosity'} >= 1);
+	}
+    }
+}
+
+
+# Essentially the same as the lucenebuilder.pm version, only using solr_passes
+# => refactor and make better use of inheritence
+
+sub build_index {
+    my $self = shift (@_);
+    my ($index,$llevel) = @_;
+    my $outhandle = $self->{'outhandle'};
+    my $build_dir = $self->{'build_dir'};
+
+    # get the full index directory path and make sure it exists
+    my $indexdir = $self->{'index_mapping'}->{$index};
+    &util::mk_all_dir (&util::filename_cat($build_dir, $indexdir));
+
+    # Find the perl script to call to run solr
+    my $solr_passes = $self->{'solr_passes'};
+    my $solr_passes_exe = $self->{'solr_passes_exe'};
+
+    # define the section names for solrpasses
+    # define the section names and possibly the doc name for solrpasses
+    my $solr_passes_sections = $llevel;
+
+    my $opt_create_index = ($self->{'incremental'}) ? "" : "-removeold";
+
+    my $osextra = "";
+    if ($ENV{'GSDLOS'} =~ /^windows$/i) {
+	$build_dir =~ s@/@\\@g;
+    } else {
+	if ($outhandle ne "STDERR") {
+	    # so solr_passes doesn't print to stderr if we redirect output
+	    $osextra .= " 2>/dev/null";
+	}
+    }
+
+    # get the index expression if this index belongs
+    # to a subcollection
+    my $indexexparr = [];
+    my $langarr = [];
+
+    # there may be subcollection info, and language info.
+    my ($fields, $subcollection, $language) = split (":", $index);
+    my @subcollections = ();
+    @subcollections = split /,/, $subcollection if (defined $subcollection);
+
+    foreach $subcollection (@subcollections) {
+	if (defined ($self->{'collect_cfg'}->{'subcollection'}->{$subcollection})) {
+	    push (@$indexexparr, $self->{'collect_cfg'}->{'subcollection'}->{$subcollection});
+	}
+    }
+
+    # add expressions for languages if this index belongs to
+    # a language subcollection - only put languages expressions for the
+    # ones we want in the index
+    my @languages = ();
+    my $languagemetadata = "Language";
+    if (defined ($self->{'collect_cfg'}->{'languagemetadata'})) {
+	$languagemetadata = $self->{'collect_cfg'}->{'languagemetadata'};
+    }
+    @languages = split /,/, $language if (defined $language);
+    foreach my $language (@languages) {
+	my $not=0;
+	if ($language =~ s/^\!//) {
+	    $not = 1;
+	}
+	if($not) {
+	    push (@$langarr, "!$language");
+	} else {
+	    push (@$langarr, "$language");
+	}
+    }
+
+    # Build index dictionary. Uses verbatim stem method
+    print $outhandle "\n    creating index dictionary (solr_passes -I1)\n"  if ($self->{'verbosity'} >= 1);
+    print STDERR "<Phase name='CreatingIndexDic'/>\n" if $self->{'gli'};
+    my ($handle);
+
+    if ($self->{'debug'}) {
+	$handle = *STDOUT;
+    } else {
+	my $collection = $self->{'collection'};
+
+	print STDERR "Cmd: $solr_passes_exe $opt_create_index $collection index $solr_passes_sections \"$build_dir\" \"$indexdir\"   $osextra\n";
+	if (!open($handle, "| $solr_passes_exe $opt_create_index $collection index $solr_passes_sections \"$build_dir\" \"$indexdir\"   $osextra")) {
+	    print STDERR "<FatalError name='NoRunSolrPasses'/>\n</Stage>\n" if $self->{'gli'};
+	    die "solrbuilder::build_index - couldn't run $solr_passes_exe\n!$\n";
+	}
+    }
+
+    my $store_levels = $self->{'levels'};
+    my $db_level = "section"; #always
+    my $dom_level = "";
+    foreach my $key (keys %$store_levels) {
+	if ($mgppbuilder::level_map{$key} eq $llevel) {
+	    $dom_level = $key;
+	}
+    }
+    if ($dom_level eq "") {
+	print STDERR "Warning: unrecognized tag level $llevel\n";
+	$dom_level = "document";
+    }
+
+    my $local_levels = { $dom_level => 1 }; # work on one level at a time
+
+    # set up the document processr
+    $self->{'buildproc'}->set_output_handle ($handle);
+    $self->{'buildproc'}->set_mode ('text');
+    $self->{'buildproc'}->set_index ($index, $indexexparr);
+    $self->{'buildproc'}->set_index_languages ($languagemetadata, $langarr) if (defined $language);
+    $self->{'buildproc'}->set_indexing_text (1);
+    #$self->{'buildproc'}->set_indexfieldmap ($self->{'indexfieldmap'});
+    $self->{'buildproc'}->set_levels ($local_levels);
+    $self->{'buildproc'}->set_db_level($db_level);
+    $self->{'buildproc'}->reset();
+
+    print $handle "<update>\n";
+
+    open(TOUT,">/tmp/solr.out"); binmode(TOUT,":utf8");
+    print TOUT "<update>\n";
+    close(TOUT);
+
+    &plugin::read ($self->{'pluginfo'}, $self->{'source_dir'},
+		   "", {}, {}, $self->{'buildproc'}, $self->{'maxdocs'}, 0, $self->{'gli'});
+
+
+    print $handle "</update>\n";
+
+    open(TOUT,">>/tmp/solr.out"); binmode(TOUT,":utf8");
+    print TOUT "</update>\n";
+    close(TOUT);
+
+    close ($handle) unless $self->{'debug'};
+
+    $self->print_stats();
+
+    $self->{'buildproc'}->set_levels ($store_levels);
+    print STDERR "</Stage>\n" if $self->{'gli'};
+
+}
+
+
+
+sub post_build_indexes {
+    my $self = shift(@_);
+
+    # deliberately override to prevent the mgpp post_build_index() calling
+    #  $self->make_final_field_list()
+    # as this has been done in our pre_build_indexes() phase for solr
+    
+}    
+
+
+1;
+
+
Index: gs3-extensions/solr/trunk/src/perllib/solrbuildproc.pm
===================================================================
--- gs3-extensions/solr/trunk/src/perllib/solrbuildproc.pm	(revision 24446)
+++ gs3-extensions/solr/trunk/src/perllib/solrbuildproc.pm	(revision 24446)
@@ -0,0 +1,582 @@
+###########################################################################
+#
+# solrbuildproc.pm -- perl wrapper for building index with Solr
+# A component of the Greenstone digital library software
+# from the New Zealand Digital Library Project at the 
+# University of Waikato, New Zealand.
+#
+# Copyright (C) 1999 New Zealand Digital Library Project
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+###########################################################################
+
+package solrbuildproc;
+
+# This document processor outputs a document for solr to process
+
+# Rather then use the XML structure developed for mgppbuilder/mgppbuildproc
+# whose use was then extended to Lucene, Solr has its own XML syntax:
+#
+#  http://wiki.apache.org/solr/UpdateXmlMessages
+#
+# Using this means we don't need to write SolrWrapper.jar, as had to be
+# done for Lucene, translating the XML syntax piped to it into appropriate
+# calls to the Lucene API
+
+
+use lucenebuildproc;
+use ghtml;
+use strict;
+no strict 'refs'; # allow filehandles to be variables and viceversa
+
+
+use IncrementalBuildUtils;
+
+sub BEGIN {
+    @solrbuildproc::ISA = ('lucenebuildproc');
+}
+
+
+sub new {
+    my $class = shift @_;
+    my $self = new lucenebuildproc (@_);
+
+    return bless $self, $class;
+}
+
+
+#----
+
+sub index_field_mapping_edit {
+    my $self = shift (@_);
+    my ($doc_obj,$file,$edit_mode) = @_;
+
+    # Only add/update gets to here
+    # Currently there is no need to distinguish between these edit modes
+
+    my $outhandle = $self->{'outhandle'};
+
+    # only study this document if it is one to be indexed
+    return if ($doc_obj->get_doc_type() ne "indexed_doc");
+
+    my $indexed_doc = $self->is_subcollection_doc($doc_obj);
+
+    # get the parameters for the output
+    # split on : just in case there is subcoll and lang stuff
+    my ($fields) = split (/:/, $self->{'index'});
+
+    my $doc_section = 0; # just for this document
+
+    # get the text for this document
+    my $section = $doc_obj->get_top_section();
+
+    while (defined $section)
+    {
+	$doc_section++;
+
+	# if we are doing subcollections, then some docs shouldn't be 
+	# considered for indexing
+
+	my $indexed_section 
+	    = $doc_obj->get_metadata_element($section, "gsdldoctype") 
+	      || "indexed_section";
+
+	if (($indexed_doc == 0) 
+	    || ($indexed_section ne "indexed_section" && $indexed_section ne "indexed_doc")) {
+            $section = $doc_obj->get_next_section($section);
+	    next;
+          }
+
+	# has the user added a 'metadata' index?
+	my $all_metadata_specified = 0;
+
+	# which fields have already been indexed?
+	# (same as fields, but in a map)
+	my $specified_fields = {};
+	
+	# do we have an allfields index??
+	my $allfields_index = 0;
+
+	# collect up all the text for it in here
+	my $allfields_text = "";
+
+	foreach my $field (split (/;/, $fields)) {
+	    if ($field eq "allfields") {
+		$allfields_index = 1;
+	    } elsif ($field eq "metadata") {
+		$all_metadata_specified = 1;
+	    }
+	}
+	
+	foreach my $field (split (/;/, $fields)) {
+	    
+	    # only deal with this field if it doesn't start with top or
+	    # this is the first section
+	    my $real_field = $field;
+	    next if (($real_field =~ s/^top//) && ($doc_section != 1));
+	    
+	    # process these two later
+	    next if ($real_field eq "allfields" || $real_field eq "metadata");
+	    
+	    # individual metadata and or text specified 
+	    # -- could be a comma separated list
+	    $specified_fields->{$real_field} = 1;
+
+	    if (!defined $self->{'indexfieldmap'}->{$real_field}) {
+		my $shortname = $self->create_shortname($real_field);
+		$self->{'indexfieldmap'}->{$real_field} = $shortname;
+		$self->{'indexfieldmap'}->{$shortname} = 1;
+	    }	    
+	} # foreach field
+
+
+   	if ($all_metadata_specified) {
+	    
+	    my $new_text = "";
+	    my $shortname = "";
+	    my $metadata = $doc_obj->get_all_metadata ($section);
+
+	    foreach my $pair (@$metadata) {
+		my ($mfield, $mvalue) = (@$pair);
+
+		# no value
+		next unless defined $mvalue && $mvalue ne "";
+
+		# we have already indexed this
+		next if defined ($specified_fields->{$mfield});
+
+		# check fields here, maybe others dont want - change to use dontindex!!
+		next if ($mfield eq "Identifier" || $mfield eq "classifytype" || $mfield eq "assocfilepath");
+		next if ($mfield =~ /^gsdl/);
+		
+		if (defined $self->{'indexfieldmap'}->{$mfield}) {
+		    $shortname = $self->{'indexfieldmap'}->{$mfield};
+		}
+		else {
+		    $shortname = $self->create_shortname($mfield);
+		    $self->{'indexfieldmap'}->{$mfield} = $shortname;
+		    $self->{'indexfieldmap'}->{$shortname} = 1;
+		}	   
+
+		if (!defined $self->{'indexfields'}->{$mfield}) {
+		    $self->{'indexfields'}->{$mfield} = 1;
+		}				    	    
+	    }
+	}
+
+	if ($allfields_index) {
+	    # add the index name mapping
+	    $self->{'indexfieldmap'}->{"allfields"} = "ZZ";
+	    $self->{'indexfieldmap'}->{"ZZ"} = 1;	    	    
+	}
+	    
+        $section = $doc_obj->get_next_section($section);
+
+    } # while defined section
+
+    
+}
+
+sub index_field_mapping {
+    my $self = shift (@_);
+    my ($doc_obj,$file) = @_;
+
+    $self->index_field_mapping_edit($doc_obj,$file,"add");
+}
+
+sub index_field_mappingreindex
+{
+    my $self = shift (@_);
+    my ($doc_obj,$file) = @_;
+
+    $self->index_field_mapping_edit($doc_obj,$file,"update");
+}
+
+sub index_field_mappingdelete
+{
+    my $self = shift (@_);
+    my ($doc_obj,$file) = @_;
+
+    return; # nothing to be done
+}
+
+
+#----
+
+sub textedit {
+    my $self = shift (@_);
+    my ($doc_obj,$file,$edit_mode) = @_;
+
+
+    if (!$self->get_indexing_text()) {
+	# In text-compress mode:
+	# => want document to be output in the simple <Doc>..</Doc> as is
+	# done by its super-class 
+	return $self->SUPER::textedit(@_); 
+    }
+
+    # "update" for $edit_mode near identical to "add" as we use Solr in its
+    # default mode of replacing an existing document if the new document
+    # has the same doc id.  Main area of difference between "add" and "update"
+    # is that we do not update our 'stats' for number of documents or number
+    # of bytes processed.  The latter is inaccurate, but considered better
+    # than allowing the value to steadily climb.
+
+
+    my $solrhandle = $self->{'output_handle'};
+    my $outhandle = $self->{'outhandle'};
+
+    # only output this document if it is one to be indexed
+    return if ($doc_obj->get_doc_type() ne "indexed_doc");
+
+    # skip this document if in "compress-text" mode and asked to delete it
+    return if (!$self->get_indexing_text() && ($edit_mode eq "delete"));
+
+    my $indexed_doc = $self->is_subcollection_doc($doc_obj);
+
+    # this is another document
+    if ($edit_mode eq "add") {
+	$self->{'num_docs'} += 1;
+    }
+    elsif ($edit_mode eq "delete") {
+	$self->{'num_docs'} -= 1;
+    }
+
+    # get the parameters for the output
+    # split on : just in case there is subcoll and lang stuff
+    my ($fields) = split (/:/, $self->{'index'});
+
+    my $levels = $self->{'levels'};
+    my $ldoc_level = $levels->{'document'};
+    my $lsec_level = $levels->{'section'};
+
+    my $gs2_docOID = $doc_obj->get_OID();
+
+
+    my $start_doc;
+    my $end_doc;
+
+    if ($edit_mode eq "add") {
+	$start_doc  = "  <add>\n";
+	$start_doc .= "    <doc>\n";
+	$start_doc .= "      <field name=\"docOID\">$gs2_docOID</field>\n";
+	
+	$end_doc    = "    </doc>\n";
+	$end_doc   .= "  </add>\n"; 
+    }
+    else {
+	$start_doc  = "  <delete>\n";
+	$start_doc .= "    <id>$gs2_docOID</id>\n";
+
+	$end_doc    = "  </delete>\n"; 
+    }
+
+    # add/update, delete
+
+    my $sec_tag_name = "";
+    if ($lsec_level)
+    {
+	$sec_tag_name = $mgppbuildproc::level_map{'section'};
+    }
+
+    my $doc_section = 0; # just for this document
+
+    # only output if working with doc level
+    my $text = $start_doc if ($sec_tag_name eq "");
+
+    # get the text for this document
+    my $section = $doc_obj->get_top_section();
+
+    while (defined $section)
+    {
+	# update a few statistics
+	$doc_section++;
+	$self->{'num_sections'}++;
+
+	my $sec_gs2_id = $self->{'num_sections'};
+	my $sec_gs2_docOID = $gs2_docOID;
+	$sec_gs2_docOID .= ".$section" if ($section ne "");
+	
+	my $start_sec;
+	my $end_sec;
+
+	if ($edit_mode eq "add") {
+	    $start_sec  = "  <add>\n";
+	    $start_sec .= "    <doc>\n";
+	    $start_sec .= "      <field name=\"docOID\">$sec_gs2_docOID</field>\n";
+
+	    $end_sec    = "    </doc>\n";
+	    $end_sec   .= "  </add>\n"; 
+	}
+	else {
+	    $start_sec  = "  <delete>\n";
+	    $start_sec .= "    <id>$sec_gs2_docOID</id>\n";
+
+	    $end_sec    = "  </delete>\n"; 
+	}
+
+
+	# if we are doing subcollections, then some docs shouldn't be indexed.
+	# but we need to put the section tag placeholders in there so the
+	# sections match up with database
+	my $indexed_section = $doc_obj->get_metadata_element($section, "gsdldoctype") || "indexed_section";
+	if (($indexed_doc == 0) || ($indexed_section ne "indexed_section" && $indexed_section ne "indexed_doc")) {
+	    if ($sec_tag_name ne "") {
+		$text .= $start_sec;
+		$text .= $end_sec;
+	    }
+            $section = $doc_obj->get_next_section($section);
+	    next;
+          }
+
+	# add in start section tag if indexing at the section level
+	$text .= $start_sec if ($sec_tag_name ne "");
+
+	if ($edit_mode eq "add") {
+	    $self->{'num_bytes'} += $doc_obj->get_text_length ($section);
+	}
+	elsif ($edit_mode eq "delete") {
+	    $self->{'num_bytes'} -= $doc_obj->get_text_length ($section);
+	}
+
+
+	# has the user added a 'metadata' index?
+	my $all_metadata_specified = 0;
+	# which fields have already been indexed? (same as fields, but in a map)
+	my $specified_fields = {};
+	
+	# do we have an allfields index??
+	my $allfields_index = 0;
+	# collect up all the text for it in here
+	my $allfields_text = "";
+	foreach my $field (split (/;/, $fields)) {
+	    if ($field eq "allfields") {
+		$allfields_index = 1;
+	    } elsif ($field eq "metadata") {
+		$all_metadata_specified = 1;
+	    }
+	}
+	
+	foreach my $field (split (/;/, $fields)) {
+	    
+	    # only deal with this field if it doesn't start with top or
+	    # this is the first section
+	    my $real_field = $field;
+	    next if (($real_field =~ s/^top//) && ($doc_section != 1));
+	    
+	    # process these two later
+	    next if ($real_field eq "allfields" || $real_field eq "metadata");
+	    
+	    #individual metadata and or text specified - could be a comma separated list
+	    $specified_fields->{$real_field} = 1;
+	    my $shortname="";
+	    my $new_field = 0; # have we found a new field name?
+	    if (defined $self->{'indexfieldmap'}->{$real_field}) {
+		$shortname = $self->{'indexfieldmap'}->{$real_field};
+	    }
+	    else {
+		$shortname = $self->create_shortname($real_field);
+		$new_field = 1;
+	    }
+
+	    my @metadata_list = (); # put any metadata values in here
+	    my $section_text = ""; # put the text in here
+	    foreach my $submeta (split /,/, $real_field) {
+		if ($submeta eq "text") {
+		    # no point in indexing text more than once
+		    if ($section_text eq "") {
+			$section_text = $doc_obj->get_text($section);
+			if ($self->{'indexing_text'}) {
+			    # we always strip html
+			    $section_text = $self->preprocess_text($section_text, 1, "");
+			}
+			else { 
+			    # leave html stuff in, but escape the tags
+			    &ghtml::htmlsafe($section_text);
+			}
+		    }
+		}
+		else {
+		    $submeta =~ s/^ex\.//; #strip off ex.
+
+		    # its a metadata element
+		    my @section_metadata = @{$doc_obj->get_metadata ($section, $submeta)};
+		    if ($section ne $doc_obj->get_top_section() && $self->{'indexing_text'} && defined ($self->{'sections_index_document_metadata'})) {
+			if ($self->{'sections_index_document_metadata'} eq "always" || ( scalar(@section_metadata) == 0 && $self->{'sections_index_document_metadata'} eq "unless_section_metadata_exists")) {
+			    push (@section_metadata, @{$doc_obj->get_metadata ($doc_obj->get_top_section(), $submeta)});
+			}
+		    }
+		    push (@metadata_list, @section_metadata);
+		}
+	    } # for each field in this one index
+	    
+	    # now we add the text and/or metadata into new_text
+	    if ($section_text ne "" || scalar(@metadata_list)) {
+		my $new_text = "";
+		
+		if ($section_text ne "") {
+		    $new_text .= "$section_text ";
+		}
+		
+		foreach my $item (@metadata_list) {
+		    &ghtml::htmlsafe($item);
+		    $new_text .= "$item ";
+		}
+
+		if ($allfields_index) {
+		    $allfields_text .= $new_text;
+		}
+
+		if ($self->{'indexing_text'}) {
+		    # add the tag
+		    $new_text = "<field name=\"$shortname\" >$new_text</field>\n";
+		}
+		# filter the text
+		$new_text = $self->filter_text ($field, $new_text);
+
+		if ($edit_mode eq "add") {
+		    $self->{'num_processed_bytes'} += length ($new_text);
+		    $text .= "$new_text";
+		}
+		elsif ($edit_mode eq "update") {
+		    $text .= "$new_text";
+		}
+		elsif ($edit_mode eq "delete") {
+		    $self->{'num_processed_bytes'} -= length ($new_text);
+		}
+		
+
+		if ($self->{'indexing_text'} && $new_field) {
+		    # we need to add to the list in indexfields
+		    
+		    $self->{'indexfieldmap'}->{$real_field} = $shortname;
+		    $self->{'indexfieldmap'}->{$shortname} = 1;
+		}
+		
+	    }
+	    
+	} # foreach field
+
+
+   	if ($all_metadata_specified) {
+	    
+	    my $new_text = "";
+	    my $shortname = "";
+	    my $metadata = $doc_obj->get_all_metadata ($section);
+	    foreach my $pair (@$metadata) {
+		my ($mfield, $mvalue) = (@$pair);
+
+		# no value
+		next unless defined $mvalue && $mvalue ne "";
+
+		# we have already indexed this
+		next if defined ($specified_fields->{$mfield});
+
+		# check fields here, maybe others dont want - change to use dontindex!!
+		next if ($mfield eq "Identifier" || $mfield eq "classifytype" || $mfield eq "assocfilepath");
+		next if ($mfield =~ /^gsdl/);
+		
+		&ghtml::htmlsafe($mvalue);
+		
+		if (defined $self->{'indexfieldmap'}->{$mfield}) {
+		    $shortname = $self->{'indexfieldmap'}->{$mfield};
+		}
+		else {
+		    $shortname = $self->create_shortname($mfield);
+		    $self->{'indexfieldmap'}->{$mfield} = $shortname;
+		    $self->{'indexfieldmap'}->{$shortname} = 1;
+		}	   
+		$new_text .= "<field name=\"$shortname\">$mvalue</field>\n";
+		if ($allfields_index) {
+		    $allfields_text .= "$mvalue ";
+		}
+
+		if (!defined $self->{'indexfields'}->{$mfield}) {
+		    $self->{'indexfields'}->{$mfield} = 1;
+		}				    
+	    
+	    }
+	    # filter the text
+	    $new_text = $self->filter_text ("metadata", $new_text);
+	    
+	    if ($edit_mode eq "add") {
+		$self->{'num_processed_bytes'} += length ($new_text);
+		$text .= "$new_text";
+	    }
+	    elsif ($edit_mode eq "update") {
+		$text .= "$new_text";
+	    }
+	    elsif ($edit_mode eq "delete") {
+		$self->{'num_processed_bytes'} -= length ($new_text);
+	    }	    
+	}
+
+	if ($allfields_index) {
+	    # add the index name mapping
+	    $self->{'indexfieldmap'}->{"allfields"} = "ZZ";
+	    $self->{'indexfieldmap'}->{"ZZ"} = 1;
+	    
+	    my $new_text = "<field name=\"ZZ\">$allfields_text</field>\n";
+	    # filter the text
+	    $new_text = $self->filter_text ("allfields", $new_text);
+	    
+	    if ($edit_mode eq "add") {
+		$self->{'num_processed_bytes'} += length ($new_text);
+		$text .= "$new_text";
+	    }
+	    elsif ($edit_mode eq "update") {
+		$text .= "$new_text";
+	    }
+	    elsif ($edit_mode eq "delete") {
+		$self->{'num_processed_bytes'} -= length ($new_text);
+	    }
+	}
+	    
+	# add in end tag if at top-level doc root, or indexing at the section level
+	$text .= $end_sec if ($sec_tag_name ne "");
+
+        $section = $doc_obj->get_next_section($section);
+    } # while defined section
+
+    
+    # only output if working with doc level
+    $text .= $end_doc if ($sec_tag_name eq "");
+
+
+##    $text .= "<commit/>\n";
+
+    print $solrhandle $text;
+
+    open(TOUT,">>/tmp/solr.out"); binmode(TOUT,":utf8");
+    print TOUT $text;
+    close(TOUT);
+}
+
+
+
+
+sub textreindex
+{
+    my $self = shift (@_);
+    my ($doc_obj,$file) = @_;
+
+    $self->textedit($doc_obj,$file,"update");
+}
+
+
+1;
+
+
Index: gs3-extensions/solr/trunk/src/setup.bash
===================================================================
--- gs3-extensions/solr/trunk/src/setup.bash	(revision 24446)
+++ gs3-extensions/solr/trunk/src/setup.bash	(revision 24446)
@@ -0,0 +1,75 @@
+
+extdesc="the Solr Extension"
+
+full_setup=`pwd`/${BASH_SOURCE}
+fulldir=${full_setup%/*}
+fulldir=${fulldir%/.}
+
+#--
+# Edit the following two port values if they conflict with
+# with existing services on your computer
+#--
+
+# The port Jetty runs on:
+SOLR_JETTY_PORT=8983
+
+# The port Jetty listens on for a "stop" command
+JETTY_STOP_PORT=8079
+
+
+if test -z $GSDLOS ; then
+  GSDLOS=`uname -s | tr '[A-Z]' '[a-z]'`
+  # check for running bash under Cygwin
+  if test "`echo $GSDLOS | sed 's/cygwin//'`" != "$GSDLOS" ;
+  then
+    GSDLOS=windows
+  fi
+  # check for running bash under MinGW/MSys
+  if test "`echo $GSDLOS | sed 's/mingw//'`" != "$GSDLOS" ;
+  then
+    GSDLOS=windows
+  fi
+  echo "GSDLOS was not set.  Setting it to '$GSDLOS'"
+  export GSDLOS
+fi
+	
+first_time=0;
+
+if [ "x$GEXT_SOLR" = "x" ] ; then
+  export GEXT_SOLR=`pwd`
+
+  if [ -d "$GEXT_SOLR/bin/script" ] ; then
+    export PATH=$GEXT_SOLR/bin/script:$PATH
+  fi
+
+  if [ -d "$GEXT_SOLR/lib" ] ; then
+    if [ "$GSDLOS" = "linux" ] ; then
+      export LD_LIBRARY_PATH=$GEXT_SOLR/lib:$LD_LIBRARY_PATH
+    elif [ "$GSDLOS" = "darwin" ] ; then
+      export DYLD_LIBRARY_PATH=$GEXT_SOLR/lib:$DYLD_LIBRARY_PATH
+    fi
+  fi
+
+  extdir=${GEXT_SOLR##*/}
+
+  if [ "x$GSDLEXTS" = "x" ] ; then
+    export GSDLEXTS=$extdir
+  else 
+    export GSDLEXTS=$GSDLEXTS:$extdir
+  fi
+
+  export SOLR_JETTY_PORT
+  export JETTY_STOP_PORT
+  first_time=1
+
+  echo "+Your environment is now setup for $extdesc"
+else
+  echo "+Your environment is already setup for $extdesc"
+fi
+
+echo "++Solr/Jetty server will run on port $SOLR_JETTY_PORT (+ port $JETTY_STOP_PORT for shutdown command)"
+
+if [ "$first_time" = "1" ] ; then
+  echo "--These port values can be changed by editing:"
+  echo "--  $full_setup"
+fi
Index: gs3-extensions/solr/trunk/src/setup.bat
===================================================================
--- gs3-extensions/solr/trunk/src/setup.bat	(revision 24446)
+++ gs3-extensions/solr/trunk/src/setup.bat	(revision 24446)
@@ -0,0 +1,62 @@
+@echo off
+pushd "%CD%"
+CD /D "%~dp0"
+
+set extdesc=the Solr Extension
+
+if "%OS%" == "Windows_NT" goto WinNT
+if "%OS%" == "" goto Win95
+if "%GSDLLANG%" == "en" echo Setup failed - your PATH has not been set
+if "%GSDLLANG%" == "es" echo No se pudo realizar la configuraci¢n - no se ha establecido la RUTA.
+if "%GSDLLANG%" == "fr" echo Echc de l'installation - votre variable PATH n'a pas t ajuste
+if "%GSDLLANG%" == "ru" echo áâ ­®¢ª  ­¥ ã€ « áì -  ­¥ ¡ë« ãáâ ­®¢«¥­
+goto End
+
+:WinNT
+set GEXT_SOLR=%CD%
+set PATH=%GEXT_SOLR%\bin\script;%PATH%
+set PATH=%GEXT_SOLR%\lib;%PATH%
+set GS_CP_SET=yes
+goto Success
+
+:Win95
+if "%1" == "SetEnv" goto Win95Env
+REM We'll invoke a second copy of the command processor to make
+REM sure there's enough environment space
+COMMAND /E:2048 /K %0 SetEnv
+goto End
+
+:Win95Env
+set GEXT_SOLR=%CD%
+set PATH="%GEXT_SOLR%\bin\script";"%PATH%"
+set PATH="%GEXT_SOLR%\lib";"%PATH%"
+set GS_CP_SET=yes
+goto Success
+
+:Success
+
+set fulldir=%~dp0
+
+:: strip off everything up to (and including) ext dir
+set extdir=%fulldir:*ext\=%
+
+:: remove trailing slash
+set extdir=%extdir:\=%
+
+setlocal enabledelayedexpansion
+if "x%GSDLEXTS%" == "x" (
+  set GSDLEXTS=!extdir!
+) else (
+  set GSDLEXTS=!GSDLEXTS!:!extdir!
+)
+endlocal & set GSDLEXTS=%GSDLEXTS%
+
+echo +Your environment is now setup for %extdesc%
+
+:: Back to delayed expansion to avoid problems with environment
+:: variables with brackets in them, such as "Program Files (x86)"
+
+
+:End
+
+popd
Index: gs3-extensions/solr/trunk/src/solr-setup.pl
===================================================================
--- gs3-extensions/solr/trunk/src/solr-setup.pl	(revision 24446)
+++ gs3-extensions/solr/trunk/src/solr-setup.pl	(revision 24446)
@@ -0,0 +1,70 @@
+
+BEGIN {
+    die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
+    die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
+    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+}
+
+use Cwd;
+require util;    
+
+my $env_ext  = "GEXT_SOLR";
+my $ext_desc = "the SOLR Extension";
+
+if (!defined $ENV{$env_ext}) {
+    
+    my $ext_home = cwd();
+    $ENV{$env_ext} = $ext_home;
+
+    my $ext_bin_script = &util::filename_cat($ENV{$env_ext},"bin","script");
+    my $ext_lib = &util::filename_cat($ENV{$env_ext},"lib");
+
+    if (-d $ext_bin_script) {
+	&util::envvar_prepend("PATH",$ext_bin_script);
+    }
+   
+    if (-d $ext_lib) {
+	if ($ENV{'GSDLOS'} =~ m/windows/i) {
+	    &util::envvar_prepend("PATH",$ext_lib);
+	} 
+	elsif ($ENV{'GSDLOS'} =~ m/darwin/i) {
+	    &util::envvar_prepend("DYLD_LIBRARY_PATH",$ext_lib);
+	}
+	else { # linux
+	    &util::envvar_prepend("LD_LIBRARY_PATH",$ext_lib);
+	}
+    }
+
+    if ($ENV{'GSDLOS'} =~ m/windows/i) {
+	$ENV{'GS_CP_SET'} = "yes";
+    }
+
+    my ($ext_dir,$_prefix_dir) = File::Basename::fileparse($ext_home);
+    # GSDLEXTS always uses : as a separator
+    if (defined $ENV{'GSDLEXTS'}) {
+	$ENV{'GSDLEXTS'} .= ":$ext_dir";
+    }
+    else {
+	$ENV{'GSDLEXTS'} = $ext_dir;
+    }
+    
+    print STDERR "+Your environment is now setup for $ext_desc\n";
+}
+else {    
+    print STDERR "+Your environment is already setup for $ext_desc\n";
+}
+
+if (scalar(@ARGV>0)) {
+
+    print STDERR "\n";
+
+    my $cmd = join(" ",map {$_ = "\"$_\""} @ARGV);
+
+    if (system($cmd)!=0) {
+	print STDERR "\nError: Failed to run '$cmd'\n";
+	print STDERR "$!\n";
+    }
+}
+
+1;
