[open-ils-commits] r12023 - in branches/staff-client-experiment: . Open-ILS/examples Open-ILS/src/c-apps Open-ILS/src/extras Open-ILS/src/extras/import Open-ILS/src/perlmods/OpenILS/Application/Trigger Open-ILS/src/sql/Pg Open-ILS/tests/datasets Open-ILS/web/js/dojo/openils Open-ILS/web/reports

svn at svn.open-ils.org svn at svn.open-ils.org
Sat Jan 31 16:16:35 EST 2009


Author: phasefx
Date: 2009-01-31 16:16:31 -0500 (Sat, 31 Jan 2009)
New Revision: 12023

Added:
   branches/staff-client-experiment/Open-ILS/src/c-apps/dump_idl.c
   branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Cleanup.pm
   branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Collector.pm
   branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Event.pm
   branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Reactor.pm
   branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Validator.pm
   branches/staff-client-experiment/Open-ILS/tests/datasets/map_data.mrc
Modified:
   branches/staff-client-experiment/
   branches/staff-client-experiment/Open-ILS/examples/fm_IDL.xml
   branches/staff-client-experiment/Open-ILS/examples/opensrf_core.xml.example
   branches/staff-client-experiment/Open-ILS/examples/permacrud.xsd
   branches/staff-client-experiment/Open-ILS/src/c-apps/Makefile.am
   branches/staff-client-experiment/Open-ILS/src/c-apps/oils_cstore.c
   branches/staff-client-experiment/Open-ILS/src/c-apps/oils_idl-core.c
   branches/staff-client-experiment/Open-ILS/src/extras/fast-extract
   branches/staff-client-experiment/Open-ILS/src/extras/import/marc_add_ids
   branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/ModRunner.pm
   branches/staff-client-experiment/Open-ILS/src/sql/Pg/400.schema.action_trigger.sql
   branches/staff-client-experiment/Open-ILS/tests/datasets/README
   branches/staff-client-experiment/Open-ILS/web/js/dojo/openils/PermaCrud.js
   branches/staff-client-experiment/Open-ILS/web/reports/oils_rpt_common.xhtml
   branches/staff-client-experiment/Open-ILS/web/reports/oils_rpt_folder_window.js
Log:
Merged revisions 11987-11992,11995,11998,12001-12007,12010-12011,12014-12019,12022 via svnmerge from 
svn://svn.open-ils.org/ILS/trunk

........
  r11987 | miker | 2009-01-26 21:15:09 -0500 (Mon, 26 Jan 2009) | 1 line
  
  initial single-event firing module
........
  r11988 | miker | 2009-01-26 21:15:47 -0500 (Mon, 26 Jan 2009) | 1 line
  
  more states available to events
........
  r11989 | miker | 2009-01-26 21:21:33 -0500 (Mon, 26 Jan 2009) | 1 line
  
  throw errors when we cannot update the event state
........
  r11990 | miker | 2009-01-26 21:23:18 -0500 (Mon, 26 Jan 2009) | 1 line
  
  for now use die instead of throw
........
  r11991 | dbs | 2009-01-26 22:28:14 -0500 (Mon, 26 Jan 2009) | 2 lines
  
  Add a little sample of geospatial data for FGDC/CSDGM transform fun
........
  r11992 | dbs | 2009-01-26 22:33:32 -0500 (Mon, 26 Jan 2009) | 3 lines
  
  We need to expose vandelay and permacrud as public services.
  Sort the list of public services so it's easy to skim through.
........
  r11995 | dbs | 2009-01-26 23:30:46 -0500 (Mon, 26 Jan 2009) | 2 lines
  
  Fix regression that prevents anyone from viewing reports
........
  r11998 | dbs | 2009-01-27 08:39:52 -0500 (Tue, 27 Jan 2009) | 1 line
  
  Second part of fix for viewing reports, related to r11995
........
  r12001 | miker | 2009-01-27 20:44:05 -0500 (Tue, 27 Jan 2009) | 1 line
  
  add specialized module namespace overrides
........
  r12002 | miker | 2009-01-27 20:44:48 -0500 (Tue, 27 Jan 2009) | 1 line
  
  refactor the general object layout; use fleshing where possible
........
  r12003 | miker | 2009-01-27 20:46:14 -0500 (Tue, 27 Jan 2009) | 1 line
  
  Add some basic dummy handlers (fourtytwo, NOOP_True and NOOP_False) for each module type
........
  r12004 | miker | 2009-01-27 20:59:53 -0500 (Tue, 27 Jan 2009) | 1 line
  
  allow either fleshed or unfleshed module objects
........
  r12005 | miker | 2009-01-27 21:01:24 -0500 (Tue, 27 Jan 2009) | 1 line
  
  remove (now) needless fleshing
........
  r12006 | miker | 2009-01-27 21:17:38 -0500 (Tue, 27 Jan 2009) | 1 line
  
  example validators; adding noop modules to the schema creation script
........
  r12007 | miker | 2009-01-28 14:02:01 -0500 (Wed, 28 Jan 2009) | 1 line
  
  can not retrieve an object before we create it ... doh! (thanks, Laura, for catching this)
........
  r12010 | miker | 2009-01-29 10:27:50 -0500 (Thu, 29 Jan 2009) | 1 line
  
  always assume disconnect succeeds ... for now
........
  r12011 | phasefx | 2009-01-29 14:11:55 -0500 (Thu, 29 Jan 2009) | 1 line
  
  this file doesn't follow the convention used elsewhere.. so wrong path to this object
........
  r12014 | miker | 2009-01-29 15:02:17 -0500 (Thu, 29 Jan 2009) | 1 line
  
  output the deleted column from fast-extract; use said column in marc_add_ids
........
  r12015 | miker | 2009-01-29 15:05:29 -0500 (Thu, 29 Jan 2009) | 1 line
  
  good-ify the output xml
........
  r12016 | miker | 2009-01-30 16:36:44 -0500 (Fri, 30 Jan 2009) | 1 line
  
  adding support for jump attribute, for remote indirection; fixing incorrect comment
........
  r12017 | miker | 2009-01-30 16:37:59 -0500 (Fri, 30 Jan 2009) | 1 line
  
  adding Scott's dump_idl utility, and adding jump support; makefile support for dump_idl
........
  r12018 | miker | 2009-01-30 16:38:47 -0500 (Fri, 30 Jan 2009) | 1 line
  
  asva needs the jump attribute to from question to survey to owner
........
  r12019 | miker | 2009-01-30 18:02:18 -0500 (Fri, 30 Jan 2009) | 1 line
  
  teaching the pcrud personallity of cstore how to use the jump attr in permacrud action context elements
........
  r12022 | miker | 2009-01-31 15:50:17 -0500 (Sat, 31 Jan 2009) | 1 line
  
  adding jump attr to the xsd; adding jump to asva
........



Property changes on: branches/staff-client-experiment
___________________________________________________________________
Name: svnmerge-integrated
   - /trunk:1-11985
   + /trunk:1-12022

Modified: branches/staff-client-experiment/Open-ILS/examples/fm_IDL.xml
===================================================================
--- branches/staff-client-experiment/Open-ILS/examples/fm_IDL.xml	2009-01-31 20:50:17 UTC (rev 12022)
+++ branches/staff-client-experiment/Open-ILS/examples/fm_IDL.xml	2009-01-31 21:16:31 UTC (rev 12023)
@@ -672,6 +672,7 @@
 			<field reporter:label="Processing Group Context Field" name="group_field" oils_obj:array_position="13" oils_persist:virtual="false"  reporter:datatype="text"/>
 			<field reporter:label="Template" name="template" oils_obj:array_position="14" oils_persist:virtual="false"  reporter:datatype="text"/>
 			<field reporter:label="Environmet Entries" name="env" oils_obj:array_position="15" oils_persist:virtual="true"  reporter:datatype="link"/>
+			<field reporter:label="Parameters" name="params" oils_obj:array_position="16" oils_persist:virtual="true"  reporter:datatype="link"/>
 		</fields>
 		<links>
 			<link field="owner" reltype="has_a" key="id" map="" class="aou"/>
@@ -681,6 +682,7 @@
 			<link field="cleanup_success" reltype="has_a" key="id" map="" class="atclean"/>
 			<link field="cleanup_failure" reltype="has_a" key="id" map="" class="atclean"/>
 			<link field="env" reltype="has_many" key="id" map="" class="atenv"/>
+			<link field="params" reltype="has_many" key="id" map="" class="atevparam"/>
 		</links>
 	</class>
 
@@ -3307,6 +3309,20 @@
 			<link field="question" reltype="has_a" key="id" map="" class="asvq"/>
 			<link field="responses" reltype="has_many" key="answer" map="" class="asvr"/>
 		</links>
+        <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+            <actions>
+                <create permission="ADMIN_SURVEY">
+                    <context link="question" jump="survey" field="owner"/>
+                </create>
+                <retrieve/>
+                <update permission="ADMIN_SURVEY">
+                    <context link="question" jump="survey" field="owner"/>
+                </update>
+                <delete permission="ADMIN_SURVEY">
+                    <context link="question" jump="survey" field="owner"/>
+                </delete>
+            </actions>
+        </permacrud>
 	</class>
 	<class id="ancc" controller="open-ils.cstore" oils_obj:fieldmapper="action::non_cataloged_circulation" oils_persist:tablename="action.non_cataloged_circulation" reporter:core="true" reporter:label="Non-cataloged Circulation">
 		<fields oils_persist:primary="id" oils_persist:sequence="action.non_cataloged_circulation_id_seq">

Modified: branches/staff-client-experiment/Open-ILS/examples/opensrf_core.xml.example
===================================================================
--- branches/staff-client-experiment/Open-ILS/examples/opensrf_core.xml.example	2009-01-31 20:50:17 UTC (rev 12022)
+++ branches/staff-client-experiment/Open-ILS/examples/opensrf_core.xml.example	2009-01-31 21:16:31 UTC (rev 12023)
@@ -19,15 +19,17 @@
 
         <services>
           <service>opensrf.math</service>
+          <service>open-ils.actor</service>
+          <service>open-ils.auth</service>
           <service>open-ils.cat</service>
-          <service>open-ils.supercat</service>
-          <service>open-ils.search</service>
           <service>open-ils.circ</service>
-          <service>open-ils.actor</service>
-          <service>open-ils.auth</service>
+          <service>open-ils.collections</service>
           <service>open-ils.fielder</service>
-          <service>open-ils.collections</service>
+          <service>open-ils.permacrud</service>
           <service>open-ils.reporter</service>
+          <service>open-ils.search</service>
+          <service>open-ils.supercat</service>
+          <service>open-ils.vandelay</service>
         </services>
       </router>
 

Modified: branches/staff-client-experiment/Open-ILS/examples/permacrud.xsd
===================================================================
--- branches/staff-client-experiment/Open-ILS/examples/permacrud.xsd	2009-01-31 20:50:17 UTC (rev 12022)
+++ branches/staff-client-experiment/Open-ILS/examples/permacrud.xsd	2009-01-31 21:16:31 UTC (rev 12023)
@@ -34,6 +34,7 @@
 <xs:element name="context" nillable="true">
  <xs:complexType>
   <xs:attribute name="link"/>
+  <xs:attribute name="jump"/>
   <xs:attribute name="field" use="required"/>
   <xs:attribute name="global_required"/>
  </xs:complexType>

Modified: branches/staff-client-experiment/Open-ILS/src/c-apps/Makefile.am
===================================================================
--- branches/staff-client-experiment/Open-ILS/src/c-apps/Makefile.am	2009-01-31 20:50:17 UTC (rev 12022)
+++ branches/staff-client-experiment/Open-ILS/src/c-apps/Makefile.am	2009-01-31 21:16:31 UTC (rev 12023)
@@ -7,11 +7,15 @@
 AM_CFLAGS = $(DEF_CFLAGS) -DOSRF_LOG_PARAMS -I at top_srcdir@/include/
 AM_LDFLAGS = $(DEF_LDFLAGS) -L$(DBI_LIBS) -lopensrf 
 
-bin_PROGRAMS = oils_dataloader
+bin_PROGRAMS = oils_dataloader dump_idl
 oils_dataloader_SOURCES = oils_dataloader.c
 oils_dataloader_LDFLAGS = $(AM_LDFLAGS) -loils_idl
 oils_dataloader_DEPENDENCIES = liboils_idl.la liboils_utils.la
 
+dump_idl_SOURCES = dump_idl.c
+dump_idl_LDFLAGS = $(AM_LDFLAGS) -loils_idl
+dump_idl_DEPENDENCIES = liboils_idl.la liboils_utils.la
+
 lib_LTLIBRARIES = liboils_idl.la liboils_utils.la oils_cstore.la oils_rstore.la oils_pcrud.la oils_auth.la
 
 liboils_idl_la_SOURCES = oils_idl-core.c

Copied: branches/staff-client-experiment/Open-ILS/src/c-apps/dump_idl.c (from rev 12022, trunk/Open-ILS/src/c-apps/dump_idl.c)
===================================================================
--- branches/staff-client-experiment/Open-ILS/src/c-apps/dump_idl.c	                        (rev 0)
+++ branches/staff-client-experiment/Open-ILS/src/c-apps/dump_idl.c	2009-01-31 21:16:31 UTC (rev 12023)
@@ -0,0 +1,412 @@
+/*
+*  C Implementation: dump_idl
+*
+* Description: 
+*
+*
+* Author: Scott McKellar <scott at esilibrary.com>, (C) 2009
+*
+* Copyright: See COPYING file that comes with this distribution
+*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <opensrf/string_array.h>
+#include <opensrf/osrf_hash.h>
+#include <openils/oils_idl.h>
+
+static void dump_idl( osrfHash* IDLHash );
+static void dump_class( osrfHash* class_hash, const char* class_name );
+static void dump_fields( osrfHash* field_hash );
+static void dump_one_field( osrfHash* field_hash, const char* field_name );
+static void dump_links( osrfHash* links_hash );
+static void dump_one_link( osrfHash* link_hash, const char* link_name );
+static void dump_permacrud( osrfHash* pcrud_hash );
+static void dump_action( osrfHash* action_hash, const char* action_name );
+static void dump_foreign_context( osrfHash* fc_hash );
+static void dump_fc_class( osrfHash* fc_class_hash, const char* class_name );
+static void dump_string_array( 
+	osrfStringArray* sarr, const char* name, const char* indent );
+
+int main( int argc, char* argv[] ) {
+	int rc = 0;
+	
+	// Suppress informational messages
+	osrfLogSetLevel( OSRF_LOG_WARNING );
+
+	// Get name of IDL file, if specified on command line
+	const char* IDL_filename = NULL;
+	int filename_expected = 0;		// boolean
+	int i;
+	for( i = 1; i < argc; ++i ) {
+		const char* arg = argv[ i ];
+		printf( "%s\n", arg );
+		if( filename_expected ) {
+			IDL_filename = arg;
+			filename_expected = 0;
+		} else {
+			if( '-' == arg[ 0 ] && 'f' == arg[1] ) {
+				if( IDL_filename ) {
+					fprintf( stderr, "Only one IDL file may be specified\n" );
+					return 1;
+				} else {
+					if( arg[ 2 ] )
+						IDL_filename = arg + 2;
+					else
+						filename_expected = 1;
+				}
+			}
+			else
+				break;
+		}
+	}
+	
+	if( filename_expected ) {
+		fprintf( stderr, "IDL filename expected on command line, not found\n" );
+		return 1;
+	}
+
+	// No filename?  Look in the environment
+	if( !IDL_filename )
+		IDL_filename = getenv( "OILS_IDL_FILENAME" );
+
+	// Still no filename?  Apply a default
+	if( !IDL_filename )
+		IDL_filename = "/openils/conf/fm_IDL.xml";
+	
+	printf( "IDL filename: %s\n", IDL_filename );
+	
+	osrfHash* IDL = oilsIDLInit( IDL_filename );
+	if( NULL == IDL ) {
+		fputs( "Failed to build IDL\n", stderr );
+		rc = 1;
+	}
+
+	if( i >= argc )
+		// No classes specified?  Dump them all
+		dump_idl( IDL );
+	else do {
+		// Dump the requested classes
+		dump_class( osrfHashGet( IDL, argv[ i ] ), argv[ i ] );
+		++i;
+	} while( i < argc );
+		
+	return rc;
+}
+
+static void dump_idl( osrfHash* IDLHash ) {
+	if( NULL == IDLHash )
+		return;
+
+	if( 0 == osrfHashGetCount( IDLHash ) )
+		return;
+
+	osrfHashIterator* iter = osrfNewHashIterator( IDLHash );
+	osrfHash* class_hash = NULL;
+	
+	// Dump each class
+	for( ;; ) {
+		class_hash = osrfHashIteratorNext( iter );
+		if( class_hash )
+			dump_class( class_hash, osrfHashIteratorKey( iter ) );
+		else
+			break;
+	}
+
+	osrfHashIteratorFree( iter );
+}
+
+static void dump_class( osrfHash* class_hash, const char* class_name )
+{
+	if( !class_hash || !class_name )
+		return;
+	
+	if( 0 == osrfHashGetCount( class_hash ) )
+		return;
+
+	printf( "Class %s\n", class_name );
+	const char* indent = "    ";
+	
+	osrfHashIterator* iter = osrfNewHashIterator( class_hash );
+	
+	// Dump each attribute, etc. of the class hash
+	for( ;; ) {
+		void* class_attr = osrfHashIteratorNext( iter );
+		if( class_attr ) {
+			const char* attr_name = osrfHashIteratorKey( iter );
+			if( !strcmp( attr_name, "classname" ) )
+				printf( "%s%s: %s\n", indent, attr_name, (char*) class_attr );
+			else if( !strcmp( attr_name, "fieldmapper" ) )
+				printf( "%s%s: %s\n", indent, attr_name, (char*) class_attr );
+			else if( !strcmp( attr_name, "tablename" ) )
+				printf( "%s%s: %s\n", indent, attr_name, (char*) class_attr );
+			else if( !strcmp( attr_name, "virtual" ) )
+				printf( "%s%s: %s\n", indent, attr_name, (char*) class_attr );
+			else if( !strcmp( attr_name, "controller" ) )
+				dump_string_array( (osrfStringArray*) class_attr, attr_name, indent );
+			else if( !strcmp( attr_name, "fields" ) )
+				dump_fields( (osrfHash*) class_attr );
+			else if( !strcmp( attr_name, "links" ) )
+				dump_links( (osrfHash*) class_attr );
+			else if( !strcmp( attr_name, "primarykey" ) )
+				printf( "%s%s: %s\n", indent, attr_name, (char*) class_attr );
+			else if( !strcmp( attr_name, "sequence" ) )
+				printf( "%s%s: %s\n", indent, attr_name, (char*) class_attr );
+			else if( !strcmp( attr_name, "permacrud" ) )
+				dump_permacrud( (osrfHash*) class_attr );
+			else if( !strcmp( attr_name, "source_definition" ) )
+				printf( "%s%s:\n%s\n", indent, attr_name, (char*) class_attr );
+			else
+				printf( "%s%s (unknown)\n", indent, attr_name );
+		} else
+			break;
+	}
+}
+
+static void dump_fields( osrfHash* fields_hash ) {
+	if( NULL == fields_hash )
+		return;
+
+	if( 0 == osrfHashGetCount( fields_hash ) )
+		return;
+
+	fputs( "    fields\n", stdout );
+	
+	osrfHashIterator* iter = osrfNewHashIterator( fields_hash );
+	osrfHash* fields_attr = NULL;
+	
+	// Dump each field
+	for( ;; ) {
+		fields_attr = osrfHashIteratorNext( iter );
+		if( fields_attr )
+			dump_one_field( fields_attr, osrfHashIteratorKey( iter ) );
+		else
+			break;
+	}
+
+	osrfHashIteratorFree( iter );
+}
+
+static void dump_one_field( osrfHash* field_hash, const char* field_name ) {
+	if( !field_hash || !field_name )
+		return;
+	
+	if( 0 == osrfHashGetCount( field_hash ) )
+		return;
+
+	printf( "        %s\n", field_name  );
+	
+	osrfHashIterator* iter = osrfNewHashIterator( field_hash );
+	const char* field_attr = NULL;
+	const char* indent = "            ";
+	
+	// Dump each field attribute
+	for( ;; ) {
+		field_attr = osrfHashIteratorNext( iter );
+		if( field_attr )
+			printf( "%s%s: %s\n", indent, osrfHashIteratorKey( iter ), field_attr );
+		else
+			break;
+	}
+
+	osrfHashIteratorFree( iter );
+}
+
+static void dump_links( osrfHash* links_hash ) {
+	if( NULL == links_hash )
+		return;
+
+	if( 0 == osrfHashGetCount( links_hash ) )
+		return;
+
+	fputs( "    links\n", stdout );
+	
+	osrfHashIterator* iter = osrfNewHashIterator( links_hash );
+	osrfHash* links_attr = NULL;
+	
+	// Dump each link
+	for( ;; ) {
+		links_attr = osrfHashIteratorNext( iter );
+		if( links_attr )
+			dump_one_link( links_attr, osrfHashIteratorKey( iter ) );
+		else
+			break;
+	}
+
+	osrfHashIteratorFree( iter );
+}
+
+static void dump_one_link( osrfHash* link_hash, const char* link_name ) {
+	if( !link_hash || !link_name )
+		return;
+	
+	if( 0 == osrfHashGetCount( link_hash ) )
+		return;
+
+	printf( "        %s\n", link_name  );
+	
+	osrfHashIterator* iter = osrfNewHashIterator( link_hash );
+	const void* link_attr = NULL;
+	const char* indent = "            ";
+	
+	// Dump each link attribute
+	for( ;; ) {
+		link_attr = osrfHashIteratorNext( iter );
+		if( link_attr ) {
+			const char* link_attr_name = osrfHashIteratorKey( iter );
+			if( !strcmp( link_attr_name, "reltype" ) )
+				printf( "%s%s: %s\n", indent, link_attr_name, (char*) link_attr );
+			else if( !strcmp( link_attr_name, "key" ) )
+				printf( "%s%s: %s\n", indent, link_attr_name, (char*) link_attr );
+			else if( !strcmp( link_attr_name, "class" ) )
+				printf( "%s%s: %s\n", indent, link_attr_name, (char*) link_attr );
+			else if( !strcmp( link_attr_name, "map" ) ) 
+				dump_string_array( (osrfStringArray*) link_attr, link_attr_name, indent );
+			else if( !strcmp( link_attr_name, "field" ) )
+				printf( "%s%s: %s\n", indent, link_attr_name, (char*) link_attr );
+			else
+				printf( "%s%s (unknown)\n", indent, link_attr_name );
+		} else
+			break;
+	}
+
+	osrfHashIteratorFree( iter );
+}
+
+static void dump_permacrud( osrfHash* pcrud_hash ) {
+	if( NULL == pcrud_hash )
+		return;
+
+	if( 0 == osrfHashGetCount( pcrud_hash ) )
+		return;
+
+	fputs( "    permacrud\n", stdout );
+	
+	osrfHashIterator* iter = osrfNewHashIterator( pcrud_hash );
+	osrfHash* pcrud_attr = NULL;
+
+	// Dump each action
+	for( ;; ) {
+		pcrud_attr = osrfHashIteratorNext( iter );
+		if( pcrud_attr )
+			dump_action( pcrud_attr, osrfHashIteratorKey( iter ) );
+		else
+			break;
+	}
+
+	osrfHashIteratorFree( iter );
+}
+
+static void dump_action( osrfHash* action_hash, const char* action_name ) {
+	if( !action_hash || !action_name )
+		return;
+
+	if( 0 == osrfHashGetCount( action_hash ) )
+		return;
+
+	printf( "        %s\n", action_name );
+
+	osrfHashIterator* iter = osrfNewHashIterator( action_hash );
+	void* action_attr = NULL;
+	const char* indent = "            ";
+
+	// Dump each attribute of the action
+	for( ;; ) {
+		action_attr = osrfHashIteratorNext( iter );
+		if( action_attr ) {
+			const char* attr_name = osrfHashIteratorKey( iter );
+			if( !strcmp( attr_name, "permission" ) )
+				dump_string_array( action_attr, attr_name, indent );
+			else if( !strcmp( attr_name, "global_required" ) )
+				printf( "%s%s: %s\n", indent, attr_name, (char*) action_attr );
+			else if( !strcmp( attr_name, "local_context" ) )
+				dump_string_array( action_attr, attr_name, indent );
+			else if( !strcmp( attr_name, "foreign_context" ) )
+				dump_foreign_context( action_attr );
+			else
+				printf( "%s%s (unknown)\n", indent, attr_name );
+		} else
+			break;
+	}
+
+	osrfHashIteratorFree( iter );
+}
+
+static void dump_foreign_context( osrfHash* fc_hash ) {
+	if( !fc_hash )
+		return;
+	
+	if( 0 == osrfHashGetCount( fc_hash ) )
+		return;
+
+	fputs( "            foreign_context\n", stdout );
+
+	osrfHashIterator* iter = osrfNewHashIterator( fc_hash );
+	osrfHash* fc_attr = NULL;
+
+	// Dump each foreign context attribute
+	for( ;; ) {
+		fc_attr = osrfHashIteratorNext( iter );
+		if( fc_attr )
+			dump_fc_class( (osrfHash*) fc_attr, osrfHashIteratorKey( iter ) );
+		else
+			break;
+	}
+
+	osrfHashIteratorFree( iter );
+}
+
+static void dump_fc_class( osrfHash* fc_class_hash, const char* class_name )
+{
+	if( ! fc_class_hash )
+		return;
+	
+	if( 0 == osrfHashGetCount( fc_class_hash ) )
+		return;
+	
+	printf( "                %s\n", class_name );
+
+	osrfHashIterator* iter = osrfNewHashIterator( fc_class_hash );
+	void* fc_class_attr = NULL;
+	const char* indent = "                    ";
+
+	// Dump each foreign context attribute
+	for( ;; ) {
+		fc_class_attr = osrfHashIteratorNext( iter );
+		if( fc_class_attr ) {
+			const char* fc_class_attr_name = osrfHashIteratorKey( iter );
+			if( !strcmp( fc_class_attr_name, "field" ) )
+				printf( "%s%s: %s\n", indent, fc_class_attr_name, (const char*) fc_class_attr );
+			else if( !strcmp( fc_class_attr_name, "fkey" ) )
+				printf( "%s%s: %s\n", indent, fc_class_attr_name, (const char*) fc_class_attr );
+			else if( !strcmp( fc_class_attr_name, "jump" ) )
+				dump_string_array( (osrfStringArray*) fc_class_attr, fc_class_attr_name, indent );
+			else if( !strcmp( fc_class_attr_name, "context" ) )
+				dump_string_array( (osrfStringArray*) fc_class_attr, fc_class_attr_name, indent );
+			else
+				printf( "%s%s\n", indent, fc_class_attr_name );
+		} else
+			break;
+	}
+
+	osrfHashIteratorFree( iter );
+}
+
+static void dump_string_array( 
+	osrfStringArray* sarr, const char* name, const char* indent ) {
+	if( !sarr || !name || !indent )
+		return;
+
+	int size = sarr->size;
+
+	// Ignore an empty array
+	if( 0 == size )
+		return;
+
+	printf( "%s%s (string array)\n", indent, name );
+
+	int i;
+	for( i = 0; i < size; ++i )
+		printf( "%s\t%s\n", indent, osrfStringArrayGetString( sarr, i ) );
+}

Modified: branches/staff-client-experiment/Open-ILS/src/c-apps/oils_cstore.c
===================================================================
--- branches/staff-client-experiment/Open-ILS/src/c-apps/oils_cstore.c	2009-01-31 20:50:17 UTC (rev 12022)
+++ branches/staff-client-experiment/Open-ILS/src/c-apps/oils_cstore.c	2009-01-31 21:16:31 UTC (rev 12023)
@@ -874,12 +874,13 @@
     osrfHash* meta = (osrfHash*) ctx->method->userData;
     osrfHash* class = osrfHashGet( meta, "class" );
     char* method_type = strdup( osrfHashGet(meta, "methodtype") );
-    int fetch = 1;
+    int fetch = 0;
 
     if ( ( *method_type == 's' || *method_type == 'i' ) ) {
         free(method_type);
-        method_type = strdup("retrieve");
-        fetch = 0; // don't go to the db for the object for retrieve-type methods
+        method_type = strdup("retrieve"); // search and id_list are equivelant to retrieve for this
+    } else if ( *method_type == 'u' || *method_type == 'd' ) {
+        fetch = 1; // MUST go to the db for the object for update and delete
     }
 
     osrfHash* pcrud = osrfHashGet( osrfHashGet(class, "permacrud"), method_type );
@@ -1059,11 +1060,44 @@
                         &err
                     );
 
-                    jsonObject* _fparam = jsonObjectGetIndex(_list, 0);
-            
+                    jsonObject* _fparam = jsonObjectClone(jsonObjectGetIndex(_list, 0));
+                    jsonObjectFree(_tmp_params);
+                    jsonObjectFree(_list);
+ 
+                    osrfStringArray* jump_list = osrfHashGet(fcontext, "jump");
+
+                    if (_fparam && jump_list) {
+                        char* flink = NULL;
+                        int k = 0;
+                        while ( (flink = osrfStringArrayGetString(jump_list, k++)) && _fparam ) {
+                            free(foreign_pkey_value);
+
+                            osrfHash* foreign_link_hash = oilsIDLFindPath( "/%s/links/%s", _fparam->classname, flink );
+
+                            foreign_pkey_value = oilsFMGetString(_fparam, flink);
+                            foreign_pkey = osrfHashGet( foreign_link_hash, "key" );
+
+                            _tmp_params = jsonParseStringFmt(
+                                "[{\"%s\":\"%s\"}]",
+                                foreign_pkey,
+                                foreign_pkey_value
+                            );
+
+                    		_list = doFieldmapperSearch(
+                                ctx,
+                                osrfHashGet( oilsIDL(), osrfHashGet( foreign_link_hash, "class" ) ),
+                                _tmp_params,
+                                &err
+                            );
+
+                            _fparam = jsonObjectClone(jsonObjectGetIndex(_list, 0));
+                            jsonObjectFree(_tmp_params);
+                            jsonObjectFree(_list);
+                        }
+                    }
+
+           
                     if (!_fparam) {
-                        jsonObjectFree(_tmp_params);
-                        jsonObjectFree(_list);
 
                         growing_buffer* msg = buffer_init(128);
                         buffer_fadd(
@@ -1091,7 +1125,6 @@
                         return 0;
                     }
         
-                    jsonObjectFree(_tmp_params);
                     free(foreign_pkey_value);
     
                     int j = 0;
@@ -1106,8 +1139,8 @@
                             osrfStringArrayGetString(context_org_array, context_org_array->size - 1)
                         );
                     }
-       
-                    jsonObjectFree(_list);
+
+                    jsonObjectFree(_fparam);
                 }
     
                 osrfStringArrayFree(class_list);

Modified: branches/staff-client-experiment/Open-ILS/src/c-apps/oils_idl-core.c
===================================================================
--- branches/staff-client-experiment/Open-ILS/src/c-apps/oils_idl-core.c	2009-01-31 20:50:17 UTC (rev 12022)
+++ branches/staff-client-experiment/Open-ILS/src/c-apps/oils_idl-core.c	2009-01-31 21:16:31 UTC (rev 12023)
@@ -329,6 +329,9 @@
 									osrfHashSet( _tmp_fcontext, osrfHashGet(_flink, "field"), "fkey" );
 									osrfHashSet( _tmp_fcontext, osrfHashGet(_flink, "key"), "field" );
 
+								    if( (prop_str = (char*)xmlGetNoNsProp(_f, BAD_CAST "jump")) )
+									    osrfHashSet( _tmp_fcontext, osrfStringArrayTokenize( prop_str, '.' ), "jump" );
+
 									// Tokenize field attribute into an osrfStringArray
 									const char * field_list = (char*) xmlGetProp(_f, BAD_CAST "field");
 									if( field_list )
@@ -345,7 +348,7 @@
 									if( (prop_str = (char*)xmlGetNoNsProp(_f, BAD_CAST "field") )) {
 										char* map_list = strdup( prop_str );
 										osrfLogDebug(OSRF_LOG_MARK,
-											"Permacrud foreign context field list is %s", prop_str );
+											"Permacrud local context field list is %s", prop_str );
 			
 										if (strlen( map_list ) > 0) {
 											char* st_tmp = NULL;

Modified: branches/staff-client-experiment/Open-ILS/src/extras/fast-extract
===================================================================
--- branches/staff-client-experiment/Open-ILS/src/extras/fast-extract	2009-01-31 20:50:17 UTC (rev 12022)
+++ branches/staff-client-experiment/Open-ILS/src/extras/fast-extract	2009-01-31 21:16:31 UTC (rev 12023)
@@ -18,12 +18,13 @@
 
 $| = 1;
 
-my ($config, $delim, $after) = ('SYSCONFDIR/opensrf_core.xml', ' | ');
+my ($config, $delim, $after,$deleted) = ('SYSCONFDIR/opensrf_core.xml', ' | ');
 
 GetOptions(
 	"after=s"	=> \$after,
 	"boostrap=s"	=> \$config,
 	"delimiter=s"	=> \$delim,
+	"include-deleted"	=> \$deleted,
 );
 
 OpenSRF::System->bootstrap_client( config_file => $config );
@@ -49,6 +50,7 @@
 
 my $SQL = 'SELECT id FROM biblio.record_entry WHERE id > 0';
 $SQL .= " AND edit_date > '$after'" if ($after);
+$SQL .= " AND deleted IS FALSE" if (!$deleted);
 
 my $ids = $dbh->selectcol_arrayref($SQL);
 
@@ -63,6 +65,6 @@
 
 for my $id ( @$ids ) {
     my $row = $dbh->selectrow_hashref( $SQL, {}, $id );
-    print "$$row{id}$delim$$row{tnc_source}$delim$$row{tcn_value}$delim$$row{marc}\n";
+    print "$$row{deleted}$delim$$row{id}$delim$$row{tnc_source}$delim$$row{tcn_value}$delim$$row{marc}\n";
 }
 

Modified: branches/staff-client-experiment/Open-ILS/src/extras/import/marc_add_ids
===================================================================
--- branches/staff-client-experiment/Open-ILS/src/extras/import/marc_add_ids	2009-01-31 20:50:17 UTC (rev 12022)
+++ branches/staff-client-experiment/Open-ILS/src/extras/import/marc_add_ids	2009-01-31 21:16:31 UTC (rev 12023)
@@ -38,6 +38,8 @@
 	$partcount++;
 }
 
+print '<collection xmlns="http://www.loc.gov/MARC21/slim">';
+
 my $count = 0;
 while (<>) {
 	chomp;
@@ -48,6 +50,7 @@
 		($partlist{tcn_value} = $values[ $partmap{tcn_value}]) =~ s/^\s*//o if ($part eq 'tcn_value');
 		($partlist{tcn_source} = $values[ $partmap{tcn_source}]) =~ s/^\s*//o if ($part eq 'tcn_source');
 		($partlist{id} = $values[ $partmap{id}]) =~ s/^\s*//o if ($part eq 'id');
+		($partlist{deleted} = $values[ $partmap{deleted}]) =~ s/^\s*//o if ($part eq 'deleted');
 		$partlist{marc} = $values[ $partmap{marc}] if ($part eq 'marc');
 
 		$partlist{tcn_value} =~ s/\s*$//o if ($part eq 'tcn_value');
@@ -88,7 +91,7 @@
             } 
         }
 
-        if ($set_as_deleted) {
+        if ($set_as_deleted && $partlist{deleted} eq 't') {
             my $leader = $r->leader();
             if (length($leader)>4) {
                 substr($leader,5,1,"d");
@@ -98,6 +101,7 @@
 
 		my $x = $r->as_xml_record;
         $x =~ s/\n//gso;
+        $x =~ s/^<[^>]>//o;
         print $x."\n";
         $count++;
         print STDERR "\r$count" unless ($quiet || $count % 100);
@@ -107,4 +111,5 @@
 	};
 }
 
+print '</collection>';
 

Copied: branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Cleanup.pm (from rev 12022, trunk/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Cleanup.pm)
===================================================================
--- branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Cleanup.pm	                        (rev 0)
+++ branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Cleanup.pm	2009-01-31 21:16:31 UTC (rev 12023)
@@ -0,0 +1,5 @@
+package OpenILS::Application::Trigger::Cleanup;
+sub fourty_two { return 42 }
+sub NOOP_True { return 1 }
+sub NOOP_False { return 0 }
+1;

Copied: branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Collector.pm (from rev 12022, trunk/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Collector.pm)
===================================================================
--- branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Collector.pm	                        (rev 0)
+++ branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Collector.pm	2009-01-31 21:16:31 UTC (rev 12023)
@@ -0,0 +1,3 @@
+package OpenILS::Application::Trigger::Collector;
+sub fourty_two { return 42 }
+1;

Copied: branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Event.pm (from rev 12022, trunk/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Event.pm)
===================================================================
--- branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Event.pm	                        (rev 0)
+++ branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Event.pm	2009-01-31 21:16:31 UTC (rev 12023)
@@ -0,0 +1,377 @@
+package OpenILS::Application::Trigger::Event;
+use OpenSRF::EX qw/:try/;
+
+use OpenSRF::Utils::Logger qw/:level/;
+
+use OpenILS::Utils::Fieldmapper;
+use OpenILS::Utils::CStoreEditor q/:funcs/;
+use OpenILS::Application::Trigger::ModRunner;
+
+my $log = 'OpenSRF::Utils::Logger';
+
+sub new {
+    my $class = shift;
+    my $id = shift;
+    $class = ref($class) || $class;
+
+    my $self = bless { id => $id, editor => new_editor() } => $class;
+
+    return $self->init()
+}
+
+sub init {
+    my $self = shift;
+    my $id = shift;
+
+    return $self if ($self->event);
+
+    $self->id( $id ); 
+    $self->environment( {} ); 
+
+    return $self if (!$self->id);
+
+    $self->event(
+        $self->editor->retrieve_action_trigger_event([
+            $self->id, {
+                flesh => 2,
+                flesh_fields => {
+                    atev    => [ 'event_def' ],
+                    atevdef => [ 'hook' ]
+                }
+            }
+        ])
+    );
+
+    my $class = $self->_fm_class_by_hint( $self->event->event_def->hook->core_type );
+    
+    my $meth = "retreive_" . $class;
+    $meth =~ s/Fieldmapper:://;
+    $meth =~ s/::/_/;
+    
+    $self->target( $self->editor->$meth( $self->event->target ) );
+
+    return $self;
+}
+
+sub cleanup {
+    my $self = shift;
+
+    if (defined $self->reacted) {
+        $self->update_state( 'cleaning') || die 'Unable to update event state';
+        try {
+            my $cleanup = $self->reacted ? $self->event->event_def->cleanup_success : $self->event->event_def->cleanup_failure;
+            $self->cleanedup(
+                OpenILS::Application::Trigger::ModRunner::Cleanup
+                    ->new( $cleanup, $self->environment )
+                    ->run
+                    ->final_result
+            );
+        } otherwise {
+            $log->error( shift() );
+            $self->update_state( 'error' ) || die 'Unable to update event state';
+        };
+
+        if ($self->cleanedup) {
+            $self->update_state( 'complete' ) || die 'Unable to update event state';
+        } else {
+            $self->update_state( 'error' ) || die 'Unable to update event state';
+        }
+
+    } else {
+        $self->{cleanedup} = undef;
+    }
+    return $self;
+}
+
+sub react {
+    my $self = shift;
+
+    if ($self->valid) {
+        if ($self->event->event_def->group_field) { # can't react individually to a grouped definition
+            $self->{reacted} = undef;
+        } else {
+            $self->update_state( 'reacting') || die 'Unable to update event state';
+            try {
+                $self->reacted(
+                    OpenILS::Application::Trigger::ModRunner::Reactor
+                        ->new( $self->event->event_def->reactor, $self->environment )
+                        ->run
+                        ->final_result
+                );
+            } otherwise {
+                $log->error( shift() );
+                $self->update_state( 'error' ) || die 'Unable to update event state';
+            };
+
+            if (defined $self->reacted) {
+                $self->update_state( 'reacted' ) || die 'Unable to update event state';
+            } else {
+                $self->update_state( 'error' ) || die 'Unable to update event state';
+            }
+        }
+    } else {
+        $self->{reacted} = undef;
+    }
+    return $self;
+}
+
+sub validate {
+    my $self = shift;
+
+    return $self if (defined $self->valid);
+
+    if ($self->build_environment->environment->{complete}) {
+        $self->update_state( 'validating') || die 'Unable to update event state';
+        try {
+            $self->valid(
+                OpenILS::Application::Trigger::ModRunner::Validator
+                    ->new( $self->event->event_def->validator, $self->environment )
+                    ->run
+                    ->final_result
+            );
+        } otherwise {
+            $log->error( shift() );
+            $self->update_state( 'error' ) || die 'Unable to update event state';
+        };
+
+        if (defined $self->valid) {
+            if ($self->valid) {
+                $self->update_state( 'valid' ) || die 'Unable to update event state';
+            } else {
+                $self->update_state( 'invalid' ) || die 'Unable to update event state';
+            }
+        } else {
+            $self->update_state( 'error' ) || die 'Unable to update event state';
+        }
+    } else {
+        $self->{valid} = undef
+    }
+
+    return $self;
+}
+ 
+sub cleanedup {
+    my $self = shift;
+    return undef unless (ref $self);
+
+    my $c = shift;
+    $self->{cleanedup} = $c if (defined $c);
+    return $self->{cleanedup};
+}
+
+sub reacted {
+    my $self = shift;
+    return undef unless (ref $self);
+
+    my $r = shift;
+    $self->{reacted} = $r if (defined $r);
+    return $self->{reacted};
+}
+
+sub valid {
+    my $self = shift;
+    return undef unless (ref $self);
+
+    my $v = shift;
+    $self->{valid} = $v if (defined $v);
+    return $self->{valid};
+}
+
+sub event {
+    my $self = shift;
+    return undef unless (ref $self);
+
+    my $e = shift;
+    $self->{event} = $e if (defined $e);
+    return $self->{event};
+}
+
+sub id {
+    my $self = shift;
+    return undef unless (ref $self);
+
+    my $i = shift;
+    $self->{id} = $i if (defined $i);
+    return $self->{id};
+}
+
+sub environment {
+    my $self = shift;
+    return undef unless (ref $self);
+
+    my $e = shift;
+    $self->{environment} = $e if (defined $e);
+    return $self->{environment};
+}
+
+sub editor {
+    my $self = shift;
+    return undef unless (ref $self);
+
+    my $e = shift;
+    $self->{editor} = $e if (defined $e);
+    return $self->{editor};
+}
+
+sub target {
+    my $self = shift;
+    return undef unless (ref $self);
+
+    my $t = shift;
+    $self->{target} = $t if (defined $t);
+    return $self->{target};
+}
+
+sub update_state {
+    my $self = shift;
+    return undef unless ($self && ref $self);
+
+    my $state = shift;
+    return undef unless ($state);
+
+    $self->editor->xact_begin || return undef;
+
+    my $e = $self->editor->retrieve_action_trigger_event( $self->id );
+    $e->update_time( 'now' );
+    $e->update_process( $$ );
+    $e->state( $state );
+    $self->editor->update_action_trigger_event( $e );
+
+    return $self->editor->xact_commit || undef;
+}
+
+sub build_environment {
+    my $self = shift;
+    return $self if ($self->environment->{complete});
+
+    $self->update_state( 'collecting') || die 'Unable to update event state';
+
+    try {
+   
+        $self->environment->{target} = $self->target;
+        $self->environment->{event} = $self->event;
+        $self->environment->{template} = $self->event->event_def->template;
+    
+        my @env_list = $self->editor->search_action_trigger_environment( { event_def => $self->event->event_def } );
+        my @param_list = $self->editor->search_action_trigger_params( { event_def => $self->event->event_def } );
+    
+        $self->environment->{params}{ $_->param } = eval $_->value for ( @param_list );
+    
+        for my $e ( @env_list ) {
+            my (@label, @path);
+            @path = split('.', $e->path) if ($e->path);
+            @label = split('.', $e->label) if ($e->label);
+    
+            $self->_object_by_path( $self->event->target, $e->collector, \@label, \@path );
+        }
+    
+        $self->environment->{complete} = 1;
+    } otherwise {
+        $log->error( shift() );
+        $self->update_state( 'error' ) || die 'Unable to update event state';
+    };
+
+    if ($self->environment->{complete}) {
+        $self->update_state( 'collected' ) || die 'Unable to update event state';
+    } else {
+        $self->update_state( 'error' ) || die 'Unable to update event state';
+    }
+
+    return $self;
+}
+
+sub _fm_class_by_hint {
+    my $self = shift;
+    my $hint = shift;
+
+    my ($class) = grep {
+        Fieldmapper->publish_fieldmapper->{$_}->{hint} eq $hint
+    } keys %{ Fieldmapper->publish_fieldmapper };
+
+    return $class;
+}
+
+sub _object_by_path {
+    my $self = shift;
+    my $context = shift;
+    my $collector = shift;
+    my $label = shift;
+    my $path = shift;
+
+    my $step = shift(@$path);
+    
+    my $fhint = Fieldmapper->publish_fieldmapper->{$context->class_name}{links}{$step}{class};
+    my $fclass = $self->_fm_class_by_hint( $fhint );
+
+    my $ffield = Fieldmapper->publish_fieldmapper->{$context->class_name}{links}{$step}{key};
+    my $rtype = Fieldmapper->publish_fieldmapper->{$context->class_name}{links}{$step}{reltype};
+
+    my $meth = 'retrieve_';
+    my $multi = 0;
+    my $lfield = $step;
+    if ($rtype eq 'has_many') {
+        $meth = 'search_';
+        $multi = 1;
+        $lfield = $context->Identity;
+    }
+
+    $meth .= $fclass;
+    $meth =~ s/Fieldmapper:://;
+    $meth =~ s/::/_/;
+
+    my $obj = $self->editor->$meth( { $ffield => $context->$lfield() } );
+
+    if (@$path) {
+
+        my $obj_list = [];
+        if (!$multi) {
+            $obj_list = [$obj] if ($obj);
+        } else {
+            $obj_list = $obj;
+        }
+
+        $self->_object_by_path( $_, $collector, $label, $path ) for (@$obj_list);
+
+        $obj = $$obj_list[0] if (!$multi);
+        $context->$step( $obj ) if ($obj && !$label);
+
+    } else {
+
+        if ($collector) {
+            my $obj_list = [$obj] if ($obj && !$multi);
+            $obj_list = $obj if ($multi);
+
+            my @new_obj_list;
+            for my $o ( @$obj_list ) {
+                push @new_obj_list,
+                    OpenILS::Application::Trigger::ModRunner::Collector
+                        ->new( $collector, $o )
+                        ->run
+                        ->final_result
+            }
+
+            if (!$multi) {
+                $obj = $new_obj_list[0];
+            } else {
+                $obj = \@new_obj_list;
+            }
+        }
+
+        if ($label) {
+            my $node = $self->environment;
+            my $i = 0; my $max = scalar(@$label) - 1;
+            for (; $i < $max; $i++) {
+                my $part = $$label[$i];
+                $$node{$part} ||= {};
+                $node = $$node{$part};
+            }
+            $$node{$$label[-1]} = $obj;
+        } else {
+            $context->$step( $obj ) if ($obj);
+        }
+    }
+
+    return $obj;
+}
+
+1;

Modified: branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/ModRunner.pm
===================================================================
--- branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/ModRunner.pm	2009-01-31 20:50:17 UTC (rev 12022)
+++ branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/ModRunner.pm	2009-01-31 21:16:31 UTC (rev 12023)
@@ -1,16 +1,17 @@
 package OpenILS::Application::Trigger::ModLoader;
 use UNIVERSAL::require;
 
+sub prefix { return 'OpenILS::Application::Trigger' }
+
 sub new {
     my $class = shift;
     $class = ref($class) || $class;
 
-    my $mod_thing = shift;
-    return undef unless ($mod_thing);
+    my $mod = shift;
+    return undef unless ($mod);
 
     my $self = bless {
-        mod_thing => $mod_thing,
-        module => $mod_thing->module(),
+        module => ref $mod ? $mod->module() : $mod,
         handler => 'handler'
     } => $class;
 
@@ -55,7 +56,7 @@
     my $loaded = $m->use;
 
     if (!$loaded) {
-        $builtin_m = "OpenILS::Application::Trigger::$m";
+        $builtin_m = $self->prefix . "::$m";
         $loaded = $builtin_m->use;
 
         if (!$loaded) {
@@ -67,13 +68,22 @@
 
                 if (!$loaded) {
                     $h =  $self->handler;
-                    my $builtin_m = "OpenILS::Application::Trigger::$m";
+                    $builtin_m = $self->prefix . "::$m";
                     $loaded = $m->use;
 
                     $m = $builtin_m if ($loaded);
                 }
             } else {
                 $loaded = $m->use;
+
+                # The following is an escape hatch for builtin dummy handlers
+                if (!$loaded) {
+                    $loaded = $self->prefix->use;
+                    if ($loaded && $self->prefix->can( $self->module ) ) {
+                        $m = $self->prefix;
+                        $h = $self->module;
+                    }
+                }
             }
         } else {
             $m = $builtin_m;
@@ -152,6 +162,22 @@
     return $self;
 };
 
+package OpenILS::Application::Trigger::ModRunner::Collector;
+use base 'OpenILS::Application::Trigger::ModRunner';
+sub prefix { return 'OpenILS::Application::Trigger::Collector' }
+
+package OpenILS::Application::Trigger::ModRunner::Validator;
+use base 'OpenILS::Application::Trigger::ModRunner';
+sub prefix { return 'OpenILS::Application::Trigger::Validator' }
+
+package OpenILS::Application::Trigger::ModRunner::Reactor;
+use base 'OpenILS::Application::Trigger::ModRunner';
+sub prefix { return 'OpenILS::Application::Trigger::Reactor' }
+
+package OpenILS::Application::Trigger::ModRunner::Cleanup;
+use base 'OpenILS::Application::Trigger::ModRunner';
+sub prefix { return 'OpenILS::Application::Trigger::Cleanup' }
+
 package OpenILS::Application::Trigger::ModStackRunner;
 use base 'OpenILS::Application::Trigger::ModRunner';
 

Copied: branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Reactor.pm (from rev 12022, trunk/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Reactor.pm)
===================================================================
--- branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Reactor.pm	                        (rev 0)
+++ branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Reactor.pm	2009-01-31 21:16:31 UTC (rev 12023)
@@ -0,0 +1,5 @@
+package OpenILS::Application::Trigger::Reactor;
+sub fourty_two { return 42 }
+sub NOOP_True { return 1 }
+sub NOOP_False { return 0 }
+1;

Copied: branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Validator.pm (from rev 12022, trunk/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Validator.pm)
===================================================================
--- branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Validator.pm	                        (rev 0)
+++ branches/staff-client-experiment/Open-ILS/src/perlmods/OpenILS/Application/Trigger/Validator.pm	2009-01-31 21:16:31 UTC (rev 12023)
@@ -0,0 +1,29 @@
+package OpenILS::Application::Trigger::Validator;
+sub fourty_two { return 42 }
+sub NOOP_True { return 1 }
+sub NOOP_False { return 0 }
+
+sub CircIsOpen {
+    my $self = shift;
+    my $env = shift;
+
+    return defined($env->{target}->checkin_time) ? 0 : 1;
+}
+
+sub HoldIsAvailable {
+    my $self = shift;
+    my $env = shift;
+
+    my $t = $env->{target}->transit;
+
+    die "Transit object exists, but is not fleshed.  Add 'transit' to the environment in order to use this Validator."
+        if ($t && !ref($t));
+
+    if ($t) {
+        return (defined($env->{target}->capture_time) && defined($t->dest_recv_time)) ? 1 : 0;
+    }
+
+    return defined($env->{target}->capture_time) ? 1 : 0;
+}
+
+1;

Modified: branches/staff-client-experiment/Open-ILS/src/sql/Pg/400.schema.action_trigger.sql
===================================================================
--- branches/staff-client-experiment/Open-ILS/src/sql/Pg/400.schema.action_trigger.sql	2009-01-31 20:50:17 UTC (rev 12022)
+++ branches/staff-client-experiment/Open-ILS/src/sql/Pg/400.schema.action_trigger.sql	2009-01-31 21:16:31 UTC (rev 12023)
@@ -49,13 +49,17 @@
     module      TEXT    PRIMARY KEY, -- All live under the OpenILS::Trigger::Collector:: namespace
     description TEXT    
 );
-INSERT INTO action_trigger.collector (module,description) VALUES ('CircCountsByCircMod','Count of Circulations for a User, broken down by circulation modifier');
+INSERT INTO action_trigger.collector (module,description) VALUES ('fourty_two','Returns the answer to life, the universe and everything');
+--INSERT INTO action_trigger.collector (module,description) VALUES ('CircCountsByCircMod','Count of Circulations for a User, broken down by circulation modifier');
 
 -- Simple tests on an FM object from hook.core_type to test for "should we still do this."
 CREATE TABLE action_trigger.validator (
     module      TEXT    PRIMARY KEY, -- All live under the OpenILS::Trigger::Validator:: namespace
     description TEXT    
 );
+INSERT INTO action_trigger.validator (module,description) VALUES ('fourty_two','Returns the answer to life, the universe and everything');
+INSERT INTO action_trigger.validator (module,description) VALUES ('NOOP_True','Always returns true -- validation always passes');
+INSERT INTO action_trigger.validator (module,description) VALUES ('NOOP_False','Always returns false -- validation always fails');
 INSERT INTO action_trigger.validator (module,description) VALUES ('CircIsOpen','Check that the circulation is still open');
 INSERT INTO action_trigger.validator (module,description) VALUES ('HoldIsAvailable','Check that an item is on the hold shelf');
 
@@ -64,6 +68,9 @@
     module      TEXT    PRIMARY KEY, -- All live under the OpenILS::Trigger::Reactor:: namespace
     description TEXT    
 );
+INSERT INTO action_trigger.reactor (module,description) VALUES ('fourty_two','Returns the answer to life, the universe and everything');
+INSERT INTO action_trigger.reactor (module,description) VALUES ('NOOP_True','Always returns true -- reaction always passes');
+INSERT INTO action_trigger.reactor (module,description) VALUES ('NOOP_False','Always returns false -- reaction always fails');
 INSERT INTO action_trigger.reactor (module,description) VALUES ('SendEmail','Send an email based on a user-defined template');
 INSERT INTO action_trigger.reactor (module,description) VALUES ('GenerateBatchOverduePDF','Output a batch PDF of overdue notices for printing');
 
@@ -72,6 +79,9 @@
     module      TEXT    PRIMARY KEY, -- All live under the OpenILS::Trigger::Cleanup:: namespace
     description TEXT    
 );
+INSERT INTO action_trigger.cleanup (module,description) VALUES ('fourty_two','Returns the answer to life, the universe and everything');
+INSERT INTO action_trigger.cleanup (module,description) VALUES ('NOOP_True','Always returns true -- cleanup always passes');
+INSERT INTO action_trigger.cleanup (module,description) VALUES ('NOOP_False','Always returns false -- cleanup always fails');
 INSERT INTO action_trigger.cleanup (module,description) VALUES ('ClearAllPending','Remove all future, pending notifications for this target');
 
 CREATE TABLE action_trigger.event_definition (
@@ -112,7 +122,7 @@
     update_time     TIMESTAMPTZ,
     complete_time   TIMESTAMPTZ,
     update_process  INT,
-    state           TEXT        NOT NULL DEFAULT 'pending' CHECK (state IN ('pending','found','collecting','validating','reacting','cleanup','complete','error')),
+    state           TEXT        NOT NULL DEFAULT 'pending' CHECK (state IN ('pending','invalid','found','collecting','collected','validating','valid','reacting','reacted','cleaning','complete','error')),
     template_output TEXT,
     error_output    TEXT
 );

Modified: branches/staff-client-experiment/Open-ILS/tests/datasets/README
===================================================================
--- branches/staff-client-experiment/Open-ILS/tests/datasets/README	2009-01-31 20:50:17 UTC (rev 12022)
+++ branches/staff-client-experiment/Open-ILS/tests/datasets/README	2009-01-31 21:16:31 UTC (rev 12023)
@@ -6,5 +6,6 @@
 | lul_fre_100.marc  | MARC21    | MARC8    | Unicorn GL3.1 | 100 records, French, pre-1923  |
 | lul_fre_500.marc  | MARC21    | MARC8    | Unicorn GL3.1 | 500 records, French, pre-1923  |
 | jazz_1k.marc      | MARC21    | MARC8    | Unicorn GL3.1 | 1000 records  |
+| map_data.marc     | MARC21    | UTF8     | Voyager (LoC) | 3 records with some geospatial metadata  |
 | music_5k.marc     | MARC21    | MARC8    | Unicorn GL3.1 | 5000 records  |
 | hebrew.marc       | MARC21    | MARC8    | III           | Hebrew scripts, 25 records |

Copied: branches/staff-client-experiment/Open-ILS/tests/datasets/map_data.mrc (from rev 12022, trunk/Open-ILS/tests/datasets/map_data.mrc)
===================================================================
(Binary files differ)

Modified: branches/staff-client-experiment/Open-ILS/web/js/dojo/openils/PermaCrud.js
===================================================================
--- branches/staff-client-experiment/Open-ILS/web/js/dojo/openils/PermaCrud.js	2009-01-31 20:50:17 UTC (rev 12022)
+++ branches/staff-client-experiment/Open-ILS/web/js/dojo/openils/PermaCrud.js	2009-01-31 21:16:31 UTC (rev 12023)
@@ -58,11 +58,13 @@
         },
 
         disconnect : function ( onerror ) {
+            this.connected = false;
+            return true;
+            // disconnect returns nothing, which is null, which is not true, cause the following to always run ... arg.
             if (!this.session.disconnect()) {
                 if (onerror) onerror(this.session);
                 return false;
             }
-            return true;
         },
         
 

Modified: branches/staff-client-experiment/Open-ILS/web/reports/oils_rpt_common.xhtml
===================================================================
--- branches/staff-client-experiment/Open-ILS/web/reports/oils_rpt_common.xhtml	2009-01-31 20:50:17 UTC (rev 12022)
+++ branches/staff-client-experiment/Open-ILS/web/reports/oils_rpt_common.xhtml	2009-01-31 21:16:31 UTC (rev 12023)
@@ -13,6 +13,7 @@
 <script type="text/javascript" src="/js/dojo/dojo/dojo.js"></script>
 <script type="text/javascript">
 	dojo.require('dojo.parser');
+	dojo.require('dojo.string');
 
 	function status_update (markup) {
 		dojo.byId('status_text').innerHTML = markup;

Modified: branches/staff-client-experiment/Open-ILS/web/reports/oils_rpt_folder_window.js
===================================================================
--- branches/staff-client-experiment/Open-ILS/web/reports/oils_rpt_folder_window.js	2009-01-31 20:50:17 UTC (rev 12022)
+++ branches/staff-client-experiment/Open-ILS/web/reports/oils_rpt_folder_window.js	2009-01-31 21:16:31 UTC (rev 12023)
@@ -371,7 +371,7 @@
 			_debug("launching report output view at URL: " + url);
 			if(isXUL()) 
 				xulG.new_tab('/xul/server/util/rbrowser.xul?url=' + url,  /* this comes from urls.XUL_REMOTE_BROWSER */
-					{tab_name: dojo.string.substitute( rpt_strings.FOLDER_WINDOW_REPORT_OUTPUT, [r.name] ), browser:true},
+					{tab_name: dojo.string.substitute( rpt_strings.FOLDER_WINDOW_REPORT_OUTPUT, [r.name()] ), browser:true},
 					{no_xulG:false, show_nav_buttons:true, show_print_button:true});
 			else {
 				//goTo(url);



More information about the open-ils-commits mailing list