You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by mi...@apache.org on 2009/08/14 17:29:36 UTC
svn commit: r804261 - in /openjpa/trunk:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/
openjpa-persistence-jdbc/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/co...
Author: mikedd
Date: Fri Aug 14 15:29:35 2009
New Revision: 804261
URL: http://svn.apache.org/viewvc?rev=804261&view=rev
Log:
OPENJPA-948:
Adding support for Ingress database (new dictionary, build config etc.).
Submitted by : Alan Raison
Added:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/IngresDictionary.java (with props)
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionaryFactory.java
openjpa/trunk/openjpa-persistence-jdbc/pom.xml
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/common/utils/AbstractTestCase.java
openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml
openjpa/trunk/openjpa-project/src/doc/manual/supported_databases.xml
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java?rev=804261&r1=804260&r2=804261&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java Fri Aug 14 15:29:35 2009
@@ -205,6 +205,7 @@
"h2", "org.apache.openjpa.jdbc.sql.H2Dictionary",
"hsql", "org.apache.openjpa.jdbc.sql.HSQLDictionary",
"informix", "org.apache.openjpa.jdbc.sql.InformixDictionary",
+ "ingres", "org.apache.openjpa.jdbc.sql.IngresDictionary",
"jdatastore", "org.apache.openjpa.jdbc.sql.JDataStoreDictionary",
"mysql", "org.apache.openjpa.jdbc.sql.MySQLDictionary",
"oracle", "org.apache.openjpa.jdbc.sql.OracleDictionary",
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionaryFactory.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionaryFactory.java?rev=804261&r1=804260&r2=804261&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionaryFactory.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionaryFactory.java Fri Aug 14 15:29:35 2009
@@ -223,6 +223,8 @@
return dbdictionaryPlugin.unalias("sybase");
if (prod.indexOf("informix") != -1 || prod.indexOf("ids") != -1)
return dbdictionaryPlugin.unalias("informix");
+ if (prod.indexOf("ingres") != -1)
+ return dbdictionaryPlugin.unalias("ingres");
if (prod.indexOf("hsql") != -1)
return dbdictionaryPlugin.unalias("hsql");
if (prod.indexOf("foxpro") != -1)
Added: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/IngresDictionary.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/IngresDictionary.java?rev=804261&view=auto
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/IngresDictionary.java (added)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/IngresDictionary.java Fri Aug 14 15:29:35 2009
@@ -0,0 +1,317 @@
+/*
+ * 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.
+ */
+package org.apache.openjpa.jdbc.sql;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.exps.FilterValue;
+import org.apache.openjpa.jdbc.schema.Sequence;
+
+public class IngresDictionary extends DBDictionary {
+
+ public IngresDictionary() {
+ // Schema Data
+ platform = "Ingres";
+ driverVendor = "Ingres Corporation";
+ maxColumnNameLength = 32;
+ maxConstraintNameLength = 32;
+ maxIndexNameLength = 32;
+ maxTableNameLength = 32;
+ supportsDeferredConstraints = false;
+ schemaCase = DBDictionary.SCHEMA_CASE_LOWER;
+ systemSchemas = "$ingres";
+ supportsDefaultDeleteAction = false;
+ supportsDefaultUpdateAction = false;
+
+ // SQL
+ validationSQL = "SELECT DATE('now')";
+ rangePosition = DBDictionary.RANGE_POST_SELECT;
+ supportsLockingWithDistinctClause = false;
+ supportsLockingWithInnerJoin = false;
+ supportsLockingWithMultipleTables = false;
+ supportsLockingWithOuterJoin = false;
+ supportsSelectEndIndex = true;
+ supportsMultipleNontransactionalResultSets = false;
+ allowsAliasInBulkClause = false;
+ requiresCastForMathFunctions = true;
+ requiresAliasForSubselect = true;
+
+ // Functions
+ stringLengthFunction = "LENGTH({0})";
+
+ // Types
+ binaryTypeName = "BYTE";
+ bitTypeName = "TINYINT";
+ blobTypeName = "LONG BYTE";
+ booleanTypeName = "TINYINT";
+ charTypeName = "CHAR";
+ clobTypeName = "LONG NVARCHAR";
+ javaObjectTypeName = "LONG BYTE";
+ numericTypeName = "DECIMAL";
+ doubleTypeName = "FLOAT";
+ longVarcharTypeName = "LONG NVARCHAR";
+ longVarbinaryTypeName = "LONG BYTE";
+ varbinaryTypeName = "LONG BYTE";
+ datePrecision = DBDictionary.NANO;
+
+ // Schema Metadata
+ supportsNullTableForGetImportedKeys = true;
+ supportsNullTableForGetImportedKeys = true;
+ supportsNullTableForGetIndexInfo = true;
+ supportsNullTableForGetPrimaryKeys = true;
+ tableTypes = "TABLE,VIEW,SYSTEM TABLE";
+ requiresAutoCommitForMetaData = true;
+
+ // Auto Increment
+ maxAutoAssignNameLength = 32;
+ supportsAutoAssign = false;
+ autoAssignClause = null;
+ autoAssignTypeName = null;
+ sequenceSQL = "SELECT seq_name AS SEQUENCE_NAME, seq_owner AS SEQUENCE_SCHEMA FROM iisequences";
+ sequenceNameSQL = "seq_name = ?";
+ sequenceSchemaSQL = "seq_owner = ?";
+ nextSequenceQuery = "SELECT NEXT VALUE FOR {0}";
+
+ systemTables =
+ "iiaccess, iialt_columns, iiattribute, iiaudit, iiaudittables, "
+ + "iicdbid_idx, iicolumns, iiconstraint_indexes, "
+ + "iiconstraints, iidatabase, iidatabase_info, iidb_comments, "
+ + "iidb_subcomments, iidbcapabilities, iidbconstants, "
+ + "iidbdepends, iidbid_idx, iidbms_comment, iidbpriv, "
+ + "iidbprivileges, iiddb_netcost, iiddb_nodecosts, iidefault, "
+ + "iidefaultidx, iidevices, iidistcol, iidistcols, "
+ + "iidistscheme, iidistschemes, iidistval, "
+ + "iievent, iievents, iiextend, iiextend_info, "
+ + "iiextended_relation, iifile_info, iigw06_attribute, "
+ + "iigw06_relation, iigw07_attribute, iigw07_index, "
+ + "iigw07_relation, iihistogram, iihistograms, iiindex, "
+ + "iiindex_columns, iiindexes, iiingres_tables, iiintegrities, "
+ + "iiintegrity, iiintegrityidx, iikey, iikey_columns, iikeys, "
+ + "iilocation_info, iilocations, iilog_help, iilpartitions, "
+ + "iimulti_locations, iiocolumns, iiotables, iipartname, "
+ + "iipermits, iiphysical_columns, iiphysical_tables, iipriv, "
+ + "iiprivlist, iiproc_access, iiproc_params, iiprocedure, "
+ + "iiprocedure_parameter, iiprocedures, iiprofile, iiprofiles, "
+ + "iiprotect, iiqrytext, iirange, iiref_constraints, "
+ + "iiregistrations, iirel_idx, iirelation, iirole, "
+ + "iirolegrant, iirolegrants, iiroles, iirule, iiruleidx, "
+ + "iiruleidx1, iirules, iischema, iischemaidx, iisecalarm, "
+ + "iisectype, iisecurity_alarms, iisecurity_state, "
+ + "iisecuritystate, iisequence, iisequences, "
+ + "iisession_privileges, iistar_cdbinfo, iistar_cdbs, "
+ + "iistatistics, iistats, iisynonym, iisynonyms, iitables, "
+ + "iitree, iiuser, iiusergroup, iiusers, iiviews, "
+ + "iixdbdepends, iixevent, iixpriv, iixprocedure, "
+ + "iixsynonym, ii_abfclasses, ii_abfdependencies, "
+ + "ii_abfobjects, ii_app_cntns_comp, ii_app_cntns_comp_index, "
+ + "ii_applications, ii_atttype, ii_client_dep_mod, "
+ + "ii_components, ii_databases, ii_dbd_acl, "
+ + "ii_dbd_identifiers, ii_dbd_locations, ii_dbd_rightslist, "
+ + "ii_dbd_table_char, ii_defaults, ii_dependencies, "
+ + "ii_dependencies_index, ii_dependencies_index2, "
+ + "ii_dict_modules, ii_domains, ii_encoded_forms, "
+ + "ii_encodings, ii_entities, ii_entities_index, ii_enttype, "
+ + "ii_fields, " + "ii_forms, ii_framevars, ii_gropts, "
+ + "ii_id, ii_incl_apps, ii_joindefs, ii_joinspecs, "
+ + "ii_key_info, ii_key_map, ii_limits, ii_locks, "
+ + "ii_longremarks, ii_menuargs, ii_objects, "
+ + "ii_objects_index, ii_qbfnames, ii_rcommands, "
+ + "ii_rel_cncts_ent, ii_reltype, ii_reports, "
+ + "ii_sequence_values, ii_sqlatts, ii_sqltables, "
+ + "ii_srcobj_encoded, ii_stored_bitmaps, ii_stored_strings, "
+ + "ii_trim, ii_vqjoins, ii_vqtabcols, ii_vqtables";
+ fixedSizeTypeNames =
+ "INTEGER,INTEGER1,INTEGER2,INTEGER4,INTEGER8,TINYINT,SMALLINT,"
+ + "BIGINT,FLOAT,FLOAT4,FLOAT8,REAL,DATE,INGRESDATE,ANSIDATE";
+ reservedWords =
+ "ABORT,BYREF,CALLPROC,COMMENT,COPY,DEFINE,DISABLE,DO,ELSEIF,"
+ + "ENABLE,ENDIF,ENDLOOP,ENDWHILE,EXCLUDING,IF,IMPORT,INDEX,"
+ + "INTEGRITY,MESSAGE,MODIFY,PERMIT,RAISE,REFERENCING,REGISTER,"
+ + "RELOCATE,REMOVE,REPEAT,RETURN,SAVE,SAVEPOINT,UNTIL,WHILE";
+
+ /* Don't allow "tid" as a column name; this is an internal column */
+ invalidColumnWordSet.add("tid");
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.openjpa.jdbc.sql.DBDictionary#connectedConfiguration(java.sql.Connection)
+ */
+ public void connectedConfiguration(Connection conn) throws SQLException {
+ super.connectedConfiguration(conn);
+
+ if (isVersion9_2orLater(conn))
+ supportsSelectStartIndex = true;
+ }
+
+ boolean isVersion9_2orLater(Connection conn) throws SQLException
+ {
+ DatabaseMetaData meta = conn.getMetaData();
+
+ int dbMajorVersion = meta.getDatabaseMajorVersion();
+ int dbMinorVersion = meta.getDatabaseMinorVersion();
+
+ if ((dbMajorVersion == 9 && dbMinorVersion >= 2) ||
+ dbMajorVersion > 9)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * Implementation of appendSelectRange for Ingres - uses "SELECT FIRST n"
+ * syntax. Not implemented in superclass.
+ *
+ * @see org.apache.openjpa.jdbc.sql.DBDictionary#appendSelectRange(
+ * org.apache.openjpa.jdbc.sql.SQLBuffer, long, long, boolean)
+ *
+ * @param buf
+ * - SQL building buffer.
+ * @param start
+ * - Ignored, not supported by Ingres. Throws an
+ * @param end
+ * - The number of records to return.
+ * @param subselect
+ * - Is the SQL query part of a subselect statement?
+ */
+ protected void appendSelectRange(SQLBuffer buf, long start, long end,
+ boolean subselect) {
+ if (!supportsSelectStartIndex && start > 0)
+ throw new IllegalArgumentException(
+ "Ingres does not support start indexes for Select Ranges");
+
+ if (start > 0 && start != Long.MAX_VALUE && !subselect)
+ buf.append(" OFFSET ").append(Long.toString(start));
+
+ if (end > 0 && end != Long.MAX_VALUE && !subselect)
+ buf.append(" FETCH NEXT ").append(Long.toString(end)).append(" ROWS ONLY");
+ }
+
+ /**
+ * Implementation of empty method in DBDictionary. Returns SQL to find the sequences defined in the database.
+ */
+ @Override
+ protected String getSequencesSQL(String schemaName, String sequenceName) {
+ StringBuffer buf = new StringBuffer();
+ buf.append(sequenceSQL);
+ if (schemaName != null || sequenceName != null)
+ buf.append(" WHERE ");
+ if (schemaName != null) {
+ buf.append(sequenceSchemaSQL);
+ if (sequenceName != null)
+ buf.append(" AND ");
+ }
+ if (sequenceName != null)
+ buf.append(sequenceNameSQL);
+ return buf.toString();
+ }
+
+ /**
+ * Overrides DBDictionary's newSequence method; trims the sequence name.
+ *
+ * @see org.apache.openjpa.jdbc.sql.DBDictionary#newSequence(ResultSet)
+ */
+ @Override
+ protected Sequence newSequence(ResultSet sequenceMeta) throws SQLException {
+ Sequence seq = super.newSequence(sequenceMeta);
+ seq.setName(seq.getName().trim());
+ return seq;
+ }
+
+ /**
+ * Invoke Ingres' IndexOf Function (Find the first index of a string in
+ * another string, starting at a given index).
+ *
+ * @see org.apache.openjpa.jdbc.sql.DBDictionary#indexOf(
+ * org.apache.openjpa.jdbc.sql.SQLBuffer,
+ * org.apache.openjpa.jdbc.kernel.exps.FilterValue,
+ * org.apache.openjpa.jdbc.kernel.exps.FilterValue,
+ * org.apache.openjpa.jdbc.kernel.exps.FilterValue)
+ *
+ * @param buf
+ * - the SQL Buffer to write the indexOf invocation to
+ * @param str
+ * - a query value representing the target string
+ * @param find
+ * - a query value representing the search string
+ * @param start
+ * - a query value representing the start index, or null to
+ * start at the beginning
+ */
+
+ public void indexOf(SQLBuffer buf, FilterValue str, FilterValue find,
+ FilterValue start) {
+ buf.append("(POSITION((");
+ find.appendTo(buf);
+ buf.append(") IN (");
+
+ if (start != null)
+ substring(buf, str, start, null);
+ else
+ str.appendTo(buf);
+
+ buf.append(")) - 1");
+
+ if (start != null) {
+ buf.append(" + ");
+ start.appendTo(buf);
+ }
+ buf.append(")");
+ }
+
+ /**
+ * @see org.apache.openjpa.jdbc.sql.DBDictionary#substring(
+ * org.apache.openjpa.jdbc.sql.SQLBuffer,
+ * org.apache.openjpa.jdbc.kernel.exps.FilterValue,
+ * org.apache.openjpa.jdbc.kernel.exps.FilterValue,
+ * org.apache.openjpa.jdbc.kernel.exps.FilterValue)
+ */
+ public void substring(SQLBuffer buf, FilterValue str, FilterValue start,
+ FilterValue end) {
+ buf.append(substringFunctionName).append("(");
+ str.appendTo(buf);
+ buf.append(", ");
+ if (start.getValue() instanceof Number) {
+ long startLong = toLong(start);
+ buf.append(Long.toString(startLong + 1));
+ } else {
+ buf.append("(CAST ((");
+ start.appendTo(buf);
+ buf.append(" + 1) AS INTEGER))");
+ }
+ if (end != null) {
+ buf.append(", ");
+ if (start.getValue() instanceof Number
+ && end.getValue() instanceof Number) {
+ long startLong = toLong(start);
+ long endLong = toLong(end);
+ buf.append(Long.toString(endLong - startLong));
+ } else {
+ buf.append("(CAST (");
+ end.appendTo(buf);
+ buf.append(" - (");
+ start.appendTo(buf);
+ buf.append(") AS INTEGER))");
+ }
+ }
+ buf.append(")");
+ }
+}
Propchange: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/IngresDictionary.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: openjpa/trunk/openjpa-persistence-jdbc/pom.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/pom.xml?rev=804261&r1=804260&r2=804261&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/pom.xml (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/pom.xml Fri Aug 14 15:29:35 2009
@@ -279,6 +279,25 @@
<connection.password>${openjpa.sybase.password}</connection.password>
</properties>
</profile>
+
+ <profile>
+ <id>test-ingres</id>
+ <activation><property><name>test-ingres</name></property></activation>
+ <dependencies>
+ <dependency>
+ <groupId>com.ingres.jdbc</groupId>
+ <artifactId>iijdbc</artifactId>
+ <version>9.2-3.4.8</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <properties>
+ <connection.driver.name>com.ingres.jdbc.IngresDriver</connection.driver.name>
+ <connection.url>${openjpa.ingres.url}</connection.url>
+ <connection.username>${openjpa.ingres.username}</connection.username>
+ <connection.password>${openjpa.ingres.password}</connection.password>
+ </properties>
+ </profile>
<!-- Profile for testing with a custom DB using a system jar -->
<!--
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/common/utils/AbstractTestCase.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/common/utils/AbstractTestCase.java?rev=804261&r1=804260&r2=804261&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/common/utils/AbstractTestCase.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/common/utils/AbstractTestCase.java Fri Aug 14 15:29:35 2009
@@ -105,6 +105,7 @@
INFORMIX,
POINTBASE,
SYBASE,
+ INGRES,
}
protected String multiThreadExecuting = null;
Modified: openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml?rev=804261&r1=804260&r2=804261&view=diff
==============================================================================
--- openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml (original)
+++ openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_dbsetup.xml Fri Aug 14 15:29:35 2009
@@ -674,6 +674,19 @@
class.
</para>
</listitem>
+ <listitem>
+ <para>
+ <indexterm>
+ <primary>
+ Ingres
+ </primary>
+ </indexterm>
+<literal>ingres</literal>: Dictionary for Ingres. This is an alias for the
+<ulink url="../javadoc/org/apache/openjpa/jdbc/sql/IngresDictionary.html">
+<classname>org.apache.openjpa.jdbc.sql.IngresDictionary</classname></ulink>
+class.
+ </para>
+ </listitem>
</itemizedlist>
<para>
The example below demonstrates how to set a dictionary and configure its
Modified: openjpa/trunk/openjpa-project/src/doc/manual/supported_databases.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-project/src/doc/manual/supported_databases.xml?rev=804261&r1=804260&r2=804261&view=diff
==============================================================================
--- openjpa/trunk/openjpa-project/src/doc/manual/supported_databases.xml (original)
+++ openjpa/trunk/openjpa-project/src/doc/manual/supported_databases.xml Fri Aug 14 15:29:35 2009
@@ -321,6 +321,20 @@
5.5 (5.5)
</entry>
</row>
+ <row>
+ <entry colname="dbname">
+ <link linkend="dbsupport_ingres">Ingres Database</link>
+ </entry>
+ <entry colname="dbversion">
+ 9.2
+ </entry>
+ <entry colname="drivname">
+ iijdbc
+ </entry>
+ <entry colname="drivversion">
+ 9.2-3.4.8
+ </entry>
+ </row>
</tbody>
</tgroup>
</table>
@@ -1067,4 +1081,31 @@
</itemizedlist>
</section>
</section>
+ <section id="dbsupport_ingres">
+ <title>
+ Ingres Database
+ </title>
+<!-- <example id="example_props_ingres">-->
+<!-- <title>-->
+<!-- Example properties for Sybase-->
+<!-- </title>-->
+<!--<programlisting>-->
+<!--openjpa.ConnectionDriverName: com.sybase.jdbc2.jdbc.SybDriver-->
+<!--openjpa.ConnectionURL: \-->
+<!-- jdbc:sybase:Tds:SERVER_NAME:4100/DB_NAME?ServiceName=DB_NAME&BE_AS_JDBC_COMPLIANT_AS_POSSIBLE=true-->
+<!--</programlisting>-->
+<!-- </example>-->
+ <section id="dbsupport_ingres_issues">
+ <title>
+ Known issues with Ingres
+ </title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ None.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ </section>
</appendix>