You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2010/12/09 22:50:49 UTC
svn commit: r1044138 [3/3] - in /openjpa/trunk/openjpa-jest: ./ src/
src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/
src/main/java/org/apache/openjpa/
src/main/java/org/apache/openjpa/persistence/
src/main/java/org/apache/openjpa/...
Propchange: openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/images/query2.png
------------------------------------------------------------------------------
svn:mime-type = image/png
Added: openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/images/underconstruction.jpg
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/images/underconstruction.jpg?rev=1044138&view=auto
==============================================================================
Binary file - no diff available.
Propchange: openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/images/underconstruction.jpg
------------------------------------------------------------------------------
svn:mime-type = image/jpeg
Added: openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest-instance.xsd
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest-instance.xsd?rev=1044138&view=auto
==============================================================================
--- openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest-instance.xsd (added)
+++ openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest-instance.xsd Thu Dec 9 21:50:47 2010
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
+ license agreements. See the NOTICE file distributed with this work for additional
+ information regarding copyright ownership. The ASF licenses this file to
+ you under the Apache License, Version 2.0 (the "License"); you may not use
+ this file except in compliance with the License. You may obtain a copy of
+ the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License. -->
+<!-- ========================================================================= -->
+<!-- Schema for serialized persistence instance. -->
+<!-- ========================================================================= -->
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ attributeFormDefault="unqualified" elementFormDefault="qualified"
+ version="1.0">
+
+ <xsd:annotation>
+ <xsd:documentation><![CDATA[
+ Describes closure of managed persistence instance.
+ Each instance is described by all its loaded persistent attribute.
+ The related instances are resolved within the document root.
+ Document root represents zero or more instances.
+
+ The file must be named "jest-instance.xsd".
+ ]]>
+ </xsd:documentation>
+ </xsd:annotation>
+
+ <!-- The root element of the document contains zero or more instances -->
+ <xsd:element name="instances">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="uri" minOccurs="1" maxOccurs="1" type="xsd:anyURI"/>
+ <xsd:element name="description" minOccurs="0" maxOccurs="1" type="xsd:string"/>
+ <xsd:element name="instance" minOccurs="0" maxOccurs="unbounded" type="instance-type" />
+ </xsd:sequence>
+ <xsd:attribute name="version" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- The root element for a single instance. Children of this element are persistent attribute -->
+ <!-- Persistent Attributes occur in order. The order is determined by the attribute category. -->
+ <!-- Attribute category is determined by the enumerated PersistentAttributeType defined in -->
+ <!-- javax.persistence.metamodel and then further refined by id, version, lob and enum. -->
+ <!-- See org.apache.openjpa.persistence.jest.MetamodelHelper for further details. -->
+ <xsd:complexType name="instance-type">
+ <xsd:sequence>
+ <xsd:element name="id" type="basic-attr-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="version" type="basic-attr-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="basic" type="basic-attr-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="enum" type="basic-attr-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="embedded" type="instance-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="lob" type="lob-attr-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="one-to-one" type="singular-attr-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="many-to-one" type="singular-attr-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="element-collection" type="collection-attr-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="one-to-many" type="collection-attr-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xsd:element name="many-to-many" type="map-attr-type" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+ <xsd:attribute name="id" type="xsd:ID" use="required" />
+ </xsd:complexType>
+
+ <!-- A reference to another instance within the same(?) document -->
+ <xsd:complexType name="ref-type">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="id" type="xsd:IDREF" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <!-- A null reference -->
+ <xsd:complexType name="ref-null">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <!-- Basic Attribute has a name and its runtime type -->
+ <!-- non-null value appears as text content. -->
+ <!-- null value appears as attribute with empty text . -->
+ <xsd:complexType name="basic-attr-type">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ <xsd:attribute name="type" type="xsd:string" use="required" />
+ <xsd:attribute name="null" type="xsd:boolean" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <!-- Large Binary Objects (LOB) represented as hex array -->
+ <xsd:complexType name="lob-attr-type">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:hexBinary">
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ <xsd:attribute name="type" type="xsd:string" use="required" />
+ <xsd:attribute name="null" type="xsd:boolean" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <!-- Singular attribute is a reference to another instance or a null reference. -->
+ <xsd:complexType name="singular-attr-type">
+ <xsd:choice>
+ <xsd:element name="null" type="ref-null" />
+ <xsd:element name="ref" type="ref-type" />
+ </xsd:choice>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ <xsd:attribute name="type" type="xsd:string" use="required" />
+ </xsd:complexType>
+
+ <!-- Collection attributes list their members with their runtime type -->
+ <!-- Members can be basic or other managed instance -->
+ <xsd:complexType name="collection-attr-type">
+ <xsd:sequence>
+ <xsd:element name="member" type="member-type" minOccurs="0"
+ maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ <xsd:attribute name="type" type="xsd:string" use="required" />
+ <xsd:attribute name="member-type" type="xsd:string" use="required" />
+ </xsd:complexType>
+
+ <!-- Map attributes list their entries with runtime type of key and value -->
+ <!-- Both key and value can be independently basic or other managed instance -->
+ <xsd:complexType name="map-attr-type">
+ <xsd:sequence>
+ <xsd:element name="entry" type="entry-type" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ <xsd:attribute name="type" type="xsd:string" use="required" />
+ <xsd:attribute name="key-type" type="xsd:string" use="required" />
+ <xsd:attribute name="value-type" type="xsd:string" use="required" />
+ </xsd:complexType>
+
+ <!-- Value of a member of basic type. -->
+ <xsd:complexType name="basic-value-type">
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="null" type="xsd:boolean" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <!-- Value of a member of a collection/map -->
+ <xsd:complexType name="member-type">
+ <xsd:choice>
+ <xsd:element name="basic" type="basic-value-type" />
+ <xsd:element name="null" type="ref-null" />
+ <xsd:element name="ref" type="ref-type" />
+ </xsd:choice>
+ </xsd:complexType>
+
+ <!-- Denotes entry of a map element -->
+ <xsd:complexType name="entry-type">
+ <xsd:sequence>
+ <xsd:element name="key" type="member-type" minOccurs="1" maxOccurs="1" />
+ <xsd:element name="value" type="member-type" minOccurs="1" maxOccurs="1" />
+ </xsd:sequence>
+ </xsd:complexType>
+
+</xsd:schema>
Propchange: openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest-instance.xsd
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.css
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.css?rev=1044138&view=auto
==============================================================================
--- openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.css (added)
+++ openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.css Thu Dec 9 21:50:47 2010
@@ -0,0 +1,248 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/** -----------------------------------------------------------------------
+ * Basic layout consists of a left menu section (class='menu')and two
+ * vertical sections for command specification (class='highlight') and
+ * JEST response (class='canvas') respectively.
+ * --------------------------------------------------------------------- */
+
+/** -----------------------------------------------------------------------
+ * div section containing the command menu.
+ * Lodged on the top-left corner
+ * -------------------------------------------------------------------- */
+.menu {
+ position:absolute;
+ left:0em;
+ top:80px;
+ width:10em;
+}
+/** -----------------------------------------------------------------------
+ * Highlighted blocks appear relative to the menu. The same top position
+ * of the menu and shifted to left of the menu by the menu's width+padding.
+ * --------------------------------------------------------------------- */
+.highlight {
+ position:relative;
+ left:10em;
+ top:0em;
+// background-color:#F9F9F9;
+ width:60em;
+
+// border:1px solid black;
+// padding:0em 1em 1em 1em; // top, right, bottom, left
+
+}
+
+.logo {
+ font-size:2em;
+ font-weight:bold;
+ font-family: "Palatino Linotype, Times Roman"
+}
+
+/** -----------------------------------------------------------------------
+ * Canvas section appears relative to the menu and the highlighted section.
+ * The top position is relative to the highlighted section and left position
+ * is relative to the menu section.
+ * --------------------------------------------------------------------- */
+.canvas {
+ position:relative;
+ left:10em;
+ top:1em;
+ width:60em;
+ padding:0em 1em 0em 1em; // top, right, bottom, left
+}
+
+.help {
+ float:right;
+ text-align:right;
+ margin-right:0.1em;
+ margin-top: -0.1em;
+}
+/** -----------------------------------------------------------------------
+ * Visible/Invisible divisions
+ * --------------------------------------------------------------------- */
+.open {
+ display:block;
+}
+.close {
+ display:none;
+}
+
+/** -----------------------------------------------------------------------
+ * Hyperlinks
+ * --------------------------------------------------------------------- */
+.url {
+ color:blue;
+ font-size:1.1em;
+ font-family:"Courier New", Arial;
+ border:0px;
+ cursor:pointer;
+}
+
+.url-invalid {
+ color:red;
+ font-size:0.9em;
+ font-family:"Courier New", Arial;
+}
+
+
+
+/** -----------------------------------------------------------------------
+ * XML Tag
+ * --------------------------------------------------------------------- */
+pre, code {
+ background-color: white;
+}
+.tag {
+ color:green;
+ font-family:"Courier New";
+ font-weight:bold;
+ border:0px;
+}
+/** -----------------------------------------------------------------------
+ * Data Table used for Tabular HTML
+ * --------------------------------------------------------------------- */
+table.data td th {
+ width : 70%;
+ border-collapse:collapse;
+ border:2px solid black;
+ margin: 10px 10px 10px 10px;
+}
+tr {
+ vertical-align:top;
+}
+th {
+ background-color:#444444;
+ color:white;
+ text-align:left;
+}
+caption {
+ background-color:#000000;
+ color:white;
+ font-size:1.2em;
+ font-weight:bold;
+ padding:5px 5px 5px 5px;
+}
+/** -----------------------------------------------------------------------
+ * Alternate Table Row
+ * --------------------------------------------------------------------- */
+tr.even td {
+ background-color: #FFFFFF; color: black;
+ padding:2px 20px;
+ border:2px solid black;
+ vertical-align:top;
+}
+tr.odd td {
+ background-color: #EEEEEE; color: black;
+ padding:2px 20px;
+ border:2px solid black;
+ vertical-align:top;
+}
+td.mandatory {
+ font-weight:bold;
+ color:red;
+}
+
+td input {
+ width : 99%;
+}
+td select {
+ width : 99%;
+}
+
+/** -----------------------------------------------------------------------
+ * Paragraph with smaller line breaks
+ * --------------------------------------------------------------------- */
+p.small {
+ line-height:60%;
+}
+
+/** -----------------------------------------------------------------------
+ * Error Page
+ * --------------------------------------------------------------------- */
+.error-header {
+ color:red;
+ font-size:2em;
+ font-weight:bold;
+}
+.error-message {
+ color:red;
+ font-size:1.2em;
+}
+
+/*
+ * JPA styles
+*/
+.id {
+ color:red;
+ font-weight:bold;
+}
+.enum {
+ color:magenta;
+ font-weight:bold;
+}
+.basic {
+ color:green;
+ font-weight:bold;
+}
+.one-to-one {
+ color:lightblue;
+ font-weight:bold;
+}
+.one-to-many {
+ color:darkblue;
+ font-weight:bold;
+}
+
+.ref {
+ color : blue;
+}
+.null {
+ color : red;
+}
+
+.delimiter {
+ color:lightgray;
+ font-weight:bold;
+}
+.attr-name {
+ color:gray;
+}
+.attr-value {
+ color:green;
+}
+.node-value {
+ font-weight:bold;
+}
+.entity {
+ font-weight:bold;
+}
+.metamodel {
+ font-weight:bold;
+}
+
+.instances {
+ font-weight:bold;
+}
+.instance {
+ font-weight:bold;
+}
+
+
+
\ No newline at end of file
Propchange: openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.css
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.html
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.html?rev=1044138&view=auto
==============================================================================
--- openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.html (added)
+++ openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.html Thu Dec 9 21:50:47 2010
@@ -0,0 +1,329 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<!--
+ The single web page for JEST is a templated HTML. This page consists of three major divisions
+ a) a section holds the menu items for available commands
+ b) a section for the command window where user enters command specifications
+ c) a section displays the server response of the command execution
+
+ This templated file contains replaceable tokens in ${token} form. JEST servlet replaces the tokens with
+ actual deployment values on initialization.
+
+ The menu navigation and command window are managed by jest.js script.
+ The rendition of server response is managed by dojo script.
+
+ All hyperlinks in this page are relative to the base URI of this page to prevent
+ any cross-domain scripting.
+
+ -->
+<html>
+<head>
+<!-- ==================================================================================== -->
+<!-- Base URI is replaced with actual deployment data on initialization -->
+<!-- ==================================================================================== -->
+<base href="${jest.uri}">
+<!-- base href="http://localhost:8080/demo/jest/" -->
+<title>JEST: REST on OpenJPA</title>
+
+<link type="text/css" rel="stylesheet" href="${dojo.base}/dijit/themes/${dojo.theme}/${dojo.theme}.css">
+<!-- link type="text/css" rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/claro/claro.css" -->
+<link type="text/css" rel="stylesheet" href="jest.css">
+<script type="text/javascript" language="javascript" djConfig="parseOnLoad: true, isDebug: true"
+ src="${dojo.base}/dojo/dojo.xd.js">
+</script>
+<!-- script type="text/javascript" djConfig="parseOnLoad:true;isDebug=true" src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js"></script -->
+<script type="text/javascript" language="javascript" src="jest.js">
+</script>
+
+<meta content="REST,OpenJPA,JPA,JEST">
+</head>
+
+
+<body class=" ${dojo.theme} ">
+<!-- body class=" claro " -->
+<a name="top"></a>
+<img src="images/jest.jpg" width="63px" height="69px" alt="JEST logo" align="middle">
+<span class="logo">JEST: REST on OpenJPA</span>
+<hr>
+<!-- ==================================================================================== -->
+<!-- Section for menu based commands. -->
+<!-- -->
+<!-- Each menu opens a command window by making a menu section visible -->
+<!-- ==================================================================================== -->
+<div id="menu" class="menu">
+<table cellspacing="1em">
+ <tr><td><img alt="Home" src="images/home.jpg" width="100" height="100"></td></tr>
+ <tr><td style="text-align:center"><a href="javascript:openMenu('home');">Info</a></td></tr>
+ <tr><td><img alt="Domain" src="images/domain.jpg" width="100" height="100"></td></tr>
+ <tr><td style="text-align:center"><a href="javascript:openMenu('domain');">browse domain</a></td></tr>
+ <tr><td><img alt="Find" src="images/find.jpg" width="100" height="100"></td></tr>
+ <tr><td style="text-align:center"><a href="javascript:openMenu('find');">find instances</a></td></tr>
+ <tr><td><img alt="Query" src="images/query2.png" width="100" height="100"></td></tr>
+ <tr><td style="text-align:center"><a href="javascript:openMenu('query');">query objects</a></td></tr>
+ <tr><td><img alt="View" src="images/properties.jpg" width="100" height="100"></td></tr>
+ <tr><td style="text-align: center"><a href="javascript:openMenu('properties');">view properties</a></td></tr>
+ <tr><td><img alt="Deploy" src="images/monitor.jpg" width="100" height="100"></td></tr>
+ <tr><td style="text-align:center"><a href="javascript:openMenu('deploy');">deploy</a></td></tr>
+</table>
+</div>
+
+<!-- ==================================================================================== -->
+<!-- Section for each command specification -->
+<!-- -->
+<!-- Contains a set of div sub-sections each for a single command. A command window -->
+<!-- consists of a brief description of the command and set of input elements where user -->
+<!-- can enter command qualifiers and arguments. -->
+<!-- The URI for the command is updated as user entry changes. If the user clicks on the -->
+<!-- URI hyperlink, then a request with the URI is sent to the server. -->
+<!-- ==================================================================================== -->
+<!-- Introduces basic information about JEST -->
+<!-- ==================================================================================== -->
+<div id="home" class="highlight" dojoType="dijit.TitlePane"
+title="<a href='http://openjpa.apache.org/jest-usage.html' target='_blank'>JEST</a>
+ <b>facilitates RESTful interaction with OpenJPA</b>">
+
+
+<UL>
+<LI>Deployed as a HTTP servlet in <b>any</b> web or enterprise application module using
+OpenJPA as its JPA persistence provider.
+</LI>
+
+<LI>Completely <b>metadata-driven</b> and hence <b>generic</b> as opposed to specific to any
+application domain.
+</LI>
+
+<LI>Introduces a <b>URI syntax</b>. Interprets the HTTP request as a JPA resource based on
+that syntax. The response is in <tt>XML</tt> or <tt>JSON</tt> format. </LI>
+
+<LI>Representational state for persistent instances is <b>coherent</b>.
+The response always contains the <em>closure</em> of the persistent instances.
+</LI>
+
+<LI>Connects to the <b>persistent unit</b> of an application in the same module. Or
+ instantiates its own persistence unit.
+</LI>
+</UL>
+</div>
+
+<!-- ==================================================================================== -->
+<!-- Describes deployment details -->
+<!-- ==================================================================================== -->
+<div id="deploy" class="highlight" style="display:none;" dojoType="dijit.TitlePane"
+ title='<a href="http://openjpa.apache.org/jest-usage.html" target="_blank">Deploy JEST</a>
+ <b>as a servlet in a web application.</b>'>
+
+
+ Following <code>WEB-INF/web.xml</code> descriptor will enable JEST to
+ operate on a persistence unit named <code>${persistence.unit}</code>. Of course, JEST
+ servlet must be in the same module scope of the application that is using using
+ <code>${persistence.unit}</code> as its persistence unit.
+ <br>
+<pre>
+<code class="tag"><servlet></code>
+ <code class="tag"><servlet-name></code>${servlet.name}<code class="tag"></servlet-name></code>
+ <code class="tag"><servlet-class></code><span style="color:blue">org.apache.openjpa.persistence.jest.JESTServlet</span><code class="tag"></servlet-class></code>
+ <code class="tag"><init-param></code>
+ <code class="tag"><param-name></code><span style="color:red;">persistence.unit</span><code class="tag"></param-name></code>
+ <code class="tag"><param-value></code><span style="color:red">${persistence.unit}</span><code class="tag"></param-value></code>
+ <code class="tag"></init-param></code>
+<code class="tag"></servlet></code>
+<code class="tag"><servlet-mapping></code>
+ <code class="tag"><servlet-name></code>${servlet.name}<code class="tag"></servlet-name></code>
+ <code class="tag"><url-pattern></code><span style="color:red">/${servlet.name}/*</span><code class="tag"></url-pattern></code>
+<code class="tag"></servlet-mapping></code>
+
+</pre>
+ When an web application module named <code>${webapp.name}</code> containing the above JEST servlet
+ in a servlet container runs on <code>${server.name}</code> at port ${server.port}, then the JEST servlet
+ can be accessed at <br>
+ <code class="url">http://${server.name}:${server.port}/${webapp.name}/${servlet.name}/</code>
+ <br>
+ (<span style="color:red">do not miss the the trailing forward-slash / character</span>)
+ <p>
+</div>
+
+<!-- ==================================================================================== -->
+<!-- Command window for find -->
+<!-- -->
+<!-- The div element contains a table and some of the table columns hold the input -->
+<!-- elements. The div, table and input elements are all identified with following -->
+<!-- naming convention: -->
+<!-- the main div section identifier is the moniker of the command itself i.e. 'find' -->
+<!-- the table identifier is 'find.command' -->
+<!-- the input element identifiers are 'find.{qualifier or argument name}' e.g. -->
+<!-- 'find.type' or 'find.format'. The qualifier or argument name must be the same as -->
+<!-- specified in jest.js JavaScript. -->
+<!-- -->
+<!-- The naming convention is crucial because the JavaScript jest.js identifies these -->
+<!-- elements by this implicit naming conventions. -->
+<!-- -->
+<!-- The user entries result in a relative URI displayed in this section itself. -->
+<!-- The event handlers on the input elements update the URI on change. -->
+<!-- The user can click the hyperlink to send the request to the server. -->
+<!-- ==================================================================================== -->
+<div id="find" class="highlight" style="display:none;" dojoType="dijit.TitlePane"
+ title='<a href="http://openjpa.apache.org/jest-syntax.html" target="_blank">Find</a>
+ <b>persistent objects by primary identifier.</b>'>
+
+ <!-- a form for user to fill in the find specifications. Script uses these entries to -->
+ <!-- build up a request URI for JEST server -->
+ <table id="find.command">
+<tr>
+ <th width="30%" class="mandatory" title="Name of a persistent entity to find.">Entity Name
+ <span class="help">
+ <img src="images/help.jpg" width="8px" height="8px" onclick="showHelp('Entity', 'help/entity-name.html');">
+ </span>
+ </th>
+ <th width="30%" class="mandatory" title="Primary Key of the entity.">Identifier</th>
+ <th width="30%" title="Fetch Plan(s) to use. Separate each plan with comma.">Fetch Plan
+ <span class="help">
+ <img src="images/help.jpg" width="8px" height="8px"
+ onclick="showHelp('Fetch Plan', 'help/fetch-plan.html');">
+ </span>
+ </th>
+ <th width="10%" title="Format of the response.">Format
+ <span class="help">
+ <img src="images/help.jpg" width="8px" height="8px"
+ onclick="showHelp('Response Format', 'help/response-format.html');"></img>
+ </span>
+ </th>
+</tr>
+ <tr>
+ <td><input id="find.type" onblur="javascript:toURI('find');"></td>
+ <td><input id="find.pk" onblur="javascript:toURI('find');"></td>
+ <td><input id="find.plan" onblur="javascript:toURI('find');" ></td>
+ <td>
+ <select id="find.format" onchange="javascript:toURI('find');" >
+ <option value=""></option>
+ <option value="xml">XML</option>
+ <option value="json">JSON</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ <p>
+ <!-- Script will fill in the URI in this element based on user entries from the above -->
+ <!-- The element is made to look like a hyperlink but actually a span to omit the -->
+ <!-- associated complexity of preventing the browser's default handling of hyperlink -->
+ <!-- click events. -->
+ <b>URI: </b><span id="find.uri" class="url-invalid">filling the form will update
+ this hyperlink.</span>
+ <button id="find.execute" style="display:none;">
+ <img src="images/arrow_right.jpg" width="12px" height="12px"></button>
+</div>
+
+<!-- ==================================================================================== -->
+<!-- Command window for Query -->
+<!-- -->
+<!-- Similar to window for 'find' command. The added complexity is variable number of -->
+<!-- query binding parameters that the user may enter for a query. -->
+<!-- Each query binding parameter is accepted via two inputs on a dynamically created row -->
+<!-- The dynamic row is identified as 'query.vararg.{n}' and the pair of input elements -->
+<!-- 'query.vararg.{n}.key' and 'query.vararg.{n}.value' respectively. {n} is a monotonic -->
+<!-- integer. If a dynamically created row is removed by the user, the index {n} does not -->
+<!-- decrement. -->
+<!-- ==================================================================================== -->
+<div id="query" class="highlight" style="display:none;" dojoType="dijit.TitlePane"
+ title='<a href="http://openjpa.apache.org/jest-syntax.html" target="_blank">Query</a>
+ <b>with JPQL or named query and binding parameters.</b>'>
+
+ <!-- a form for user to fill in the find specifications. Script uses these entries to -->
+ <!-- build up a request URI for JEST server. This form is more complicated than that -->
+ <!-- of find, because a query can accept variable number of binding parameters -->
+ <table id="query.command">
+ <tr>
+ <th width="20%" class="mandatory" title="JPQL query or a named query">Query
+ <span class="help"><img src="images/help.jpg" width="8px" height="8px"
+ onclick="showHelp('Query', 'help/query.html');"></img></span></th>
+ <th width="10%"style="display: hidden"></th>
+ <th width="10%"style="display: hidden"></th>
+ <th width="10%"style="display: hidden"></th>
+ <th width="5%" title="Is it a named query?">Single</th>
+ <th width="5%" title="Returns single result?">Named</th>
+ <th width="30%" title="Fetch Plan(s) to use. Separate each plan with comma.">Fetch Plan
+ <span class="help"><img src="images/help.jpg" width="8px" height="8px"
+ onclick="showHelp('Fetch Plan', 'help/fetch-plan.html');"></img></span></th>
+ <th width="10%" title="Format of the response.">Format
+ </tr>
+ <tr>
+ <td colspan="4"><input id="query.q" onblur="javascript:toURI('query');"></td>
+ <td><input id="query.single" type="checkbox" value="true" onchange="javascript:toURI('query');"></td>
+ <td><input id="query.named" type="checkbox" value="true" onchange="javascript:toURI('query');"></td>
+ <td><input id="query.plan" onblur="javascript:toURI('query');" ></td>
+ <td>
+ <select id="query.format" onchange="javascript:toURI('query');" >
+ <option value=""></option>
+ <option value="xml">XML</option>
+ <option value="json">JSON</option>
+ </select>
+ </td>
+ </tr>
+ <tr id="query.vararg.0">
+ <td>
+ <button onclick="javascript:addVarArgRow('query.vararg',0,'Bind Query Parameter');">Bind Parameter</button>
+ </td>
+ </tr>
+ </table>
+ <p>
+ <!-- Script will fill in the URI in this element based on user entries from the above -->
+ <!-- The element is made to look like a hyperlink but actually a span to omit the -->
+ <!-- associated complexity of preventing the browser's default handling of hyperlink -->
+ <!-- click events. -->
+ <b>URI: </b><span id="query.uri" class="url-invalid">filling the form will update
+ this hyperlink.</span> <button id="query.execute" style="display:none;">
+ <img src="images/arrow_right.jpg" width="12px" height="12px"></button>
+
+</div>
+
+<!-- ==================================================================================== -->
+<!-- Command window for browsing persistent domain model -->
+<!-- ==================================================================================== -->
+<div id="domain" class="highlight" style="display:none;" dojoType="dijit.TitlePane"
+ title='<a href="http://openjpa.apache.org/jest-syntax.html" target="_blank">Browse</a>
+ <b>persistent domain model.</b>'>
+
+ This command accepts no qualifier or arguments. <br>
+
+ <b>JEST URI: </b><span id="domain.uri" class="url"
+ onclick="javascript:render('domain','canvas', 'domain', 'xml');">domain</span>
+</div>
+
+<!-- ==================================================================================== -->
+<!-- Command window for viewing configuration of the persistence unit. -->
+<!-- ==================================================================================== -->
+<div id="properties" class="highlight" style="display:none;" dojoType="dijit.TitlePane"
+ title='<a href="http://openjpa.apache.org/jest-syntax.html" target="_blank">View</a>
+ <b>configuration properties of the persistence unit.</b>'>
+
+ This command accepts no qualifier or arguments <br>
+
+ <b>URI: </b><span id="properties.uri" class="url"
+ onclick="javascript:render('properties','canvas', 'properties', 'xml');">properties</span>
+</div>
+
+<!-- ==================================================================================== -->
+<!-- This empty section will be filled in by server response -->
+<!-- ==================================================================================== -->
+<div id="canvas" class="canvas">
+</div>
+
+
+</body>
+</html>
\ No newline at end of file
Propchange: openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.html
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.js
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.js?rev=1044138&view=auto
==============================================================================
--- openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.js (added)
+++ openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.js Thu Dec 9 21:50:47 2010
@@ -0,0 +1,1146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+dojo.require("dijit.form.Button");
+dojo.require("dijit.TitlePane");
+dojo.require("dojox.xml.parser");
+dojo.require("dijit.Dialog");
+
+
+/** -----------------------------------------------------------------------------------------
+ * Navigation functions
+ *
+ * Available commands appear on left menu. Clicking on any command makes a corresponding
+ * highlighted section to appear at a fixed position. These command windows are identified
+ * and these identifiers are used to make only one of the section to be visible while
+ * hiding the rest.
+ *
+ * The jest.html document will use these same identifiers in their command section.
+ * ------------------------------------------------------------------------------------------
+ *
+ * The identifiers of every element to be shown or hidden.
+ * --------------------------------------------------------------------------------------- */
+
+var menuIds = new Array('home', 'deploy', 'find', 'query', 'domain', 'properties');
+
+/**
+ * Opening a menu implies clearing the canvas, hiding the current menu item and making
+ * the given menu identifier visible.
+ *
+ * @param id menu section identifier
+ */
+function openMenu(/*HTML element id*/id) {
+ clearElement('canvas');
+ switchId(id, menuIds);
+ document.location = "#top";
+}
+/**
+ * Show the division identified by the given id, and hide all others
+ */
+function switchId(/*string*/id, /*string[]*/highlightedSections) {
+ for (var i=0; i < highlightedSections.length; i++){
+ var section = document.getElementById(highlightedSections[i]);
+ if (section != null) {
+ section.style.display = 'none';
+ }
+ }
+ var div = document.getElementById(id);
+ if (div != null) {
+ div.style.display = 'block';
+ div.focus();
+ }
+}
+
+/** -----------------------------------------------------------------------------------------
+ * Generic Command handling functions
+ *
+ * All available JEST commands are enumerated by their qualifiers and arguments.
+ *
+ * Specification of a JEST Command requires the following:
+ * a) a name
+ * b) zero or more Qualifiers. Qualifiers are not ordered. All Qualifiers are optional.
+ * c) zero or more Arguments. Arguments are ordered. Some Arguments can be mandatory.
+ *
+ * Command, Qualifier and Argument are 'objects' -- in a curious JavaScript sense. They
+ * are responsible to harvest their state value from the HTML element such as a input
+ * text box or a check box etc. The aim of harvesting the values is to construct a
+ * relative URI that can be passed to the server via a HTTP get request.
+ *
+ * jest.html attaches change event handlers to all input elements and the on change
+ * event handler updates the URI.
+ *
+ * The complexity is added because some commands may take variable number of arguments.
+ * Hence the input text boxes to enter arbitrary number of key-value pair can be created
+ * or removed by the user.
+ *
+ * A lot of implicit naming convention for the element identifiers are used in this
+ * script. These naming conventions are documented in jest.html.
+ * --------------------------------------------------------------------------------------- */
+var findCommand = new Command('find',
+ new Array( //
+ new Qualifier("plan", "plan", false),
+ new Qualifier("format", "format", false),
+ new Qualifier("ignoreCache", "ignoreCache", true)
+ ),
+ new Array( // Order of arguments is significant
+ new Argument("type", "type", true),
+ new Argument("pk", null, true)
+ ));
+
+var queryCommand = new Command('query',
+ new Array( // Qualifiers are not ordered
+ new Qualifier("plan", "plan", false),
+ new Qualifier("format", "format", false),
+ new Qualifier("single", "single", true),
+ new Qualifier("named", "named", true),
+ new Qualifier("ignoreCache", "ignoreCache", true)
+ ),
+ new Array( // Order of arguments is significant
+ new Argument("q", "q", true)
+ ));
+
+var domainCommand = new Command('domain', new Array(), new Array());
+
+var propertiesCommand = new Command('properties', new Array(), new Array());
+
+var commands = new Array(findCommand, queryCommand, domainCommand, propertiesCommand);
+
+/** -----------------------------------------------------------------------------------------
+ * Creates a relative URI for the given commandName by reading the content of the given HTML
+ * element and its children.
+ * The URI is written to the HTML anchor element identified by {commandName} + '.uri'.
+ *
+ * @param commandName name of the command. All source HTML element are identified by this
+ * command name as prefix.
+ * --------------------------------------------------------------------------------------- */
+function toURI(commandName) {
+ var command = null;
+ switch (commandName) {
+ case 'find' : command = findCommand; break;
+ case 'query' : command = queryCommand; break;
+ case 'domain' : command = domainCommand; break;
+ case 'properties' : command = propertiesCommand; break;
+ }
+ if (command != null)
+ command.toURI();
+}
+
+/** -----------------------------------------------------------------------------------------
+ * Adds columns to the given row for entering a variable argument key-value pair.
+ * A remove button is created as well to remove the row.
+ * A new row is created to invoke this function again to add another new row.
+ *
+ * @param rowIdPrefix a string such as query.vararg or find.vararg
+ * @param index a integer appended to the prefix to identify the row such as query.vararg.3
+ * @param message the label on the new button
+ * --------------------------------------------------------------------------------------- */
+function addVarArgRow(rowIdPrefix, index, message) {
+ var rowId = rowIdPrefix + '.' + index;
+ var row = document.getElementById(rowId);
+ clearElement(rowId);
+
+ // New input column for parameter name. Element id is rowId + '.key'
+ var argNameColumn = document.createElement('td');
+ var argNameInput = document.createElement('input');
+ argNameInput.setAttribute('type', 'text');
+ argNameInput.setAttribute('id', rowId + '.key');
+ argNameInput.setAttribute('onblur', 'javascript:toURI("' + rowIdPrefix.split('.')[0] + '");');
+ argNameColumn.appendChild(argNameInput);
+
+ // New input column for parameter value. Element id is rowId + '.value'
+ var argValueColumn = document.createElement('td');
+ var argValueInput = document.createElement('input');
+ argValueInput.setAttribute('type', 'text');
+ argValueInput.setAttribute('id', rowId + '.value');
+ argValueInput.setAttribute('onblur', 'javascript:toURI("' + rowIdPrefix.split('.')[0] + '");');
+ argValueColumn.appendChild(argValueInput);
+
+ // New column for remove button. Will remove this row.
+ var removeColumn = document.createElement('td');
+ var removeColumnButton = document.createElement('button');
+ removeColumnButton.innerHTML = 'Remove';
+ removeColumnButton.setAttribute('onclick', 'javascript:removeVarArgRow("' + rowId + '");');
+ removeColumn.appendChild(removeColumnButton);
+
+ // Empty column as the first column
+ var emptyColumn = document.createElement('td');
+ emptyColumn.appendChild(document.createTextNode("Key-Value pair"));
+
+ // Add the empty column, two input columns and remove button to the current row
+ row.appendChild(emptyColumn);
+ row.appendChild(argNameColumn);
+ row.appendChild(argValueColumn);
+ row.appendChild(removeColumn);
+
+ // create a new row with a single column to add another parameter.
+ // This new row looks similar to the original state of the modified column
+ var newIndex = index + 1;
+ var newRowId = rowIdPrefix + '.' + newIndex;
+ var newRow = document.createElement('tr');
+ newRow.setAttribute('id', newRowId);
+ var newColumn = document.createElement('td');
+ var addColumnButton = document.createElement('button');
+ addColumnButton.innerHTML = message;
+ addColumnButton.setAttribute('onclick', 'javascript:addVarArgRow("' + rowIdPrefix + '",' + newIndex + ',"'
+ + message + '");');
+ newColumn.appendChild(addColumnButton);
+
+ newRow.appendChild(newColumn);
+ row.parentNode.appendChild(newRow);
+}
+
+/** -----------------------------------------------------------------------------------------
+ * Removes a variable argument row.
+ * The URI is updated.
+ *
+ * @param rowId the identifier of the row to be removed. The identifier follows the
+ * naming convention of the variable argument row i.e. {commandName}.varargs.{n}
+ * --------------------------------------------------------------------------------------- */
+function removeVarArgRow(rowId) {
+ var row = document.getElementById(rowId);
+ row.parentNode.removeChild(row);
+ toURI(rowId.split('.')[0]);
+}
+
+/** -----------------------------------------------------------------------------------------
+ * Definition of Command as a JavScript object.
+ *
+ * @param name name of the command. Used to identify the command, or identify input elements.
+ * @param qualifiers zero or more Qualifier objects
+ * @param arguments zero or more Argument objects
+ *
+ *
+ * --------------------------------------------------------------------------------------- */
+function Command(name, qualifiers, arguments) {
+ this.name = name;
+ this.qualifiers = qualifiers;
+ this.arguments = arguments;
+ this.toURI = Command_toURI;
+}
+
+/** -----------------------------------------------------------------------------------------
+ * Harvests the input HTML elements for a commands qualifiers and arguments and builds up
+ * a URI.
+ * Uses several naming convention that are documented in jest.html to identify the input
+ * elements.
+ * The naming of the function and its capitalization follows JavaScript convention for it
+ * to behave as a faux object method.
+ *
+ * @returns a string form of URI
+ * --------------------------------------------------------------------------------------- */
+function Command_toURI() {
+ var uri = this.name; // command name is same as URI name -- need not be
+ var iformat = 'xml'; // default response format
+ for (var i = 0; i < this.qualifiers.length; i++) {
+ var id = this.name + '.' + this.qualifiers[i].name;
+ var inode = document.getElementById(id);
+ var path = this.qualifiers[i].toURI(inode);
+ if (path != null) {
+ uri = uri.concat('/').concat(path);
+ if (this.qualifiers[i].key == 'format') {
+ iformat = getNodeValue(inode);
+ }
+ }
+ }
+ var args = "";
+ var invalid = null;
+ for (var i = 0; i < this.arguments.length; i++) {
+ var id = this.name + '.' + this.arguments[i].name;
+ var inode = document.getElementById(id);
+ var arg = this.arguments[i].toURI(inode);
+ if (arg != null) {
+ args = args.concat(args.length == 0 ? '' : '&').concat(arg);
+ } else if (this.arguments[i].mandatory) {
+ invalid = 'Missing mandatory ' + this.arguments[i].name + ' argument';
+ }
+ }
+
+ // Variable argument processing
+ var children = document.getElementById(this.name + '.command').getElementsByTagName('tr');
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i];
+ if (isVarArgRow(child, this.name)) {
+ var varargRow = child;
+ var pair = varargRow.getElementsByTagName('input');
+ var key = getNodeValue(pair[0]);
+ var value = getNodeValue(pair[1]);
+ if (key != null && value != null) {
+ args = args.concat(args.length == 0 ? '' : '&').concat(key).concat('=').concat(value);
+ }
+ }
+ }
+ if (args.length > 0) {
+ uri = uri.concat('?').concat(args);
+ }
+
+ // update the command URI element
+ console.log("New URI is " + uri);
+ var uriNode = document.getElementById(this.name + ".uri");
+ var uriCtrl = document.getElementById(this.name + ".execute");
+ if (invalid == null) {
+ uriNode.setAttribute('class', 'url');
+ uriNode.innerHTML = uri;
+ var contentType = getContentTypeForCommand(this.name);
+ uriCtrl.setAttribute('onclick',
+ 'javascript:render("'
+ + uri
+ + '", "canvas"' + ',"'
+ + contentType + '","'
+ + iformat + '");');
+ uriCtrl.style.display = 'inline';
+ } else {
+ uriNode.setAttribute('class', 'url-invalid');
+ uriNode.innerHTML = uri + ' (' + invalid + ')';
+ uriCtrl.style.display = 'none';
+ uriCtrl.removeAttribute('onclick');
+ }
+ return uri;
+}
+
+function getContentTypeForCommand(/*string*/ commandName) {
+ if (commandName == 'find' || commandName == 'query') return 'instances';
+ if (commandName == 'domain') return 'domain';
+ if (commandName == 'properties') return 'properties';
+
+}
+
+/** -----------------------------------------------------------------------------------------
+ * Definition of Qualifier JavaScript object.
+ *
+ * A qualifier decorates a Command. For example, a query command can be decorated with
+ * 'single' qualifier to return a single result. A 'plan' qualifier can decorate a find or
+ * query command to use a named fetch plan etc.
+ * A qualifier is encoded in the path segment of JEST URI followed by the
+ * command name e.g. /query/single or /find/plan=myFetchPlan etc.
+ *
+ *
+ * @param name a name when prefixed by the name of the command identifies the HTML element
+ * that carries the value of this qualifier.
+ * @param key the identifier for this qualifier used in the JEST URI
+ * @param isBoolean is this qualifier carries a boolean value?
+ *
+ * @returns {Qualifier}
+ * -------------------------------------------------------------------------------------- */
+function Qualifier(name, key, isBoolean) {
+ this.name = name;
+ this.key = key;
+ this.isBoolean = isBoolean;
+ this.toURI = Qualifier_toURI;
+}
+
+/** -----------------------------------------------------------------------------------------
+ * Generates a string for this qualifier to appear in the command URI.
+ *
+ * A qualifier is translated to a URI fragment as a key=value pair. A boolean
+ * qualifier is translated to a URI fragment only if the corresponding HTML
+ * element is checked. And even then, only the key is sufficient.
+ *
+ * @returns a string
+ * --------------------------------------------------------------------------------------- */
+function Qualifier_toURI(inode) {
+ var value = getNodeValue(inode);
+ if (isEmpty(value) || (this.isBoolean && !inode.checked)) {
+ return null;
+ }
+ if (this.isBoolean) {
+ return this.key + (value == 'true' ? '' : '=' + value);
+ }
+ return this.key + '=' + value;
+}
+
+/** -----------------------------------------------------------------------------------------
+ * Definition of Argument JavaScript object.
+ *
+ * An argument for a command. Some argument can be mandatory. <br>
+ * Each argument is encoded as key=value pair in JEST URI in query parameters
+ * separated by '&' character.
+ *
+ * @param name a name when prefixed by the name of the command identifies the HTML element
+ * that carries the value of this argument.
+ * @param key the identifier for this argument used in the JEST URI
+ * @param mandatory is this argument mandatory?
+ *
+ * @returns {Argument}
+ * -------------------------------------------------------------------------------------- */
+function Argument(name, key, mandatory) {
+ this.name = name;
+ this.key = key;
+ this.mandatory = mandatory;
+ this.toURI = Argument_toURI;
+}
+
+/** -----------------------------------------------------------------------------------------
+ * Generates a string for this argument to appear in the command URI.
+ *
+ * An argument is translated to a URI fragment as a key=value pair.
+ *
+ * @returns a string
+ * --------------------------------------------------------------------------------------- */
+function Argument_toURI(inode) {
+ var value = getNodeValue(inode);
+ if (isEmpty(value))
+ return null;
+ if (this.key == null) {
+ return value;
+ } else {
+ return this.key + '=' + value;
+ }
+}
+
+/** ----------------------------------------------------------------------------------------
+ * Utility functions
+ * ------------------------------------------------------------------------------------- */
+/**
+ * Trims a String.
+ */
+String.prototype.trim = function () {
+ return this.replace(/^\s*/, "").replace(/\s*$/, "");
+};
+
+/**
+ * Affirms if the given string appears at the start of this string.
+ */
+String.prototype.startsWith = function(s) {
+ return this.indexOf(s, 0) == 0;
+};
+
+/**
+ * Affirms if the given string is null or zero-length or trimmed to zero-length.
+ *
+ * @param str a string to test for 'emptiness'
+ * @returns {Boolean}
+ */
+function isEmpty(str) {
+ return str == null || str.length == 0 || str.trim().length == 0;
+}
+
+/**
+ * Gets the string value of the given node.
+ *
+ * @param inode a HTML element
+ * @returns null if given node is null or its value is an empty string.
+ * Otherwise, trimmed string.
+ */
+function getNodeValue(inode) {
+ if (inode == null) {
+ return null;
+ }
+ if (isEmpty(inode.value)) {
+ return null;
+ } else {
+ return inode.value.trim();
+ }
+}
+
+/**
+ * Affirms if the given HTML row element represents a variable argument row
+ * for the given commandName.
+ * @param row a HTML row element
+ * @param commandName name of a command
+ *
+ * @returns true if row identifer starts with commandName + '.vararg.'
+ */
+function isVarArgRow(row, commandName) {
+ return row != null && row.nodeName != '#text'
+ && row.hasAttribute("id")
+ && row.getAttribute("id").startsWith(commandName + '.vararg.');
+}
+
+/**
+ * Removes all children of the given element.
+ */
+function clearElement(/* HTML element id */ id) {
+ var element = dojo.byId(id);
+ if (element == null) return;
+ while (element.childNodes.length > 0) {
+ element.removeChild(element.firstChild);
+ }
+}
+
+/**
+ * Prints and alerts with the given message string.
+ * @param message a warning message
+ */
+function warn(/*string*/message) {
+ console.log(message);
+ alert(message);
+}
+
+/** -----------------------------------------------------------------------------------------
+ * Rendering functions
+ *
+ * Several rendering functions to display server response in the canvas section.
+ * The server responds in following formats :
+ * 1a) XML
+ * 1b) JSON
+ * The response can be rendered in following display modes :
+ * 2a) raw XML text
+ * 2b) HTML table
+ * 2c) Dojo Widgets
+ * 2d) JSON as text
+ * The content can be one of the following
+ * 3a) instances from find() or query() command
+ * 3b) domain model from domain() command
+ * 3c) configuration properties from properties() command
+ * 3d) error stack trace
+ *
+ * Thus there are 2x4x4 = 32 possible combinations. However, response format for
+ * certain content type is fixed e.g. server always sends domain/properties/error
+ * stack trace in XML format. Moreover certain content-response format-display mode
+ * combinations are not supported. The following matrix describes the supported
+ * display modes for content-response format combinations.
+ * [y] : supported
+ * [x] : not supported
+ * n/a : not available
+ * --------------------------------------------------------------------------------
+ * Response Content
+ * --------------------------------------------------------------------------------
+ * instances domain properties error
+ * --------------------------------------------------------------------------------
+ * XML [y] XML text [y] XML text [y] XML text [x] XML text
+ * [y] HTML [y] HTML [y] HTML [y] HTML
+ * [y] Dojo Widgets [y] Dojo Widgets [x] Dojo Widgets [x] Dojo Widgets
+ * [x] JSON [x] JSON [x] JSON [x] JSON
+ *
+ * JSON [x] XML text n/a n/a n/a
+ * [x] HTML Table n/a n/a [y] HTML
+ * [x] Dojo Widgets n/a n/a n/a
+ * [y] JSON n/a n/a n/a
+ * ---------------------------------------------------------------------------------
+ * The above matrix shows that there are 10 supported combinations.
+ * ------------------------------------------------------------------------------------- */
+var supportedResponseFormats = new Array('xml', 'json');
+var supportedContentTypes = new Array('instances', 'domain', 'properties', 'error');
+var renderingCombo = new Array(
+
+/*XML*/ new Array(new Array('xml', 'dojo', 'html'), // instances
+ new Array('xml', 'dojo', 'html'), // domain
+ new Array('xml','html'), // properties
+ new Array('html')), // error
+/*JSON*/new Array(new Array('json'), // instances
+ new Array('xml', 'dojo', 'html'), // domain
+ new Array('xml', 'html'), // properties
+ new Array('html'))); // error
+/**
+ * Gets the ordinal index of the given key in the given array
+ * @param array an array of enumerated strings.
+ * @param key a key to search for.
+ *
+ * @returns {Number} 0-based index of the key in the array.
+ */
+function getOrdinal(/*Array*/array, /*string*/key) {
+ for (var i = 0; i < array.length; i++) {
+ if (key == array[i]) return i;
+ }
+ console.log(key + " is not a valid enum in " + array);
+ return 0;
+}
+/**
+ * Gets ordinal number for enumerated response format.
+ *
+ * @param iformat response format. one of 'xml', 'json'
+ *
+ * @returns {Number} ordinal number 0 for 'xml',
+ */
+function getOrdinalResponseFormat(/*enum*/iformat) {
+ return getOrdinal(supportedResponseFormats, iformat);
+}
+
+/**
+ * Gets ordinal number of the enumerated content types.
+ * @param contentType type of content. One of 'instances', 'domain', 'properties', 'error'
+ * @returns
+ */
+function getOrdinalContentType(/*enum*/contentType) {
+ return getOrdinal(supportedContentTypes, contentType);
+}
+
+/**
+ * Gets the array of enumerated strings of display format for the given response format and content type.
+ * @param iformat
+ * @param contentType
+ * @returns
+ */
+function getSupportedDisplayModes(/*enum*/iformat,/*enum*/contentType) {
+ var displayModes = renderingCombo[getOrdinalResponseFormat(iformat)][getOrdinalContentType(contentType)];
+ if (displayModes == null) {
+ warn("No display format for response format [" + iformat + "] and content type [" + contentType + "]");
+ }
+ return displayModes;
+}
+
+/**
+ * Render the response from the given URI on to the given HTML element identified by targetId.
+ *
+ * The URI is requested from server in an asynchronous call. Then the server response is rendered
+ * in all supported display format but only the given display format is made visible.
+ *
+ * @param uri the request URI
+ * @param targetId identifier of the HTML element that will display the data
+ * @param contentType type of the content, one of 'instances', 'domain', 'properties', 'error'
+ * @param iformat format of the server response, one of 'xml' or 'json'
+ * @param oformat format for display, one of 'xml', 'json', 'dojo', 'html'
+ *
+ * The combination of iformat-contentType-oformat must be compatiable as described in above matrix.
+ *
+ * @returns {Boolean} to prevent default event propagation
+ */
+function render(/* string */ uri, /* id */ targetId, /* enum */contentType, /* enum */iformat) {
+ var targetNode = dojo.byId(targetId);
+ clearElement(targetId);
+
+ //The parameters to pass to xhrGet, the url, how to handle it, and the callbacks.
+ var xhrArgs = {
+ url: uri,
+ handleAs: (iformat == 'json' && contentType == 'instances') ? 'json' : 'xml',
+ preventCache: contentType == 'instances',
+ timeout : 1000,
+ load: function(data, ioargs) {
+ if (ioargs.xhr.status == 200) { // HTTP OK
+ var newDivs = null;
+ if (iformat == 'json') {
+ newDivs = renderJSONResponse(data, contentType);
+ } else {
+ newDivs = renderXMLResponse(data, contentType);
+ }
+ var displayModes = getSupportedDisplayModes(iformat, contentType);
+ targetNode.appendChild(createDisplayModeControl(displayModes));
+ for (var i = 0; i < newDivs.length; i++) {
+ targetNode.appendChild(newDivs[i]);
+ }
+ } else {
+ var errorDiv = renderErrorFromXMLAsHTML(data, ioargs);
+ targetNode.appendChild(errorDiv);
+ }
+ },
+ error: function(error, ioargs) {
+ var errorDiv = renderErrorFromXMLAsHTML(ioargs.xhr.responseXML, ioargs);
+ targetNode.appendChild(errorDiv);
+ }
+ };
+
+ //Call the asynchronous xhrGet
+ var deferred = dojo.xhrGet(xhrArgs);
+ return false;
+}
+
+/**
+ * Creates a table with radio buttons for supported display modes.
+ *
+ * @param displayModes name of supported display modes.
+ *
+ * @returns an unattached HTML table
+ */
+function createDisplayModeControl(displayModes) {
+ var displayMode = document.createElement("table");
+ displayMode.style.width = "100%";
+
+ var tr = document.createElement("tr");
+ displayMode.appendChild(tr);
+ // append columns. 0-th an dfirst columns are descriptive texts.
+ var caption = document.createElement("th");
+ caption.style.width = (100 - displayModes.length*12) + '%';
+ caption.appendChild(document.createTextNode("JEST Response"));
+ tr.appendChild(caption);
+
+ for (var i = 0; i < displayModes.length; i++) {
+ var mode = displayModes[i];
+ var modeColumn = document.createElement("th");
+ modeColumn.style.width = "12%";
+ tr.appendChild(modeColumn);
+
+ var radio = document.createElement("input");
+ radio.setAttribute("type", "radio");
+ radio.setAttribute("value", mode);
+ radio.setAttribute("name", "display.mode");
+ if (i == 0) radio.setAttribute("checked", "checked");
+ radio.setAttribute('onchange', createModeSwitchFunction(mode, displayModes));
+
+ modeColumn.appendChild(radio);
+ modeColumn.appendChild(document.createTextNode(mode.toUpperCase()));
+ }
+
+ return displayMode;
+}
+
+/**
+ * Creates a string for javascript function call to switch between display modes
+ * @param visible the visible display mode
+ * @param all available display modes
+ * @returns {String} a event handler function string
+ */
+function createModeSwitchFunction(/* string */ visible, /* string[] */ all) {
+ var array = '';
+ for (var i = 0; i < all.length; i++) {
+ if (all[i] != visible) {
+ array = array + (array.length == 0 ? '' : ', ') + '"display.mode.' + all[i] + '"';
+ }
+ }
+ return 'javascript:switchId("display.mode.' + visible+ '", [' + array + '])';
+}
+
+/**
+ * The big switch for rendering all content types received as XML DOM.
+ * Finds out the supported display format for given content type and renders each display format
+ * in separate divs. The div corresponding to the given display format is made visible, and others
+ * are hidden. None of the divs are attached to the main document.
+ *
+ * @param dom server response as a XML DOM document
+ * @param contentType enumerated content type. One of 'instances', 'domain', 'properties' or 'error'
+ *
+ * @returns an array of unattached divs only one of which is visible.
+ */
+function renderXMLResponse(/*XML DOM*/dom, /*enum*/contentType) {
+ var displayModes = getSupportedDisplayModes('xml', contentType);
+ var newDivs = new Array(displayModes.length);
+ for (var i = 0; i < displayModes.length; i++) {
+ var displayMode = displayModes[i];
+ if (displayMode == 'xml') {
+ newDivs[i] = renderXMLasXML(dom);
+ } else if (contentType == 'instances') {
+ if (displayMode == 'html') {
+ newDivs[i] = renderInstancesFromXMLAsHTML(dom);
+ } else if (displayMode == 'dojo') {
+ newDivs[i] = renderInstancesFromXMLAsDojo(dom);
+ }
+ } else if (contentType == 'domain') {
+ if (displayMode == 'html') {
+ newDivs[i] = renderDomainFromXMLAsHTML(dom);
+ } else if (displayMode == 'dojo') {
+ newDivs[i] = renderDomainFromXMLAsDojo(dom);
+ }
+ } else if (contentType == 'properties') {
+ newDivs[i] = renderPropertiesFromXMLAsHTML(dom);
+ }
+ newDivs[i].style.display = (i == 0 ? 'block' : 'none');
+ newDivs[i].setAttribute("id", "display.mode." + displayMode);
+ }
+ return newDivs;
+}
+
+/**
+ * Renders the given instance data in the format of a XML DOM document into a set of Dojo widgets
+ * inside a div element.
+ *
+ * @param data the root node of a XML document containing instances data
+ *
+ * @returns an unattached div containing a set of dojo widgets
+ */
+function renderInstancesFromXMLAsDojo(/* XML DOM*/data) {
+ var target = document.createElement('div');
+ var panels = new Array();
+ dojo.query("instance", data).forEach(function(item, index) {
+ var panel = createInstanceDojoWidget(item);
+ panels[index] = panel;
+ });
+
+ // assign random location to each panel and add them to canvas
+ dojo.forEach(panels, function(item, index) {
+ var domNode = item.domNode;
+ domNode.style.width = "200px";
+ domNode.style.position = "absolute";
+ domNode.style.left = 100 + (index % 5)*300 + "px";
+ domNode.style.top = 100 + Math.floor(index / 5)*200 +"px";
+ target.appendChild(domNode);
+ });
+ return target;
+}
+
+/**
+ * Renders given DOM for metamodel as dojo widgets.
+ *
+ * @param data XML DOM for domain model.
+ * @returns a HTML div
+ */
+function renderDomainFromXMLAsDojo(/*XML DOM*/data) {
+ var target = document.createElement('div');
+ var panels = new Array();
+ dojo.query("entity, embeddable, mapped-superclass", data)
+ .forEach(function(item, index) {
+ var panel = createEntityTypeDojoWidget(item);
+ panels[index] = panel;
+ });
+
+ // assign random location to each panel and add them to canvas
+ dojo.forEach(panels, function(item, index) {
+ var domNode = item.domNode;
+ domNode.style.width = "200px";
+ domNode.style.position = "absolute";
+ domNode.style.left = 100 + (index % 5)*300 + "px";
+ domNode.style.top = 100 + Math.floor(index / 5)*200 +"px";
+ target.appendChild(domNode);
+ });
+ return target;
+}
+
+/**
+ * Renders given XML DOM for instances to HTML tables.
+ * *** NOT IMPLEMENTED
+ *
+ * @param data XML DOM for list of instances. All instanes may not belong to same entity.
+ * @returns a div with zero or more tables.
+ */
+function renderInstancesFromXMLAsHTML(/* XML DOM */data) {
+ return unimplemented("Rendering Instances as HTML is not implemented");
+}
+
+/**
+ * Renders given XML DOM for domain model to HTML tables.
+ * *** NOT IMPLEMENTED
+ *
+ * @param data XML DOM for list of domain model.
+ * @returns a div with zero or more tables.
+ */
+function renderDomainFromXMLAsHTML(/* XML DOM */data) {
+ return unimplemented("Rendering Domain as HTML is not implemented");
+}
+
+function unimplemented(/*string*/message) {
+ var empty = document.createElement('img');
+ empty.setAttribute("src", "images/underconstruction.jpg");
+ empty.setAttribute("alt", message);
+ return empty;
+}
+
+/**
+ * Renders configration (name-value pairs) in a HTML table.
+ *
+ * @param data XML DOM for name-value pair properties.
+ * @returns a HTML table
+ */
+function renderPropertiesFromXMLAsHTML(/* XML DOM */data) {
+ var table = document.createElement("table");
+ var caption = document.createElement("caption");
+ caption.innerHTML = "Configuration Properties";
+ table.appendChild(caption);
+ dojo.query("property", data)
+ .forEach(function(item, index) {
+ var row = document.createElement("tr");
+ row.className = index%2 == 0 ? 'even' : 'odd';
+ var key = document.createElement("td");
+ var val = document.createElement("td");
+ key.innerHTML = item.getAttribute("name");
+ val.innerHTML = item.getAttribute("value");
+ row.appendChild(key);
+ row.appendChild(val);
+ table.appendChild(row);
+ }
+ );
+ return table;
+}
+
+/**
+ * Renders error message in HTML
+ *
+ * @param data XML DOM containing error description
+ *
+ * @returns a div element with error details
+ */
+function renderErrorFromXMLAsHTML(/*response as XML DOM*/responseXML, ioargs) {
+ var div = document.createElement("div");
+ var ecode = document.createElement("h3");
+ var header = document.createElement("p");
+ var msg = document.createElement("p");
+ var trace = document.createElement("pre");
+ ecode.setAttribute("class", "error-header");
+ header.setAttribute("class", "error-message");
+ msg.setAttribute("class", "error-message");
+
+ var serverError = responseXML.documentElement;
+ ecode.innerHTML = "HTTP Error " + ioargs.xhr.status;
+ header.innerHTML = dojox.xml.parser.textContent(serverError.getElementsByTagName("error-header").item(0));
+ msg.innerHTML = dojox.xml.parser.textContent(serverError.getElementsByTagName("error-message").item(0));
+ trace.innerHTML = dojox.xml.parser.textContent(serverError.getElementsByTagName("stacktrace").item(0));
+ div.appendChild(ecode);
+ div.appendChild(header);
+ div.appendChild(msg);
+ div.appendChild(trace);
+
+ return div;
+}
+
+/**
+ * Creates a dojo Title Pane from a DOM instance node. The pane has the instance
+ * id as its title. The content is a table with name and value of each attribute
+ * in each row. Multi-cardinality values are in separate row without the attribute
+ * name repeated except the first row.
+ *
+ * @param instanceNode an XML instance node
+ *
+ * @returns dojo widget for a single instance
+ */
+function createInstanceDojoWidget(/*XML node*/instanceNode) {
+ var instanceTable = document.createElement("table");
+ dojo.query('id, basic, enum, version', instanceNode)
+ .forEach(function(item) {
+ var attrRow = document.createElement("tr");
+ var nameColumn = document.createElement("td");
+ var valueColumn = document.createElement("td");
+ nameColumn.className = item.nodeName.toLowerCase(); /* May be cross-browser trouble */
+ nameColumn.innerHTML = item.getAttribute("name");
+ valueColumn.innerHTML = dojox.xml.parser.textContent(item);
+ attrRow.appendChild(nameColumn);
+ attrRow.appendChild(valueColumn);
+ instanceTable.appendChild(attrRow);
+ }
+ );
+ dojo.query('one-to-one, many-to-one', instanceNode)
+ .forEach(function(item) {
+ var attrRow = document.createElement("tr");
+ var nameColumn = document.createElement("td");
+ var valueColumn = document.createElement("td");
+ nameColumn.className = item.nodeName.toLowerCase(); /* May be cross-browser trouble */
+ nameColumn.innerHTML = item.getAttribute("name");
+ dojo.query('ref, null', instanceNode)
+ .forEach(function(ref) {
+ valueColumn.innerHTML = ref.nodeName == 'null' ? 'null' : ref.getAttribute("id");
+ valueColumn.className = ref.nodeName.toLowerCase();
+ attrRow.appendChild(nameColumn);
+ attrRow.appendChild(valueColumn);
+ instanceTable.appendChild(attrRow);
+ });
+ });
+ dojo.query('one-to-many, many-to-many', instanceNode).forEach(function(item) {
+ var attrRow = document.createElement("tr");
+ var nameColumn = document.createElement("td");
+ var valueColumn = document.createElement("td");
+ nameColumn.className = item.nodeName.toLowerCase(); /* May be cross-browser trouble */
+ nameColumn.innerHTML = item.getAttribute("name");
+ var refs = item.getElementsByTagName("ref");
+ for (var i = 0; i < refs.length; i++) {
+ if (i == 0) {
+ valueColumn.innerHTML = refs[i].getAttribute("id");
+ valueColumn.className = refs[i].nodeName.toLowerCase();
+ attrRow.appendChild(nameColumn);
+ attrRow.appendChild(valueColumn);
+ instanceTable.appendChild(attrRow);
+ } else {
+ var attrRow = document.createElement("tr");
+ var nameColumn = document.createElement("td"); // empty column
+ var valueColumn = document.createElement("td");
+ valueColumn.className = refs[i].nodeName.toLowerCase();
+ valueColumn.innerHTML = refs[i].getAttribute("id");
+ attrRow.appendChild(nameColumn);
+ attrRow.appendChild(valueColumn);
+ instanceTable.appendChild(attrRow);
+ }
+ }
+ }
+ );
+
+ var pane = new dijit.TitlePane({title:instanceNode.getAttribute("id"),content:instanceTable});
+ return pane;
+}
+
+
+/**
+ * Creates a dojo Title Pane from a DOM instance node. The pane has the instance
+ * id as its title. The content is name and value of each attribute in separate
+ * line.
+ *
+ * @param node
+ * an instance node
+ * @returns
+ */
+function createEntityTypeDojoWidget(node) {
+ var entityTable = document.createElement("table");
+ dojo.query('id, basic, enum, version, one-to-one, many-to-one, one-to-many, many-to-many', node)
+ .forEach(function(item) {
+ var attr = document.createElement("tr");
+ var name = document.createElement("td");
+ name.className = item.nodeName.toLowerCase(); /* May be cross-browser trouble */
+ var type = item.getAttribute("type");
+ name.innerHTML = type;
+ if (name.className == 'one-to-many') {
+ name.innerHTML = type + '<' + item.getAttribute("member-type") + '>';
+ }
+ var value = document.createElement("td");
+ value.innerHTML = dojox.xml.parser.textContent(item);
+ attr.appendChild(name);
+ attr.appendChild(value);
+ entityTable.appendChild(attr);
+ }
+ );
+
+ var pane = new dijit.TitlePane({title:node.getAttribute("name"), content: entityTable});
+ return pane;
+}
+
+/**
+ * Generic routine to render the given XML Document as a raw but indented text in to an unattached div section.
+ *
+ * @param dom a XML DOM
+ *
+ * @returns an unattached div section
+ */
+function renderXMLasXML(/*XML DOM*/dom) {
+ var newDiv = document.createElement('div');
+ print(dom.documentElement, newDiv, 0);
+ return newDiv;
+}
+
+/**
+ * Renders a XML DOM node as a new child of the given HTML node.
+ *
+ * CSS styles used:
+ * node-value : The value of a text node
+ * attr-name : The name of an attribute
+ * attr-value : The value of an attribute
+ * delimiter : symbols such = " < \ > used in visual XML
+ * the XML element name : e.g. A <metamodel> tag will be decorated with .metamodel CSS style
+ *
+ */
+function print(/* XML node */xnode, /* HTML node*/ hnode, /*int*/counter) {
+ if (xnode.nodeName == '#text') {
+ addTextNode(hnode, xnode.nodeValue, "node-value");
+ return;
+ }
+ var root = document.createElement('div');
+ root.style.position = 'relative';
+ root.style.left = '2em';
+ addRoot(xnode, hnode, root, ++counter);
+
+ var attrs = xnode.attributes;
+ if (attrs) {
+ for (var i = 0; i < attrs.length; i++) {
+ var attr = attrs[i];
+ addTextNode(root, ' ' + attr.nodeName, "attr-name");
+ addDelimiter(root, '=');
+ addTextNode(root, '"' + attr.nodeValue + '"', "attr-value");
+ }
+ addDelimiter(root, '>');
+ }
+ var children = xnode.childNodes;
+ if (children) {
+ for (var i = 0; i < children.length; i++) {
+ print(children[i], root, ++counter);
+ }
+ }
+ addDelimiter(root, '</');
+ addTextNode(root, xnode.nodeName, xnode.nodeName);
+ addDelimiter(root, '>');
+ return;
+}
+
+/**
+ * Adds the given delimiter text with CSS style 'delimiter' to the given parent node
+ * @param parentNode
+ * @param text
+ */
+function addDelimiter(/* HTML node*/ parentNode, /* Delimiter String*/ delim) {
+ addTextNode(parentNode, delim, 'delimiter');
+}
+/**
+ * Adds a <span> node of given className to the given parentNode with the given text.
+ *
+ * @param parentNode the parent node to which new text is added as a <span> element.
+ * @param text text to be added to the new <span> element
+ * @param className class of the new <span> element
+ * @returns the new <span> node
+ */
+function addTextNode(/* HTML node*/parentNode, /* String */text, /* String*/className) {
+ if (isEmpty(text)) return null;
+ newNode = document.createElement('span');
+ if (className) {
+ newNode.className = className;
+ }
+ if (text) {
+ newNode.appendChild(document.createTextNode(text));
+ }
+ if (parentNode) {
+ parentNode.appendChild(newNode);
+ }
+ return newNode;
+}
+function isTextNode(/* XML node */ xnode) {
+ return xnode == null || xnode.nodeName == '#text';
+}
+
+function isTogglable(/* XML node */ xnode) {
+ if (xnode == null) return false;
+ if (isTextNode(xnode)) return false;
+ var children = xnode.childNodes;
+ if (children == null || children.length == 0) return false;
+ if (children.length == 1 && isTextNode(children[0])) return false;
+ return true;
+}
+
+function addRoot(xnode, hnode, root, counter) {
+ if (isTogglable(xnode)) {
+ hnode.appendChild(document.createElement('br'));
+ var ctrl = addTextNode(hnode, '-');
+ root.setAttribute("id", counter);
+ var moniker = '<' + xnode.nodeName + '>...';
+ ctrl.setAttribute("onclick", 'javascript:toggle(this, "' + moniker + '", "' + counter + '");');
+ }
+ addDelimiter(root, '<');
+ addTextNode(root, xnode.nodeName, xnode.nodeName);
+ hnode.appendChild(root);
+
+}
+
+function toggle(/* HTML node */ctrl, /* id */ moniker, /* id */ targetId) {
+ var visible = ctrl.innerHTML == '-';
+ ctrl.innerHTML = visible ? '+' + moniker : '-';
+ var target = document.getElementById(targetId);
+ if (visible) {
+ target.style.display = "none";
+ } else {
+ target.style.display = "inline";
+ }
+}
+
+
+/**
+ * Renders server response of JSON objects.
+ * Server sends always an array of JSON objects.
+ * @param json an array of hopefully non-empty array of JSON objects
+ * @param contentType type of content. Currently only instances are JSONized.
+ * @returns an array of div with a single member
+ */
+function renderJSONResponse(/*JSON[]*/json, /*enum*/contentType) {
+ var text = dojo.toJson(json, true);
+ var div = document.createElement("div");
+ var pre = document.createElement("pre");
+ pre.innerHTML = text;
+ div.appendChild(pre);
+ return [div]; // an array of a single div
+}
+
+/**
+ * Help related utilities.
+ */
+
+var helpDialog;
+
+function createDialog() {
+ if (helpDialog == null) {
+ helpDialog = new dijit.Dialog({style: "width: 400px; height:300px;overflow:auto"});
+ }
+ return helpDialog;
+}
+
+function showHelp(title, href) {
+ var dialog = createDialog();
+ dialog.set("title", title);
+ dialog.set("href", href);
+ dialog.show();
+}
+
+
Propchange: openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/jest.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/localizer.properties
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/localizer.properties?rev=1044138&view=auto
==============================================================================
--- openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/localizer.properties (added)
+++ openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/localizer.properties Thu Dec 9 21:50:47 2010
@@ -0,0 +1,60 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+no-persistence-unit-param: Missing <b>persistence.unit</b> parameter. JEST Servlet must be \
+ configured with a parameter named <b>persistence.unit<b> in <init-param> clause \
+ of <servlet> declaration in <code>WEB-INF/web.xml</code> descriptor.
+servlet-init: JEST Servlet is initialized for "{0}" persistence unit.
+servlet-not-init: JEST Servlet can not find "{0}" persistence unit during servlet initialization. \
+ JEST Servlet will try to locate the unit when a request is to be served.
+
+no-persistence-unit: JEST can not locate the component using persistence unit <b>{0}</b>. This can happen \
+ for several reasons: \
+ <OL>the component is not initialized. </OL>\
+ <OL>the component and JEST servlet do not belong to the same deployment module</OL>\
+ <OL>the component did not configure the persistence unit for pooling. To enable pooling, \
+ create the persistence unit with configuration property <code>openjpa.EntityManagerFactoryPool=true</code>.<br> \
+ The property must be passed to <code>Persistence.createEntityManagerFactory(String unit, Map props)</code> \
+ with the second <code>Map</code> argument and <em>not</em> via <code>META-INF/persistence.xml</code></OL>.
+
+
+resource-not-found: Can not locate resource {0}. <br>This can happen for wrong URI syntax. See \
+<A href="http://openjpa.apache.org/jest-syntax.html" target="_blank">JEST URI Help page</A> for correct syntax.
+
+query-execution-error: Error executing query "{0}". See stacktrace for details.
+parse-invalid-qualifier: {0} command does not recognize "{1}" as a qualifier. Valid qualifiers are {2}.
+parse-missing-mandatory-argument: {0} command must have "{1}" argument. Available arguments are {2}.
+parse-less-argument: {0} command must have at least {2} argument. Available arguments are {1}.
+# ----------------------------------------------------------------------
+# Format related error
+# ----------------------------------------------------------------------
+format-xml-null-parent: A null XML parent element encountered during serialization
+format-xml-null-doc: Given parent element is not part of XML document
+format-xml-null-closure: Set of visited instances can not be null for serialization
+format-not-supported: format {0} in command {1} is not registered. Available formats are {2}.
+
+properties-caption: Configuration of {0} Persistence Unit
+entity-not-found: Resource of type {0} with identifier {1} is not found.
+bad-uri: Can not reconstruct URI from original URL {0}
+
+
+find-title: JEST find
+find-desc: JEST find command may return more than one result. Why?
+query-title: JEST query
+query-desc: JEST query command may return more than the directly selected result. Why?
+domain-command: JEST domain
+domain-desc: JEST domain command prints the persistent domain model
Propchange: openjpa/trunk/openjpa-jest/src/main/resources/org/apache/openjpa/persistence/jest/localizer.properties
------------------------------------------------------------------------------
svn:eol-style = native