[open-ils-commits] r11543 - in trunk/Open-ILS: examples src/c-apps

svn at svn.open-ils.org svn at svn.open-ils.org
Sun Dec 14 16:19:48 EST 2008


Author: miker
Date: 2008-12-14 16:19:44 -0500 (Sun, 14 Dec 2008)
New Revision: 11543

Modified:
   trunk/Open-ILS/examples/extract-IDL-permissions.xsl
   trunk/Open-ILS/examples/fm_IDL.xml
   trunk/Open-ILS/src/c-apps/Makefile.am
   trunk/Open-ILS/src/c-apps/oils_cstore.c
   trunk/Open-ILS/src/c-apps/oils_idl-core.c
   trunk/Open-ILS/src/c-apps/oils_utils.c
Log:
C port of the permacrud service.  This touches a lot of code, so expect some
early breakage.

* The IDL permacrud permission and context org lists are now space-separated
  instead of pipe-separated.

* oils_utils.c now looks for an org unit with a null parent_ou instead of
  assuming that 1 is correct.

* oils_idl-core.c parses the <permacrud> parts of the IDL now, noting the
  state of the global_required attribute, any class-local context fields
  and any foreign class context fields.

* oils_cstore.c now has a new IDL context and personality, open-ils.pcrud,
  which (like cstore and reporter-store) ignore classes that do not have the
  appropriate setting in their controller attribute.

* Said new personality will only create methods for classes where both the
  controller attr contains open-ils.pcrud and there is a permacrud block,
  and only for those actions listed in the block.

* Much (ugly, currently) #ifdef'ing was used to segregate the permacrud code.
  This was done to avoid breaking cstore and reporter-store, if possible,
  while pcrud is worked out.

... fun times ...



Modified: trunk/Open-ILS/examples/extract-IDL-permissions.xsl
===================================================================
--- trunk/Open-ILS/examples/extract-IDL-permissions.xsl	2008-12-12 19:35:57 UTC (rev 11542)
+++ trunk/Open-ILS/examples/extract-IDL-permissions.xsl	2008-12-14 21:19:44 UTC (rev 11543)
@@ -18,8 +18,8 @@
 	<xsl:template name="output-tokens">
 		<xsl:param name="list" />
 		<xsl:variable name="newlist" select="normalize-space($list)" />
-		<xsl:variable name="first" select="substring-before($newlist, '|')" />
-		<xsl:variable name="remaining" select="substring-after($list, '|')" />
+		<xsl:variable name="first" select="substring-before($newlist, ' ')" />
+		<xsl:variable name="remaining" select="substring-after($list, ' ')" />
 		<xsl:choose test="$first">
 			<xsl:when test="$first">
 				<xsl:value-of select="$first" /><xsl:text>

Modified: trunk/Open-ILS/examples/fm_IDL.xml
===================================================================
--- trunk/Open-ILS/examples/fm_IDL.xml	2008-12-12 19:35:57 UTC (rev 11542)
+++ trunk/Open-ILS/examples/fm_IDL.xml	2008-12-14 21:19:44 UTC (rev 11543)
@@ -135,7 +135,7 @@
 
 
 	<!-- Actually in the DB -->
-	<class id="vibtf" controller="open-ils.cstore" oils_obj:fieldmapper="vandelay::import_bib_trash_fields" oils_persist:tablename="vandelay.import_bib_trash_fields" reporter:label="Import/Overlay Fields for Removal">
+	<class id="vibtf" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="vandelay::import_bib_trash_fields" oils_persist:tablename="vandelay.import_bib_trash_fields" reporter:label="Import/Overlay Fields for Removal">
 		<fields oils_persist:primary="id" oils_persist:sequence="vandelay.import_bib_trash_fields_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -150,14 +150,14 @@
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
 				<create permission="CREATE_IMPORT_TRASH_FIELD" context_field="owner"/>
-				<retrieve permission="CREATE_IMPORT_TRASH_FIELD|UPDATE_IMPORT_TRASH_FIELD|DELETE_IMPORT_TRASH_FIELD" context_field="owner"/>
+				<retrieve permission="CREATE_IMPORT_TRASH_FIELD UPDATE_IMPORT_TRASH_FIELD DELETE_IMPORT_TRASH_FIELD" context_field="owner"/>
 				<update permission="UPDATE_IMPORT_TRASH_FIELD" context_field="owner"/>
 				<delete permission="DELETE_IMPORT_TRASH_FIELD" context_field="owner"/>
 			</actions>
 		</permacrud>
 	</class>
 
-	<class id="vii" controller="open-ils.cstore" oils_obj:fieldmapper="vandelay::import_item" oils_persist:tablename="vandelay.import_item" reporter:label="Import Item Attribute Definition">
+	<class id="vii" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="vandelay::import_item" oils_persist:tablename="vandelay.import_item" reporter:label="Import Item Attribute Definition">
 		<fields oils_persist:primary="id" oils_persist:sequence="vandelay.import_item_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -194,7 +194,7 @@
 				<create permission="CREATE_IMPORT_ITEM">
                     <context link="definition" field="owner"/>
 				</create>
-				<retrieve permission="CREATE_IMPORT_ITEM|UPDATE_IMPORT_ITEM|DELETE_IMPORT_ITEM">
+				<retrieve permission="CREATE_IMPORT_ITEM UPDATE_IMPORT_ITEM DELETE_IMPORT_ITEM">
                     <context link="definition" field="owner"/>
 				</retrieve>
 				<update permission="UPDATE_IMPORT_ITEM">
@@ -207,7 +207,7 @@
 		</permacrud>
 	</class>
 
-	<class id="viiad" controller="open-ils.cstore" oils_obj:fieldmapper="vandelay::import_item_attr_definition" oils_persist:tablename="vandelay.import_item_attr_definition" reporter:label="Import Item Attribute Definition">
+	<class id="viiad" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="vandelay::import_item_attr_definition" oils_persist:tablename="vandelay.import_item_attr_definition" reporter:label="Import Item Attribute Definition">
 		<fields oils_persist:primary="id" oils_persist:sequence="vandelay.import_item_attr_definition_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -243,14 +243,14 @@
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
 				<create permission="CREATE_IMPORT_ITEM_ATTR_DEF" context_field="owner"/>
-				<retrieve permission="CREATE_IMPORT_ITEM_ATTR_DEF|UPDATE_IMPORT_ITEM_ATTR_DEF|DELETE_IMPORT_ITEM_ATTR_DEF" context_field="owner"/>
+				<retrieve permission="CREATE_IMPORT_ITEM_ATTR_DEF UPDATE_IMPORT_ITEM_ATTR_DEF DELETE_IMPORT_ITEM_ATTR_DEF" context_field="owner"/>
 				<update permission="UPDATE_IMPORT_ITEM_ATTR_DEF" context_field="owner"/>
 				<delete permission="DELETE_IMPORT_ITEM_ATTR_DEF" context_field="owner"/>
 			</actions>
 		</permacrud>
 	</class>
 
-	<class id="vbq" controller="open-ils.cstore" oils_obj:fieldmapper="vandelay::bib_queue" oils_persist:tablename="vandelay.bib_queue" reporter:label="Import/Overlay Bib Queue">
+	<class id="vbq" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="vandelay::bib_queue" oils_persist:tablename="vandelay.bib_queue" reporter:label="Import/Overlay Bib Queue">
 		<fields oils_persist:primary="id" oils_persist:sequence="vandelay.queue_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -267,14 +267,14 @@
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
 				<create permission="CREATE_BIB_IMPORT_QUEUE" global_required="true"/>
-				<retrieve permission="CREATE_BIB_IMPORT_QUEUE|UPDATE_BIB_IMPORT_QUEUE|DELETE_BIB_IMPORT_QUEUE" global_required="true"/>
+				<retrieve permission="CREATE_BIB_IMPORT_QUEUE UPDATE_BIB_IMPORT_QUEUE DELETE_BIB_IMPORT_QUEUE" global_required="true"/>
 				<update permission="UPDATE_BIB_IMPORT_QUEUE" global_required="true"/>
 				<delete permission="DELETE_BIB_IMPORT_QUEUE" global_required="true"/>
 			</actions>
 		</permacrud>
 	</class>
 
-	<class id="vqbr" controller="open-ils.cstore" oils_obj:fieldmapper="vandelay::queued_bib_record" oils_persist:tablename="vandelay.queued_bib_record" reporter:label="Queued Bib Record">
+	<class id="vqbr" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="vandelay::queued_bib_record" oils_persist:tablename="vandelay.queued_bib_record" reporter:label="Queued Bib Record">
 		<fields oils_persist:primary="id" oils_persist:sequence="vandelay.queued_record_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -300,14 +300,14 @@
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
 				<create permission="CREATE_BIB_IMPORT_QUEUE" global_required="true"/>
-				<retrieve permission="CREATE_BIB_IMPORT_QUEUE|UPDATE_BIB_IMPORT_QUEUE|DELETE_BIB_IMPORT_QUEUE" global_required="true"/>
+				<retrieve permission="CREATE_BIB_IMPORT_QUEUE UPDATE_BIB_IMPORT_QUEUE DELETE_BIB_IMPORT_QUEUE" global_required="true"/>
 				<update permission="UPDATE_BIB_IMPORT_QUEUE" global_required="true"/>
 				<delete permission="DELETE_BIB_IMPORT_QUEUE" global_required="true"/>
 			</actions>
 		</permacrud>
 	</class>
 
-	<class id="vqbrad" controller="open-ils.cstore" oils_obj:fieldmapper="vandelay::bib_attr_definition" oils_persist:tablename="vandelay.bib_attr_definition" reporter:label="Queued Bib Record Attribute Definition">
+	<class id="vqbrad" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="vandelay::bib_attr_definition" oils_persist:tablename="vandelay.bib_attr_definition" reporter:label="Queued Bib Record Attribute Definition">
 		<fields oils_persist:primary="id" oils_persist:sequence="vandelay.bib_attr_definition_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -325,7 +325,7 @@
 				<create permission="CREATE_BIB_IMPORT_FIELD_DEF" global_required="true"/>
                 <retrieve/>
                 <!--
-				<retrieve permission="CREATE_BIB_IMPORT_IMPORT_FIELD_DEF|UPDATE_BIB_IMPORT_IMPORT_FIELD_DEF|DELETE_BIB_IMPORT_IMPORT_FIELD_DEF" global_required="true"/>
+				<retrieve permission="CREATE_BIB_IMPORT_IMPORT_FIELD_DEF UPDATE_BIB_IMPORT_IMPORT_FIELD_DEF DELETE_BIB_IMPORT_IMPORT_FIELD_DEF" global_required="true"/>
                 -->
 				<update permission="UPDATE_BIB_IMPORT_IMPORT_FIELD_DEF" global_required="true"/>
 				<delete permission="DELETE_BIB_IMPORT_IMPORT_FIELD_DEF" global_required="true"/>
@@ -333,7 +333,7 @@
 		</permacrud>
 	</class>
 
-	<class id="vqbra" controller="open-ils.cstore" oils_obj:fieldmapper="vandelay::queued_bib_record_attr" oils_persist:tablename="vandelay.queued_bib_record_attr" reporter:label="Queued Bib Record Attribute">
+	<class id="vqbra" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="vandelay::queued_bib_record_attr" oils_persist:tablename="vandelay.queued_bib_record_attr" reporter:label="Queued Bib Record Attribute">
 		<fields oils_persist:primary="id" oils_persist:sequence="vandelay.queued_bib_record_attr_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -350,14 +350,14 @@
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
 				<create permission="CREATE_BIB_IMPORT_QUEUE" global_required="true"/>
-				<retrieve permission="CREATE_BIB_IMPORT_QUEUE|UPDATE_BIB_IMPORT_QUEUE|DELETE_BIB_IMPORT_QUEUE" global_required="true"/>
+				<retrieve permission="CREATE_BIB_IMPORT_QUEUE UPDATE_BIB_IMPORT_QUEUE DELETE_BIB_IMPORT_QUEUE" global_required="true"/>
 				<update permission="UPDATE_BIB_IMPORT_QUEUE" global_required="true"/>
 				<delete permission="DELETE_BIB_IMPORT_QUEUE" global_required="true"/>
 			</actions>
 		</permacrud>
 	</class>
 
-	<class id="vbm" controller="open-ils.cstore" oils_obj:fieldmapper="vandelay::bib_match" oils_persist:tablename="vandelay.bib_match" reporter:label="Queued Bib Record Match">
+	<class id="vbm" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="vandelay::bib_match" oils_persist:tablename="vandelay.bib_match" reporter:label="Queued Bib Record Match">
 		<fields oils_persist:primary="id" oils_persist:sequence="vandelay.bib_match_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -376,14 +376,14 @@
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
 				<create permission="CREATE_BIB_IMPORT_QUEUE" global_required="true"/>
-				<retrieve permission="CREATE_BIB_IMPORT_QUEUE|UPDATE_BIB_IMPORT_QUEUE|DELETE_BIB_IMPORT_QUEUE" global_required="true"/>
+				<retrieve permission="CREATE_BIB_IMPORT_QUEUE UPDATE_BIB_IMPORT_QUEUE DELETE_BIB_IMPORT_QUEUE" global_required="true"/>
 				<update permission="UPDATE_BIB_IMPORT_QUEUE" global_required="true"/>
 				<delete permission="DELETE_BIB_IMPORT_QUEUE" global_required="true"/>
 			</actions>
 		</permacrud>
 	</class>
 
-	<class id="vaq" controller="open-ils.cstore" oils_obj:fieldmapper="vandelay::authority_queue" oils_persist:tablename="vandelay.authority_queue" reporter:label="Import/Overlay Authority Queue">
+	<class id="vaq" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="vandelay::authority_queue" oils_persist:tablename="vandelay.authority_queue" reporter:label="Import/Overlay Authority Queue">
 		<fields oils_persist:primary="id" oils_persist:sequence="vandelay.queue_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -400,14 +400,14 @@
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
 				<create permission="CREATE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
-				<retrieve permission="CREATE_AUTHORITY_IMPORT_QUEUE|UPDATE_AUTHORITY_IMPORT_QUEUE|DELETE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
+				<retrieve permission="CREATE_AUTHORITY_IMPORT_QUEUE UPDATE_AUTHORITY_IMPORT_QUEUE DELETE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
 				<update permission="UPDATE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
 				<delete permission="DELETE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
 			</actions>
 		</permacrud>
 	</class>
 
-	<class id="vqar" controller="open-ils.cstore" oils_obj:fieldmapper="vandelay::queued_authority_record" oils_persist:tablename="vandelay.queued_authority_record" reporter:label="Queued Authority Record">
+	<class id="vqar" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="vandelay::queued_authority_record" oils_persist:tablename="vandelay.queued_authority_record" reporter:label="Queued Authority Record">
 		<fields oils_persist:primary="id" oils_persist:sequence="vandelay.queued_record_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -431,14 +431,14 @@
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
 				<create permission="CREATE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
-				<retrieve permission="CREATE_AUTHORITY_IMPORT_QUEUE|UPDATE_AUTHORITY_IMPORT_QUEUE|DELETE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
+				<retrieve permission="CREATE_AUTHORITY_IMPORT_QUEUE UPDATE_AUTHORITY_IMPORT_QUEUE DELETE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
 				<update permission="UPDATE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
 				<delete permission="DELETE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
 			</actions>
 		</permacrud>
 	</class>
 
-	<class id="vqarad" controller="open-ils.cstore" oils_obj:fieldmapper="vandelay::authority_attr_definition" oils_persist:tablename="vandelay.authority_attr_definition" reporter:label="Queued Authority Record Attribute Definition">
+	<class id="vqarad" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="vandelay::authority_attr_definition" oils_persist:tablename="vandelay.authority_attr_definition" reporter:label="Queued Authority Record Attribute Definition">
 		<fields oils_persist:primary="id" oils_persist:sequence="vandelay.authority_attr_definition_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -456,7 +456,7 @@
 				<create permission="CREATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF" global_required="true"/>
                 <retrieve/>
                 <!--
-				<retrieve permission="CREATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF|UPDATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF|DELETE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF" global_required="true"/>
+				<retrieve permission="CREATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF UPDATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF DELETE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF" global_required="true"/>
                 -->
 				<update permission="UPDATE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF" global_required="true"/>
 				<delete permission="DELETE_AUTHORITY_IMPORT_IMPORT_FIELD_DEF" global_required="true"/>
@@ -464,7 +464,7 @@
 		</permacrud>
 	</class>
 
-	<class id="vqara" controller="open-ils.cstore" oils_obj:fieldmapper="vandelay::queued_authority_record_attr" oils_persist:tablename="vandelay.queued_authority_record_attr" reporter:label="Queued Authority Record Attribute">
+	<class id="vqara" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="vandelay::queued_authority_record_attr" oils_persist:tablename="vandelay.queued_authority_record_attr" reporter:label="Queued Authority Record Attribute">
 		<fields oils_persist:primary="id" oils_persist:sequence="vandelay.queued_authority_record_attr_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -481,14 +481,14 @@
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
 				<create permission="CREATE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
-				<retrieve permission="CREATE_AUTHORITY_IMPORT_QUEUE|UPDATE_AUTHORITY_IMPORT_QUEUE|DELETE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
+				<retrieve permission="CREATE_AUTHORITY_IMPORT_QUEUE UPDATE_AUTHORITY_IMPORT_QUEUE DELETE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
 				<update permission="UPDATE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
 				<delete permission="DELETE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
 			</actions>
 		</permacrud>
 	</class>
 
-	<class id="vam" controller="open-ils.cstore" oils_obj:fieldmapper="vandelay::authority_match" oils_persist:tablename="vandelay.authority_match" reporter:label="Queued Authority Record Match">
+	<class id="vam" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="vandelay::authority_match" oils_persist:tablename="vandelay.authority_match" reporter:label="Queued Authority Record Match">
 		<fields oils_persist:primary="id" oils_persist:sequence="vandelay.authority_match_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -506,7 +506,7 @@
 		<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
 			<actions>
 				<create permission="CREATE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
-				<retrieve permission="CREATE_AUTHORITY_IMPORT_QUEUE|UPDATE_AUTHORITY_IMPORT_QUEUE|DELETE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
+				<retrieve permission="CREATE_AUTHORITY_IMPORT_QUEUE UPDATE_AUTHORITY_IMPORT_QUEUE DELETE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
 				<update permission="UPDATE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
 				<delete permission="DELETE_AUTHORITY_IMPORT_QUEUE" global_required="true"/>
 			</actions>
@@ -534,7 +534,7 @@
 		</links>
 	</class>
 
-    <class id="czs" controller="open-ils.cstore" oils_obj:fieldmapper="config::z3950_source" oils_persist:tablename="config.z3950_source" reporter:label="Z39.50 Source">
+    <class id="czs" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::z3950_source" oils_persist:tablename="config.z3950_source" reporter:label="Z39.50 Source">
         <fields oils_persist:primary="name">
             <field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
             <field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -594,7 +594,7 @@
 		</links>
 	</class>
 
-	<class id="ccm" controller="open-ils.cstore" oils_obj:fieldmapper="config::circ_modifier" oils_persist:tablename="config.circ_modifier" reporter:label="Circulation Modifier">
+	<class id="ccm" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::circ_modifier" oils_persist:tablename="config.circ_modifier" reporter:label="Circulation Modifier">
 		<fields oils_persist:primary="code">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -616,7 +616,7 @@
         </permacrud>
 	</class>
 
-	<class id="ccpbt" controller="open-ils.cstore" oils_obj:fieldmapper="container::copy_bucket_type" oils_persist:tablename="container.copy_bucket_type" reporter:label="Copy Bucket Type" oils_persist:field_safe="true">
+	<class id="ccpbt" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="container::copy_bucket_type" oils_persist:tablename="container.copy_bucket_type" reporter:label="Copy Bucket Type" oils_persist:field_safe="true">
 		<fields oils_persist:primary="code">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -628,14 +628,14 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_COPY_BTYPE" global_required="true"/>
-                <retrieve permission="CREATE_COPY_BTYPE|UPDATE_COPY_BTYPE|DELETE_COPY_BTYPE" global_required="true"/>
+                <retrieve permission="CREATE_COPY_BTYPE UPDATE_COPY_BTYPE DELETE_COPY_BTYPE" global_required="true"/>
                 <update permission="UPDATE_COPY_BTYPE" global_required="true"/>
                 <delete permission="DELETE_COPY_BTYPE" global_required="true"/>
             </actions>
         </permacrud>
 	</class>
 
-	<class id="ccnbt" controller="open-ils.cstore" oils_obj:fieldmapper="container::call_number_bucket_type" oils_persist:tablename="container.call_number_bucket_type" reporter:label="Call Number Bucket Type" oils_persist:field_safe="true">
+	<class id="ccnbt" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="container::call_number_bucket_type" oils_persist:tablename="container.call_number_bucket_type" reporter:label="Call Number Bucket Type" oils_persist:field_safe="true">
 		<fields oils_persist:primary="code">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -647,14 +647,14 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_CN_BTYPE" global_required="true"/>
-                <retrieve permission="CREATE_CN_BTYPE|UPDATE_CN_BTYPE|DELETE_CN_BTYPE" global_required="true"/>
+                <retrieve permission="CREATE_CN_BTYPE UPDATE_CN_BTYPE DELETE_CN_BTYPE" global_required="true"/>
                 <update permission="UPDATE_CN_BTYPE" global_required="true"/>
                 <delete permission="DELETE_CN_BTYPE" global_required="true"/>
             </actions>
         </permacrud>
 	</class>
 
-	<class id="cbrebt" controller="open-ils.cstore" oils_obj:fieldmapper="container::biblio_record_entry_bucket_type" oils_persist:tablename="container.biblio_record_entry_bucket_type" reporter:label="Bibliographic Record Bucket Type" oils_persist:field_safe="true">
+	<class id="cbrebt" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="container::biblio_record_entry_bucket_type" oils_persist:tablename="container.biblio_record_entry_bucket_type" reporter:label="Bibliographic Record Bucket Type" oils_persist:field_safe="true">
 		<fields oils_persist:primary="code">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -666,14 +666,14 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_BIB_BTYPE" global_required="true"/>
-                <retrieve permission="CREATE_BIB_BTYPE|UPDATE_BIB_BTYPE|DELETE_BIB_BTYPE" global_required="true"/>
+                <retrieve permission="CREATE_BIB_BTYPE UPDATE_BIB_BTYPE DELETE_BIB_BTYPE" global_required="true"/>
                 <update permission="UPDATE_BIB_BTYPE" global_required="true"/>
                 <delete permission="DELETE_BIB_BTYPE" global_required="true"/>
             </actions>
         </permacrud>
 	</class>
 
-	<class id="cubt" controller="open-ils.cstore" oils_obj:fieldmapper="container::user_bucket_type" oils_persist:tablename="container.user_bucket_type" reporter:label="User Bucket Type" oils_persist:field_safe="true">
+	<class id="cubt" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="container::user_bucket_type" oils_persist:tablename="container.user_bucket_type" reporter:label="User Bucket Type" oils_persist:field_safe="true">
 		<fields oils_persist:primary="code">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -685,14 +685,14 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_USER_BTYPE" global_required="true"/>
-                <retrieve permission="CREATE_USER_BTYPE|UPDATE_USER_BTYPE|DELETE_USER_BTYPE" global_required="true"/>
+                <retrieve permission="CREATE_USER_BTYPE UPDATE_USER_BTYPE DELETE_USER_BTYPE" global_required="true"/>
                 <update permission="UPDATE_USER_BTYPE" global_required="true"/>
                 <delete permission="DELETE_USER_BTYPE" global_required="true"/>
             </actions>
         </permacrud>
 	</class>
 
-	<class id="cvrfm" controller="open-ils.cstore" oils_obj:fieldmapper="config::videorecording_format_map" oils_persist:tablename="config.videorecording_format_map" reporter:label="Videorecording Format" oils_persist:field_safe="true">
+	<class id="cvrfm" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::videorecording_format_map" oils_persist:tablename="config.videorecording_format_map" reporter:label="Videorecording Format" oils_persist:field_safe="true">
 		<fields oils_persist:primary="code">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -704,7 +704,7 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_MARC_CODE" global_required="true"/>
-                <retrieve permission="CREATE_MARC_CODE|UPDATE_MARC_CODE|DELETE_MARC_CODE" global_required="true"/>
+                <retrieve permission="CREATE_MARC_CODE UPDATE_MARC_CODE DELETE_MARC_CODE" global_required="true"/>
                 <update permission="UPDATE_MARC_CODE" global_required="true"/>
                 <delete permission="DELETE_MARC_CODE" global_required="true"/>
             </actions>
@@ -939,7 +939,7 @@
 			<link field="org_unit" reltype="has_a" key="id" map="" class="aou"/>
 		</links>
 	</class>
-	<class id="atc" controller="open-ils.cstore" oils_obj:fieldmapper="action::transit_copy" oils_persist:tablename="action.transit_copy" reporter:core="true" reporter:label="Copy Transit">
+	<class id="atc" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="action::transit_copy" oils_persist:tablename="action.transit_copy" reporter:core="true" reporter:label="Copy Transit">
 		<fields oils_persist:primary="id" oils_persist:sequence="action.transit_copy_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -968,8 +968,8 @@
                     <context link="target_copy" field="circ_lib"/>
                 </create>
                 <retrieve/>
-                <update permission="UPDATE_TRANSIT" context_field="dest|source"/>
-                <delete permission="DELETE_TRANSIT" context_field="dest|source"/>
+                <update permission="UPDATE_TRANSIT" context_field="dest source"/>
+                <delete permission="DELETE_TRANSIT" context_field="dest source"/>
             </actions>
         </permacrud>
 	</class>
@@ -1050,7 +1050,7 @@
 			<link field="record" reltype="has_a" key="id" map="" class="are"/>
 		</links>
 	</class>
-	<class id="clm" controller="open-ils.cstore" oils_obj:fieldmapper="config::language_map" oils_persist:tablename="config.language_map" reporter:label="Language Map" oils_persist:field_safe="true">
+	<class id="clm" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::language_map" oils_persist:tablename="config.language_map" reporter:label="Language Map" oils_persist:field_safe="true">
 		<fields oils_persist:primary="code" oils_persist:sequence="">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1062,7 +1062,7 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_MARC_CODE" global_required="true"/>
-                <retrieve permission="CREATE_MARC_CODE|UPDATE_MARC_CODE|DELETE_MARC_CODE" global_required="true"/>
+                <retrieve permission="CREATE_MARC_CODE UPDATE_MARC_CODE DELETE_MARC_CODE" global_required="true"/>
                 <update permission="UPDATE_MARC_CODE" global_required="true"/>
                 <delete permission="DELETE_MARC_CODE" global_required="true"/>
             </actions>
@@ -1096,7 +1096,7 @@
 			<link field="xact" reltype="has_a" key="id" map="" class="mbt"/>
 		</links>
 	</class>
-	<class id="cxt" controller="open-ils.cstore" oils_obj:fieldmapper="config::xml_transform" oils_persist:tablename="config.xml_transform" reporter:label="XML/XSLT Transform Definition">
+	<class id="cxt" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::xml_transform" oils_persist:tablename="config.xml_transform" reporter:label="XML/XSLT Transform Definition">
 		<fields oils_persist:primary="name">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1117,7 +1117,7 @@
             </actions>
         </permacrud>
 	</class>
-	<class id="cmf" controller="open-ils.cstore" oils_obj:fieldmapper="config::metabib_field" oils_persist:tablename="config.metabib_field">
+	<class id="cmf" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::metabib_field" oils_persist:tablename="config.metabib_field">
 		<fields oils_persist:primary="id" oils_persist:sequence="config.metabib_field_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1141,7 +1141,7 @@
             </actions>
         </permacrud>
 	</class>
-	<class id="cam" controller="open-ils.cstore" oils_obj:fieldmapper="config::audience_map" oils_persist:tablename="config.audience_map" reporter:label="Audience Map" oils_persist:field_safe="true">
+	<class id="cam" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::audience_map" oils_persist:tablename="config.audience_map" reporter:label="Audience Map" oils_persist:field_safe="true">
 		<fields oils_persist:primary="code" oils_persist:sequence="">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1154,13 +1154,13 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_MARC_CODE" global_required="true"/>
-                <retrieve permission="CREATE_MARC_CODE|UPDATE_MARC_CODE|DELETE_MARC_CODE" global_required="true"/>
+                <retrieve permission="CREATE_MARC_CODE UPDATE_MARC_CODE DELETE_MARC_CODE" global_required="true"/>
                 <update permission="UPDATE_MARC_CODE" global_required="true"/>
                 <delete permission="DELETE_MARC_CODE" global_required="true"/>
             </actions>
         </permacrud>
 	</class>
-	<class id="cifm" controller="open-ils.cstore" oils_obj:fieldmapper="config::item_form_map" oils_persist:tablename="config.item_form_map" reporter:label="Item Form Map" oils_persist:field_safe="true">
+	<class id="cifm" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::item_form_map" oils_persist:tablename="config.item_form_map" reporter:label="Item Form Map" oils_persist:field_safe="true">
 		<fields oils_persist:primary="code" oils_persist:sequence="">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1172,13 +1172,13 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_MARC_CODE" global_required="true"/>
-                <retrieve permission="CREATE_MARC_CODE|UPDATE_MARC_CODE|DELETE_MARC_CODE" global_required="true"/>
+                <retrieve permission="CREATE_MARC_CODE UPDATE_MARC_CODE DELETE_MARC_CODE" global_required="true"/>
                 <update permission="UPDATE_MARC_CODE" global_required="true"/>
                 <delete permission="DELETE_MARC_CODE" global_required="true"/>
             </actions>
         </permacrud>
 	</class>
-	<class id="acn" controller="open-ils.cstore" oils_obj:fieldmapper="asset::call_number" oils_persist:tablename="asset.call_number" reporter:label="Call Number/Volume">
+	<class id="acn" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="asset::call_number" oils_persist:tablename="asset.call_number" reporter:label="Call Number/Volume">
 		<fields oils_persist:primary="id" oils_persist:sequence="asset.call_number_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1234,7 +1234,7 @@
 		</fields>
 		<links/>
 	</class>
-	<class id="mct" controller="open-ils.cstore" oils_obj:fieldmapper="money::collections_tracker" oils_persist:tablename="money.collections_tracker">
+	<class id="mct" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="money::collections_tracker" oils_persist:tablename="money.collections_tracker">
 		<fields oils_persist:primary="id" oils_persist:sequence="money.collections_tracker_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1258,7 +1258,7 @@
             </actions>
         </permacrud>
 	</class>
-	<class id="bre" controller="open-ils.cstore" oils_obj:fieldmapper="biblio::record_entry" oils_persist:tablename="biblio.record_entry" reporter:core="true" reporter:label="Bibliographic Record">
+	<class id="bre" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="biblio::record_entry" oils_persist:tablename="biblio.record_entry" reporter:core="true" reporter:label="Bibliographic Record">
 		<fields oils_persist:primary="id" oils_persist:sequence="biblio.record_entry_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1308,13 +1308,13 @@
 		</links>
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
-                <create permission="CREATE_MARC|IMPORT_MARC" global_required="true"/>
+                <create permission="CREATE_MARC IMPORT_MARC" global_required="true"/>
                 <retrieve/>
                 <update permission="UPDATE_MARC" global_required="true"/>
             </actions>
         </permacrud>
 	</class>
-	<class id="aouhoo" controller="open-ils.cstore" oils_obj:fieldmapper="actor::org_unit::hours_of_operation" oils_persist:tablename="actor.hours_of_operation">
+	<class id="aouhoo" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="actor::org_unit::hours_of_operation" oils_persist:tablename="actor.hours_of_operation">
 		<fields oils_persist:primary="id" oils_persist:sequence="">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1348,7 +1348,7 @@
             </actions>
         </permacrud>
 	</class>
-	<class id="aoucd" controller="open-ils.cstore" oils_obj:fieldmapper="actor::org_unit::closed_date" oils_persist:tablename="actor.org_unit_closed">
+	<class id="aoucd" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="actor::org_unit::closed_date" oils_persist:tablename="actor.org_unit_closed">
 		<fields oils_persist:primary="id" oils_persist:sequence="actor.org_unit_closed_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1371,7 +1371,7 @@
             </actions>
         </permacrud>
 	</class>
-	<class id="crcd" controller="open-ils.cstore" oils_obj:fieldmapper="config::rules::circ_duration" oils_persist:tablename="config.rule_circ_duration">
+	<class id="crcd" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::rules::circ_duration" oils_persist:tablename="config.rule_circ_duration">
 		<fields oils_persist:primary="id" oils_persist:sequence="config.rule_circ_duration_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1530,7 +1530,7 @@
 			<link field="org_unit" reltype="has_a" key="id" map="" class="aou"/>
 		</links>
 	</class>
-	<class id="acpn" controller="open-ils.cstore" oils_obj:fieldmapper="asset::copy_note" oils_persist:tablename="asset.copy_note" reporter:label="Copy Note">
+	<class id="acpn" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="asset::copy_note" oils_persist:tablename="asset.copy_note" reporter:label="Copy Note">
 		<fields oils_persist:primary="id" oils_persist:sequence="asset.copy_note_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1597,7 +1597,7 @@
 			<link field="source_records" reltype="has_many" key="metarecord" map="source" class="mmrsm"/>
 		</links>
 	</class>
-	<class id="cnal" controller="open-ils.cstore" oils_obj:fieldmapper="config::net_access_level" oils_persist:tablename="config.net_access_level">
+	<class id="cnal" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::net_access_level" oils_persist:tablename="config.net_access_level">
 		<fields oils_persist:primary="id" oils_persist:sequence="config.net_access_level_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1615,7 +1615,7 @@
             </actions>
         </permacrud>
 	</class>
-	<class id="ppl" controller="open-ils.cstore" oils_obj:fieldmapper="permission::perm_list" oils_persist:tablename="permission.perm_list">
+	<class id="ppl" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="permission::perm_list" oils_persist:tablename="permission.perm_list">
 		<fields oils_persist:primary="id" oils_persist:sequence="permission.perm_list_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1628,7 +1628,7 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_PERM" global_required="true"/>
-                <retrieve permission="CREATE_PERM|UPDATE_PERM|DELETE_PERM" global_required="true"/>
+                <retrieve permission="CREATE_PERM UPDATE_PERM DELETE_PERM" global_required="true"/>
                 <update permission="UPDATE_PERM" global_required="true"/>
                 <delete permission="DELETE_PERM" global_required="true"/>
             </actions>
@@ -1741,7 +1741,7 @@
 		</links>
 	</class>
 
-	<class id="csp" controller="open-ils.cstore" oils_obj:fieldmapper="config::standing_penalty" oils_persist:tablename="config.standing_penalty">
+	<class id="csp" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::standing_penalty" oils_persist:tablename="config.standing_penalty">
 		<fields oils_persist:primary="id" oils_persist:sequence="config.standing_penalty_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1755,13 +1755,13 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_STANDING_PENALTY" global_required="true"/>
-                <retrieve permission="CREATE_STANDING_PENALTY|UPDATE_STANDING_PENALTY|DELETE_STANDING_PENALTY" global_required="true"/>
+                <retrieve permission="CREATE_STANDING_PENALTY UPDATE_STANDING_PENALTY DELETE_STANDING_PENALTY" global_required="true"/>
                 <update permission="UPDATE_STANDING_PENALTY" global_required="true"/>
                 <delete permission="DELETE_STANDING_PENALTY" global_required="true"/>
             </actions>
         </permacrud>
 	</class>
-	<class id="pgpt" controller="open-ils.cstore" oils_obj:fieldmapper="permission::grp_penalty_threshold" oils_persist:tablename="permission.grp_penalty_threshold">
+	<class id="pgpt" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="permission::grp_penalty_threshold" oils_persist:tablename="permission.grp_penalty_threshold">
 		<fields oils_persist:primary="id" oils_persist:sequence="permission.grp_penalty_threshold_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1781,14 +1781,14 @@
             <actions>
                 <create permission="CREATE_GROUP_PENALTY_THRESHOLD" context_field='org_unit'/>
                 <retrieve 
-                    permission="VIEW_GROUP_PENALTY_THRESHOLD|CREATE_GROUP_PENALTY_THRESHOLD|UPDATE_GROUP_PENALTY_THRESHOLD|DELETE_GROUP_PENALTY_THRESHOLD" 
+                    permission="VIEW_GROUP_PENALTY_THRESHOLD CREATE_GROUP_PENALTY_THRESHOLD UPDATE_GROUP_PENALTY_THRESHOLD DELETE_GROUP_PENALTY_THRESHOLD" 
                     context_field='org_unit'/>
                 <update permission="UPDATE_GROUP_PENALTY_THRESHOLD" context_field='org_unit'/>
                 <delete permission="DELETE_GROUP_PENALTY_THRESHOLD" context_field='org_unit'/>
             </actions>
         </permacrud>
 	</class>
-	<class id="ccs" controller="open-ils.cstore" oils_obj:fieldmapper="config::copy_status" oils_persist:tablename="config.copy_status">
+	<class id="ccs" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::copy_status" oils_persist:tablename="config.copy_status">
 		<fields oils_persist:primary="id" oils_persist:sequence="config.copy_status_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1802,7 +1802,7 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_COPY_STATUS" global_required="true"/>
-                <retrieve permission="CREATE_COPY_STATUS|UPDATE_COPY_STATUS|DELETE_COPY_STATUS" global_required="true"/>
+                <retrieve permission="CREATE_COPY_STATUS UPDATE_COPY_STATUS DELETE_COPY_STATUS" global_required="true"/>
                 <update permission="UPDATE_COPY_STATUS" global_required="true"/>
                 <delete permission="DELETE_COPY_STATUS" global_required="true"/>
             </actions>
@@ -1850,7 +1850,7 @@
 			<link field="usr" reltype="has_a" key="id" map="" class="au"/>
 		</links>
 	</class>
-	<class id="acnn" controller="open-ils.cstore" oils_obj:fieldmapper="asset::call_number_note" oils_persist:tablename="asset.call_number_note">
+	<class id="acnn" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="asset::call_number_note" oils_persist:tablename="asset.call_number_note">
 		<fields oils_persist:primary="id" oils_persist:sequence="asset.call_number_note_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -1883,7 +1883,7 @@
             </actions>
         </permacrud>
 	</class>
-	<class id="arn" controller="open-ils.cstore" oils_obj:fieldmapper="authority::record_note" oils_persist:tablename="authority.record_note">
+	<class id="arn" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="authority::record_note" oils_persist:tablename="authority.record_note">
 		<fields oils_persist:primary="id" oils_persist:sequence="authority.record_note_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -2161,7 +2161,7 @@
 			<link field="notify_staff" reltype="has_a" key="id" map="" class="au"/>
 		</links>
 	</class>
-	<class id="acpl" controller="open-ils.cstore" oils_obj:fieldmapper="asset::copy_location" oils_persist:tablename="asset.copy_location" reporter:label="Copy/Shelving Location">
+	<class id="acpl" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="asset::copy_location" oils_persist:tablename="asset.copy_location" reporter:label="Copy/Shelving Location">
 		<fields oils_persist:primary="id" oils_persist:sequence="asset.copy_location_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -2202,7 +2202,7 @@
 			<link field="stat_cat" reltype="has_a" key="id" map="" class="asc"/>
 		</links>
 	</class>
-	<class id="citm" controller="open-ils.cstore" oils_obj:fieldmapper="config::item_type_map" oils_persist:tablename="config.item_type_map" reporter:label="Item Type Map" oils_persist:field_safe="true">
+	<class id="citm" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::item_type_map" oils_persist:tablename="config.item_type_map" reporter:label="Item Type Map" oils_persist:field_safe="true">
 		<fields oils_persist:primary="code">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -2214,13 +2214,13 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_MARC_CODE" global_required="true"/>
-                <retrieve permission="CREATE_MARC_CODE|UPDATE_MARC_CODE|DELETE_MARC_CODE" global_required="true"/>
+                <retrieve permission="CREATE_MARC_CODE UPDATE_MARC_CODE DELETE_MARC_CODE" global_required="true"/>
                 <update permission="UPDATE_MARC_CODE" global_required="true"/>
                 <delete permission="DELETE_MARC_CODE" global_required="true"/>
             </actions>
         </permacrud>
 	</class>
-	<class id="cblvl" controller="open-ils.cstore" oils_obj:fieldmapper="config::bib_level_map" oils_persist:tablename="config.bib_level_map" reporter:label="Bib Level Map" oils_persist:field_safe="true">
+	<class id="cblvl" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::bib_level_map" oils_persist:tablename="config.bib_level_map" reporter:label="Bib Level Map" oils_persist:field_safe="true">
 		<fields oils_persist:primary="code">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -2232,13 +2232,13 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_MARC_CODE" global_required="true"/>
-                <retrieve permission="CREATE_MARC_CODE|UPDATE_MARC_CODE|DELETE_MARC_CODE" global_required="true"/>
+                <retrieve permission="CREATE_MARC_CODE UPDATE_MARC_CODE DELETE_MARC_CODE" global_required="true"/>
                 <update permission="UPDATE_MARC_CODE" global_required="true"/>
                 <delete permission="DELETE_MARC_CODE" global_required="true"/>
             </actions>
         </permacrud>
 	</class>
-	<class id="sra" controller="open-ils.cstore" oils_obj:fieldmapper="search::relevance_adjustment" oils_persist:tablename="search.relevance_adjustment" reporter:label="Relevance Adjustment">
+	<class id="sra" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="search::relevance_adjustment" oils_persist:tablename="search.relevance_adjustment" reporter:label="Relevance Adjustment">
 		<fields oils_persist:primary="id" oils_persist:sequence="search.relevance_adjustment_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -2255,13 +2255,13 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_RELEVANCE_ADJUSTMENT" global_required="true"/>
-                <retrieve permission="CREATE_RELEVANCE_ADJUSTMENT|UPDATE_RELEVANCE_ADJUSTMENT|DELETE_RELEVANCE_ADJUSTMENT" global_required="true"/>
+                <retrieve permission="CREATE_RELEVANCE_ADJUSTMENT UPDATE_RELEVANCE_ADJUSTMENT DELETE_RELEVANCE_ADJUSTMENT" global_required="true"/>
                 <update permission="UPDATE_RELEVANCE_ADJUSTMENT" global_required="true"/>
                 <delete permission="DELETE_RELEVANCE_ADJUSTMENT" global_required="true"/>
             </actions>
         </permacrud>
 	</class>
-	<class id="lasso" controller="open-ils.cstore" oils_obj:fieldmapper="actor::org_lasso" oils_persist:tablename="actor.org_lasso">
+	<class id="lasso" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="actor::org_lasso" oils_persist:tablename="actor.org_lasso">
 		<fields oils_persist:primary="id" oils_persist:sequence="actor.org_lasso_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -2273,13 +2273,13 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_LASSO" global_required="true"/>
-                <retrieve permission="CREATE_LASSO|UPDATE_LASSO|DELETE_LASSO" global_required="true"/>
+                <retrieve permission="CREATE_LASSO UPDATE_LASSO DELETE_LASSO" global_required="true"/>
                 <update permission="UPDATE_LASSO" global_required="true"/>
                 <delete permission="DELETE_LASSO" global_required="true"/>
             </actions>
         </permacrud>
 	</class>
-	<class id="lmap" controller="open-ils.cstore" oils_obj:fieldmapper="actor::org_lasso_map" oils_persist:tablename="actor.org_lasso_map">
+	<class id="lmap" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="actor::org_lasso_map" oils_persist:tablename="actor.org_lasso_map">
 		<fields oils_persist:primary="id" oils_persist:sequence="actor.org_lasso_map_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -2295,7 +2295,7 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_LASSO_MAP" global_required="true"/>
-                <retrieve permission="CREATE_LASSO_MAP|UPDATE_LASSO_MAP|DELETE_LASSO_MAP" global_required="true"/>
+                <retrieve permission="CREATE_LASSO_MAP UPDATE_LASSO_MAP DELETE_LASSO_MAP" global_required="true"/>
                 <update permission="UPDATE_LASSO_MAP" global_required="true"/>
                 <delete permission="DELETE_LASSO_MAP" global_required="true"/>
             </actions>
@@ -2332,7 +2332,7 @@
 		</fields>
 		<links/>
 	</class>
-	<class id="asv" controller="open-ils.cstore" oils_obj:fieldmapper="action::survey" oils_persist:tablename="action.survey" reporter:label="Survey">
+	<class id="asv" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="action::survey" oils_persist:tablename="action.survey" reporter:label="Survey">
 		<fields oils_persist:primary="id" oils_persist:sequence="action.survey_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -2364,7 +2364,7 @@
             </actions>
         </permacrud>
 	</class>
-	<class id="aoa" controller="open-ils.cstore" oils_obj:fieldmapper="actor::org_address" oils_persist:tablename="actor.org_address">
+	<class id="aoa" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="actor::org_address" oils_persist:tablename="actor.org_address">
 		<fields oils_persist:primary="id" oils_persist:sequence="actor.org_address_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -2444,7 +2444,7 @@
 			<link field="bib_rec" reltype="might_have" key="id" map="" class="rhrr"/>
 		</links>
 	</class>
-	<class id="aou" controller="open-ils.cstore" oils_obj:fieldmapper="actor::org_unit" oils_persist:tablename="actor.org_unit" reporter:label="Organizational Unit" oils_persist:field_safe="true">
+	<class id="aou" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="actor::org_unit" oils_persist:tablename="actor.org_unit" reporter:label="Organizational Unit" oils_persist:field_safe="true">
 		<fields oils_persist:primary="id" oils_persist:sequence="actor.org_unit_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -2489,7 +2489,7 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_ORG_UNIT" context_field="parent_ou"/>
-                <retrieve permission="CREATE_ORG_UNIT|UPDATE_ORG_UNIT|DELETE_ORG_UNIT">
+                <retrieve permission="CREATE_ORG_UNIT UPDATE_ORG_UNIT DELETE_ORG_UNIT">
                     <context field="id"/>
                     <context field="parent_ou"/>
 				</retrieve>
@@ -2648,7 +2648,7 @@
 			<link field="owning_lib" reltype="has_a" key="id" map="" class="aou"/>
 		</links>
 	</class>
-	<class id="aout" controller="open-ils.cstore" oils_obj:fieldmapper="actor::org_unit_type" oils_persist:tablename="actor.org_unit_type" reporter:label="Organizational Unit Type">
+	<class id="aout" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="actor::org_unit_type" oils_persist:tablename="actor.org_unit_type" reporter:label="Organizational Unit Type">
 		<fields oils_persist:primary="id" oils_persist:sequence="actor.org_unit_type_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -2671,7 +2671,7 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_ORG_TYPE" global_required="true"/>
-                <retrieve permission="CREATE_ORG_UNIT|UPDATE_ORG_UNIT|DELETE_ORG_UNIT" global_required="true"/>
+                <retrieve permission="CREATE_ORG_UNIT UPDATE_ORG_UNIT DELETE_ORG_UNIT" global_required="true"/>
                 <update permission="UPDATE_ORG_TYPE" global_required="true"/>
                 <delete permission="DELETE_ORG_TYPE" global_required="true"/>
             </actions>
@@ -2738,7 +2738,7 @@
 			<link field="payment_total" reltype="might_have" key="xact" map="" class="rxpt"/>
 		</links>
 	</class>
-	<class id="cbs" controller="open-ils.cstore" oils_obj:fieldmapper="config::bib_source" oils_persist:tablename="config.bib_source">
+	<class id="cbs" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::bib_source" oils_persist:tablename="config.bib_source">
 		<fields oils_persist:primary="id" oils_persist:sequence="config.bib_source_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -2829,7 +2829,7 @@
 			<link field="usr" reltype="has_a" key="id" map="" class="au"/>
 		</links>
 	</class>
-	<class id="clfm" controller="open-ils.cstore" oils_obj:fieldmapper="config::lit_form_map" oils_persist:tablename="config.lit_form_map" reporter:label="Literary Form" oils_persist:field_safe="true">
+	<class id="clfm" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::lit_form_map" oils_persist:tablename="config.lit_form_map" reporter:label="Literary Form" oils_persist:field_safe="true">
 		<fields oils_persist:primary="code" oils_persist:sequence="">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -2842,7 +2842,7 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_MARC_CODE" global_required="true"/>
-                <retrieve permission="CREATE_MARC_CODE|UPDATE_MARC_CODE|DELETE_MARC_CODE" global_required="true"/>
+                <retrieve permission="CREATE_MARC_CODE UPDATE_MARC_CODE DELETE_MARC_CODE" global_required="true"/>
                 <update permission="UPDATE_MARC_CODE" global_required="true"/>
                 <delete permission="DELETE_MARC_CODE" global_required="true"/>
             </actions>
@@ -2981,7 +2981,7 @@
 			<link field="xact" reltype="has_a" key="id" map="" class="mbt"/>
 		</links>
 	</class>
-	<class id="acp" controller="open-ils.cstore" oils_obj:fieldmapper="asset::copy" oils_persist:tablename="asset.copy" reporter:core="true" reporter:label="Item">
+	<class id="acp" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="asset::copy" oils_persist:tablename="asset.copy" reporter:core="true" reporter:label="Item">
 		<fields oils_persist:primary="id" oils_persist:sequence="asset.copy_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -3074,7 +3074,7 @@
 		</fields>
 		<links/>
 	</class>
-	<class id="pgt" controller="open-ils.cstore" oils_obj:fieldmapper="permission::grp_tree" oils_persist:tablename="permission.grp_tree" reporter:label="Permission Group">
+	<class id="pgt" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="permission::grp_tree" oils_persist:tablename="permission.grp_tree" reporter:label="Permission Group">
 		<fields oils_persist:primary="id" oils_persist:sequence="permission.grp_tree_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -3095,7 +3095,7 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_PERM" global_required="true"/>
-                <retrieve permission="CREATE_PERM|UPDATE_PERM|DELETE_PERM" global_required="true"/>
+                <retrieve permission="CREATE_PERM UPDATE_PERM DELETE_PERM" global_required="true"/>
                 <update permission="UPDATE_PERM" global_required="true"/>
                 <delete permission="DELETE_PERM" global_required="true"/>
             </actions>
@@ -3196,7 +3196,7 @@
 			<link field="stat_cat" reltype="has_a" key="id" map="" class="actsc"/>
 		</links>
 	</class>
-	<class id="pgpm" controller="open-ils.cstore" oils_obj:fieldmapper="permission::grp_perm_map" oils_persist:tablename="permission.grp_perm_map">
+	<class id="pgpm" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="permission::grp_perm_map" oils_persist:tablename="permission.grp_perm_map">
 		<fields oils_persist:primary="id" oils_persist:sequence="permission.grp_perm_map_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -3214,7 +3214,7 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="ASSIGN_GROUP_PERM" global_required="true"/>
-                <retrieve permission="ASSIGN_GROUP_PERM|UPDATE_GROUP_PERM|REMOVE_GROUP_PERM" global_required="true"/>
+                <retrieve permission="ASSIGN_GROUP_PERM UPDATE_GROUP_PERM REMOVE_GROUP_PERM" global_required="true"/>
                 <update permission="UPDATE_GROUP_PERM" global_required="true"/>
                 <delete permission="REMOVE_GROUP_PERM" global_required="true"/>
             </actions>
@@ -3429,7 +3429,7 @@
 			<link field="owner" reltype="has_a" key="id" map="" class="aou"/>
 		</links>
 	</class>
-	<class id="ahtc" controller="open-ils.cstore" oils_obj:fieldmapper="action::hold_transit_copy" oils_persist:tablename="action.hold_transit_copy" reporter:core="true" reporter:label="Hold Transit">
+	<class id="ahtc" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="action::hold_transit_copy" oils_persist:tablename="action.hold_transit_copy" reporter:core="true" reporter:label="Hold Transit">
 		<fields oils_persist:primary="id" oils_persist:sequence="action.transit_copy_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -3460,8 +3460,8 @@
                     <context link="target_copy" field="circ_lib"/>
                 </create>
                 <retrieve/>
-                <update permission="UPDATE_TRANSIT" context_field="dest|source"/>
-                <delete permission="DELETE_TRANSIT" context_field="dest|source"/>
+                <update permission="UPDATE_TRANSIT" context_field="dest source"/>
+                <delete permission="DELETE_TRANSIT" context_field="dest source"/>
             </actions>
         </permacrud>
 	</class>
@@ -3501,7 +3501,7 @@
 			<link field="usr" reltype="has_a" key="id" map="" class="au"/>
 		</links>
 	</class>
-	<class id="i18n" controller="open-ils.cstore" oils_obj:fieldmapper="config::i18n_core" oils_persist:tablename="config.i18n_core" oils_persist:field_safe="true">
+	<class id="i18n" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::i18n_core" oils_persist:tablename="config.i18n_core" oils_persist:field_safe="true">
 		<fields oils_persist:primary="id" oils_persist:sequence="config.i18n_core_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -3518,13 +3518,13 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_TRANSLATION" global_required="true"/>
-                <retrieve permission="CREATE_TRANSLATION|UPDATE_TRANSLATION|DELETE_TRANSLATION" global_required="true"/>
+                <retrieve permission="CREATE_TRANSLATION UPDATE_TRANSLATION DELETE_TRANSLATION" global_required="true"/>
                 <update permission="UPDATE_TRANSLATION" global_required="true"/>
                 <delete permission="DELETE_TRANSLATION" global_required="true"/>
             </actions>
         </permacrud>
 	</class>
-	<class id="i18n_l" controller="open-ils.cstore" oils_obj:fieldmapper="config::i18n_locale" oils_persist:tablename="config.i18n_locale" oils_persist:field_safe="true">
+	<class id="i18n_l" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::i18n_locale" oils_persist:tablename="config.i18n_locale" oils_persist:field_safe="true">
 		<fields oils_persist:primary="code">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -3538,13 +3538,13 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_LOCALE" global_required="true"/>
-                <retrieve permission="CREATE_LOCALE|UPDATE_LOCALE|DELETE_LOCALE" global_required="true"/>
+                <retrieve permission="CREATE_LOCALE UPDATE_LOCALE DELETE_LOCALE" global_required="true"/>
                 <update permission="UPDATE_LOCALE" global_required="true"/>
                 <delete permission="DELETE_LOCALE" global_required="true"/>
             </actions>
         </permacrud>
 	</class>
-	<class id="cbt" controller="open-ils.cstore" oils_obj:fieldmapper="config::billing_type" oils_persist:tablename="config.billing_type">
+	<class id="cbt" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::billing_type" oils_persist:tablename="config.billing_type">
 		<fields oils_persist:primary="id" oils_persist:sequence="config.billing_type_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -3560,13 +3560,13 @@
         <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
             <actions>
                 <create permission="CREATE_BILLING_TYPE" context_field="owner"/>
-                <retrieve permission="VIEW_BILLING_TYPE|CREATE_BILLING_TYPE|UPDATE_BILLING_TYPE|DELETE_BILLING_TYPE" context_field="owner"/>
+                <retrieve permission="VIEW_BILLING_TYPE CREATE_BILLING_TYPE UPDATE_BILLING_TYPE DELETE_BILLING_TYPE" context_field="owner"/>
                 <update permission="UPDATE_BILLING_TYPE" context_field="owner"/>
                 <delete permission="DELETE_BILLING_TYPE" context_field="owner"/>
             </actions>
         </permacrud>
 	</class>
-	<class id="acqct" controller="open-ils.cstore open-ils.reporter-store" oils_obj:fieldmapper="acq::currency_type" oils_persist:tablename="acq.currency_type">
+	<class id="acqct" controller="open-ils.cstore open-ils.reporter-store open-ils.pcrud" oils_obj:fieldmapper="acq::currency_type" oils_persist:tablename="acq.currency_type">
 		<fields oils_persist:primary="code">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />
@@ -3618,7 +3618,7 @@
 		</links>
 	</class>
 
-	<class id="acqfs" controller="open-ils.cstore open-ils.reporter-store" oils_obj:fieldmapper="acq::funding_source" oils_persist:tablename="acq.funding_source">
+	<class id="acqfs" controller="open-ils.cstore open-ils.reporter-store open-ils.pcrud" oils_obj:fieldmapper="acq::funding_source" oils_persist:tablename="acq.funding_source">
 		<fields oils_persist:primary="id" oils_persist:sequence="acq.funding_source_id_seq">
 			<field name="isnew" oils_obj:array_position="0" oils_persist:virtual="true" />
 			<field name="ischanged" oils_obj:array_position="1" oils_persist:virtual="true" />

Modified: trunk/Open-ILS/src/c-apps/Makefile.am
===================================================================
--- trunk/Open-ILS/src/c-apps/Makefile.am	2008-12-12 19:35:57 UTC (rev 11542)
+++ trunk/Open-ILS/src/c-apps/Makefile.am	2008-12-14 21:19:44 UTC (rev 11543)
@@ -12,7 +12,7 @@
 oils_dataloader_LDFLAGS = $(AM_LDFLAGS) -loils_idl
 oils_dataloader_DEPENDENCIES = liboils_idl.la liboils_utils.la
 
-lib_LTLIBRARIES = liboils_idl.la liboils_utils.la oils_cstore.la oils_rstore.la oils_auth.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
 
@@ -27,6 +27,11 @@
 oils_rstore_la_LDFLAGS = $(AM_LDFLAGS) -loils_idl -ldbi -ldbdpgsql -module
 oils_rstore_la_DEPENDENCIES = liboils_utils.la liboils_idl.la
 
+oils_pcrud_la_SOURCES = oils_cstore.c
+oils_pcrud_la_CFLAGS = $(AM_CFLAGS) -DPCRUD -c
+oils_pcrud_la_LDFLAGS = $(AM_LDFLAGS) -loils_idl -ldbi -ldbdpgsql -module
+oils_pcrud_la_DEPENDENCIES = liboils_utils.la liboils_idl.la
+
 oils_auth_la_SOURCES = oils_auth.c
 oils_auth_la_LDFLAGS = -module -loils_idl -loils_utils
 oils_auth_la_DEPENDENCIES = liboils_utils.la

Modified: trunk/Open-ILS/src/c-apps/oils_cstore.c
===================================================================
--- trunk/Open-ILS/src/c-apps/oils_cstore.c	2008-12-12 19:35:57 UTC (rev 11542)
+++ trunk/Open-ILS/src/c-apps/oils_cstore.c	2008-12-14 21:19:44 UTC (rev 11543)
@@ -4,7 +4,7 @@
 #include "opensrf/utils.h"
 #include "opensrf/osrf_json.h"
 #include "opensrf/log.h"
-#include "openils/oils_idl.h"
+#include "openils/oils_utils.h"
 #include <dbi/dbi.h>
 
 #include <time.h>
@@ -15,7 +15,11 @@
 #ifdef RSTORE
 #  define MODULENAME "open-ils.reporter-store"
 #else
-#  define MODULENAME "open-ils.cstore"
+#  ifdef PCRUD
+#    define MODULENAME "open-ils.pcrud"
+#  else
+#    define MODULENAME "open-ils.cstore"
+#  endif
 #endif
 
 #define SUBSELECT	4
@@ -69,6 +73,10 @@
 static void sessionDataFree( char*, void* );
 static char* getSourceDefinition( osrfHash* );
 
+#ifdef PCRUD
+static int verifyObjectPCRUD( osrfMethodContext*, const jsonObject* );
+#endif
+
 static dbi_conn writehandle; /* our MASTER db connection */
 static dbi_conn dbhandle; /* our CURRENT db connection */
 //static osrfHash * readHandles;
@@ -95,19 +103,21 @@
 }
 
 int osrfAppInitialize() {
-	growing_buffer* method_name;
 
 	osrfLogInfo(OSRF_LOG_MARK, "Initializing the CStore Server...");
 	osrfLogInfo(OSRF_LOG_MARK, "Finding XML file...");
 
 	if (!oilsIDLInit( osrf_settings_host_value("/IDL") )) return 1; /* return non-zero to indicate error */
 
+    char* method_str = NULL;
+	growing_buffer* method_name = buffer_init(64);
+#ifndef PCRUD
 	// Generic search thingy
-	method_name =  buffer_init(64);
 	buffer_fadd(method_name, "%s.json_query", MODULENAME);
-	char* method_str = buffer_data(method_name);
+	method_str = buffer_data(method_name);
 	osrfAppRegisterMethod( MODULENAME, method_str, "doJSONSearch", "", 1, OSRF_METHOD_STREAMING );
 	free(method_str);
+#endif;
 
 	// first we register all the transaction and savepoint methods
 	buffer_reset(method_name);
@@ -190,6 +200,11 @@
 
 			if (!osrfHashGet(idlClass, "fieldmapper")) continue;
 
+#ifdef PCRUD
+			if (!osrfHashGet(idlClass, "permacrud")) continue;
+			if (!osrfHashGet( osrfHashGet(idlClass, "permacrud"), method_type )) continue;
+#endif
+
 			char* readonly = osrfHashGet(idlClass, "readonly");
 			if (	readonly &&
 				!strncasecmp( "true", readonly, 4) &&
@@ -202,7 +217,7 @@
 			_fm = strdup( (char*)osrfHashGet(idlClass, "fieldmapper") );
 			part = strtok_r(_fm, ":", &st_tmp);
 
-			growing_buffer* method_name =  buffer_init(64);
+			method_name =  buffer_init(64);
 			buffer_fadd(method_name, "%s.direct.%s", MODULENAME, part);
 
 			while ((part = strtok_r(NULL, ":", &st_tmp))) {
@@ -646,12 +661,20 @@
 	}
 	else if (!strcmp(methodtype, "search")) {
 
-		obj = doFieldmapperSearch(ctx, class_obj, ctx->params, &err);
+		jsonObject* _p = jsonObjectClone( ctx->params );
+#ifdef PCRUD
+        jsonObjectRemoveIndex(_p, 0);
+#endif
+
+		obj = doFieldmapperSearch(ctx, class_obj, _p, &err);
 		if(err) return err;
 
 		jsonObject* cur;
 		jsonIterator* itr = jsonNewIterator( obj );
 		while ((cur = jsonIteratorNext( itr ))) {
+#ifdef PCRUD
+        	if(!verifyObjectPCRUD(ctx, cur)) continue;
+#endif
 			osrfAppRespond( ctx, cur );
 		}
 		jsonIteratorFree(itr);
@@ -659,19 +682,28 @@
 
 	} else if (!strcmp(methodtype, "id_list")) {
 
+		int _opt_pos = 1;
+#ifdef PCRUD
+		_opt_pos = 2;
+#endif
+
 		jsonObject* _p = jsonObjectClone( ctx->params );
-		if (jsonObjectGetIndex( _p, 1 )) {
-			jsonObjectRemoveKey( jsonObjectGetIndex( _p, 1 ), "flesh" );
-			jsonObjectRemoveKey( jsonObjectGetIndex( _p, 1 ), "flesh_columns" );
+#ifdef PCRUD
+        jsonObjectRemoveIndex(_p, 0);
+#endif
+
+		if (jsonObjectGetIndex( _p, _opt_pos )) {
+			jsonObjectRemoveKey( jsonObjectGetIndex( _p, _opt_pos ), "flesh" );
+			jsonObjectRemoveKey( jsonObjectGetIndex( _p, _opt_pos ), "flesh_columns" );
 		} else {
-			jsonObjectSetIndex( _p, 1, jsonNewObjectType(JSON_HASH) );
+			jsonObjectSetIndex( _p, _opt_pos, jsonNewObjectType(JSON_HASH) );
 		}
 
 		growing_buffer* sel_list = buffer_init(64);
 		buffer_fadd(sel_list, "{ \"%s\":[\"%s\"] }", osrfHashGet( class_obj, "classname" ), osrfHashGet( class_obj, "primarykey" ));
 		char* _s = buffer_release(sel_list);
 
-		jsonObjectSetKey( jsonObjectGetIndex( _p, 1 ), "select", jsonParseString(_s) );
+		jsonObjectSetKey( jsonObjectGetIndex( _p, _opt_pos ), "select", jsonParseString(_s) );
 		osrfLogDebug(OSRF_LOG_MARK, "%s: Select qualifer set to [%s]", MODULENAME, _s);
 		free(_s);
 
@@ -682,20 +714,12 @@
 		jsonObject* cur;
 		jsonIterator* itr = jsonNewIterator( obj );
 		while ((cur = jsonIteratorNext( itr ))) {
+#ifdef PCRUD
+        	if(!verifyObjectPCRUD(ctx, cur)) continue;
+#endif
 			osrfAppRespond(
 				ctx,
-				jsonObjectGetIndex(
-					cur,
-					atoi(
-						osrfHashGet(
-							osrfHashGet(
-								osrfHashGet( class_obj, "fields" ),
-								osrfHashGet( class_obj, "primarykey")
-							),
-							"array_position"
-						)
-					)
-				)
+				oilsFMGetObject( cur, osrfHashGet( class_obj, "primarykey" ) )
 			);
 		}
 		jsonIteratorFree(itr);
@@ -712,6 +736,7 @@
 
 static int verifyObjectClass ( osrfMethodContext* ctx, const jsonObject* param ) {
 	
+    int ret = 1;
 	osrfHash* meta = (osrfHash*) ctx->method->userData;
 	osrfHash* class = osrfHashGet( meta, "class" );
 	
@@ -734,14 +759,258 @@
 
 		return 0;
 	}
-	return 1;
+
+#ifdef PCRUD
+    ret = verifyObjectPCRUD( ctx, param );
+#endif
+
+	return ret;
 }
 
+#ifdef PCRUD
+static int verifyObjectPCRUD (  osrfMethodContext* ctx, const jsonObject* obj ) {
+
+	dbhandle = writehandle;
+
+	osrfHash* meta = (osrfHash*) ctx->method->userData;
+	osrfHash* class = osrfHashGet( meta, "class" );
+    char* method_type = strdup( osrfHashGet(meta, "methodtype") );
+
+    if ( ( *method_type == 's' || *method_type == 'i' ) ) {
+        free(method_type);
+        method_type = strdup("retrieve");
+    }
+	
+    osrfHash* pcrud = osrfHashGet( osrfHashGet(class, "permacrud"), method_type );
+	free(method_type);
+
+    if (!pcrud) {
+        // No permacrud for this method type on this class
+
+   		growing_buffer* msg = buffer_init(128);
+		buffer_fadd(
+			msg,
+			"%s: %s on class %s has no permacrud IDL entry",
+			MODULENAME,
+			osrfHashGet(meta, "methodtype"),
+			osrfHashGet(class, "classname")
+		);
+
+		char* m = buffer_release(msg);
+		osrfAppSessionStatus( ctx->session, OSRF_STATUS_BADREQUEST, "osrfMethodException", ctx->request, m );
+
+		free(m);
+
+		return 0;
+    }
+
+    //XXX turn this into a user id
+	char* auth = jsonObjectToSimpleString( jsonObjectGetIndex( ctx->params, 0 ) );
+    jsonObject* user = oilsUtilsQuickReq("open-ils.auth","open-ils.auth.session.retrieve", jsonNewObject(auth));
+
+    if (!user) {
+        free(auth);
+        return 0;
+    }
+
+    int userid = atoi( oilsFMGetString( user, "id" ) );
+
+    jsonObjectFree(user);
+    free(auth);
+
+    osrfStringArray* permission = osrfHashGet(pcrud, "permission");
+    char* global_required = osrfHashGet(pcrud, "global_required");
+    osrfStringArray* local_context = osrfHashGet(pcrud, "local_context");
+    osrfHash* foreign_context = osrfHashGet(pcrud, "foreign_context");
+
+    osrfStringArray* context_org_array = osrfNewStringArray(1);
+
+    char* pkey_value = NULL;
+    int OK = 0;
+    int err = 0;
+    if (global_required && strcmp( "true", global_required )) {
+        // check for perm at top of org tree
+        jsonObject* _tmp_params = jsonParseString("{\"parent_ou\":null}");
+		jsonObject* _list = doFieldmapperSearch(ctx, oilsIDLFindPath("/aou"), _tmp_params, &err);
+
+        jsonObject* _tree_top = jsonObjectGetIndex(_list, 0);
+
+        if (!_tree_top) {
+            jsonObjectFree(_tmp_params);
+            jsonObjectFree(_list);
+            return -1;
+        }
+
+        osrfStringArrayAdd( context_org_array, oilsFMGetString( _tree_top, "id" ) );
+
+        jsonObjectFree(_tmp_params);
+        jsonObjectFree(_list);
+
+    } else {
+
+        jsonObject *param = NULL;
+        if (obj) param = jsonObjectClone(obj);
+	    if (!param) param = jsonObjectClone(jsonObjectGetIndex( ctx->params, 1 ));
+
+       // XXX if the object has a non-null pkey, check for object-specific perm,
+       // else context org(s) for group perm check
+	    char* pkey = osrfHashGet(class, "primarykey");
+
+        if (param->classname) {
+            pkey_value = oilsFMGetString( param, pkey );
+
+        } else {
+            pkey_value = jsonObjectToSimpleString( param );
+
+            jsonObject* _tmp_params = jsonParseStringFmt("{\"%s\":\"%s\"}", pkey, pkey_value);
+    		jsonObject* _list = doFieldmapperSearch(
+                ctx,
+                class,
+                _tmp_params,
+                &err
+            );
+    
+            jsonObjectFree(param);
+            param = jsonObjectClone(jsonObjectGetIndex(_list, 0));
+    
+            if (!param) {
+                jsonObjectFree(_tmp_params);
+                jsonObjectFree(_list);
+                return -1;
+            }
+
+            jsonObjectFree(_tmp_params);
+            jsonObjectFree(_list);
+
+        }
+
+        if (local_context->size > 0) {
+            int i = 0;
+            char* lcontext = NULL;
+            while ( (lcontext = osrfStringArrayGetString(local_context, i++)) ) {
+                osrfStringArrayAdd( context_org_array, oilsFMGetString( param, lcontext ) );
+            }
+        }
+
+        if (foreign_context->size > 0) {
+        	osrfStringArray* class_list = osrfHashKeys( foreign_context );
+
+            int i = 0;
+            char* class_name = NULL;
+        	while ( (class_name = osrfStringArrayGetString(class_list, i++)) ) {
+                osrfHash* fcontext = osrfHashGet(foreign_context, class_name);
+
+                jsonObject* _tmp_params = jsonParseStringFmt(
+                    "{\"%s\":\"%s\"}",
+                    osrfHashGet(fcontext, "field"),
+                    oilsFMGetString(param, osrfHashGet(fcontext, "fkey"))
+                );
+
+        		jsonObject* _list = doFieldmapperSearch(
+                    ctx,
+                    class,
+                    _tmp_params,
+                    &err
+                );
+        
+   
+                jsonObject* _fparam = jsonObjectGetIndex(_list, 0);
+        
+                if (!_fparam) {
+                    jsonObjectFree(_tmp_params);
+                    jsonObjectFree(_list);
+                    return -1;
+                }
+    
+                jsonObjectFree(_tmp_params);
+                jsonObjectFree(_list);
+
+                char* foreign_field = NULL;
+                while ( (foreign_field = osrfStringArrayGetString(osrfHashGet(fcontext,"context"), i++)) ) {
+                    osrfStringArrayAdd( context_org_array, oilsFMGetString( _fparam, foreign_field ) );
+                }
+   
+                jsonObjectFree(_fparam);
+            }
+
+            osrfStringArrayFree(class_list);
+        }
+
+        jsonObjectFree(param);
+    }
+
+    char* context_org;
+    char* perm;
+    
+    int i = 0;
+    while ( (perm = osrfStringArrayGetString(permission, i++)) ) {
+        int j = 0;
+        while ( (context_org = osrfStringArrayGetString(context_org_array, j++)) ) {
+            dbi_result result;
+
+            if (pkey_value) {
+                result = dbi_conn_queryf(
+                    writehandle,
+                    "SELECT permission.usr_has_object_perm(%d, '%s', '%s', '%s', %d) AS has_perm;",
+                    userid,
+                    perm,
+                    osrfHashGet(class, "classname"),
+                    pkey_value,
+                    atoi(context_org)
+                );
+
+                if (result) {
+                    jsonObject* return_val = oilsMakeJSONFromResult( result );
+                    char* has_perm = jsonObjectToSimpleString( jsonObjectGetKeyConst(return_val, "has_perm") );
+                    if ( *has_perm == 't' ) OK = 1;
+                    free(has_perm); 
+                    jsonObjectFree(return_val);
+                    dbi_result_free(result); 
+                    break;
+                }
+            }
+
+            result = dbi_conn_queryf(
+                writehandle,
+                "SELECT permission.usr_has_perm(%d, '%s', %d) AS has_perm;",
+                userid,
+                perm,
+                atoi(context_org)
+            );
+
+            if (result) {
+                jsonObject* return_val = oilsMakeJSONFromResult( result );
+                char* has_perm = jsonObjectToSimpleString( jsonObjectGetKeyConst(return_val, "has_perm") );
+                if ( *has_perm == 't' ) OK = 1;
+                free(has_perm); 
+                jsonObjectFree(return_val);
+                dbi_result_free(result); 
+                break;
+            }
+
+        }
+        if (OK) break;
+    }
+
+    if (pkey_value) free(pkey_value);
+    osrfStringArrayFree(context_org_array);
+
+    if (!OK) return 0;
+    return 1;
+}
+#endif
+
+
 static jsonObject* doCreate(osrfMethodContext* ctx, int* err ) {
 
 	osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
+#ifdef PCRUD
+	jsonObject* target = jsonObjectGetIndex( ctx->params, 1 );
+	jsonObject* options = jsonObjectGetIndex( ctx->params, 2 );
+#else
 	jsonObject* target = jsonObjectGetIndex( ctx->params, 0 );
 	jsonObject* options = jsonObjectGetIndex( ctx->params, 1 );
+#endif
 
 	if (!verifyObjectClass(ctx, target)) {
 		*err = -1;
@@ -780,9 +1049,8 @@
 	char* trans_id = osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" );
 
         // Set the last_xact_id
-	osrfHash* last_xact_id;
-	if ((last_xact_id = oilsIDLFindPath("/%s/fields/last_xact_id", target->classname))) {
-		int index = atoi( osrfHashGet(last_xact_id, "array_position") );
+	int index = oilsIDL_ntop( target->classname, "last_xact_id" );
+	if (index > -1) {
 		osrfLogDebug(OSRF_LOG_MARK, "Setting last_xact_id to %s on %s at position %d", trans_id, target->classname, index);
 		jsonObjectSetIndex(target, index, jsonNewObject(trans_id));
 	}       
@@ -814,25 +1082,14 @@
 
 		if(!( strcmp( osrfHashGet(osrfHashGet(fields,field_name), "virtual"), "true" ) )) continue;
 
-		jsonObject* field_object = jsonObjectGetIndex( target, atoi(osrfHashGet(field, "array_position")) );
+		const jsonObject* field_object = oilsFMGetObject( target, field_name );
 
 		char* value;
 		if (field_object && field_object->classname) {
-			value = jsonObjectToSimpleString(
-					jsonObjectGetIndex(
-						field_object,
-						atoi(
-							osrfHashGet(
-								osrfHashGet(
-									oilsIDLFindPath("/%s/fields", field_object->classname),
-									(char*)oilsIDLFindPath("/%s/primarykey", field_object->classname)
-								),
-								"array_position"
-							)
-						)
-					)
-				);
-
+			value = oilsFMGetString(
+				field_object,
+				(char*)oilsIDLFindPath("/%s/primarykey", field_object->classname)
+			);
 		} else {
 			value = jsonObjectToSimpleString( field_object );
 		}
@@ -927,8 +1184,7 @@
 		*err = -1;
 	} else {
 
-		int pos = atoi(osrfHashGet( osrfHashGet(fields, pkey), "array_position" ));
-		char* id = jsonObjectToSimpleString(jsonObjectGetIndex(target, pos));
+		char* id = oilsFMGetString(target, pkey);
 		if (!id) {
 			unsigned long long new_id = dbi_conn_sequence_last(writehandle, seq);
 			growing_buffer* _id = buffer_init(10);
@@ -954,7 +1210,7 @@
 
 			jsonObjectSetKey(
 				jsonObjectGetIndex(fake_params, 0),
-				osrfHashGet(meta, "primarykey"),
+				pkey,
 				jsonNewObject(id)
 			);
 
@@ -984,16 +1240,24 @@
 
 static jsonObject* doRetrieve(osrfMethodContext* ctx, int* err ) {
 
+    int id_pos = 0;
+    int order_pos = 1;
+
+#ifdef PCRUD
+    id_pos = 1;
+    order_pos = 2;
+#endif
+
 	osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
 
 	jsonObject* obj;
 
-	char* id = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
-	jsonObject* order_hash = jsonObjectGetIndex(ctx->params, 1);
+	char* id = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, id_pos));
+	jsonObject* order_hash = jsonObjectGetIndex(ctx->params, order_pos);
 
 	osrfLogDebug(
 		OSRF_LOG_MARK,
-		"%s retrieving %s object with id %s",
+		"%s retrieving %s object with primary key value of %s",
 		MODULENAME,
 		osrfHashGet(meta, "fieldmapper"),
 		id
@@ -1024,6 +1288,13 @@
 	jsonObjectFree( list );
 	jsonObjectFree( fake_params );
 
+#ifdef PCRUD
+	if(!verifyObjectPCRUD(ctx, obj)) {
+        jsonObjectFree(obj);
+		return jsonNULL;
+	}
+#endif
+
 	return obj;
 }
 
@@ -2646,8 +2917,7 @@
 			osrfLogDebug(OSRF_LOG_MARK, "Query returned at least one row");
 			do {
 				obj = oilsMakeFieldmapperFromResult( result, meta );
-				int pkey_pos = atoi( osrfHashGet( osrfHashGet( fields, pkey ), "array_position" ) );
-				char* pkey_val = jsonObjectToSimpleString( jsonObjectGetIndex( obj, pkey_pos ) );
+				char* pkey_val = oilsFMGetString( obj, pkey );
 				if ( osrfHashGet( dedup, pkey_val ) ) {
 					jsonObjectFree(obj);
 					free(pkey_val);
@@ -2916,7 +3186,11 @@
 static jsonObject* doUpdate(osrfMethodContext* ctx, int* err ) {
 
 	osrfHash* meta = osrfHashGet( (osrfHash*) ctx->method->userData, "class" );
-	jsonObject* target = jsonObjectGetIndex(ctx->params, 0);
+#ifdef PCRUD
+	jsonObject* target = jsonObjectGetIndex( ctx->params, 1 );
+#else
+	jsonObject* target = jsonObjectGetIndex( ctx->params, 0 );
+#endif
 
 	if (!verifyObjectClass(ctx, target)) {
 		*err = -1;
@@ -2952,9 +3226,8 @@
 	char* trans_id = osrfHashGet( (osrfHash*)ctx->session->userData, "xact_id" );
 
         // Set the last_xact_id
-	osrfHash* last_xact_id;
-	if ((last_xact_id = oilsIDLFindPath("/%s/fields/last_xact_id", target->classname))) {
-		int index = atoi( osrfHashGet(last_xact_id, "array_position") );
+	int index = oilsIDL_ntop( target->classname, "last_xact_id" );
+	if (index > -1) {
 		osrfLogDebug(OSRF_LOG_MARK, "Setting last_xact_id to %s on %s at position %d", trans_id, target->classname, index);
 		jsonObjectSetIndex(target, index, jsonNewObject(trans_id));
 	}       
@@ -2962,13 +3235,7 @@
 	char* pkey = osrfHashGet(meta, "primarykey");
 	osrfHash* fields = osrfHashGet(meta, "fields");
 
-	char* id =
-		jsonObjectToSimpleString(
-			jsonObjectGetIndex(
-				target,
-				atoi( osrfHashGet( osrfHashGet( fields, pkey ), "array_position" ) )
-			)
-		);
+	char* id = oilsFMGetString( target, pkey );
 
 	osrfLogDebug(
 		OSRF_LOG_MARK,
@@ -2993,25 +3260,14 @@
 		if(!( strcmp( field_name, pkey ) )) continue;
 		if(!( strcmp( osrfHashGet(osrfHashGet(fields,field_name), "virtual"), "true" ) )) continue;
 
-		jsonObject* field_object = jsonObjectGetIndex( target, atoi(osrfHashGet(field, "array_position")) );
+		const jsonObject* field_object = oilsFMGetObject( target, field_name );
 
 		char* value;
 		if (field_object && field_object->classname) {
-			value = jsonObjectToSimpleString(
-					jsonObjectGetIndex(
-						field_object,
-						atoi(
-							osrfHashGet(
-								osrfHashGet(
-									oilsIDLFindPath("/%s/fields", field_object->classname),
-									(char*)oilsIDLFindPath("/%s/primarykey", field_object->classname)
-								),
-								"array_position"
-							)
-						)
-					)
-				);
-
+			value = oilsFMGetString(
+				field_object,
+				(char*)oilsIDLFindPath("/%s/primarykey", field_object->classname)
+            );
 		} else {
 			value = jsonObjectToSimpleString( field_object );
 		}
@@ -3129,21 +3385,27 @@
 
 	char* pkey = osrfHashGet(meta, "primarykey");
 
+	int _obj_pos = 0;
+#ifdef PCRUD
+		_obj_pos = 1;
+#endif
+
 	char* id;
-	if (jsonObjectGetIndex(ctx->params, 0)->classname) {
-		if (!verifyObjectClass(ctx, jsonObjectGetIndex( ctx->params, 0 ))) {
+	if (jsonObjectGetIndex(ctx->params, _obj_pos)->classname) {
+		if (!verifyObjectClass(ctx, jsonObjectGetIndex( ctx->params, _obj_pos ))) {
 			*err = -1;
 			return jsonNULL;
 		}
 
-		id = jsonObjectToSimpleString(
-			jsonObjectGetIndex(
-				jsonObjectGetIndex(ctx->params, 0),
-				atoi( osrfHashGet( osrfHashGet( osrfHashGet(meta, "fields"), pkey ), "array_position") )
-			)
-		);
+		id = oilsFMGetString( jsonObjectGetIndex(ctx->params, _obj_pos), pkey );
 	} else {
-		id = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, 0));
+#ifdef PCRUD
+        if (!verifyObjectPCRUD( ctx, NULL )) {
+			*err = -1;
+			return jsonNULL;
+        }
+#endif
+		id = jsonObjectToSimpleString(jsonObjectGetIndex(ctx->params, _obj_pos));
 	}
 
 	osrfLogDebug(

Modified: trunk/Open-ILS/src/c-apps/oils_idl-core.c
===================================================================
--- trunk/Open-ILS/src/c-apps/oils_idl-core.c	2008-12-12 19:35:57 UTC (rev 11542)
+++ trunk/Open-ILS/src/c-apps/oils_idl-core.c	2008-12-14 21:19:44 UTC (rev 11543)
@@ -15,6 +15,8 @@
 #define PERSIST_NS "http://open-ils.org/spec/opensrf/IDL/persistence/v1"
 #define OBJECT_NS "http://open-ils.org/spec/opensrf/IDL/objects/v1"
 #define BASE_NS "http://opensrf.org/spec/IDL/base/v1"
+#define REPORTER_NS "http://open-ils.org/spec/opensrf/IDL/reporter/v1"
+#define PERM_NS "http://open-ils.org/spec/opensrf/IDL/permacrud/v1"
 
 static xmlDocPtr idlDoc = NULL; // parse and store the IDL here
 
@@ -95,6 +97,7 @@
 			osrfHash* _tmp;
 			osrfHash* links = osrfNewHash();
 			osrfHash* fields = osrfNewHash();
+			osrfHash* pcrud = osrfNewHash();
 
 			osrfHashSet( usrData, fields, "fields" );
 			osrfHashSet( usrData, links, "links" );
@@ -270,7 +273,158 @@
 						_l = _l->next;
 					}
 				}
+/**** Structure of permacrud in memory ****
 
+{ create :
+    { permission : [ x, y, z ],
+      global_required : "true", -- anything else, or missing, is false
+      local_context : [ f1, f2 ],
+      foreign_context : { class1 : { fkey : local_class_key, field : class1_field, context : [ a, b, c ] }, ...}
+    },
+  retrieve : null, -- no perm check, or structure similar to the others
+  update : -- like create
+    ...
+  delete : -- like create
+    ...
+}   
+
+**** Structure of permacrud in memory ****/
+
+				if (!strcmp( (char*)_cur->name, "permacrud" )) {
+					osrfHashSet( usrData, pcrud, "permacrud" );
+					xmlNodePtr _l = _cur->children;
+
+					while(_l) {
+						if (strcmp( (char*)_l->name, "actions" )) {
+							_l = _l->next;
+							continue;
+						}
+
+						xmlNodePtr _a = _l->children;
+
+						while(_a) {
+							if (
+								strcmp( (char*)_a->name, "create" ) &&
+								strcmp( (char*)_a->name, "retreive" ) &&
+								strcmp( (char*)_a->name, "update" ) &&
+								strcmp( (char*)_a->name, "delete" )
+							) {
+								_a = _a->next;
+								continue;
+							}
+
+							string_tmp = strdup( (char*)_a->name );
+							osrfLogDebug(OSRF_LOG_MARK, "Found Permacrud action %s for class %s", string_tmp, osrfHashGet(usrData, "classname") );
+
+							_tmp = osrfNewHash();
+							osrfHashSet( pcrud, _tmp, string_tmp );
+
+							osrfStringArray* map = osrfNewStringArray(0);
+							string_tmp = NULL;
+							if( (string_tmp = (char*)xmlGetProp(_l, BAD_CAST "permission") )) {
+								char* map_list = strdup( string_tmp );
+								osrfLogDebug(OSRF_LOG_MARK, "Permacrud permission list is %s", string_tmp );
+	
+								if (strlen( map_list ) > 0) {
+									char* st_tmp = NULL;
+									char* _map_class = strtok_r(map_list, "|", &st_tmp);
+									osrfStringArrayAdd(map, strdup(_map_class));
+							
+									while ((_map_class = strtok_r(NULL, "|", &st_tmp))) {
+										osrfStringArrayAdd(map, strdup(_map_class));
+									}
+								}
+								free(map_list);
+								osrfHashSet( _tmp, map, "permission");
+							}
+
+					    	osrfHashSet( _tmp, (char*)xmlGetProp(_l, BAD_CAST "global_required"), "global_required");
+
+							map = osrfNewStringArray(0);
+							string_tmp = NULL;
+							if( (string_tmp = (char*)xmlGetProp(_l, BAD_CAST "context_field") )) {
+								char* map_list = strdup( string_tmp );
+								osrfLogDebug(OSRF_LOG_MARK, "Permacrud context_field list is %s", string_tmp );
+	
+								if (strlen( map_list ) > 0) {
+									char* st_tmp = NULL;
+									char* _map_class = strtok_r(map_list, "|", &st_tmp);
+									osrfStringArrayAdd(map, strdup(_map_class));
+							
+									while ((_map_class = strtok_r(NULL, "|", &st_tmp))) {
+										osrfStringArrayAdd(map, strdup(_map_class));
+									}
+								}
+								free(map_list);
+							}
+							osrfHashSet( _tmp, map, "local_context");
+
+							xmlNodePtr _f = _l->children;
+
+							while(_f) {
+								if ( strcmp( (char*)_f->name, "context" ) ) {
+									_f = _f->next;
+									continue;
+								}
+
+								string_tmp = NULL;
+								if( (string_tmp = (char*)xmlGetProp(_f, BAD_CAST "link")) ) {
+									osrfLogDebug(OSRF_LOG_MARK, "Permacrud context link definition is %s", string_tmp );
+
+									osrfHash* _tmp_fcontext = osrfNewHash();
+									osrfHash* _flink = oilsIDLFindPath("/%s/links/%s", osrfHashGet(usrData, "classname"), string_tmp);
+
+									osrfHashSet( _tmp_fcontext, osrfNewHash(), osrfHashGet(_flink, "class") );
+									_tmp_fcontext = osrfHashGet( _tmp_fcontext, osrfHashGet(_flink, "class") );
+									osrfHashSet( _tmp_fcontext, osrfHashGet(_flink, "field"), "fkey" );
+									osrfHashSet( _tmp_fcontext, osrfHashGet(_flink, "key"), "field" );
+
+									map = osrfNewStringArray(0);
+									string_tmp = NULL;
+									if( (string_tmp = (char*)xmlGetProp(_f, BAD_CAST "field") )) {
+										char* map_list = strdup( string_tmp );
+										osrfLogDebug(OSRF_LOG_MARK, "Permacrud foreign context field list is %s", string_tmp );
+			
+										if (strlen( map_list ) > 0) {
+											char* st_tmp = NULL;
+											char* _map_class = strtok_r(map_list, "|", &st_tmp);
+											osrfStringArrayAdd(map, strdup(_map_class));
+									
+											while ((_map_class = strtok_r(NULL, "|", &st_tmp))) {
+												osrfStringArrayAdd(map, strdup(_map_class));
+											}
+										}
+										free(map_list);
+									}
+									osrfHashSet( _tmp_fcontext, map, "context");
+
+								} else {
+
+									if( (string_tmp = (char*)xmlGetProp(_f, BAD_CAST "field") )) {
+										char* map_list = strdup( string_tmp );
+										osrfLogDebug(OSRF_LOG_MARK, "Permacrud foreign context field list is %s", string_tmp );
+			
+										if (strlen( map_list ) > 0) {
+											char* st_tmp = NULL;
+											char* _map_class = strtok_r(map_list, "|", &st_tmp);
+											osrfStringArrayAdd(osrfHashGet( _tmp, "local_context"), strdup(_map_class));
+									
+											while ((_map_class = strtok_r(NULL, "|", &st_tmp))) {
+												osrfStringArrayAdd(osrfHashGet( _tmp, "local_context"), strdup(_map_class));
+											}
+										}
+										free(map_list);
+									}
+
+								}
+								_f = _f->next;
+							}
+							_a = _a->next;
+						}
+						_l = _l->next;
+					}
+				}
+
 				if (!strcmp( (char*)_cur->name, "source_definition" )) {
 					string_tmp = NULL;
 					if( (string_tmp = (char*)xmlNodeGetContent(_cur)) ) {

Modified: trunk/Open-ILS/src/c-apps/oils_utils.c
===================================================================
--- trunk/Open-ILS/src/c-apps/oils_utils.c	2008-12-12 19:35:57 UTC (rev 11542)
+++ trunk/Open-ILS/src/c-apps/oils_utils.c	2008-12-14 21:19:44 UTC (rev 11543)
@@ -74,13 +74,24 @@
 
 
 oilsEvent* oilsUtilsCheckPerms( int userid, int orgid, char* permissions[], int size ) {
-	if(!permissions) return NULL;
+	if (!permissions) return NULL;
 	int i;
 	oilsEvent* evt = NULL;
-	if(orgid == -1) orgid = 1; /* XXX  */
 
-	for( i = 0; i != size && permissions[i]; i++ ) {
+	if (orgid == -1) {
+		jsonObject* org = oilsUtilsQuickReq(
+            "open-ils.cstore", 
+            "open-ils.cstore.direct.actor.org_unit.search",
+            jsonParseString("{\"parent_ou\":null}")
+        );
 
+        orgid = (int)jsonObjectGetNumber( oilsFMGetObject( org, "id" ) );
+
+        jsonObjectFree(org);
+    }
+
+	for( i = 0; i < size && permissions[i]; i++ ) {
+
 		char* perm = permissions[i];
 		jsonObject* params = jsonParseStringFmt("[%d, \"%s\", %d]", userid, perm, orgid);
 		jsonObject* o = oilsUtilsQuickReq( "open-ils.storage", 



More information about the open-ils-commits mailing list