<?xml version="1.0" encoding="UTF-8"?>
<!--
  ! CCPL HEADER START
  !
  ! This work is licensed under the Creative Commons
  ! Attribution-NonCommercial-NoDerivs 3.0 Unported License.
  ! To view a copy of this license, visit
  ! http://creativecommons.org/licenses/by-nc-nd/3.0/
  ! or send a letter to Creative Commons, 444 Castro Street,
  ! Suite 900, Mountain View, California, 94041, USA.
  !
  ! You can also obtain a copy of the license at
  ! legal/CC-BY-NC-ND.txt.
  ! See the License for the specific language governing permissions
  ! and limitations under the License.
  !
  ! If applicable, add the following below this CCPL HEADER, with the fields
  ! enclosed by brackets "[]" replaced with your own identifying information:
  !      Portions Copyright [yyyy] [name of copyright owner]
  !
  ! CCPL HEADER END
  !
  !      Copyright 2012 ForgeRock AS
  !    
-->
<appendix xml:id="appendix-router"
 version="5.0"
 xml:lang="en"
 xmlns="http://docbook.org/ns/docbook"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd"
 xmlns:xlink="http://www.w3.org/1999/xlink"
 xmlns:xinclude="http://www.w3.org/2001/XInclude">
 <title>Router Service Reference</title>
  <indexterm>
   <primary>Router service</primary>
  </indexterm>

  <para>The OpenIDM router service provides the uniform interface to all
  objects in OpenIDM: managed objects, system objects, configuration
  objects, and so on.</para>

 <section xml:id="router-configuration">
  <title>Configuration</title>

  <para>The router object as shown in <filename>conf/router.json</filename>
  defines an array of filter objects.</para>
 
  <programlisting language="javascript">
{
  "filters": [ <replaceable>filter object</replaceable>, ... ]
}</programlisting>

  <para>The required filters array defines a list of filters to be processed
  on each router request. Filters are processed in the order they are
  specified in this array.</para>

  <section xml:id="filter-object">
   <title>Filter Objects</title>
   <para>Filter objects are defined as follows.</para>

   <programlisting language="javascript">
{
  "pattern": <replaceable>string</replaceable>,
  "methods": [ <replaceable>string</replaceable>, ... ],
  "condition": <replaceable>script object</replaceable>,
  "onRequest": <replaceable>script object</replaceable>,
  "onResponse": <replaceable>script object</replaceable>,
  "onFailure": <replaceable>script object</replaceable>
}</programlisting>

   <variablelist>
    <varlistentry>
     <term>"pattern"</term>
     <listitem>
      <para>string, optional</para>
      <para>Specifies a regular expression pattern matching the JSON pointer of
      the object to trigger scripts. If not specified, all identifiers
      (including <literal>null</literal>) match.</para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term>"methods"</term>
     <listitem>
      <para>array of strings, optional</para>
      <para>One or more methods for which the script(s) should be triggered.
      Supported methods are: <literal>"create"</literal>,
      <literal>"read"</literal>, <literal>"update"</literal>,
      <literal>"delete"</literal>, <literal>"patch"</literal>,
      <literal>"query"</literal>, <literal>"action"</literal>. If not specified,
      then all methods are matched.</para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term>"condition"</term>
     <listitem>
      <para>script object, optional</para>
      <para>Specifies a script that is called first to determine if the script
      should be triggered. If the condition yields <literal>"true"</literal>,
      then the other script(s) are executed. If not specified, the script(s)
      are called unconditionally.</para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term>"onRequest"</term>
     <listitem>
      <para>script object, optional</para>
      <para>Specifies a script to execute before the request is dispatched to
      the resource. If the script throws an exception, the method is is not
      performed, and a client error response is provided.</para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term>"onResponse"</term>
     <listitem>
      <para>script object, optional</para>
      <para>Specifies a script to execute after the request is successfully
      dispatched to the resource and a response is returned. Throwing an
      exception from this script does not undo the method already
      performed.</para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term>"onFailure"</term>
     <listitem>
      <para>script object, optional</para>
      <para>Specifies a script to execute if the request resulted in an
      exception being thrown. Throwing an exception from this script does not
      undo the method already performed.</para>
     </listitem>
    </varlistentry>
   </variablelist>
  </section>

  <section xml:id="filter-script-scope">
   <title>Script Scope</title>

   <para>Scripts are provided with the following scope.</para>

   <programlisting language="javascript">
{
  "openidm": openidm-functions object,
  "request": resource-request object,
  "response": resource-response object,
  "exception": exception object
}</programlisting>

   <variablelist>
    <varlistentry>
     <term>"openidm"</term>
     <listitem>
      <para><link xlink:href="integrators-guide#function-ref"
      xlink:role="http://docbook.org/xlink/role/olink">openidm-functions</link>
      object</para>
      <para>Provides access to OpenIDM resources.</para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term>"request"</term>
     <listitem>
      <!-- Link to the JSON resource content rather than document it separately
      in OpenIDM for now. -->
      <para><link xlink:show="new"
      xlink:href="https://wikis.forgerock.org/confluence/display/json/resource-request"
      >resource-request</link> object</para>
      <para>The resource-request context, which has one or more parent context.
      Provided in scope of <literal>"condition"</literal>,
      <literal>"onRequest"</literal>, <literal>"onResponse"</literal> and
      <literal>"onException"</literal> scripts.</para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term>"response"</term>
     <listitem>
      <para><link xlink:href="integrators-guide#function-ref"
      xlink:role="http://docbook.org/xlink/role/olink">openidm-functions</link>
      object</para>
      <para>The response to the resource-request. Only provided in the scope of
      the <literal>"onResponse"</literal> script.</para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term>"exception"</term>
     <listitem>
      <para>exception object</para>
      <para>The exception value that was thrown as a result of processing the
      request. Only provided in the scope of the
      <literal>"onException"</literal> script.</para>
     </listitem>
    </varlistentry>
   </variablelist>
   
   <para>An exception object is defined as follows.</para>

   <programlisting language="javascript">
{
  "error": integer,
  "reason": string,
  "detail": string
}</programlisting>

   <variablelist>
    <varlistentry>
     <term>"error"</term>
     <listitem>
      <para>integer</para>
      <para>The numeric code of the exception.</para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term>"reason"</term>
     <listitem>
      <para>string</para>
      <para>The short reason phrase of the exception.</para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term>"detail"</term>
     <listitem>
      <para>string</para>
      <para>The detailed message for the exception.</para>
     </listitem>
    </varlistentry>
   </variablelist>
  </section>
 </section>

 <section xml:id="router-example">
  <title>Example</title>

  <para>The following example executes a script after a managed user object is
  created or updated.</para>

  <programlisting language="javascript">
{
    "filters": [
        {
            "pattern": "^managed/user/.*",
            "methods": [
                "create",
                "update"
            ],
            "onResponse": {
                "type": "text/javascript",
                "file": "scripts/afterUpdateUser.js"
            }
        }
    ]
}</programlisting>
 </section>
</appendix>

