Clean up 1.6 branch.
[Evergreen-DocBook.git] / 2.0 / development / datamodelsandaccess.xml
diff --git a/2.0/development/datamodelsandaccess.xml b/2.0/development/datamodelsandaccess.xml
deleted file mode 100644 (file)
index 93ec246..0000000
+++ /dev/null
@@ -1,789 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>\r
-<chapter xml:id="data_models_and_access" xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="EN"\r
-    xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink">\r
-       <chapterinfo>\r
-       <title>Evergreen Data Models and Access</title>\r
-       </chapterinfo>\r
-               <abstract id="DM_abstract">\r
-               <simpara>This chapter was taken from Dan Scott's <emphasis>Developer Workshop</emphasis>, February 2010.</simpara>\r
-       </abstract>\r
-       <section id="exploring_database_schema">\r
-               <title>Exploring the Database Schema</title>\r
-               <simpara>The database schema is tied pretty tightly to PostgreSQL. Although PostgreSQL<indexterm><primary>databases</primary><secondary>PostgreSQL</secondary></indexterm>\r
-               adheres closely to ANSI SQL standards, the use of schemas, SQL functions<indexterm><primary>ANSI</primary></indexterm>\r
-               implemented in both <systemitem>plpgsql</systemitem> and <systemitem>plperl</systemitem>, and PostgreSQL&#8217;s native full-text\r
-               search would make it&#8230; challenging&#8230; to port to other database platforms.</simpara>\r
-               <simpara>A few common PostgreSQL interfaces for poking around the schema and\r
-               manipulating data are:</simpara>\r
-               <itemizedlist>\r
-               <listitem>\r
-               <simpara>\r
-               psql (the command line client)<indexterm><primary>databases</primary><secondary>PostgreSQL</secondary><tertiery>psql</tertiery></indexterm>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               pgadminIII (a GUI client).<indexterm><primary>databases</primary><secondary>PostgreSQL</secondary><tertiery>pgadminIII</tertiery></indexterm>\r
-               </simpara>\r
-               </listitem>\r
-               </itemizedlist>\r
-               <simpara>Or you can read through the source files in <filename class="directoy">Open-ILS/src/sql/Pg</filename>.</simpara>\r
-               <simpara>Let&#8217;s take a quick tour through the schemas, pointing out some highlights\r
-               and some key interdependencies:</simpara>\r
-               <itemizedlist>\r
-               <listitem>\r
-               <simpara>\r
-               actor.org_unit &#8594; asset.copy_location\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               actor.usr &#8594; actor.card\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               biblio.record_entry &#8594; asset.call_number &#8594; asset.copy\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               config.metabib_field &#8594; metabib.*_field_entry\r
-               </simpara>\r
-               </listitem>\r
-               </itemizedlist>\r
-               This documentation also contains an Appendix for the Evergreen <xref linkend="databaseschema"/>.         \r
-       </section>\r
-       <section id="_database_access_methods">\r
-               <title>Database access methods</title>\r
-               <simpara>You could use direct access to the database via Perl DBI, JDBC, etc,\r
-               but Evergreen offers several database CRUD services for\r
-               creating / retrieving / updating / deleting data. These avoid tying\r
-               you too tightly to the current database schema and they funnel database\r
-               access through the same mechanism, rather than tying up connections\r
-               with other interfaces.</simpara>\r
-       </section>\r
-       <section id="_evergreen_interface_definition_language_idl">\r
-               <title>Evergreen Interface Definition Language (IDL)</title>\r
-               <indexterm><primary>Evergreen Interface Definition Language (IDL)</primary></indexterm>\r
-               <simpara>Defines properties and required permissions for Evergreen classes.\r
-               To reduce network overhead, a given object is identified via a\r
-               class-hint and serialized as a JSON array of properties (no named properties).</simpara>\r
-               <simpara>As of 1.6, fields will be serialized in the order in which they appear\r
-               in the IDL definition file, and the is_new / is_changed / is_deleted\r
-               properties are automatically added. This has greatly reduced the size of\r
-               the <literal>fm_IDL.xml</literal> file and makes DRY people happier :)</simpara>\r
-               <itemizedlist>\r
-               <listitem>\r
-               <simpara>\r
-               &#8230; oils_persist:readonly tells us, if true, that the data lives in the database, but is pulled from the SELECT statement defined in the &lt;oils_persist:source_definition&gt; \r
-               child element\r
-               </simpara>\r
-               </listitem>\r
-               </itemizedlist>\r
-               <simplesect id="_idl_basic_example_config_language_map">\r
-                       <title>IDL basic example (config.language_map)</title>\r
-<programlisting language="xml" linenumbering="unnumbered">\r
-&lt;class id="clm" controller="open-ils.cstore open-ils.pcrud"\r
-       oils_obj:fieldmapper="config::language_map"\r
-       oils_persist:tablename="config.language_map"\r
-       reporter:label="Language Map" oils_persist:field_safe="true"&gt; <co id="dmCO5-1"/> <co id="dmCO5-2"/> <co id="dmCO5-3"/> <co id="dmCO5-4"/>\r
-    &lt;fields oils_persist:primary="code" oils_persist:sequence=""&gt;  <co id="dmCO5-5"/>\r
-       &lt;field reporter:label="Language Code" name="code"\r
-           reporter:selector="value" reporter:datatype="text"/&gt; <co id="dmCO5-6"/>\r
-       &lt;field reporter:label="Language" name="value"\r
-           reporter:datatype="text" oils_persist:i18n="true"/&gt; <co id="dmCO5-7"/>\r
-    &lt;/fields&gt;\r
-    &lt;links/&gt;\r
-    &lt;permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1"&gt; <co id="dmCO5-8"/>\r
-       &lt;actions&gt;\r
-           &lt;create global_required="true" permission="CREATE_MARC_CODE"&gt; <co id="dmCO5-9"/>\r
-           &lt;retrieve global_required="true"\r
-               permission="CREATE_MARC_CODE UPDATE_MARC_CODE DELETE_MARC_CODE"&gt;\r
-           &lt;update global_required="true" permission="UPDATE_MARC_CODE"&gt;\r
-           &lt;delete global_required="true" permission="DELETE_MARC_CODE"&gt;\r
-       &lt;/actions&gt;\r
-    &lt;/permacrud&gt;\r
-&lt;/class&gt;\r
-</programlisting>\r
-                       <calloutlist>\r
-                       <callout arearefs="dmCO5-1">\r
-                       <simpara>\r
-                       The <literal>class</literal> element defines the attributes and permissions for classes,\r
-                       and relationships between classes.\r
-                       </simpara>\r
-                       <indexterm><primary>Evergreen Interface Definition Language (IDL)</primary><secondary>class element</secondary></indexterm>\r
-                       <itemizedlist>\r
-                       <listitem>\r
-                       <simpara>\r
-                       The <literal>id</literal> attribute on the <literal>class</literal> element defines the class hint that is\r
-                       used everywhere in Evergreen.\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <simpara>\r
-                       The <literal>controller</literal> attribute defines the OpenSRF\r
-                       services that provide access to the data for the class objects.\r
-                       </simpara>\r
-                       </listitem>\r
-                       </itemizedlist>\r
-                       </callout>\r
-                       <callout arearefs="dmCO5-2">\r
-                       <simpara>\r
-                       The <literal>oils_obj::fieldmapper</literal> attribute defines the name of the class that\r
-                       is generated by <literal>OpenILS::Utils::Fieldmapper</literal>.\r
-                       </simpara>\r
-                       </callout>\r
-                       <callout arearefs="dmCO5-3">\r
-                       <simpara>\r
-                       The <literal>oils_persist:tablename</literal> attribute defines the name of the table\r
-                       that contains the data for the class objects.\r
-                       </simpara>\r
-                       </callout>\r
-                       <callout arearefs="dmCO5-4">\r
-                       <simpara>\r
-                       The reporter interface uses <literal>reporter:label</literal> attribute values in\r
-                       the source list to provide meaningful class and attribute names. The\r
-                       <literal>open-ils.fielder</literal> service generates a set of methods that provide direct\r
-                       access to the classes for which <literal>oils_persist:field_safe</literal> is <literal>true</literal>. For\r
-                       example,\r
-                       </simpara>\r
-<screen>\r
-<userinput>\r
-srfsh# request open-ils.fielder open-ils.fielder.clm.atomic \\r
-{"query":{"code":{"=":"eng"}}}\r
-\r
-Received Data: [\r
-       {\r
-       "value":"English",\r
-       "code":"eng"\r
-       }\r
-]\r
-</userinput>\r
-</screen>\r
-                       </callout>\r
-                       <callout arearefs="dmCO5-5">\r
-                       <simpara>\r
-                       The <literal>fields</literal> element defines the list of fields for the class.\r
-                       </simpara>\r
-                       <indexterm><primary>Evergreen Interface Definition Language (IDL)</primary><secondary>fields element</secondary></indexterm>\r
-                       <itemizedlist>\r
-                       <listitem>\r
-                       <simpara>\r
-                       The <literal>oils_persist:primary</literal> attribute defines the column that acts as\r
-                       the primary key for the table.\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <simpara>\r
-                       The <literal>oils_persist:sequence</literal> attribute holds the name of the database\r
-                       sequence.\r
-                       </simpara>\r
-                       </listitem>\r
-                       </itemizedlist>\r
-                       </callout>\r
-                       <callout arearefs="dmCO5-6">\r
-                       <simpara>\r
-                       Each <literal>field</literal> element defines one property of the class.\r
-                       </simpara>\r
-                       <indexterm><primary>Evergreen Interface Definition Language (IDL)</primary><secondary>field element</secondary></indexterm>\r
-                       <itemizedlist>\r
-                       <listitem>\r
-                       <simpara>\r
-                       The <literal>name</literal> attribute defines the getter/setter method name for the field.\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <simpara>\r
-                       The <literal>reporter:label</literal> attribute defines the attribute name as used in\r
-                       the reporter interface.\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <simpara>\r
-                       The <literal>reporter:selector</literal> attribute defines the field used in the reporter\r
-                       filter interface to provide a selectable list. This gives the user a more\r
-                       meaningful access point than the raw numeric ID or abstract code.\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <simpara>\r
-                       The <literal>reporter:datatype</literal> attribute defines the type of data held by\r
-                       this property for the purposes of the reporter.\r
-                       </simpara>\r
-                       </listitem>\r
-                       </itemizedlist>\r
-                       </callout>\r
-                       <callout arearefs="dmCO5-7">\r
-                       <simpara>\r
-                       The <literal>oils_persist:i18n</literal> attribute, when <literal>true</literal>, means that\r
-                       translated values for the field&#8217;s contents may be accessible in\r
-                       different locales.\r
-                       </simpara>\r
-                       </callout>\r
-                       <callout arearefs="dmCO5-8">\r
-                       <simpara>\r
-                       <indexterm><primary>Evergreen Interface Definition Language (IDL)</primary><secondary>permacrud element</secondary></indexterm>\r
-                       The <literal>permacrud</literal> element defines the permissions (if any) required\r
-                       to <emphasis role="strong">c</emphasis>reate, <emphasis role="strong">r</emphasis>etrieve, <emphasis role="strong">u</emphasis>pdate, \r
-                       and <emphasis role="strong">d</emphasis>elete data for this\r
-                       class. <literal>open-ils.permacrud</literal> must be defined as a controller for the class\r
-                       for the permissions to be applied.\r
-                       </simpara>\r
-                       \r
-                       </callout>\r
-                       <callout arearefs="dmCO5-9">\r
-                       <simpara>\r
-                       Each action requires one or more <literal>permission</literal> values that the\r
-                       user must possess to perform the action.\r
-                       </simpara>\r
-                       <itemizedlist>\r
-                       <listitem>\r
-                       <simpara>\r
-                       If the <literal>global_required</literal> attribute is <literal>true</literal>, then the user must\r
-                       have been granted that permission globally (depth = 0) to perform\r
-                       the action.\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <simpara>\r
-                       The <literal>context_field</literal> attribute denotes the <literal>&lt;field&gt;</literal> that identifies\r
-                       the org_unit at which the user must have the pertinent permission.\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <indexterm><primary>Evergreen Interface Definition Language (IDL)</primary><secondary>action element</secondary></indexterm>\r
-                       <simpara>\r
-                       An action element may contain a <literal>&lt;context_field&gt;</literal> element that\r
-                       defines the linked class (identified by the <literal>link</literal> attribute) and\r
-                       the field in the linked class that identifies the org_unit where\r
-                       the permission must be held.\r
-                       </simpara>\r
-                       <itemizedlist>\r
-                       <listitem>\r
-                       <indexterm><primary>Evergreen Interface Definition Language (IDL)</primary><secondary>context_field element</secondary></indexterm>\r
-                       <simpara>\r
-                       If the <literal>&lt;context_field&gt;</literal> element contains a <literal>jump</literal> attribute,\r
-                       then it defines a link to a link to a class with a field identifying\r
-                       the org_unit where the permission must be held.\r
-                       </simpara>\r
-                       </listitem>\r
-                       </itemizedlist>\r
-                       </listitem>\r
-                       </itemizedlist>\r
-                       </callout>\r
-                       </calloutlist>\r
-               </simplesect>\r
-               <simplesect id="_reporter_data_types_and_their_possible_values">\r
-                       <title>Reporter data types and their possible values</title>\r
-                       <itemizedlist>\r
-                       <listitem>\r
-                       <simpara>\r
-                       <literal>bool</literal>: Boolean <literal>true</literal> or <literal>false</literal>\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <simpara>\r
-                       <literal>id</literal>: ID of the row in the database\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <simpara>\r
-                       <literal>int</literal>: integer value\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <simpara>\r
-                       <literal>interval</literal>: PostgreSQL time interval\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <simpara>\r
-                       <literal>link</literal>: link to another class, as defined in the <literal>&lt;links&gt;</literal>\r
-                       element of the class definition\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <simpara>\r
-                       <literal>money</literal>: currency amount\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <simpara>\r
-                       <literal>org_unit</literal>: list of org_units\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <simpara>\r
-                       <literal>text</literal>: text value\r
-                       </simpara>\r
-                       </listitem>\r
-                       <listitem>\r
-                       <simpara>\r
-                       <literal>timestamp</literal>: PostgreSQL timestamp\r
-                       </simpara>\r
-                       </listitem>\r
-                       </itemizedlist>\r
-               </simplesect>\r
-               <simplesect id="_idl_example_with_linked_fields_actor_workstation">\r
-                       <title>IDL example with linked fields (actor.workstation)</title>\r
-                       <simpara>Just as tables often include columns with foreign keys that point\r
-                       to values stored in the column of a different table, IDL classes\r
-                       can contain fields that link to fields in other classes. The <literal>&lt;links&gt;</literal>\r
-                       element defines which fields link to fields in other classes, and\r
-                       the nature of the relationship:</simpara>\r
-<programlisting language="xml" linenumbering="unnumbered">\r
-&lt;class id="aws" controller="open-ils.cstore"\r
-       oils_obj:fieldmapper="actor::workstation"\r
-       oils_persist:tablename="actor.workstation"\r
-       reporter:label="Workstation"&gt;\r
-    &lt;fields oils_persist:primary="id"\r
-           oils_persist:sequence="actor.workstation_id_seq"&gt;\r
-       &lt;field reporter:label="Workstation ID" name="id"\r
-               reporter:datatype="id"/&gt;\r
-       &lt;field reporter:label="Workstation Name" name="name"\r
-               reporter:datatype="text"/&gt;\r
-       &lt;field reporter:label="Owning Library" name="owning_lib"\r
-               reporter:datatype="org_unit"/&gt;\r
-       &lt;field reporter:label="Circulations" name="circulations"\r
-               oils_persist:virtual="true" reporter:datatype="link"/&gt; <co id="dmCO6-1"/>\r
-    &lt;/fields&gt;\r
-    &lt;links&gt;  <co id="dmCO6-2"/>\r
-       &lt;link field="owning_lib" reltype="has_a" key="id"\r
-               map="" class="aou"/&gt;  <co id="dmCO6-3"/>\r
-       &lt;link field="circulations" reltype="has_many" key="workstation"\r
-               map="" class="circ"/&gt;\r
-       &lt;link field="circulation_checkins" reltype="has_many"\r
-               key="checkin_workstation" map="" class="circ"/&gt;\r
-    &lt;/links&gt;\r
-&lt;/class&gt;\r
-</programlisting>\r
-                       <calloutlist>\r
-                       <callout arearefs="dmCO6-1">\r
-                       <simpara>\r
-                       This field includes an <literal>oils_persist:virtual</literal> attribute with the value of\r
-                       <literal>true</literal>, meaning that the linked class <literal>circ</literal> is a virtual class.\r
-                       </simpara>\r
-                       </callout>\r
-                       <callout arearefs="dmCO6-2">\r
-                       <simpara>\r
-                       The <literal>&lt;links&gt;</literal> element contains 0 or more <literal>&lt;link&gt;</literal> elements.\r
-                       </simpara>\r
-                       </callout>\r
-                       <callout arearefs="dmCO6-3">\r
-                       <simpara>\r
-                       Each <literal>&lt;link&gt;</literal> element defines the field (<literal>field</literal>) that links to a different\r
-                       class (<literal>class</literal>), the relationship (<literal>rel_type</literal>) between this field and the target\r
-                       field (<literal>key</literal>). If the field in this class links to a virtual class, the (<literal>map</literal>)\r
-                       attribute defines the field in the target class that returns a list of matching\r
-                       objects for each object in this class.\r
-                       </simpara>\r
-                       </callout>\r
-                       </calloutlist>\r
-               </simplesect>\r
-       </section>\r
-       <section id="open_ils_cstore_literal_data_access_interfaces">\r
-               <title><literal>open-ils.cstore</literal> data access interfaces</title>\r
-               <indexterm><primary>cstore</primary></indexterm>\r
-               <simpara>For each class documented in the IDL, the <literal>open-ils.cstore</literal> service\r
-               automatically generates a set of data access methods, based on the\r
-               <literal>oils_persist:tablename</literal> class attribute.</simpara>\r
-               <simpara>For example, for the class hint <literal>clm</literal>, cstore generates the following\r
-               methods with the <literal>config.language_map</literal> qualifer:</simpara>\r
-               <itemizedlist>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.cstore.direct.config.language_map.id_list {"code" { "like": "e%" } }</literal>\r
-               </simpara>\r
-               <simpara>Retrieves a list composed only of the IDs that match the query.</simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.cstore.direct.config.language_map.retrieve "eng"</literal>\r
-               </simpara>\r
-               <simpara>Retrieves the object that matches a specific ID.</simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.cstore.direct.config.language_map.search {"code" : "eng"}</literal>\r
-               </simpara>\r
-               <simpara>Retrieves a list of objects that match the query.</simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.cstore.direct.config.language_map.create &lt;_object_&gt;</literal>\r
-               </simpara>\r
-               <simpara>Creates a new object from the passed in object.</simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.cstore.direct.config.language_map.update &lt;_object_&gt;</literal>\r
-               </simpara>\r
-               <simpara>Updates the object that has been passed in.</simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.cstore.direct.config.language_map.delete "eng"</literal>\r
-               </simpara>\r
-               <simpara>Deletes the object that matches the query.</simpara>\r
-               </listitem>\r
-               </itemizedlist>\r
-       </section>\r
-       <section id="_open_ils_pcrud_data_access_interfaces">\r
-               <title>open-ils.pcrud data access interfaces</title>\r
-               <indexterm><primary>pcrud</primary></indexterm>\r
-               <simpara>For each class documented in the IDL, the <literal>open-ils.pcrud</literal> service\r
-               automatically generates a set of data access methods, based on the\r
-               <literal>oils_persist:tablename</literal> class attribute.</simpara>\r
-               <simpara>For example, for the class hint <literal>clm</literal>, <literal>open-ils.pcrud</literal> generates the following\r
-               methods that parallel the <literal>open-ils.cstore</literal> interface:</simpara>\r
-               <itemizedlist>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.pcrud.id_list.clm &lt;_authtoken_&gt;, { "code": { "like": "e%" } }</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.pcrud.retrieve.clm &lt;_authtoken_&gt;, "eng"</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.pcrud.search.clm &lt;_authtoken_&gt;, { "code": "eng" }</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.pcrud.create.clm &lt;_authtoken_&gt;, &lt;_object_&gt;</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.pcrud.update.clm &lt;_authtoken_&gt;, &lt;_object_&gt;</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.pcrud.delete.clm &lt;_authtoken_&gt;, "eng"</literal>\r
-               </simpara>\r
-               </listitem>\r
-               </itemizedlist>\r
-       </section>\r
-       <section id="_transaction_and_savepoint_control">\r
-               <title>Transaction and savepoint control</title>\r
-               <simpara>Both <literal>open-ils.cstore</literal> and <literal>open-ils.pcrud</literal> enable you to control database transactions\r
-               to ensure that a set of operations either all succeed, or all fail,\r
-               atomically:</simpara>\r
-               <itemizedlist>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.cstore.transaction.begin</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.cstore.transaction.commit</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.cstore.transaction.rollback</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.pcrud.transaction.begin</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.pcrud.transaction.commit</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.pcrud.transaction.rollback</literal>\r
-               </simpara>\r
-               </listitem>\r
-               </itemizedlist>\r
-               <simpara>At a more granular level, <literal>open-ils.cstore</literal> and <literal>open-ils.pcrud</literal> enable you to set database\r
-               savepoints to ensure that a set of operations either all succeed, or all\r
-               fail, atomically, within a given transaction:</simpara>\r
-               <itemizedlist>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.cstore.savepoint.begin</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.cstore.savepoint.commit</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.cstore.savepoint.rollback</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.pcrud.savepoint.begin</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.pcrud.savepoint.commit</literal>\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               <literal>open-ils.pcrud.savepoint.rollback</literal>\r
-               </simpara>\r
-               </listitem>\r
-               </itemizedlist>\r
-               <simpara>Transactions and savepoints must be performed within a stateful\r
-               connection to the <literal>open-ils.cstore</literal> and <literal>open-ils.pcrud</literal> services.\r
-               In <literal>srfsh</literal>, you can open a stateful connection using the <literal>open</literal>\r
-               command, and then close the stateful connection using the <literal>close</literal>\r
-               command - for example:</simpara>\r
-               <screen>srfsh# open open-ils.cstore\r
-               ... perform various transaction-related work\r
-               srfsh# close open-ils.cstore</screen>\r
-               <simplesect id="_json_queries">\r
-                       <title>JSON Queries</title>\r
-                       <indexterm><primary>JSON</primary></indexterm>\r
-                       <simpara>Beyond simply retrieving objects by their ID using the <literal>\*.retrieve</literal>\r
-                       methods, you can issue queries against the <literal>\*.delete</literal> and <literal>\*.search</literal>\r
-                       methods using JSON to filter results with simple or complex search\r
-                       conditions.</simpara>\r
-                       <simpara>For example, to generate a list of barcodes that are held in a\r
-                       copy location that allows holds and is visible in the OPAC:</simpara>\r
-<programlisting language="sh" linenumbering="unnumbered">\r
-srfsh# request open-ils.cstore open-ils.cstore.json_query  <co id="dmCO7-1"/>\r
-    {"select": {"acp":["barcode"], "acpl":["name"]}, <co id="dmCO7-2"/>\r
-     "from":   {"acp":"acpl"},   <co id="dmCO7-3"/>\r
-     "where":  [     <co id="dmCO7-4"/>\r
-        {"+acpl": "holdable"},   <co id="dmCO7-5"/>\r
-        {"+acpl": "opac_visible"}     <co id="dmCO7-6"/>\r
-     ]}\r
-\r
-Received Data: {\r
-  "barcode":"BARCODE1",\r
-  "name":"Stacks"\r
-}\r
-\r
-Received Data: {\r
-  "barcode":"BARCODE2",\r
-  "name":"Stacks"\r
-}\r
-</programlisting>\r
-                       <calloutlist>\r
-                       <callout arearefs="dmCO7-1">\r
-                       <simpara>\r
-                       Invoke the <literal>json_query</literal> service.\r
-                       </simpara>\r
-                       </callout>\r
-                       <callout arearefs="dmCO7-2">\r
-                       <simpara>\r
-                       Select the <literal>barcode</literal> field from the <literal>acp</literal> class and the <literal>name</literal>\r
-                       field from the <literal>acpl</literal> class.\r
-                       </simpara>\r
-                       </callout>\r
-                       <callout arearefs="dmCO7-3">\r
-                       <simpara>\r
-                       Join the <literal>acp</literal> class to the <literal>acpl</literal> class based on the linked field\r
-                       defined in the IDL.\r
-                       </simpara>\r
-                       </callout>\r
-                       <callout arearefs="dmCO7-4">\r
-                       <simpara>\r
-                       Add a <literal>where</literal> clause to filter the results. We have more than one\r
-                       condition beginning with the same key, so we wrap the conditions inside\r
-                       an array.\r
-                       </simpara>\r
-                       </callout>\r
-                       <callout arearefs="dmCO7-5">\r
-                       <simpara>\r
-                       The first condition tests whether the boolean value of the <literal>holdable</literal>\r
-                       field on the <literal>acpl</literal> class is true.\r
-                       </simpara>\r
-                       </callout>\r
-                       <callout arearefs="dmCO7-6">\r
-                       <simpara>\r
-                       The second condition tests whether the boolean value of the\r
-                       <literal>opac_visible</literal> field on the <literal>acpl</literal> class is true.\r
-                       </simpara>\r
-                       </callout>\r
-                       </calloutlist>\r
-                       <simpara>For thorough coverage of the breadth of support offered by JSON\r
-                       query syntax, see <ulink url="http://open-ils.org/dokuwiki/doku.php?id=documentation:technical:jsontutorial">JSON Queries: A Tutorial</ulink>.</simpara>\r
-               </simplesect>\r
-               <simplesect id="_fleshing_linked_objects">\r
-                       <title>Fleshing linked objects</title>\r
-                       <simpara>A simplistic approach to retrieving a set of objects that are linked to\r
-                       an object that you are retrieving - for example, a set of call numbers\r
-                       linked to the barcodes that a given user has borrowed - would be to:\r
-                         1. Retrieve the list of circulation objects (<literal>circ</literal> class)\r
-                       for a given user (<literal>usr</literal> class).\r
-                         2. For each circulation object, look up the target copy (<literal>target_copy</literal>\r
-                       field, linked to the <literal>acp</literal> class).\r
-                         3. For each copy, look up the call number for that copy (<literal>call_number</literal>\r
-                       field, linked to the <literal>acn</literal> class).</simpara>\r
-                       <simpara>However, this would result in potentially hundreds of round-trip\r
-                       queries from the client to the server. Even with low-latency connections,\r
-                       the network overhead would be considerable. So, built into the <literal>open-ils.cstore</literal> and\r
-                       <literal>open-ils.pcrud</literal> access methods is the ability to <emphasis>flesh</emphasis> linked fields -\r
-                       that is, rather than return an identifier to a given linked field,\r
-                       the method can return the entire object as part of the initial response.</simpara>\r
-                       <simpara>Most of the interfaces that return class instances from the IDL offer the\r
-                       ability to flesh returned fields. For example, the\r
-                       <literal>open-ils.cstore.direct.\*.retrieve</literal> methods allow you to specify a\r
-                       JSON structure defining the fields you wish to flesh in the returned object.</simpara>\r
-                       <formalpara><title>Fleshing fields in objects returned by <literal>open-ils.cstore</literal></title><para>\r
-<programlisting language="sh" linenumbering="unnumbered">\r
-srfsh# request open-ils.cstore open-ils.cstore.direct.asset.copy.retrieve 1, \\r
-    {\r
-       "flesh": 1,    <co id="dmCO8-1"/>\r
-       "flesh_fields": {   <co id="dmCO8-2"/>\r
-           "acp": ["location"]\r
-       }\r
-    }\r
-</programlisting>\r
-                       </para></formalpara>\r
-                       <calloutlist>\r
-                       <callout arearefs="dmCO8-1">\r
-                       <simpara>\r
-                       The <literal>flesh</literal> argument is the depth at which objects should be fleshed.\r
-                       For example, to flesh out a field that links to another object that includes\r
-                       a field that links to another object, you would specify a depth of 2.\r
-                       </simpara>\r
-                       </callout>\r
-                       <callout arearefs="dmCO8-2">\r
-                       <simpara>\r
-                       The <literal>flesh_fields</literal> argument contains a list of objects with the fields\r
-                       to flesh for each object.\r
-                       </simpara>\r
-                       </callout>\r
-                       </calloutlist>\r
-                       <simpara>Let&#8217;s flesh things a little deeper. In addition to the copy location,\r
-                       let&#8217;s also flesh the call number attached to the copy, and then flesh\r
-                       the bibliographic record attached to the call number.</simpara>\r
-                       <formalpara><title>Fleshing fields in fields of objects returned by <literal>open-ils.cstore</literal></title><para>\r
-<programlisting language="java" linenumbering="unnumbered">\r
-request open-ils.cstore open-ils.cstore.direct.asset.copy.retrieve 1, \\r
-    {\r
-       "flesh": 2,\r
-       "flesh_fields": {\r
-           "acp": ["location", "call_number"],\r
-           "acn": ["record"]\r
-        }\r
-    }\r
-</programlisting>\r
-                       </para></formalpara>\r
-               </simplesect>\r
-       </section>\r
-       <section id="_adding_an_idl_entry_for_resolverresolver">\r
-               <title>Adding an IDL entry for ResolverResolver</title>\r
-               <simpara>Most OpenSRF methods in Evergreen define their object interface in the\r
-               IDL. Without an entry in the IDL, the prospective caller of a given\r
-               method is forced to either call the method and inspect the returned\r
-               contents, or read the source to work out the structure of the JSON\r
-               payload. At this stage of the tutorial, we have not defined an entry\r
-               in the IDL to represent the object returned by the\r
-               <literal>open-ils.resolver.resolve_holdings</literal> method. It is time to complete\r
-               that task.</simpara>\r
-               <simpara>The <literal>open-ils.resolver</literal> service is unlike many of the other classes\r
-               defined in the IDL because its data is not stored in the Evergreen\r
-               database. Instead, the data is requested from an external Web service\r
-               and only temporarily cached in <literal>memcached</literal>. Fortunately, the IDL\r
-               enables us to represent this kind of class by setting the\r
-               <literal>oils_persist:virtual</literal> class attribute to <literal>true</literal>.</simpara>\r
-               <simpara>So, let&#8217;s add an entry to the IDL for the <literal>open-ils.resolver.resolve_holdings</literal>\r
-               service:</simpara>\r
-               <programlisting language="xml" linenumbering="unnumbered"></programlisting>\r
-               <simpara>And let&#8217;s make <literal>ResolverResolver.pm</literal> return an array composed of our new\r
-               <literal>rhr</literal> classes rather than raw JSON objects:</simpara>\r
-               <programlisting language="perl" linenumbering="unnumbered"></programlisting>\r
-               <simpara>Once we add the new entry to the IDL and copy the revised <literal>ResolverResolver.pm</literal>\r
-               Perl module to <literal>/openils/lib/perl5/OpenILS/Application/</literal>, we need to:</simpara>\r
-               <orderedlist numeration="arabic">\r
-               <listitem>\r
-               <simpara>\r
-               Copy the updated IDL to both the <literal>/openils/conf/</literal> and\r
-               <literal>/openils/var/web/reports/</literal> directories. The Dojo approach to\r
-               parsing the IDL uses the IDL stored in the reports directory.\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               Restart the Perl services to make the new IDL visible to the services\r
-               and refresh the <literal>open-ils.resolver</literal> implementation\r
-               </simpara>\r
-               </listitem>\r
-               <listitem>\r
-               <simpara>\r
-               Rerun <filename>/openils/bin/autogen.sh</filename> to regenerate the JavaScript versions<indexterm><primary>autogen</primary></indexterm>\r
-               of the IDL required by the HTTP translator and gateway.\r
-               </simpara>\r
-               </listitem>\r
-               </orderedlist>\r
-               <simpara>We also need to adjust our JavaScript client to use the nifty new<indexterm><primary>JavaScript</primary></indexterm>\r
-               objects that <literal>open-ils.resolver.resolve_holdings</literal> now returns.\r
-               The best approach is to use the support in Evergreen&#8217;s Dojo extensions<indexterm><primary>Dojo toolkit</primary></indexterm>\r
-               to generate the JavaScript classes directly from the IDL XML file.</simpara>\r
-               <formalpara><title>Accessing classes defined in the IDL via Fieldmapper</title><para>\r
-               <programlisting language="html" linenumbering="unnumbered"></programlisting>\r
-               </para></formalpara>\r
-               <calloutlist>\r
-               <callout arearefs="">\r
-               <simpara>\r
-               Load the Dojo core.\r
-               </simpara>\r
-               </callout>\r
-               <callout arearefs="">\r
-               <simpara>\r
-               <literal>fieldmapper.AutoIDL</literal> reads <filename>/openils/var/reports/fm_IDL.xml</filename> to\r
-               generate a list of class properties.\r
-               </simpara>\r
-               </callout>\r
-               <callout arearefs="">\r
-               <simpara>\r
-               <literal>fieldmapper.dojoData</literal> seems to provide a store for Evergreen data\r
-               accessed via Dojo.\r
-               </simpara>\r
-               </callout>\r
-               <callout arearefs="">\r
-               <simpara>\r
-               <literal>fieldmapper.Fieldmapper</literal> converts the list of class properties into\r
-               actual classes.\r
-               </simpara>\r
-               </callout>\r
-               <callout arearefs="">\r
-               <simpara>\r
-               <literal>fieldmapper.standardRequest</literal> invokes an OpenSRF method and returns\r
-               an array of objects.\r
-               </simpara>\r
-               </callout>\r
-               <callout arearefs="">\r
-               <simpara>\r
-               The first argument to <literal>fieldmapper.standardRequest</literal> is an array\r
-               containing the OpenSRF service name and method name.\r
-               </simpara>\r
-               </callout>\r
-               <callout arearefs="">\r
-               <simpara>\r
-               The second argument to <literal>fieldmapper.standardRequest</literal> is an array\r
-               containing the arguments to pass to the OpenSRF method.\r
-               </simpara>\r
-               </callout>\r
-               <callout arearefs="">\r
-               <simpara>\r
-               As Fieldmapper has instantiated the returned objects based on their\r
-               class hints, we can invoke getter/setter methods on the objects.\r
-               </simpara>\r
-               </callout>\r
-               </calloutlist>\r
-       </section>\r
-       \r
-</chapter>\r