DNA SVN: r114 - in trunk/docs/getting_started/en: images and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-04-30 15:30:18 -0400 (Wed, 30 Apr 2008)
New Revision: 114
Added:
trunk/docs/getting_started/en/images/dna-architecture.png
Removed:
trunk/docs/getting_started/en/images/build.png
trunk/docs/getting_started/en/images/docbook-dir.png
Modified:
trunk/docs/getting_started/en/master.xml
Log:
Added overview and architecture sections.
Deleted: trunk/docs/getting_started/en/images/build.png
===================================================================
(Binary files differ)
Added: trunk/docs/getting_started/en/images/dna-architecture.png
===================================================================
(Binary files differ)
Property changes on: trunk/docs/getting_started/en/images/dna-architecture.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Deleted: trunk/docs/getting_started/en/images/docbook-dir.png
===================================================================
(Binary files differ)
Modified: trunk/docs/getting_started/en/master.xml
===================================================================
--- trunk/docs/getting_started/en/master.xml 2008-04-30 17:52:22 UTC (rev 113)
+++ trunk/docs/getting_started/en/master.xml 2008-04-30 19:30:18 UTC (rev 114)
@@ -8,19 +8,18 @@
<subtitle>Getting Started Guide</subtitle>
<issuenum>0.1</issuenum>
<productnumber>1</productnumber>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Author_Group.xml"/>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Legal_Notice.xml"/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Author_Group.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Legal_Notice.xml" />
</bookinfo>
<preface id="preface" revision="1">
<title>What this book covers</title>
<para>The goal of this book is to help you learn about JBoss DNA and how you can use it in your own applications to get the
most out of your JCR repositories.</para>
- <para>The part of the book starts out with an introduction to content repositories and an overview of the JCR API, both of which are an
- important aspect of JBoss DNA. This is followed by an overview of the the JBoss DNA project, it's architecture, and a basic
- roadmap for what's coming next.</para>
- <para>The next part of the book covers how to download and build the examples, how to use JBoss DNA with
- existing repositories, and how to build and use custom sequencers.
- </para>
+ <para>The part of the book starts out with an introduction to content repositories and an overview of the JCR API, both of
+ which are an important aspect of JBoss DNA. This is followed by an overview of the the JBoss DNA project, it's architecture,
+ and a basic roadmap for what's coming next.</para>
+ <para>The next part of the book covers how to download and build the examples, how to use JBoss DNA with existing
+ repositories, and how to build and use custom sequencers.</para>
<para>
If you have any questions or comments, please feel free to contact JBoss DNA's
<ulink url="mailto:dna-users@jboss.org">user mailing list</ulink>
@@ -132,6 +131,137 @@
<chapter id="jboss_dna">
<title>JBoss DNA</title>
<sect1>
+ <title>Overview</title>
+ <para>JBoss DNA is a repository and set of tools that make it easy to capture, version, analyze, and understand the
+ fundamental building blocks of information. As models, service and process definitions, schemas, source code, and other
+ artifacts are added to the repository, JBoss DNA "sequences" the makeup of these components and extracts their structure
+ and interdependencies. The JBoss DNA web application allows end users to access, visualize, and edit this information in
+ the terminology and structure they are familiar with. Such domain-specific solutions can be easily created with little or
+ no programming.</para>
+ <para> JBoss DNA supports the Java Content Repository (JCR) standard and is able to provide a single integrated view of
+ multiple repositories, external databases, services, and applications, ensuring that JBoss DNA has access to the latest
+ and most reliable master data. For instance, DNA could provide in a single view valuable insight into the business
+ processes and process-level services impacted by a change to in an intermediary web server operation defined via WSDL.
+ Similarly, a user could quickly view and navigate the dependencies between the data source models and transformation
+ information stored within a content repository, the code base stored within a version control system, and the database
+ schemas used by an application.</para>
+ </sect1>
+ <sect1 id="architecture">
+ <title>Architecture</title>
+ <para>The architecture for JBoss DNA consists of several major components that will be built on top of standard APIs,
+ including JCR, JDBC, JNDI and HTTP. The goal is to allow these components to be assembled as needed and add value on top
+ of other DNA components or third-party systems that support the standard APIs.</para>
+ <!-- mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="images/dna-architecture.png"/>
+ </imageobject>
+ </mediaobject -->
+ <figure id="dna-architecture">
+ <title>JBoss DNA Architecture</title>
+ <graphic align="center" scale="60" fileref="images/dna-architecture.png" />
+ </figure>
+ <para>
+ As shown in the diagram above, the major components are (starting at the top):
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Eclipse Plugins</emphasis>
+ enable Eclipse users to access the contents of a JBoss DNA repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA JDBC Driver</emphasis>
+ provides a driver implementation, allowing JDBC-aware applications to connect to and use a JBoss DNA repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Remote JCR</emphasis>
+ is a client-side component for accessing remote JCR repositories.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Web Application</emphasis>
+ is used by end users and domain experts to visualize, search, edit, change and tag the repository content. The web
+ application uses views to define how different types of information are to be presented and edited in
+ domain-specific ways. The goal is that this web application is easily customized and branded for inclusion into
+ other solutions and application systems. The DNA Web Application operate upon any JCR-compliant repository, although
+ it does rely upon the DNA analysis and templating services.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Publishing Server</emphasis>
+ allows content to be downloaded, uploaded and edited using the Atom Publishing Protocol. With the DNA Publishing
+ Server, the content of the repository can easily be created, read, edited and deleted using the standard HTTP
+ operations of POST, GET, PUT and DELETE (respectively). More and more tools are being created that support working
+ with Atom Publishing servers. The DNA Publishing Server operates upon any JCR-compliant repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA WebDAV Server</emphasis>
+ allows clients such as Microsoft Windows and Apple OS X to connect to, read and edit the content in the repository
+ using the WebDAV standard. Since WebDAV is an extension of HTTP, web browsers are able to read (but not modify) the
+ content served by a WebDAV compliant server. The DNA WebDAV Server operates upon any JCR-compliant repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Sequencers</emphasis>
+ are pluggable components that make it possible for content to be uploaded to the repository and automatically
+ processed to extract meaningful structure and place that structure in the repository. Once this information is in
+ the repository, it can be viewed, edited, analyzed, searched, and related to other content. DNA defines a Java
+ interface that sequencers must implement. DNA sequencers operate upon any JCR-compliant repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Analyses</emphasis>
+ are pluggable components that analyze the content and the relationships between the content to generate reports or
+ to answer queries. DNA will include some standard analyzers, like dependency analysis and similarity analysis, that
+ are commonly needed by many different solutions. DNA analyzers operate upon any JCR-compliant repository.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Views</emphasis>
+ are definitions of how types of information are to be presented in a user interface to allow for creation, reading,
+ editing, and deletion of information. DNA view definitions consist of data stored in a JCR repository, and as such
+ views can be easily added, changed or removed entirely by using the DNA Web Application, requiring no programming.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Federation</emphasis>
+ is an implementation of the JCR API that builds the content within the repository by accessing and integrating
+ information from multiple sources. DNA Federation allows the integration of external system, like other JCR
+ repositories, databases, applications, and services.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Connectors</emphasis>
+ are used to communicate with these external sources of information. In the federation engine, each source is able to
+ contribute node structure and node properties to any part of the federated graph, although typically many connectors
+ will contribute most of their information to isolated subgraphs. The result is that integration from a wide range of
+ systems can be integrated and accessed through the DNA Web Application, DNA Publishing Server, and DNA WebDAV
+ Server. Connectors also may optionally participate in distributed transactions by exposing an XAResource.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis role="strong">DNA Maven</emphasis>
+ is a classloader library compatible with Maven 2 project dependencies. This allows the creation of Java ClassLoader
+ instances using Maven 2 style paths, and all dependencies are transitively managed and included.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect1>
+ <sect1>
<title>Sequencers</title>
<para> The current JBoss DNA release contains a sequencing framework that is designed to sequence data (typically files)
stored in a JCR repository to automatically extract meaningful and useful information. This additional information is then
@@ -150,11 +280,11 @@
<itemizedlist>
<listitem>
<para>
- Image sequencer - A sequencer that processes the binary content of an image file, extracts the metadata for the
- image, and then writes that image metadata to the repository. Gets the file format, image resolution, number of bits
- per pixel and optionally number of images, comments and physical resolution from JPEG, GIF, BMP, PCX, PNG, IFF, RAS,
- PBM, PGM, PPM and PSD files. (This sequencer may be improved in the future to also extract EXIF metadata from JPEG
- files; see
+ <emphasis role="strong">Image sequencer</emphasis>
+ - A sequencer that processes the binary content of an image file, extracts the metadata for the image, and then
+ writes that image metadata to the repository. Gets the file format, image resolution, number of bits per pixel and
+ optionally number of images, comments and physical resolution from JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM, PGM, PPM
+ and PSD files. (This sequencer may be improved in the future to also extract EXIF metadata from JPEG files; see
<ulink url="http://jira.jboss.org/jira/browse/DNA-26">DNA-26</ulink>
.)
</para>
@@ -167,94 +297,103 @@
<itemizedlist>
<listitem>
<para>
- XML Schema Document (XSD) Sequencer - Process XSD files and extract the various elements, attributes, complex types,
- simple types, and groups. (See
+ <emphasis role="strong">XML Schema Document (XSD) Sequencer</emphasis>
+ - Process XSD files and extract the various elements, attributes, complex types, simple types, and groups. (See
<ulink url="http://jira.jboss.org/jira/browse/DNA-32">DNA-32</ulink>
)
</para>
</listitem>
<listitem>
<para>
- Web Service Definition Language (WSDL) Sequencer - Process WSDL files and extract the services, bindings, ports,
- operations, parameters, and other information. (See
+ <emphasis role="strong">Web Service Definition Language (WSDL) Sequencer</emphasis>
+ - Process WSDL files and extract the services, bindings, ports, operations, parameters, and other information. (See
<ulink url="http://jira.jboss.org/jira/browse/DNA-33">DNA-33</ulink>
)
</para>
</listitem>
<listitem>
<para>
- Hibernate File Sequencer - Process Hibernate configuration (cfg.xml) and mapping (hbm.xml) files to extract the
- configuration and mapping information. (See
+ <emphasis role="strong">Hibernate File Sequencer</emphasis>
+ - Process Hibernate configuration (cfg.xml) and mapping (hbm.xml) files to extract the configuration and mapping
+ information. (See
<ulink url="http://jira.jboss.org/jira/browse/DNA-61">DNA-61</ulink>
)
</para>
</listitem>
<listitem>
<para>
- XML Metadata Interchange (XMI) Sequencer - Process XMI documents that contain UML models or models using another
- metamodel, extracting the model structure into the repository. (See
+ <emphasis role="strong">XML Metadata Interchange (XMI) Sequencer</emphasis>
+ - Process XMI documents that contain UML models or models using another metamodel, extracting the model structure
+ into the repository. (See
<ulink url="http://jira.jboss.org/jira/browse/DNA-31">DNA-31</ulink>
)
</para>
</listitem>
<listitem>
<para>
- ZIP Archive Sequencer - Process ZIP archive files to extract (explode) the contents into the repository. (See
+ <emphasis role="strong">ZIP Archive Sequencer</emphasis>
+ - Process ZIP archive files to extract (explode) the contents into the repository. (See
<ulink url="http://jira.jboss.org/jira/browse/DNA-63">DNA-63</ulink>
)
</para>
</listitem>
<listitem>
<para>
- Java Archive (JAR) Sequencer - Process JAR files to extract (explode) the contents into the classes and file
- resources. (See
+ <emphasis role="strong">Java Archive (JAR) Sequencer</emphasis>
+ - Process JAR files to extract (explode) the contents into the classes and file resources. (See
<ulink url="http://jira.jboss.org/jira/browse/DNA-64">DNA-64</ulink>
)
</para>
</listitem>
<listitem>
<para>
- Java Class File Sequencer - Process Java class files (bytecode) to extract the class structure (including
- annotations) into the repository. (See
+ <emphasis role="strong">Java Class File Sequencer</emphasis>
+ - Process Java class files (bytecode) to extract the class structure (including annotations) into the repository.
+ (See
<ulink url="http://jira.jboss.org/jira/browse/DNA-62">DNA-62</ulink>
)
</para>
</listitem>
<listitem>
<para>
- Java Source File Sequencer - Process Java source files (bytecode) to extract the class structure (including
- annotations) into the repository. (See
+ <emphasis role="strong">Java Source File Sequencer</emphasis>
+ - Process Java source files (bytecode) to extract the class structure (including annotations) into the repository.
+ (See
<ulink url="http://jira.jboss.org/jira/browse/DNA-51">DNA-51</ulink>
)
</para>
</listitem>
<listitem>
<para>
- PDF Sequencer - Process PDF files to extract the document metadata, including table of contents. (See
+ <emphasis role="strong">PDF Sequencer</emphasis>
+ - Process PDF files to extract the document metadata, including table of contents. (See
<ulink url="http://jira.jboss.org/jira/browse/DNA-50">DNA-50</ulink>
)
</para>
</listitem>
<listitem>
<para>
- Maven 2 POM Sequencer - Process Maven 2 Project Object Model (POM) files to extract the project information,
- dependencies, plugins, and other content. (See
+ <emphasis role="strong">Maven 2 POM Sequencer</emphasis>
+ - Process Maven 2 Project Object Model (POM) files to extract the project information, dependencies, plugins, and
+ other content. (See
<ulink url="http://jira.jboss.org/jira/browse/DNA-24">DNA-24</ulink>
)
</para>
</listitem>
<listitem>
<para>
- Data Definition Language (DDL) Sequencer - Process various dialects of DDL, including that from Oracle, SQL Server,
- MySQL, PostgreSQL, and others. May need to be split up into a different sequencer for each dialect. (See
+ <emphasis role="strong">Data Definition Language (DDL) Sequencer</emphasis>
+ - Process various dialects of DDL, including that from Oracle, SQL Server, MySQL, PostgreSQL, and others. May need
+ to be split up into a different sequencer for each dialect. (See
<ulink url="http://jira.jboss.org/jira/browse/DNA-26">DNA-26</ulink>
)
</para>
</listitem>
<listitem>
<para>
- MP3 and MP4 Sequencer - Process MP3 and MP4 audio files to extract the name of the song, artist, album, track
- number, and other metadata. (See
+ <emphasis role="strong">MP3 and MP4 Sequencer</emphasis>
+ - Process MP3 and MP4 audio files to extract the name of the song, artist, album, track number, and other metadata.
+ (See
<ulink url="http://jira.jboss.org/jira/browse/DNA-30">DNA-30</ulink>
)
</para>
@@ -265,8 +404,8 @@
The
<link linkend="using_dna">examples</link>
in this book go into more detail about how sequencers are managed and used, and
-<link linkend="custom_sequencers">Chapter 5</link> goes into detail about how to
- write custom sequencers.
+ <link linkend="custom_sequencers">Chapter 5</link>
+ goes into detail about how to write custom sequencers.
</para>
</sect1>
<sect1>
@@ -299,41 +438,63 @@
in those systems. Some ideas for connectors include:
<itemizedlist>
<listitem>
- <para>JCR Repository Connector - Connect to and interact with other JCR repositories.</para>
+ <para>
+ <emphasis role="strong">JCR Repository Connector</emphasis>
+ - Connect to and interact with other JCR repositories.
+ </para>
</listitem>
<listitem>
- <para>File System Connector - Expose the files and directories on a file system through JCR.</para>
+ <para>
+ <emphasis role="strong">File System Connector</emphasis>
+ - Expose the files and directories on a file system through JCR.
+ </para>
</listitem>
<listitem>
- <para>Maven 2 Repository Connector - Access and expose the contents of a Maven 2 repository (either on the
- local file system or via HTTP) through JCR.</para>
+ <para>
+ <emphasis role="strong">Maven 2 Repository Connector</emphasis>
+ - Access and expose the contents of a Maven 2 repository (either on the local file system or via HTTP) through
+ JCR.
+ </para>
</listitem>
<listitem>
- <para>JDBC Metadata Connector - Connect to relational databases via JDBC and expose their schema as content in a
- repository.</para>
+ <para>
+ <emphasis role="strong">JDBC Metadata Connector</emphasis>
+ - Connect to relational databases via JDBC and expose their schema as content in a repository.
+ </para>
</listitem>
<listitem>
- <para>UDDI Connector - Interact with UDDI registries to integrate their content into a repository.</para>
+ <para>
+ <emphasis role="strong">UDDI Connector</emphasis>
+ - Interact with UDDI registries to integrate their content into a repository.
+ </para>
</listitem>
<listitem>
<para>
- SVN Connector - Interact with Subversion software configuration management (SCM) repositories to expose the
- managed resources through JCR. Consider using
+ <emphasis role="strong">SVN Connector</emphasis>
+ - Interact with Subversion software configuration management (SCM) repositories to expose the managed resources
+ through JCR. Consider using
<ulink url="http://svnkit.com/">SVNkit</ulink>
(dual license) library for API into Subversion.
</para>
</listitem>
<listitem>
- <para>CVS Connector - Interact with CVS software configuration management (SCM) repositories, to expose the
- managed resources through JCR.</para>
+ <para>
+ <emphasis role="strong">CVS Connector</emphasis>
+ - Interact with CVS software configuration management (SCM) repositories, to expose the managed resources through
+ JCR.
+ </para>
</listitem>
<listitem>
- <para>JDBC Storage Connector - Store and access information in a relational database. Also useful for persisting
- information in the federated repository not stored elsewhere.</para>
+ <para>
+ <emphasis role="strong">JDBC Storage Connector</emphasis>
+ - Store and access information in a relational database. Also useful for persisting information in the federated
+ repository not stored elsewhere.
+ </para>
</listitem>
<listitem>
<para>
- Distributed Database Connector - Store and access information in a
+ <emphasis role="strong">Distributed Database Connector</emphasis>
+ - Store and access information in a
<ulink url="http://www.hypertable.org/">Hypertable</ulink>
or
<ulink url="http://hadoop.apache.org/hbase/">HBase</ulink>
@@ -535,7 +696,7 @@
<chapter id="future_directions">
<title>Future directions</title>
<para>What's next for JBoss DNA? Well, sequencers are just the beginning.
- Remember our <link linkend="jboss_dna">architecture</link>?
+ Remember our <link linkend="architecture">architecture</link>?
There are a lot of components on our roadmap, including federating
</para>
16 years
DNA SVN: r113 - trunk/docs/getting_started/en.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-04-30 13:52:22 -0400 (Wed, 30 Apr 2008)
New Revision: 113
Removed:
trunk/docs/getting_started/en/modules/
Log:
Removed unused files.
16 years
DNA SVN: r112 - trunk/docs/getting_started/en.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-04-30 13:48:50 -0400 (Wed, 30 Apr 2008)
New Revision: 112
Added:
trunk/docs/getting_started/en/Author_Group.xml
trunk/docs/getting_started/en/Legal_Notice.xml
Modified:
trunk/docs/getting_started/en/master.xml
Log:
Restructured into a single docbook file, using an older version of the JDocBook plugin
Added: trunk/docs/getting_started/en/Author_Group.xml
===================================================================
--- trunk/docs/getting_started/en/Author_Group.xml (rev 0)
+++ trunk/docs/getting_started/en/Author_Group.xml 2008-04-30 17:48:50 UTC (rev 112)
@@ -0,0 +1,6 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE authorgroup PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<authorgroup>
+ <corpauthor>Randall Hauch</corpauthor>
+</authorgroup>
\ No newline at end of file
Added: trunk/docs/getting_started/en/Legal_Notice.xml
===================================================================
--- trunk/docs/getting_started/en/Legal_Notice.xml (rev 0)
+++ trunk/docs/getting_started/en/Legal_Notice.xml 2008-04-30 17:48:50 UTC (rev 112)
@@ -0,0 +1,16 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE authorgroup PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<legalnotice id="Book-Legal_Notice">
+ <title>Legal Notice</title>
+ <para>
+ <address>
+ <street>1801 Varsity Drive</street>
+ <city>Raleigh</city>, <state>NC</state> <postcode>27606-2072</postcode> <country>USA</country>
+ <phone>Phone: +1 919 754 3700</phone>
+ <phone>Phone: 888 733 4281</phone>
+ <fax>Fax: +1 919 754 3701</fax>
+ <pob>PO Box 13588</pob>, <city>Research Triangle Park</city>, <state>NC</state> <postcode>27709</postcode> <country>USA</country>
+ </address>
+ </para>
+</legalnotice>
\ No newline at end of file
Modified: trunk/docs/getting_started/en/master.xml
===================================================================
--- trunk/docs/getting_started/en/master.xml 2008-04-28 19:55:31 UTC (rev 111)
+++ trunk/docs/getting_started/en/master.xml 2008-04-30 17:48:50 UTC (rev 112)
@@ -1,41 +1,26 @@
-<?xml version='1.0' encoding='ISO-8859-1'?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
- "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
-<book lang="en">
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+<!ENTITY % RH-ENTITIES SYSTEM "Common_Config/rh-entities.ent">
+]>
+<book>
<bookinfo>
<title>JBoss DNA</title>
<subtitle>Getting Started Guide</subtitle>
- <releaseinfo>0.1</releaseinfo>
+ <issuenum>0.1</issuenum>
+ <productnumber>1</productnumber>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Author_Group.xml"/>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Legal_Notice.xml"/>
</bookinfo>
- <toc>
- <title>Table of Contents</title>
- </toc>
<preface id="preface" revision="1">
<title>What this book covers</title>
<para>The goal of this book is to help you learn about JBoss DNA and how you can use it in your own applications to get the
most out of your JCR repositories.</para>
- <para> The first part of the book provides some background on content repositories and the Java Content Repository (JCR) API.
- Content repositories are an important aspect of JBoss DNA, so it's probably worth reading even if you're already familiar
- with these technologies. Besides, it's really not that long.</para>
- <para> The If you're already familiar with these technologies, you can probably skip this section. However, most readers will
- probably want to</para>
- <para> and then introduces JBoss DNA project and its relationship to JCR. The second part</para>
- <para>
- <link linkend="part1">Part I intr oduces JBoss DNAFeature Analysis and Design</link>
- Part 1
+ <para>The part of the book starts out with an introduction to content repositories and an overview of the JCR API, both of which are an
+ important aspect of JBoss DNA. This is followed by an overview of the the JBoss DNA project, it's architecture, and a basic
+ roadmap for what's coming next.</para>
+ <para>The next part of the book covers how to download and build the examples, how to use JBoss DNA with
+ existing repositories, and how to build and use custom sequencers.
</para>
- <para>This document introduces the JBoss DNA project.</para>
- <itemizedlist>
- <listitem>
- <para>
- The build process is simplified and standardized. Just follow the instructions in this guide to setup your
- <literal>docs</literal>
- directory and copy a very simple
- <literal>pom.xml</literal>
- file.
- </para>
- </listitem>
- </itemizedlist>
<para>
If you have any questions or comments, please feel free to contact JBoss DNA's
<ulink url="mailto:dna-users@jboss.org">user mailing list</ulink>
@@ -51,10 +36,518 @@
same thing.
</para>
</preface>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/introduction.xml" xml:base="./" />
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/jboss_dna.xml" xml:base="./" />
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/downloading.xml" xml:base="./" />
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/using_dna.xml" xml:base="./" />
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/custom_sequencers.xml" xml:base="./" />
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/future_directions.xml" xml:base="./" />
+ <chapter id="introduction">
+ <title>Introduction</title>
+ <para>There are a lot of choices for how applications can store information persistently so that it can be accessed at a
+ later time and by other processes. The challenge developers face is to use an approach that most closes matches the needs of
+ their application. This choice is more important as developers choose to focus their efforts on the application-specific
+ logic, delegating much of the responsibilities for persistence to libraries and frameworks.</para>
+ <para>
+ Perhaps one of the easiest techniques is to simply store information in
+ <emphasis>files</emphasis>
+ . The Java language makes working with files relatively easy, but Java really doesn't provide many bells and whistles. So
+ using files is an easy choice when the information is either not complicated (for example property files), or when users may
+ need to read or change the information outside of the application (for example log files or configuration files). But using
+ files to persist information becomes more difficult as the information becomes more complex, as the volume of it increases,
+ or if it needs to be accessed by multiple processes. For these situations, other techniques are often a better choice.
+ </para>
+ <para>
+ Another technique built into the Java language is
+ <emphasis>Java serialization</emphasis>
+ , which is capable of persisting the state of an object graph so that it can be read back in at a later time. However, Java
+ serialization can quickly become tricky if the classes are changed, and so its beneficial usually when the information is
+ persisted for a very short period of time. For example, serialization is sometimes used to send an object graph from one
+ process to another.
+ </para>
+ <para>
+ One of the more popular persistence technologies is the
+ <emphasis>relational database</emphasis>
+ . Relational database management systems have been around for decades and are very capable. The Java Database Connectivity
+ (JDBC) API provides a standard interface for connecting to and interacting with relational databases. However, it is a
+ low-level API that requires a lot of code to use correctly, and it still doesn't abstract away the DBMS-specific SQL
+ grammar. Also, working with relational data in an object-oriented language can feel somewhat unnatural, so many developers
+ map this data to classes that fit much more cleanly into their application. The problem is that manually creating this
+ mapping layer requires a lot of repetitive and non-trivial JDBC code.
+ </para>
+ <para>
+ <emphasis>Object-relational mapping</emphasis>
+ libraries automate the creation of this mapping layer and result in far less code that is much more maintainable with often
+ as good (if not better) performance than handwritten JDBC code. The new
+ <ulink url="http://java.sun.com/developer/technicalArticles/J2EE/jpa/">Java Persistence API (JPA)</ulink>
+ provide a standard mechanism for defining the mappings (through annotations) and working with these entity objects. Several
+ commercial and open-source libraries implement JPA, and some even offer additional capabilities and features that go beyond
+ JPA. For example,
+ <ulink url="http://www.hibernate.org">Hibernate</ulink>
+ is one of the most feature-rich JPA implementations and offers object caching, statement caching, extra association
+ mappings, and other features that help to improve performance and usefulness.
+ </para>
+ <para>
+ While relational databases and JPA are solutions that work for many applications, they become more limited in cases when the
+ information structure is highly flexible, is not known a priori, or is subject to frequent change and customization. In
+ these situations,
+ <emphasis>content repositories</emphasis>
+ may offer a better choice for persistence. Content repositories are almost a hybrid between relational databases and file
+ systems, and typically provide other capabilies as well, including versioning, indexing, search, access control,
+ transactions, and observation. Because of this, content repositories are used by content management systems (CMS), document
+ management systems (DMS), and other applications that manage electronic files (e.g., documents, images, multi-media, web
+ content, etc.) and metadata associated with them (e.g., author, date, status, security information, etc.). The
+ <ulink url="http://www.jcp.org/en/jsr/detail?id=170">Content Repository for Java technology API</ulink>
+ provides a standard Java API for working with content repositories. Abbreviated "JCR", this API was developed as part of the
+ Java Community Process under
+ <ulink url="http://www.jcp.org/en/jsr/detail?id=170">JSR-170</ulink>
+ and is being revised under
+ <ulink url="http://www.jcp.org/en/jsr/detail?id=283">JSR-283</ulink>
+ .
+ </para>
+ <para>
+ The
+ <emphasis>JBoss DNA project</emphasis>
+ is building the tooles and services that surround content repositories. Nearly all of these capabilities are to be hidden
+ below the JCR API and involve automated processing of the information in the repository. Thus, JBoss DNA can add value to
+ existing repository implementations. For example, JCR repositories offer the ability to upload files into the repository and
+ have the file content index for search purposes. JBoss DNA defines a library for also sequencing that content to extract
+ meaningful information and store it in the repository, where it can then be searched, accessed and analyzed using the JCR
+ API.
+ </para>
+ <para> JBoss DNA is building other features as well. One goal of JBoss DNA is to create federated repositories that
+ dynamically merge the information from multiple databases, services, applications, and other JCR repositories. Another is to
+ create customized views based upon the type of data and the role of the user that is accessing the data. And yet another is
+ to create a REST-ful API to allow the JCR content to be accessed easily by other applications written in other languages.
+ </para>
+ <para>
+ The
+ <link linkend="jboss_dna">next chapter</link>
+ in this book goes into more detail about JBoss DNA and its architecture, the different components, what's available now, and
+ what's coming in future releases.
+ <link linkend="downloading">Chapter 3</link>
+ then provides instructions for downloading and compiling the sequencer examples for the current release.
+ <link linkend="using_dna">Chapter 4</link>
+ walks through these examples, while
+ <link linkend="custom_sequencers">Chapter 5</link>
+ goes over how to create custom sequencers. Finally,
+ <link linkend="future_directions">Chapter 6</link>
+ wraps things up.
+ </para>
+ </chapter>
+ <chapter id="jboss_dna">
+ <title>JBoss DNA</title>
+ <sect1>
+ <title>Sequencers</title>
+ <para> The current JBoss DNA release contains a sequencing framework that is designed to sequence data (typically files)
+ stored in a JCR repository to automatically extract meaningful and useful information. This additional information is then
+ saved back into the repository, where it can be accessed and used.</para>
+ <para> In other words, you can just upload various kinds of files into a JCR repository, and DNA automatically processes
+ those files to extract meaningful structured information. For example, load DDL files into the repository, and let
+ sequencers extract the structure and metadata for the database schema. Load Hibernate configuration files into the
+ repository, and let sequencers extract the schema and mapping information. Load Java source into the repository, and let
+ sequencers extract the class structure, JavaDoc, annotations. Load a PNG, JPEG, or other image into the repository, and
+ let sequencers extract the metadata from the image and save it in the repository. The same with XSDs, WSDL, WS policies,
+ UML, MetaMatrix models, etc.</para>
+ <para>
+ JBoss DNA sequencers sit on top of existing JCR repositories (including federated repositories) - it basically extracts
+ more useful information from what's already stored in the repository. And it uses the existing JCR versioning system. Each
+ sequencer typically processes a single kind of file format. The following sequencer is included in JBoss DNA:
+ <itemizedlist>
+ <listitem>
+ <para>
+ Image sequencer - A sequencer that processes the binary content of an image file, extracts the metadata for the
+ image, and then writes that image metadata to the repository. Gets the file format, image resolution, number of bits
+ per pixel and optionally number of images, comments and physical resolution from JPEG, GIF, BMP, PCX, PNG, IFF, RAS,
+ PBM, PGM, PPM and PSD files. (This sequencer may be improved in the future to also extract EXIF metadata from JPEG
+ files; see
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-26">DNA-26</ulink>
+ .)
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ As the community develops additional sequencers, they will also be included in JBoss DNA. Some of those that have been
+ identified as being useful include:
+ <itemizedlist>
+ <listitem>
+ <para>
+ XML Schema Document (XSD) Sequencer - Process XSD files and extract the various elements, attributes, complex types,
+ simple types, and groups. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-32">DNA-32</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Web Service Definition Language (WSDL) Sequencer - Process WSDL files and extract the services, bindings, ports,
+ operations, parameters, and other information. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-33">DNA-33</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Hibernate File Sequencer - Process Hibernate configuration (cfg.xml) and mapping (hbm.xml) files to extract the
+ configuration and mapping information. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-61">DNA-61</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ XML Metadata Interchange (XMI) Sequencer - Process XMI documents that contain UML models or models using another
+ metamodel, extracting the model structure into the repository. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-31">DNA-31</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ ZIP Archive Sequencer - Process ZIP archive files to extract (explode) the contents into the repository. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-63">DNA-63</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Java Archive (JAR) Sequencer - Process JAR files to extract (explode) the contents into the classes and file
+ resources. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-64">DNA-64</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Java Class File Sequencer - Process Java class files (bytecode) to extract the class structure (including
+ annotations) into the repository. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-62">DNA-62</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Java Source File Sequencer - Process Java source files (bytecode) to extract the class structure (including
+ annotations) into the repository. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-51">DNA-51</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ PDF Sequencer - Process PDF files to extract the document metadata, including table of contents. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-50">DNA-50</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Maven 2 POM Sequencer - Process Maven 2 Project Object Model (POM) files to extract the project information,
+ dependencies, plugins, and other content. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-24">DNA-24</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Data Definition Language (DDL) Sequencer - Process various dialects of DDL, including that from Oracle, SQL Server,
+ MySQL, PostgreSQL, and others. May need to be split up into a different sequencer for each dialect. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-26">DNA-26</ulink>
+ )
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ MP3 and MP4 Sequencer - Process MP3 and MP4 audio files to extract the name of the song, artist, album, track
+ number, and other metadata. (See
+ <ulink url="http://jira.jboss.org/jira/browse/DNA-30">DNA-30</ulink>
+ )
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ The
+ <link linkend="using_dna">examples</link>
+ in this book go into more detail about how sequencers are managed and used, and
+<link linkend="custom_sequencers">Chapter 5</link> goes into detail about how to
+ write custom sequencers.
+ </para>
+ </sect1>
+ <sect1>
+ <title>Federation</title>
+ <para>There is a lot of information stored in many of different places: databases, repositories, SCM systems,
+ registries, file systems, services, etc. The purpose of the federation engine is to allow applications to use the JCR API
+ to access that information as if it were all stored in a single JCR repository, but to really leave the information where
+ it is.</para>
+ <para>Why not just move the information into a JCR repository? Most likely there are existing applications that rely upon
+ that information being where it is. If we were to move it, then all those applications would break. Or they'd have to be
+ changed to use JCR. If the information is being used, the most practical thing is to leave it where it is.</para>
+ <para>
+ Then why not just copy the information into a JCR repository? Actually, there are times when it's perfectly reasonable to
+ make a copy of the data. Perhaps the system managing the existing information cannot handle the additional load of more
+ clients. Or, perhaps the information doesn't change, or it does change and we want snapshots that don't change. But more
+ likely, the data
+ <emphasis>does</emphasis>
+ change. So if applications are to use the most current information and we make copies of the data, we have to keep the
+ copies synchronized with the master. That's generally a lot of work.
+ </para>
+ <para>The JBoss DNA federation engine lets us leave the information where it is, yet lets client applications use the JCR
+ API to access all the information without caring where the information really exists. If the underlying information
+ changes, client applications using JCR observation will be notified of the changes. If a JBoss DNA federated repository is
+ configured to allow updates, client applications can change the information in the repository and JBoss DNA will propagate
+ those changes down to the original source.</para>
+ <sect2>
+ <title>Connectors</title>
+ <para>
+ The JBoss DNA federation engine will use connectors to interact with different information sources to get at the content
+ in those systems. Some ideas for connectors include:
+ <itemizedlist>
+ <listitem>
+ <para>JCR Repository Connector - Connect to and interact with other JCR repositories.</para>
+ </listitem>
+ <listitem>
+ <para>File System Connector - Expose the files and directories on a file system through JCR.</para>
+ </listitem>
+ <listitem>
+ <para>Maven 2 Repository Connector - Access and expose the contents of a Maven 2 repository (either on the
+ local file system or via HTTP) through JCR.</para>
+ </listitem>
+ <listitem>
+ <para>JDBC Metadata Connector - Connect to relational databases via JDBC and expose their schema as content in a
+ repository.</para>
+ </listitem>
+ <listitem>
+ <para>UDDI Connector - Interact with UDDI registries to integrate their content into a repository.</para>
+ </listitem>
+ <listitem>
+ <para>
+ SVN Connector - Interact with Subversion software configuration management (SCM) repositories to expose the
+ managed resources through JCR. Consider using
+ <ulink url="http://svnkit.com/">SVNkit</ulink>
+ (dual license) library for API into Subversion.
+ </para>
+ </listitem>
+ <listitem>
+ <para>CVS Connector - Interact with CVS software configuration management (SCM) repositories, to expose the
+ managed resources through JCR.</para>
+ </listitem>
+ <listitem>
+ <para>JDBC Storage Connector - Store and access information in a relational database. Also useful for persisting
+ information in the federated repository not stored elsewhere.</para>
+ </listitem>
+ <listitem>
+ <para>
+ Distributed Database Connector - Store and access information in a
+ <ulink url="http://www.hypertable.org/">Hypertable</ulink>
+ or
+ <ulink url="http://hadoop.apache.org/hbase/">HBase</ulink>
+ distributed databases. Also useful for persisting information in the federated repository not stored elsewhere.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ If the connectors allow the information they contribute to be updated, they must provide an
+ <code>XAResource</code>
+ implementation that can be used with a Java Transaction Service. Connectors that provide read-only access need not
+ provide an implementation.
+ </para>
+ </sect2>
+ <sect2>
+ <title>Sources</title>
+ <para>
+ Each JBoss DNA federated repository is configured to federate and integrate information from one or more
+ <emphasis>sources</emphasis>
+ . Each source contains the configuration details (e.g., connection information, location, properties, options, etc.) for
+ working with that particular source, as well as a reference to the connector that should be used to establish
+ connections to the source. And of course, sources can be added or removed without having to stop and restart the
+ federated repository.
+ </para>
+ </sect2>
+ <sect2>
+ <title>Building the unified graph</title>
+ <para> The federation engine works by effectively building up a single graph by querying each source and merging or
+ unifying the responses. This information is cached, which improves performance, reduces the number of (potentially
+ expensive) remote calls, reduces the load on the sources, and helps mitigate problems with source availability. As
+ clients interact with the repository, this cache is consulted first. When the requested portion of the graph (or
+ "subgraph") is contained completely in the cache, it is retuned immediately. However, if any part of the requested
+ subgraph is not in the cache, each source is consulted for their contributions to that subgraph, and any results are
+ cached.</para>
+ <para> This basic flow makes it possible for the federated repository to build up a local cache of the integrated graph
+ (or at least the portions that are used by clients). In fact, the federated repository caches information in a manner
+ that is similar to that of the Domain Name System (DNS). As sources are consulted for their contributions, the source
+ also specifies whether it is the authoritative source for this information (some sources that are themselves federated
+ may not be the information's authority), whether the information may be modified, the time-to-live (TTL) value (the time
+ after which the cached information should be refreshed), and the expiration time (the time after which the cached
+ information is no longer valid). In effect, the source has complete control over how the information it contributes is
+ cached and used.</para>
+ <para>
+ The federated repository also needs to incorporate
+ <emphasis>negative caching</emphasis>
+ , which is storage of the knowledge that something does not exist. Sources can be configured to contribute information
+ only below certain paths (e.g.,
+ <code>/A/B/C</code>
+ ), and the federation engine can take advantage of this by never consulting that source for contributions to information
+ on other paths. However, below that path, any negative responses must also be cached (with appropriate TTL and expiry
+ parameters) to prevent the exclusion of that source (in case the source has information to contribute at a later time)
+ or the frequent checking with the source.
+ </para>
+ </sect2>
+ <sect2>
+ <title>Queries</title>
+ <para> The JBoss DNA federated repository will also support queries against the integrated and unified graph. In some
+ situations the query can be determined to apply to a single source, but in most situations the query must be planned
+ (and possibly rewritten) such that it can be pushed down to all the appropriate sources. Also, the cached results must
+ be consulted prior to returning the query results, as the results from one source might have contributions from another
+ source.</para>
+ <para> It is hoped that the MetaMatrix query engine can be used for this purpose, after it is open sourced. This engine
+ implements sophisticated query planning and optimization techniques for working efficiently with multiple sources.
+ </para>
+ </sect2>
+ <sect2>
+ <title>Updates</title>
+ <para>
+ The JBoss DNA federated repositories also make it possible for client applications to make changes to the unified graph
+ within the context of distributed transactions. According to the JCR API, client applications use the Java Transaction
+ API (JTA) to control the boundaries of their transactions. Meanwhile, the federated repository uses a
+ <ulink url="http://www.jboss.org/jbosstm/">distributed transaction service</ulink>
+ to coordinate the XA resources provided by the connectors.
+ </para>
+ <para> It is quite possible that clients add properties to nodes in the unified graph, and that this information cannot be
+ handled by the same underlying source that contributed to the node. In this case, the federated repository can be
+ configured with a fallback source that will be used used to store this "extra" information.</para>
+ <para>
+ It is a goal that non-XA sources (i.e., sources that use connectors without XA resources) can participate in distributed
+ transactions through the use of
+ <emphasis>compensating transactions</emphasis>
+ . Because the JBoss DNA federation engine implements the JCR observation system, it is capable of recording all of the
+ changes made to the distributed graph (and those changes sent to each updatable source). Therefore, if a non-XA source
+ is involved in a distributed transaction that must be rolled back, any changes made to non-XA sources can be undone. (Of
+ course, this does not make the underlying source transactional: non-transactional sources still may expose the interim
+ changes to other clients.)
+ </para>
+ </sect2>
+ <sect2>
+ <title>Events</title>
+ <para> The JCR API supports observing a repository to receive notifications of additions, changes and deletions of nodes
+ and properties. The JBoss DNA federated repository will support this API through two primary means.</para>
+ <para> When the changes are made through the federated repository, the JBoss DNA federation engine is well aware of the
+ set of changes that have been (or are being) made to the unified graph. These events are directly propagated to
+ listeners.</para>
+ <para> Sources have the ability to publish events, making it possible for the JBoss DNA federation engine and clients that
+ have registered listeners to be notified of changes in the information managed by that source. These events are first
+ processed by the federation engine and possibly altered based upon contributions from other sources. (The federation
+ engine also uses these events to update or purge information in the cache, which may add to the event set.) The
+ resulting (and possibly altered) event set is then sent to all client listeners.</para>
+ </sect2>
+ </sect1>
+ </chapter>
+ <!-- ====================================================================================================
+ Chapter
+ ==================================================================================================== -->
+ <chapter id="downloading">
+ <title>Downloading the examples</title>
+ <para>JBoss DNA is built using Maven 2, so it's much easier to following along with the examples in this document if you
+ install and configure Maven. Once this is done, you can very easily build the examples or even create a maven project that
+ depends on the JBoss DNA JARs. Maven will automatically download the right versions of the JARs, including those other
+ libraries on which JBoss DNA depends. Maven also makes it very easy to create an assembly of your final application so that
+ you can package into a distributable form.</para>
+ <para>
+ The examples created for this User Guide use Maven2 to achieve exactly this so it is highly recommended that you
+ <ulink url="http://labs.jboss.com/file-access/default/members/jbossmc/downloads/userG...">download</ulink>
+ these first and take a look at how they work.
+ </para>
+ <note>
+ <para>
+ To build and run the examples you first need to install and configure Maven 2.0.7 available from
+ <ulink url="http://maven.apache.org/">http://maven.apache.org/</ulink>
+ </para>
+ <para>Installation is performed by downloading and unzipping the maven-2.0.7-bin.zip file to a convenient
+ location on your local disk. Configuration consists of adding $MAVEN_HOME/bin to your path and adding the following
+ profile to your ~/.m2/settings.xml file:</para>
+ <programlisting role="XML"><settings>
+ <profiles>
+ <profile>
+ <id>jboss.repository</id>
+ <activation>
+ <property>
+ <name>!jboss.repository.off</name>
+ </property>
+ </activation>
+ <repositories>
+ <repository>
+ <id>snapshots.jboss.org</id>
+ <url>http://snapshots.jboss.org/maven2</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
+ <repository>
+ <id>repository.jboss.org</id>
+ <url>http://repository.jboss.org/maven2</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+ <pluginRepositories>
+ <pluginRepository>
+ <id>repository.jboss.org</id>
+ <url>http://repository.jboss.org/maven2</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </pluginRepository>
+ <pluginRepository>
+ <id>snapshots.jboss.org</id>
+ <url>http://snapshots.jboss.org/maven2</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </pluginRepository>
+ </pluginRepositories>
+ </profile>
+ </profiles>
+</settings></programlisting>
+ <para>This profile informs maven of the two JBoss repositories (snapshots and releases) that are needed to download the JBoss Microcontainer and dependant JARs.</para>
+ </note>
+ <para>Once you have configured Maven and downloaded the examples then you can go to one of the following subdirectories in the <code>examples/User_Guide</code> directory and enter <code>mvn install</code> to perform a build:</para>
+ <itemizedlist>
+ <listitem>
+ <para>gettingStarted - projects for creating and using a service together with AOP</para>
+ </listitem>
+ <listitem>
+ <para>pojoDevelopment - examples of creating and configuring POJOs using XML and annotations</para>
+ </listitem>
+ <listitem>
+ <para>aopDevelopment - examples of using AOP to add behaviour to POJOs</para>
+ </listitem>
+ <listitem>
+ <para>extending - examples of how we created various extensions to the microcontainer by creating new dependencies</para>
+ </listitem>
+ </itemizedlist>
+ <para>Instructions on how to run the individual examples can be found in the corresponding parts of this guide.</para>
+ </chapter>
+<chapter id="using_dna">
+ <title>Using JBoss DNA</title>
+ <para></para>
+</chapter>
+<chapter id="custom_sequencers">
+ <title>Custom sequencers</title>
+ <para></para>
+</chapter>
+<chapter id="future_directions">
+ <title>Future directions</title>
+ <para>What's next for JBoss DNA? Well, sequencers are just the beginning.
+ Remember our <link linkend="jboss_dna">architecture</link>?
+ There are a lot of components on our roadmap, including federating
+
+ </para>
+ <para> Roadmap: We'll start on the federation engine as soon as 0.1 is out. The 0.1 release will contain the sequencing
+ system, and while there will be one sequencer, we hope the community will help build the ones they need. Serge has started
+ on a Java sequencer, and MetaMatrix is starting on a sequencer for MetaMatrix models. Check out JIRA for the list of the
+ ones we've thought of.</para>
+ <para> Your need for a web UI is very typical, which is why we also want to create a web interface (and RESTful service) that
+ presents data using "domain-specific" views - that is, views that are specific to the type of data and user role. For
+ example, if a user is viewing database information, the views should be structured to show all the information for a table
+ and its columns, keys, and indexes. (This is in contrast with a "generic" node-based view where there is one page that shows
+ the table and only links to the other columns, keys, etc. See http://www.jcr-explorer.org/screenshots.html for an example of
+ a "generic" web UI.)</para>
+</chapter>
</book>
\ No newline at end of file
16 years
DNA SVN: r111 - in trunk/docs/getting_started/en: modules and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-04-28 15:55:31 -0400 (Mon, 28 Apr 2008)
New Revision: 111
Added:
trunk/docs/getting_started/en/modules/custom_sequencers.xml
trunk/docs/getting_started/en/modules/downloading.xml
trunk/docs/getting_started/en/modules/future_directions.xml
trunk/docs/getting_started/en/modules/jboss_dna.xml
trunk/docs/getting_started/en/modules/using_dna.xml
Removed:
trunk/docs/getting_started/en/modules/styles.xml
Modified:
trunk/docs/getting_started/en/master.xml
trunk/docs/getting_started/en/modules/introduction.xml
Log:
Committing interim state of the document, which is still very rough.
Modified: trunk/docs/getting_started/en/master.xml
===================================================================
--- trunk/docs/getting_started/en/master.xml 2008-04-25 04:02:32 UTC (rev 110)
+++ trunk/docs/getting_started/en/master.xml 2008-04-28 19:55:31 UTC (rev 111)
@@ -1,30 +1,60 @@
<?xml version='1.0' encoding='ISO-8859-1'?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3CR3//EN" "../../../../docbook-support/support/docbook-dtd/docbookx.dtd" [
-<!ENTITY introduction SYSTEM "modules/introduction.xml">
-<!ENTITY styles SYSTEM "modules/styles.xml">
-]>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<book lang="en">
<bookinfo>
<title>JBoss DNA</title>
<subtitle>Getting Started Guide</subtitle>
<releaseinfo>0.1</releaseinfo>
</bookinfo>
- <toc/>
- <preface id="target" revision="1">
- <title>Target Audience</title>
- <para>This guide is for anybody who is new to JBoss DNA, and will help you learn the ins and outs of
- configuring and using JBoss DNA. </para>
- </preface>
+ <toc>
+ <title>Table of Contents</title>
+ </toc>
<preface id="preface" revision="1">
- <title>Preface</title>
+ <title>What this book covers</title>
+ <para>The goal of this book is to help you learn about JBoss DNA and how you can use it in your own applications to get the
+ most out of your JCR repositories.</para>
+ <para> The first part of the book provides some background on content repositories and the Java Content Repository (JCR) API.
+ Content repositories are an important aspect of JBoss DNA, so it's probably worth reading even if you're already familiar
+ with these technologies. Besides, it's really not that long.</para>
+ <para> The If you're already familiar with these technologies, you can probably skip this section. However, most readers will
+ probably want to</para>
+ <para> and then introduces JBoss DNA project and its relationship to JCR. The second part</para>
+ <para>
+ <link linkend="part1">Part I intr oduces JBoss DNAFeature Analysis and Design</link>
+ Part 1
+ </para>
<para>This document introduces the JBoss DNA project.</para>
<itemizedlist>
<listitem>
- <para>The build process is simplified and standardized. Just
- follow the instructions in this guide to setup your <literal>docs</literal>
- directory and copy a very simple <literal>pom.xml</literal> file. </para>
+ <para>
+ The build process is simplified and standardized. Just follow the instructions in this guide to setup your
+ <literal>docs</literal>
+ directory and copy a very simple
+ <literal>pom.xml</literal>
+ file.
+ </para>
</listitem>
</itemizedlist>
- <para> If you have any questions, please feel free to contact <ulink url="mailto:rhauch@jboss.org">Randall Hauch</ulink> (Project Lead) for more information. </para>
+ <para>
+ If you have any questions or comments, please feel free to contact JBoss DNA's
+ <ulink url="mailto:dna-users@jboss.org">user mailing list</ulink>
+ or use the
+ <ulink url="http://www.jboss.com/index.html?module=bb&op=viewforum&f=272">user forums</ulink>
+ . If you'd like to get involved on the project, join the
+ <ulink url="http://www.jboss.org/dna/lists.html">mailing lists</ulink>
+ ,
+ <ulink url="http://www.jboss.org/dna/subversion.html">download the code</ulink>
+ and get it building, and visit our
+ <ulink url="http://jira.jboss.org/jira/browse/DNA">JIRA issue management system</ulink>
+ . If there's something in particular you're interested in, talk with the community - there may be others interested in the
+ same thing.
+ </para>
</preface>
-&introduction;&howto;&styles;</book>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/introduction.xml" xml:base="./" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/jboss_dna.xml" xml:base="./" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/downloading.xml" xml:base="./" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/using_dna.xml" xml:base="./" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/custom_sequencers.xml" xml:base="./" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="modules/future_directions.xml" xml:base="./" />
+</book>
\ No newline at end of file
Added: trunk/docs/getting_started/en/modules/custom_sequencers.xml
===================================================================
--- trunk/docs/getting_started/en/modules/custom_sequencers.xml (rev 0)
+++ trunk/docs/getting_started/en/modules/custom_sequencers.xml 2008-04-28 19:55:31 UTC (rev 111)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+<chapter id="custom_sequencers">
+ <title>Custom sequencers</title>
+ <para></para>
+</chapter>
\ No newline at end of file
Property changes on: trunk/docs/getting_started/en/modules/custom_sequencers.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied: trunk/docs/getting_started/en/modules/downloading.xml (from rev 106, trunk/docs/getting_started/en/modules/styles.xml)
===================================================================
--- trunk/docs/getting_started/en/modules/downloading.xml (rev 0)
+++ trunk/docs/getting_started/en/modules/downloading.xml 2008-04-28 19:55:31 UTC (rev 111)
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+<chapter id="downloading">
+ <title>Downloading the examples</title>
+ <para>JBoss DNA is built using Maven 2, so it's much easier to following along with the examples in this document
+ if you install and configure Maven. Once this is done, you can very easily build the examples or even create a maven project that
+ depends on the JBoss DNA JARs. Maven will automatically download the right versions of the JARs, including those other libraries
+ on which JBoss DNA depends. Maven also makes it very easy to create an assembly of your final application
+ so that you can package into a distributable form.</para>
+ <para>
+ The examples created for this User Guide use Maven2 to achieve exactly this so it is highly recommended that you
+ <ulink url="http://labs.jboss.com/file-access/default/members/jbossmc/downloads/userG...">download</ulink>
+ these first and take a look at how they work.
+ </para>
+ <note>
+ <para>
+ To build and run the examples you first need to install and configure Maven 2.0.7 available from
+ <ulink url="http://maven.apache.org/">http://maven.apache.org/</ulink>
+ </para>
+ <para>Installation is performed by downloading and unzipping the maven-2.0.7-bin.zip file to a convenient location
+ on your local disk. Configuration consists of adding $MAVEN_HOME/bin to your path and adding the following profile to your
+ ~/.m2/settings.xml file:</para>
+ <programlisting role="XML"><settings>
+ <profiles>
+ <profile>
+ <id>jboss.repository</id>
+ <activation>
+ <property>
+ <name>!jboss.repository.off</name>
+ </property>
+ </activation>
+ <repositories>
+ <repository>
+ <id>snapshots.jboss.org</id>
+ <url>http://snapshots.jboss.org/maven2</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </repository>
+ <repository>
+ <id>repository.jboss.org</id>
+ <url>http://repository.jboss.org/maven2</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+ <pluginRepositories>
+ <pluginRepository>
+ <id>repository.jboss.org</id>
+ <url>http://repository.jboss.org/maven2</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </pluginRepository>
+ <pluginRepository>
+ <id>snapshots.jboss.org</id>
+ <url>http://snapshots.jboss.org/maven2</url>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </pluginRepository>
+ </pluginRepositories>
+ </profile>
+ </profiles>
+</settings></programlisting>
+ <para>This profile informs maven of the two JBoss repositories (snapshots and releases) that are needed to download the JBoss Microcontainer and dependant JARs.</para>
+ </note>
+ <para>Once you have configured Maven and downloaded the examples then you can go to one of the following subdirectories in the <code>examples/User_Guide</code> directory and enter <code>mvn install</code> to perform a build:</para>
+ <itemizedlist>
+ <listitem>
+ <para>gettingStarted - projects for creating and using a service together with AOP</para>
+ </listitem>
+ <listitem>
+ <para>pojoDevelopment - examples of creating and configuring POJOs using XML and annotations</para>
+ </listitem>
+ <listitem>
+ <para>aopDevelopment - examples of using AOP to add behaviour to POJOs</para>
+ </listitem>
+ <listitem>
+ <para>extending - examples of how we created various extensions to the microcontainer by creating new dependencies</para>
+ </listitem>
+ </itemizedlist>
+ <para>Instructions on how to run the individual examples can be found in the corresponding parts of this guide.</para>
+</chapter>
\ No newline at end of file
Added: trunk/docs/getting_started/en/modules/future_directions.xml
===================================================================
--- trunk/docs/getting_started/en/modules/future_directions.xml (rev 0)
+++ trunk/docs/getting_started/en/modules/future_directions.xml 2008-04-28 19:55:31 UTC (rev 111)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+<chapter id="future_directions">
+ <title>Future directions</title>
+ <para>What's next for JBoss DNA? Well, sequencers are just the beginning.
+ Remember our <link linkend="jboss_dna">architecture</link>?
+ There are a lot of components on our roadmap, including federating
+
+ </para>
+</chapter>
\ No newline at end of file
Property changes on: trunk/docs/getting_started/en/modules/future_directions.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/docs/getting_started/en/modules/introduction.xml
===================================================================
--- trunk/docs/getting_started/en/modules/introduction.xml 2008-04-25 04:02:32 UTC (rev 110)
+++ trunk/docs/getting_started/en/modules/introduction.xml 2008-04-28 19:55:31 UTC (rev 111)
@@ -1,25 +1,94 @@
-<?xml version='1.0' encoding='UTF-8'?><chapter id="introduction">
- <title>Introduction to DocBook processing</title>
- <para>DocBook is an XML format for writing documents. It allows the author to
- focus on the content itself during the writing process instead of
- worrying about the presentation. </para>
- <para>Using standard DocBook tags, we can tag the content according to
- its syntatic structure. The DocBook document is then processed using
- XSL stylesheets so that each tagged DocBook element is transformed to a
- corresponding element in the target output format. For example each <para></para> element in DocBook could be transformed into a <p></p> element in XHTML. </para>
- <para>Using different XSL stylesheets, we can generate different
- output formats. For example, we can generate both XHTML and PDF outputs from
- a single DocBook source. We can also generate multiple versions of XHTML
- (or PDF) files each with a different style if necessary.</para>
- <para>In the JBoss DocBook system, we provide XSL stylesheets to build XHTML, PDF and Eclipse Help output formats from the DocBook source. The build process is
- illustrated in <xref linkend="build.fig"/>. </para>
- <figure id="build.fig">
- <title>The DocBook build process </title>
- <mediaobject>
- <imageobject>
- <imagedata align="center" fileref="images/build.png"/>
- </imageobject>
- </mediaobject>
- </figure>
- <para>XHTML is used instead of HTML as it ensures that the content is completely separated from its style using Cascading Style Sheets (CSS) and image files.</para>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+<chapter id="introduction">
+ <title>Introduction</title>
+ <para>There are a lot of choices for how applications can store information persistently so that it can be accessed at a
+ later time and by other processes. The challenge developers face is to use an approach that most closes matches the needs of
+ their application. This choice is more important as developers choose to focus their efforts on the application-specific
+ logic, delegating much of the responsibilities for persistence to libraries and frameworks.</para>
+ <para>
+ Perhaps one of the easiest techniques is to simply store information in
+ <emphasis>files</emphasis>
+ . The Java language makes working with files relatively easy, but Java really doesn't provide many bells and whistles. So
+ using files is an easy choice when the information is either not complicated (for example property files), or when users may
+ need to read or change the information outside of the application (for example log files or configuration files). But using
+ files to persist information becomes more difficult as the information becomes more complex, as the volume of it increases, or
+ if it needs to be accessed by multiple processes. For these situations, other techniques are often a better choice.
+ </para>
+ <para>
+ Another technique built into the Java language is
+ <emphasis>Java serialization</emphasis>
+ , which is capable of persisting the state of an object graph so that it can be read back in at a later time. However, Java
+ serialization can quickly become tricky if the classes are changed, and so its beneficial usually when the information is
+ persisted for a very short period of time. For example, serialization is sometimes used to send an object graph from one
+ process to another.
+ </para>
+ <para>
+ One of the more popular persistence technologies is the
+ <emphasis>relational database</emphasis>
+ . Relational database management systems have been around for decades and are very capable. The Java Database Connectivity
+ (JDBC) API provides a standard interface for connecting to and interacting with relational databases. However, it is a
+ low-level API that requires a lot of code to use correctly, and it still doesn't abstract away the DBMS-specific SQL grammar.
+ Also, working with relational data in an object-oriented language can feel somewhat unnatural, so many developers map this
+ data to classes that fit much more cleanly into their application. The problem is that manually creating this mapping layer
+ requires a lot of repetitive and non-trivial JDBC code.
+ </para>
+ <para>
+ <emphasis>Object-relational mapping</emphasis>
+ libraries automate the creation of this mapping layer and result in far less code that is much more maintainable with often as
+ good (if not better) performance than handwritten JDBC code. The new
+ <ulink url="http://java.sun.com/developer/technicalArticles/J2EE/jpa/">Java Persistence API (JPA)</ulink>
+ provide a standard mechanism for defining the mappings (through annotations) and working with these entity objects. Several
+ commercial and open-source libraries implement JPA, and some even offer additional capabilities and features that go beyond
+ JPA. For example,
+ <ulink url="http://www.hibernate.org">Hibernate</ulink>
+ is one of the most feature-rich JPA implementations and offers object caching, statement caching, extra association mappings,
+ and other features that help to improve performance and usefulness.
+ </para>
+ <para>
+ While relational databases and JPA are solutions that work for many applications, they become more limited in cases when the
+ information structure is highly flexible, is not known a priori, or is subject to frequent change and customization. In these
+ situations,
+ <emphasis>content repositories</emphasis>
+ may offer a better choice for persistence. Content repositories are almost a hybrid between relational databases and file
+ systems, and typically provide other capabilies as well, including versioning, indexing, search, access control, transactions,
+ and observation. Because of this, content repositories are used by content management systems (CMS), document management
+ systems (DMS), and other applications that manage electronic files (e.g., documents, images, multi-media, web content, etc.)
+ and metadata associated with them (e.g., author, date, status, security information, etc.). The
+ <ulink url="http://www.jcp.org/en/jsr/detail?id=170">Content Repository for Java technology API</ulink>
+ provides a standard Java API for working with content repositories. Abbreviated "JCR", this API was developed as part of the
+ Java Community Process under
+ <ulink url="http://www.jcp.org/en/jsr/detail?id=170">JSR-170</ulink>
+ and is being revised under
+ <ulink url="http://www.jcp.org/en/jsr/detail?id=283">JSR-283</ulink>
+ .
+ </para>
+ <para>
+ The
+ <emphasis>JBoss DNA project</emphasis>
+ is building the tooles and services that surround content repositories. Nearly all of these capabilities are to be hidden
+ below the JCR API and involve automated processing of the information in the repository. Thus, JBoss DNA can add value to
+ existing repository implementations. For example, JCR repositories offer the ability to upload files into the repository and
+ have the file content index for search purposes. JBoss DNA defines a library for also sequencing that content to extract
+ meaningful information and store it in the repository, where it can then be searched, accessed and analyzed using the JCR API.
+ </para>
+ <para> JBoss DNA is building other features as well. One goal of JBoss DNA is to create federated repositories that dynamically
+ merge the information from multiple databases, services, applications, and other JCR repositories. Another is to create
+ customized views based upon the type of data and the role of the user that is accessing the data. And yet another is to create
+ a REST-ful API to allow the JCR content to be accessed easily by other applications written in other languages.</para>
+ <para>
+ The
+ <link linkend="jboss_dna">next chapter</link>
+ in this book goes into more detail about JBoss DNA and its architecture, the different components, what's available now, and
+ what's coming in future releases.
+ <link linkend="downloading">Chapter 3</link>
+ then provides instructions for downloading and compiling the sequencer examples for the current release.
+ <link linkend="using_dna">Chapter 4</link>
+ walks through these examples, while
+ <link linkend="custom_sequencers.xml">Chapter 5</link>
+ goes over how to create custom sequencers. Finally,
+ <link linkend="future_directions">Chapter 6</link>
+ wraps things up.
+ </para>
</chapter>
\ No newline at end of file
Added: trunk/docs/getting_started/en/modules/jboss_dna.xml
===================================================================
--- trunk/docs/getting_started/en/modules/jboss_dna.xml (rev 0)
+++ trunk/docs/getting_started/en/modules/jboss_dna.xml 2008-04-28 19:55:31 UTC (rev 111)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+<chapter id="jboss_dna">
+ <title>JBoss DNA</title>
+ <para>What's next for JBoss DNA? Well, sequencers are just the beginning.
+ Remember our <link linkend="introduction">architecture</link>?
+ There are a lot of components on our roadmap, including federating
+
+ </para>
+</chapter>
\ No newline at end of file
Property changes on: trunk/docs/getting_started/en/modules/jboss_dna.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Deleted: trunk/docs/getting_started/en/modules/styles.xml
===================================================================
--- trunk/docs/getting_started/en/modules/styles.xml 2008-04-25 04:02:32 UTC (rev 110)
+++ trunk/docs/getting_started/en/modules/styles.xml 2008-04-28 19:55:31 UTC (rev 111)
@@ -1,35 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?><chapter id="styles">
- <title>Maintaining the JBoss DocBook system</title>
- <para>The structure of the <literal>
- <ulink url="http://anonsvn.jboss.org/repos/jbossas/trunk/docbook-support/">docbook-support</ulink>
- </literal> project is
- illustrated in <xref linkend="docbook.fig"/>. The contents are as follows:</para>
- <figure id="docbook.fig">
- <title>The docbook-support project </title>
- <mediaobject>
- <imageobject>
- <imagedata align="center" fileref="images/docbook-dir.png"/>
- </imageobject>
- </mediaobject>
- </figure>
- <itemizedlist>
- <listitem>
- <para>The <literal>docs</literal> directory contains the DocBook source for this guide to
- serve as a template for other projects. </para>
- </listitem>
- <listitem>
- <para>The <literal>jbossorg-documentation</literal> directory contains the maven plugin source for the parent POM that is referenced by each project's <literal>pom.xml</literal> file. The parent POM contains common configuration information so that it does not have to be duplicated across multiple JBoss.org projects.</para>
- </listitem>
- <listitem>
- <para>The <literal>jbossorg-docbook-xslt</literal> directory contains the maven plugin source for the default JBoss.org XSL stylesheets. These stylesheets produce XHTML, PDF and Eclipse Help output.</para>
- </listitem>
- <listitem>
- <para>The <literal>jbossorg-jdocbook-style</literal> directory contains the maven plugin source for the default JBoss.org CSS and image files. These provide the JBoss.org community-driven look & feel.</para>
- </listitem>
- <listitem>
- <para>The <literal>styles</literal> and <literal>support</literal> directories together with the <literal>support.xml</literal> file are provided for backwards compatibility with projects that wish to continue using Ant instead of Maven. The <literal>styles</literal> directory contains XSL stylesheets together with CSS files to produce HTML and PDF outputs. The <literal>support</literal> directory contains the DocBook
- libraries and DTDs along with
- the standard XSL stylesheets. The <literal>support.xml</literal> file contains common Ant tasks to perform the build.</para>
- </listitem>
- </itemizedlist>
-</chapter>
\ No newline at end of file
Added: trunk/docs/getting_started/en/modules/using_dna.xml
===================================================================
--- trunk/docs/getting_started/en/modules/using_dna.xml (rev 0)
+++ trunk/docs/getting_started/en/modules/using_dna.xml 2008-04-28 19:55:31 UTC (rev 111)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
+<chapter id="using_dna">
+ <title>Using JBoss DNA</title>
+ <para></para>
+</chapter>
\ No newline at end of file
Property changes on: trunk/docs/getting_started/en/modules/using_dna.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
16 years
DNA SVN: r110 - in trunk/dna-common/src/test: resources/org/jboss/dna/common/monitor and 1 other directory.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-04-25 00:02:32 -0400 (Fri, 25 Apr 2008)
New Revision: 110
Modified:
trunk/dna-common/src/test/java/org/jboss/dna/common/monitor/SimpleProgressMonitorTest.java
trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/SimpleProgressMonitorTest$I18nMessages_fr.properties
Log:
Test case did not properly specify unicode characters for expected French result, so corrected that. (Interesting that the tests were problems on Linux but worked perfectly on OS X.)
Modified: trunk/dna-common/src/test/java/org/jboss/dna/common/monitor/SimpleProgressMonitorTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/monitor/SimpleProgressMonitorTest.java 2008-04-25 03:05:53 UTC (rev 109)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/monitor/SimpleProgressMonitorTest.java 2008-04-25 04:02:32 UTC (rev 110)
@@ -76,7 +76,7 @@
monitor.worked(10.0d);
ProgressStatus status = monitor.getStatus(Locale.FRANCE);
assertThat(status, is(notNullValue()));
- assertThat(status.getMessage(), is("t�che d'essai"));
+ assertThat(status.getMessage(), is("examinez le message"));
assertThat(status.getPercentWorked(), is(closeTo(10.0d, 0.001d)));
status = monitor.getStatus(Locale.ENGLISH);
@@ -101,7 +101,7 @@
monitor.worked(10.0d);
ProgressStatus status = monitor.getStatus(Locale.FRANCE);
assertThat(status, is(notNullValue()));
- assertThat(status.getMessage(), is("deuxi�me t�che d'essai 2"));
+ assertThat(status.getMessage(), is("examinez le message 2"));
assertThat(status.getPercentWorked(), is(closeTo(10.0d, 0.001d)));
status = monitor.getStatus(Locale.ENGLISH);
Modified: trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/SimpleProgressMonitorTest$I18nMessages_fr.properties
===================================================================
--- trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/SimpleProgressMonitorTest$I18nMessages_fr.properties 2008-04-25 03:05:53 UTC (rev 109)
+++ trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/SimpleProgressMonitorTest$I18nMessages_fr.properties 2008-04-25 04:02:32 UTC (rev 110)
@@ -1,2 +1,2 @@
-testTaskName = t�che d'essai
-testTaskName2 = deuxi�me t�che d'essai {0}
\ No newline at end of file
+testTaskName = examinez le message
+testTaskName2 = examinez le message {0}
\ No newline at end of file
16 years
DNA SVN: r109 - in trunk/dna-common/src: main/java/org/jboss/dna/common/monitor and 4 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-04-24 23:05:53 -0400 (Thu, 24 Apr 2008)
New Revision: 109
Added:
trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/
trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/SimpleProgressMonitorTest$I18nMessages_en.properties
trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/SimpleProgressMonitorTest$I18nMessages_fr.properties
Modified:
trunk/dna-common/src/main/java/org/jboss/dna/common/CommonI18n.java
trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/LoggingProgressMonitor.java
trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/NullProgressMonitor.java
trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/ProgressMonitor.java
trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/ProgressMonitorWrapper.java
trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/SimpleProgressMonitor.java
trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/SubProgressMonitor.java
trunk/dna-common/src/main/resources/org/jboss/dna/common/CommonI18n.properties
trunk/dna-common/src/test/java/org/jboss/dna/common/monitor/SimpleProgressMonitorTest.java
Log:
DNA-60: Progress monitor framework does not allow for localization of progress statuses
http://jira.jboss.org/jira/browse/DNA-60
Changed the "getStatus()" method in ProgresMonitor to be "getStatus(Locale)" that can take a null locale when the default locale should be used. All implementation classes were affected (this is before 0.1 release, so that's acceptable). Corrected how the SimpleProgressMonitor handles the taskName and taskNameParameters. Also Added test cases for when the monitor has not yet been started as well as after it has been started (and given a task name). The latter is done by supplying different locales (with and without parameters).
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/CommonI18n.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/CommonI18n.java 2008-04-24 13:49:15 UTC (rev 108)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/CommonI18n.java 2008-04-25 03:05:53 UTC (rev 109)
@@ -34,15 +34,15 @@
// Make sure the following I18n.java-related fields are defined before all other fields to ensure a valid error message is
// produced in the event of a missing/duplicate/unused property
- /**
- * Parameters:
- * <ol>
- * <li>{@link I18n#id() ID}</li>
- * <li>Number of supplied arguments</li>
- * <li>Localized text before parameter substitution</li>
- * <li>Localized text after parameter substitution</li>
- * </ol>
- */
+ /**
+ * Parameters:
+ * <ol>
+ * <li>{@link I18n#id() ID}</li>
+ * <li>Number of supplied arguments</li>
+ * <li>Localized text before parameter substitution</li>
+ * <li>Localized text after parameter substitution</li>
+ * </ol>
+ */
public static I18n i18nArgumentsMismatchedParameter;
public static I18n i18nArgumentMismatchedParameters;
public static I18n i18nArgumentsMismatchedParameters;
@@ -56,15 +56,15 @@
public static I18n i18nFieldNotPublic;
public static I18n i18nFieldNotStatic;
public static I18n i18nLocalizationFileNotFound;
- public static I18n i18nLocalizationProblems;
+ public static I18n i18nLocalizationProblems;
- /**
- * Parameters:
- * <ol>
- * <li>{@link I18n#id() Property}</li>
- * <li>Localization file URL</li>
- * </ol>
- */
+ /**
+ * Parameters:
+ * <ol>
+ * <li>{@link I18n#id() Property}</li>
+ * <li>Localization file URL</li>
+ * </ol>
+ */
public static I18n i18nPropertyDuplicate;
public static I18n i18nPropertyMissing;
public static I18n i18nPropertyUnused;
@@ -74,7 +74,7 @@
public static I18n componentNotConfigured;
public static I18n progressMonitorBeginTask;
public static I18n progressMonitorStatus;
- public static I18n initialProgressMonitorTaskName;
+ public static I18n nullProgressMonitorTaskName;
public static I18n argumentMayNotBeNegative;
public static I18n argumentMayNotBePositive;
@@ -112,14 +112,14 @@
}
public static Set<Locale> getLocalizationProblemLocales() {
- return I18n.getLocalizationProblemLocales(CommonI18n.class);
- }
+ return I18n.getLocalizationProblemLocales(CommonI18n.class);
+ }
public static Set<String> getLocalizationProblems() {
- return I18n.getLocalizationProblems(CommonI18n.class);
- }
+ return I18n.getLocalizationProblems(CommonI18n.class);
+ }
public static Set<String> getLocalizationProblems( Locale locale ) {
- return I18n.getLocalizationProblems(CommonI18n.class, locale);
- }
+ return I18n.getLocalizationProblems(CommonI18n.class, locale);
+ }
}
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/LoggingProgressMonitor.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/LoggingProgressMonitor.java 2008-04-24 13:49:15 UTC (rev 108)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/LoggingProgressMonitor.java 2008-04-25 03:05:53 UTC (rev 109)
@@ -22,6 +22,7 @@
package org.jboss.dna.common.monitor;
+import java.util.Locale;
import org.jboss.dna.common.CommonI18n;
import org.jboss.dna.common.i18n.I18n;
import org.jboss.dna.common.util.Logger;
@@ -33,13 +34,19 @@
private final Logger logger;
private final Logger.Level level;
+ private final Locale locale;
public LoggingProgressMonitor( ProgressMonitor delegate, Logger logger, Logger.Level level ) {
+ this(delegate, logger, level, null);
+ }
+
+ public LoggingProgressMonitor( ProgressMonitor delegate, Logger logger, Logger.Level level, Locale locale ) {
super(delegate);
assert level != null;
assert logger != null;
this.level = level;
this.logger = logger;
+ this.locale = locale;
}
/**
@@ -57,7 +64,7 @@
@Override
public void done() {
super.done();
- this.logger.log(level, CommonI18n.progressMonitorStatus, super.getStatus());
+ this.logger.log(level, CommonI18n.progressMonitorStatus, super.getStatus(this.locale));
}
/**
@@ -66,7 +73,7 @@
@Override
public void setCancelled( boolean value ) {
super.setCancelled(value);
- this.logger.log(level, CommonI18n.progressMonitorStatus, super.getStatus());
+ this.logger.log(level, CommonI18n.progressMonitorStatus, super.getStatus(this.locale));
}
/**
@@ -75,7 +82,7 @@
@Override
public void worked( double work ) {
super.worked(work);
- this.logger.log(level, CommonI18n.progressMonitorStatus, super.getStatus());
+ this.logger.log(level, CommonI18n.progressMonitorStatus, super.getStatus(this.locale));
}
}
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/NullProgressMonitor.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/NullProgressMonitor.java 2008-04-24 13:49:15 UTC (rev 108)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/NullProgressMonitor.java 2008-04-25 03:05:53 UTC (rev 109)
@@ -22,7 +22,9 @@
package org.jboss.dna.common.monitor;
+import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;
+import org.jboss.dna.common.CommonI18n;
import org.jboss.dna.common.i18n.I18n;
import net.jcip.annotations.ThreadSafe;
@@ -92,7 +94,7 @@
/**
* {@inheritDoc}
*/
- public ProgressStatus getStatus() {
- return new ProgressStatus(this.activityName, "Not available", 0.0d, cancelled.get());
+ public ProgressStatus getStatus( Locale locale ) {
+ return new ProgressStatus(this.activityName, CommonI18n.nullProgressMonitorTaskName.text(locale), 0.0d, cancelled.get());
}
}
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/ProgressMonitor.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/ProgressMonitor.java 2008-04-24 13:49:15 UTC (rev 108)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/ProgressMonitor.java 2008-04-25 03:05:53 UTC (rev 109)
@@ -22,6 +22,7 @@
package org.jboss.dna.common.monitor;
+import java.util.Locale;
import org.jboss.dna.common.i18n.I18n;
/**
@@ -83,10 +84,12 @@
boolean isCancelled();
/**
- * Return the current status of this activity. This method returns an immutable but consistent snapshot of the status for this
- * activity. Note that if this instance is a {@link #createSubtask(double) subtask}, this method returns the status of the
- * subtask.
+ * Return the current status of this activity, localized to the specified locale. This method returns an immutable but
+ * consistent snapshot of the status for this activity. Note that if this instance is a {@link #createSubtask(double) subtask},
+ * this method returns the status of the subtask.
+ * @param locale the locale in which the status is to be represented; if null, the {@link Locale#getDefault() default locale}
+ * will be used
* @return the status of this activity
*/
- ProgressStatus getStatus();
+ ProgressStatus getStatus( Locale locale );
}
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/ProgressMonitorWrapper.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/ProgressMonitorWrapper.java 2008-04-24 13:49:15 UTC (rev 108)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/ProgressMonitorWrapper.java 2008-04-25 03:05:53 UTC (rev 109)
@@ -22,6 +22,7 @@
package org.jboss.dna.common.monitor;
+import java.util.Locale;
import org.jboss.dna.common.i18n.I18n;
/**
@@ -73,8 +74,8 @@
/**
* {@inheritDoc}
*/
- public ProgressStatus getStatus() {
- return this.delegate.getStatus();
+ public ProgressStatus getStatus( Locale locale ) {
+ return this.delegate.getStatus(locale);
}
/**
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/SimpleProgressMonitor.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/SimpleProgressMonitor.java 2008-04-24 13:49:15 UTC (rev 108)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/SimpleProgressMonitor.java 2008-04-25 03:05:53 UTC (rev 109)
@@ -22,13 +22,13 @@
package org.jboss.dna.common.monitor;
+import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
-import org.jboss.dna.common.CommonI18n;
-import org.jboss.dna.common.i18n.I18n;
import net.jcip.annotations.GuardedBy;
import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.i18n.I18n;
/**
* A basic progress monitor
@@ -40,7 +40,7 @@
@GuardedBy( "lock" )
private I18n taskName;
@GuardedBy( "lock" )
- private Object[] params;
+ private Object[] taskNameParams;
@GuardedBy( "lock" )
private double totalWork;
@GuardedBy( "lock" )
@@ -54,7 +54,8 @@
public SimpleProgressMonitor( String activityName ) {
this.activityName = activityName != null ? activityName.trim() : "";
- this.taskName = CommonI18n.initialProgressMonitorTaskName;
+ this.taskName = null;
+ this.taskNameParams = null;
}
/**
@@ -72,7 +73,7 @@
try {
this.lock.writeLock().lock();
this.taskName = name;
- this.params = params;
+ this.taskNameParams = params;
this.totalWork = totalWork;
this.worked = 0.0d;
} finally {
@@ -140,10 +141,11 @@
/**
* {@inheritDoc}
*/
- public ProgressStatus getStatus() {
+ public ProgressStatus getStatus( Locale locale ) {
try {
this.lock.readLock().lock();
- return new ProgressStatus(this.getActivityName(), this.taskName.text(this.params), this.worked, this.totalWork, this.isCancelled());
+ String localizedTaskName = this.taskName == null ? "" : this.taskName.text(locale, this.taskNameParams);
+ return new ProgressStatus(this.getActivityName(), localizedTaskName, this.worked, this.totalWork, this.isCancelled());
} finally {
this.lock.readLock().unlock();
}
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/SubProgressMonitor.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/SubProgressMonitor.java 2008-04-24 13:49:15 UTC (rev 108)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/monitor/SubProgressMonitor.java 2008-04-25 03:05:53 UTC (rev 109)
@@ -22,6 +22,7 @@
package org.jboss.dna.common.monitor;
+import java.util.Locale;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.jboss.dna.common.i18n.I18n;
@@ -146,10 +147,10 @@
/**
* {@inheritDoc}
*/
- public ProgressStatus getStatus() {
+ public ProgressStatus getStatus( Locale locale ) {
try {
this.lock.readLock().lock();
- return new ProgressStatus(this.getActivityName(), this.taskName.text(this.params), this.submittedToParent, this.subtaskTotalInParent, this.isCancelled());
+ return new ProgressStatus(this.getActivityName(), this.taskName.text(locale, this.params), this.submittedToParent, this.subtaskTotalInParent, this.isCancelled());
} finally {
this.lock.readLock().unlock();
}
Modified: trunk/dna-common/src/main/resources/org/jboss/dna/common/CommonI18n.properties
===================================================================
--- trunk/dna-common/src/main/resources/org/jboss/dna/common/CommonI18n.properties 2008-04-24 13:49:15 UTC (rev 108)
+++ trunk/dna-common/src/main/resources/org/jboss/dna/common/CommonI18n.properties 2008-04-25 03:05:53 UTC (rev 109)
@@ -24,7 +24,7 @@
componentNotConfigured = The component {0} was not configured and will not be used
progressMonitorBeginTask = Beginning {0} ({1})
progressMonitorStatus = {0}
-initialProgressMonitorTaskName =
+nullProgressMonitorTaskName = Not available
argumentMayNotBeNegative = The {0} argument value, {1}, may not be negative
argumentMayNotBePositive = The {0} argument value, {1}, may not be positive
Modified: trunk/dna-common/src/test/java/org/jboss/dna/common/monitor/SimpleProgressMonitorTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/monitor/SimpleProgressMonitorTest.java 2008-04-24 13:49:15 UTC (rev 108)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/monitor/SimpleProgressMonitorTest.java 2008-04-25 03:05:53 UTC (rev 109)
@@ -22,12 +22,16 @@
package org.jboss.dna.common.monitor;
+import java.util.Locale;
+import java.util.Set;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.hamcrest.core.IsSame.sameInstance;
import static org.hamcrest.number.IsCloseTo.closeTo;
import static org.junit.Assert.assertThat;
+import org.jboss.dna.common.CommonI18n;
+import org.jboss.dna.common.i18n.I18n;
import org.jboss.dna.common.i18n.MockI18n;
import org.junit.Before;
import org.junit.Test;
@@ -54,8 +58,71 @@
}
@Test
+ public void shouldReturnProgressStatusWithEmptyMessageBeforeTaskIsBegun() {
+ ProgressStatus status = monitor.getStatus(Locale.FRANCE);
+ assertThat(status, is(notNullValue()));
+ assertThat(status.getMessage(), is(""));
+ assertThat(status.getPercentWorked(), is(closeTo(0.0d, 0.001d)));
+
+ status = monitor.getStatus(null);
+ assertThat(status, is(notNullValue()));
+ assertThat(status.getMessage(), is(""));
+ assertThat(status.getPercentWorked(), is(closeTo(0.0d, 0.001d)));
+ }
+
+ @Test
+ public void shouldReturnProgressStatusWithCorrectMessageAfterTaskIsBegun() {
+ monitor.beginTask(100, I18nMessages.testTaskName);
+ monitor.worked(10.0d);
+ ProgressStatus status = monitor.getStatus(Locale.FRANCE);
+ assertThat(status, is(notNullValue()));
+ assertThat(status.getMessage(), is("t�che d'essai"));
+ assertThat(status.getPercentWorked(), is(closeTo(10.0d, 0.001d)));
+
+ status = monitor.getStatus(Locale.ENGLISH);
+ assertThat(status, is(notNullValue()));
+ assertThat(status.getMessage(), is("test task"));
+ assertThat(status.getPercentWorked(), is(closeTo(10.0d, 0.001d)));
+
+ status = monitor.getStatus(Locale.getDefault());
+ assertThat(status, is(notNullValue()));
+ assertThat(status.getMessage(), is("test task"));
+ assertThat(status.getPercentWorked(), is(closeTo(10.0d, 0.001d)));
+
+ status = monitor.getStatus(null);
+ assertThat(status, is(notNullValue()));
+ assertThat(status.getMessage(), is("test task"));
+ assertThat(status.getPercentWorked(), is(closeTo(10.0d, 0.001d)));
+ }
+
+ @Test
+ public void shouldReturnProgressStatusWithCorrectMessageAndSubstitutedParametersAfterTaskIsBegun() {
+ monitor.beginTask(100, I18nMessages.testTaskName2, 2);
+ monitor.worked(10.0d);
+ ProgressStatus status = monitor.getStatus(Locale.FRANCE);
+ assertThat(status, is(notNullValue()));
+ assertThat(status.getMessage(), is("deuxi�me t�che d'essai 2"));
+ assertThat(status.getPercentWorked(), is(closeTo(10.0d, 0.001d)));
+
+ status = monitor.getStatus(Locale.ENGLISH);
+ assertThat(status, is(notNullValue()));
+ assertThat(status.getMessage(), is("second test task 2"));
+ assertThat(status.getPercentWorked(), is(closeTo(10.0d, 0.001d)));
+
+ status = monitor.getStatus(Locale.getDefault());
+ assertThat(status, is(notNullValue()));
+ assertThat(status.getMessage(), is("second test task 2"));
+ assertThat(status.getPercentWorked(), is(closeTo(10.0d, 0.001d)));
+
+ status = monitor.getStatus(null);
+ assertThat(status, is(notNullValue()));
+ assertThat(status.getMessage(), is("second test task 2"));
+ assertThat(status.getPercentWorked(), is(closeTo(10.0d, 0.001d)));
+ }
+
+ @Test
public void shouldHaveProgressOfZeroPercentUponCreation() {
- ProgressStatus status = monitor.getStatus();
+ ProgressStatus status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(""));
@@ -65,7 +132,7 @@
@Test
public void shouldHaveProgressOfZeroPercentUponBeginningTask() {
this.monitor.beginTask(100, MockI18n.passthrough, validTaskName);
- ProgressStatus status = monitor.getStatus();
+ ProgressStatus status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -75,7 +142,7 @@
@Test
public void shouldShowProperProgress() {
this.monitor.beginTask(1000, MockI18n.passthrough, validTaskName);
- ProgressStatus status = monitor.getStatus();
+ ProgressStatus status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -83,7 +150,7 @@
for (int i = 1; i <= 9; ++i) {
this.monitor.worked(100);
// Check the monitor's status ...
- status = monitor.getStatus();
+ status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -92,7 +159,7 @@
}
monitor.done();
// Check the monitor's status shows 100%
- status = monitor.getStatus();
+ status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -103,7 +170,7 @@
@Test
public void shouldShowProperProgressUsingSubtasks() {
monitor.beginTask(1000, MockI18n.passthrough, validTaskName);
- ProgressStatus status = monitor.getStatus();
+ ProgressStatus status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -123,7 +190,7 @@
subtask.worked(1);
// Check the submonitor's status
- status = subtask.getStatus();
+ status = subtask.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(subtaskName));
@@ -135,7 +202,7 @@
subtask.done();
// Check the main monitor's status
- status = monitor.getStatus();
+ status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -145,7 +212,7 @@
monitor.done();
// Check the monitor's status shows 100%
- status = monitor.getStatus();
+ status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -156,7 +223,7 @@
@Test
public void shouldAllowDoneToBeCalledEvenAfterFinished() {
monitor.beginTask(1000, MockI18n.passthrough, validTaskName);
- ProgressStatus status = monitor.getStatus();
+ ProgressStatus status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -168,7 +235,7 @@
monitor.done();
// Check the status ...
- status = monitor.getStatus();
+ status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -185,7 +252,7 @@
@Test
public void shouldAllowCancelToBeRejected() {
monitor.beginTask(1000, MockI18n.passthrough, validTaskName);
- ProgressStatus status = monitor.getStatus();
+ ProgressStatus status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -194,7 +261,7 @@
monitor.worked(100);
// Check the monitor's status ...
- status = monitor.getStatus();
+ status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -207,7 +274,7 @@
}
monitor.done();
// Check the monitor's status shows 100%
- status = monitor.getStatus();
+ status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -219,7 +286,7 @@
@Test
public void shouldContinueToRecordWorkEvenWhenCancelled() {
monitor.beginTask(1000, MockI18n.passthrough, validTaskName);
- ProgressStatus status = monitor.getStatus();
+ ProgressStatus status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -228,7 +295,7 @@
monitor.worked(100);
// Check the monitor's status ...
- status = monitor.getStatus();
+ status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -241,7 +308,7 @@
}
monitor.done();
// Check the monitor's status shows 100%
- status = monitor.getStatus();
+ status = monitor.getStatus(null);
assertThat(status, is(notNullValue()));
assertThat(status.getActivityName(), is(sameInstance(monitor.getActivityName())));
assertThat(status.getMessage(), is(validTaskName));
@@ -249,4 +316,31 @@
assertThat(status.isDone(), is(true));
assertThat(monitor.isCancelled(), is(true));
}
+
+ public static class I18nMessages {
+
+ public static I18n testTaskName;
+ public static I18n testTaskName2;
+
+ static {
+ try {
+ I18n.initialize(SimpleProgressMonitorTest.I18nMessages.class);
+ } catch (final Exception err) {
+ System.err.println(err);
+ }
+ }
+
+ public static Set<Locale> getLocalizationProblemLocales() {
+ return I18n.getLocalizationProblemLocales(CommonI18n.class);
+ }
+
+ public static Set<String> getLocalizationProblems() {
+ return I18n.getLocalizationProblems(CommonI18n.class);
+ }
+
+ public static Set<String> getLocalizationProblems( Locale locale ) {
+ return I18n.getLocalizationProblems(CommonI18n.class, locale);
+ }
+
+ }
}
Added: trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/SimpleProgressMonitorTest$I18nMessages_en.properties
===================================================================
--- trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/SimpleProgressMonitorTest$I18nMessages_en.properties (rev 0)
+++ trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/SimpleProgressMonitorTest$I18nMessages_en.properties 2008-04-25 03:05:53 UTC (rev 109)
@@ -0,0 +1,2 @@
+testTaskName = test task
+testTaskName2 = second test task {0}
\ No newline at end of file
Property changes on: trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/SimpleProgressMonitorTest$I18nMessages_en.properties
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ text/plain
Added: trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/SimpleProgressMonitorTest$I18nMessages_fr.properties
===================================================================
--- trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/SimpleProgressMonitorTest$I18nMessages_fr.properties (rev 0)
+++ trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/SimpleProgressMonitorTest$I18nMessages_fr.properties 2008-04-25 03:05:53 UTC (rev 109)
@@ -0,0 +1,2 @@
+testTaskName = t�che d'essai
+testTaskName2 = deuxi�me t�che d'essai {0}
\ No newline at end of file
Property changes on: trunk/dna-common/src/test/resources/org/jboss/dna/common/monitor/SimpleProgressMonitorTest$I18nMessages_fr.properties
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ text/plain
16 years
DNA SVN: r108 - trunk.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-04-24 09:49:15 -0400 (Thu, 24 Apr 2008)
New Revision: 108
Modified:
trunk/pom.xml
Log:
Updated excludes for test cases
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2008-04-24 13:48:43 UTC (rev 107)
+++ trunk/pom.xml 2008-04-24 13:49:15 UTC (rev 108)
@@ -49,6 +49,7 @@
</includes>
<excludes>
<exclude>**/Abstract*TestCase.java</exclude>
+ <exclude>**/Abstract*Test.java</exclude>
</excludes>
</configuration>
</plugin>
16 years
DNA SVN: r107 - trunk/dna-common/src/test/java/org/jboss/dna/common.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-04-24 09:48:43 -0400 (Thu, 24 Apr 2008)
New Revision: 107
Modified:
trunk/dna-common/src/test/java/org/jboss/dna/common/AbstractI18nTest.java
Log:
Fixed a bad test case.
Modified: trunk/dna-common/src/test/java/org/jboss/dna/common/AbstractI18nTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/AbstractI18nTest.java 2008-04-24 01:42:52 UTC (rev 106)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/AbstractI18nTest.java 2008-04-24 13:48:43 UTC (rev 107)
@@ -17,36 +17,35 @@
/**
* @author John Verhaeg
*/
-public class AbstractI18nTest {
+public abstract class AbstractI18nTest {
- private Class i18nClass;
+ private Class i18nClass;
- protected AbstractI18nTest( Class i18nClass ) {
- this.i18nClass = i18nClass;
- }
+ protected AbstractI18nTest( Class i18nClass ) {
+ this.i18nClass = i18nClass;
+ }
- @Test
- @SuppressWarnings( "unchecked" )
- public void shouldNotHaveLocalizationProblems() throws Exception {
- Method method = i18nClass.getDeclaredMethod("getLocalizationProblemLocales", (Class[])null);
- Set<Locale> locales = (Set<Locale>)method.invoke(null, (Object[])null);
- method = i18nClass.getDeclaredMethod("getLocalizationProblems", Locale.class);
- for (Locale locale : locales) {
- assertThat(((Set<String>)method.invoke(null, locale)).isEmpty(), is(true));
- }
- }
+ @Test
+ @SuppressWarnings( "unchecked" )
+ public void shouldNotHaveLocalizationProblems() throws Exception {
+ Method method = i18nClass.getDeclaredMethod("getLocalizationProblemLocales", (Class[])null);
+ Set<Locale> locales = (Set<Locale>)method.invoke(null, (Object[])null);
+ method = i18nClass.getDeclaredMethod("getLocalizationProblems", Locale.class);
+ for (Locale locale : locales) {
+ assertThat(((Set<String>)method.invoke(null, locale)).isEmpty(), is(true));
+ }
+ }
- @Test
- public void shouldNotHaveProblems() throws IllegalAccessException {
- for (Field fld : i18nClass.getDeclaredFields()) {
- if (fld.getType() == I18n.class && (fld.getModifiers() & Modifier.PUBLIC) == Modifier.PUBLIC
- && (fld.getModifiers() & Modifier.STATIC) == Modifier.STATIC
- && (fld.getModifiers() & Modifier.FINAL) != Modifier.FINAL) {
- I18n i18n = (I18n)fld.get(null);
- if (i18n.hasProblem()) {
- fail();
- }
- }
- }
- }
+ @Test
+ public void shouldNotHaveProblems() throws IllegalAccessException {
+ for (Field fld : i18nClass.getDeclaredFields()) {
+ if (fld.getType() == I18n.class && (fld.getModifiers() & Modifier.PUBLIC) == Modifier.PUBLIC && (fld.getModifiers() & Modifier.STATIC) == Modifier.STATIC
+ && (fld.getModifiers() & Modifier.FINAL) != Modifier.FINAL) {
+ I18n i18n = (I18n)fld.get(null);
+ if (i18n.hasProblem()) {
+ fail();
+ }
+ }
+ }
+ }
}
16 years
DNA SVN: r106 - in trunk: dna-common/src/test/java/org/jboss/dna/common/i18n and 5 other directories.
by dna-commits@lists.jboss.org
Author: jverhaeg(a)redhat.com
Date: 2008-04-23 21:42:52 -0400 (Wed, 23 Apr 2008)
New Revision: 106
Added:
trunk/dna-common/src/test/java/org/jboss/dna/common/AbstractI18nTest.java
trunk/dna-common/src/test/java/org/jboss/dna/common/CommonI18nTest.java
trunk/dna-maven-classloader/src/test/java/org/jboss/dna/maven/MavenI18nTest.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryI18nTest.java
Removed:
trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/CommonI18nTest.java
trunk/dna-repository/src/test/java/org/jboss/dna/services/
Modified:
trunk/dna-maven-classloader/src/main/java/org/jboss/dna/maven/MavenI18n.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java
Log:
DNA-27: Added convenience methods to project I18n classes, and tests for each (that extend an abstract test class) to ensure they have no localization problems. Also moved CommonI18nTest to correct package.
Added: trunk/dna-common/src/test/java/org/jboss/dna/common/AbstractI18nTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/AbstractI18nTest.java (rev 0)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/AbstractI18nTest.java 2008-04-24 01:42:52 UTC (rev 106)
@@ -0,0 +1,52 @@
+/*
+ *
+ */
+package org.jboss.dna.common;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Locale;
+import java.util.Set;
+import org.jboss.dna.common.i18n.I18n;
+import org.junit.Test;
+
+/**
+ * @author John Verhaeg
+ */
+public class AbstractI18nTest {
+
+ private Class i18nClass;
+
+ protected AbstractI18nTest( Class i18nClass ) {
+ this.i18nClass = i18nClass;
+ }
+
+ @Test
+ @SuppressWarnings( "unchecked" )
+ public void shouldNotHaveLocalizationProblems() throws Exception {
+ Method method = i18nClass.getDeclaredMethod("getLocalizationProblemLocales", (Class[])null);
+ Set<Locale> locales = (Set<Locale>)method.invoke(null, (Object[])null);
+ method = i18nClass.getDeclaredMethod("getLocalizationProblems", Locale.class);
+ for (Locale locale : locales) {
+ assertThat(((Set<String>)method.invoke(null, locale)).isEmpty(), is(true));
+ }
+ }
+
+ @Test
+ public void shouldNotHaveProblems() throws IllegalAccessException {
+ for (Field fld : i18nClass.getDeclaredFields()) {
+ if (fld.getType() == I18n.class && (fld.getModifiers() & Modifier.PUBLIC) == Modifier.PUBLIC
+ && (fld.getModifiers() & Modifier.STATIC) == Modifier.STATIC
+ && (fld.getModifiers() & Modifier.FINAL) != Modifier.FINAL) {
+ I18n i18n = (I18n)fld.get(null);
+ if (i18n.hasProblem()) {
+ fail();
+ }
+ }
+ }
+ }
+}
Property changes on: trunk/dna-common/src/test/java/org/jboss/dna/common/AbstractI18nTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied: trunk/dna-common/src/test/java/org/jboss/dna/common/CommonI18nTest.java (from rev 105, trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/CommonI18nTest.java)
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/CommonI18nTest.java (rev 0)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/CommonI18nTest.java 2008-04-24 01:42:52 UTC (rev 106)
@@ -0,0 +1,14 @@
+/*
+ *
+ */
+package org.jboss.dna.common;
+
+/**
+ * @author John Verhaeg
+ */
+public class CommonI18nTest extends AbstractI18nTest {
+
+ public CommonI18nTest() {
+ super(CommonI18n.class);
+ }
+}
Property changes on: trunk/dna-common/src/test/java/org/jboss/dna/common/CommonI18nTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Deleted: trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/CommonI18nTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/CommonI18nTest.java 2008-04-24 00:45:28 UTC (rev 105)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/CommonI18nTest.java 2008-04-24 01:42:52 UTC (rev 106)
@@ -1,23 +0,0 @@
-/*
- *
- */
-package org.jboss.dna.common.i18n;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import java.util.Locale;
-import org.jboss.dna.common.CommonI18n;
-import org.junit.Test;
-
-/**
- * @author John Verhaeg
- */
-public class CommonI18nTest {
-
- @Test
- public void shouldNotHaveLocalizationProblems() {
- for (Locale locale : CommonI18n.getLocalizationProblemLocales()) {
- assertThat(CommonI18n.getLocalizationProblems(locale).isEmpty(), is(true));
- }
- }
-}
Modified: trunk/dna-maven-classloader/src/main/java/org/jboss/dna/maven/MavenI18n.java
===================================================================
--- trunk/dna-maven-classloader/src/main/java/org/jboss/dna/maven/MavenI18n.java 2008-04-24 00:45:28 UTC (rev 105)
+++ trunk/dna-maven-classloader/src/main/java/org/jboss/dna/maven/MavenI18n.java 2008-04-24 01:42:52 UTC (rev 106)
@@ -2,7 +2,7 @@
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
+ * distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
@@ -21,6 +21,8 @@
*/
package org.jboss.dna.maven;
+import java.util.Locale;
+import java.util.Set;
import org.jboss.dna.common.i18n.I18n;
/**
@@ -28,36 +30,48 @@
*/
public final class MavenI18n {
- static {
- try {
- I18n.initialize(MavenI18n.class);
- } catch (final Exception err) {
- System.err.println(err);
- }
- }
+ public static I18n errorGettingUrlForMavenProject;
+ public static I18n unsupportedMavenCoordinateFormat;
+ public static I18n errorCreatingUrlForMavenId;
+ public static I18n errorGettingPomFileForMavenIdAtUrl;
+ public static I18n pomFileIsInvalid;
+ public static I18n pomFileContainsUnexpectedId;
+ public static I18n errorCreatingXpathStatementsToEvaluatePom;
+ public static I18n errorCreatingXpathParserToEvaluatePom;
+ public static I18n errorReadingXmlDocumentToEvaluatePom;
+ public static I18n errorClosingUrlStreamToPom;
- public static I18n errorGettingUrlForMavenProject;
- public static I18n unsupportedMavenCoordinateFormat;
- public static I18n errorCreatingUrlForMavenId;
- public static I18n errorGettingPomFileForMavenIdAtUrl;
- public static I18n pomFileIsInvalid;
- public static I18n pomFileContainsUnexpectedId;
- public static I18n errorCreatingXpathStatementsToEvaluatePom;
- public static I18n errorCreatingXpathParserToEvaluatePom;
- public static I18n errorReadingXmlDocumentToEvaluatePom;
- public static I18n errorClosingUrlStreamToPom;
+ public static I18n unableToOpenSessiontoRepositoryWhenCreatingNode;
+ public static I18n unableToFindWorkspaceWhenCreatingNode;
+ public static I18n errorCreatingNode;
+ public static I18n unableToOpenSessiontoRepositoryWhenReadingNode;
+ public static I18n unableToFindWorkspaceWhenReadingNode;
+ public static I18n errorReadingNode;
+ public static I18n unableToOpenSessiontoRepositoryWhenWritingNode;
+ public static I18n unableToFindWorkspaceWhenWritingNode;
+ public static I18n errorWritingNode;
- public static I18n unableToOpenSessiontoRepositoryWhenCreatingNode;
- public static I18n unableToFindWorkspaceWhenCreatingNode;
- public static I18n errorCreatingNode;
- public static I18n unableToOpenSessiontoRepositoryWhenReadingNode;
- public static I18n unableToFindWorkspaceWhenReadingNode;
- public static I18n errorReadingNode;
- public static I18n unableToOpenSessiontoRepositoryWhenWritingNode;
- public static I18n unableToFindWorkspaceWhenWritingNode;
- public static I18n errorWritingNode;
+ public static I18n unableToWriteToClosedStream;
+ public static I18n errorClosingTempFileStreamAfterWritingContent;
+ public static I18n errorDeletingTempFileStreamAfterWritingContent;
- public static I18n unableToWriteToClosedStream;
- public static I18n errorClosingTempFileStreamAfterWritingContent;
- public static I18n errorDeletingTempFileStreamAfterWritingContent;
+ static {
+ try {
+ I18n.initialize(MavenI18n.class);
+ } catch (final Exception err) {
+ System.err.println(err);
+ }
+ }
+
+ public static Set<Locale> getLocalizationProblemLocales() {
+ return I18n.getLocalizationProblemLocales(MavenI18n.class);
+ }
+
+ public static Set<String> getLocalizationProblems() {
+ return I18n.getLocalizationProblems(MavenI18n.class);
+ }
+
+ public static Set<String> getLocalizationProblems( Locale locale ) {
+ return I18n.getLocalizationProblems(MavenI18n.class, locale);
+ }
}
Added: trunk/dna-maven-classloader/src/test/java/org/jboss/dna/maven/MavenI18nTest.java
===================================================================
--- trunk/dna-maven-classloader/src/test/java/org/jboss/dna/maven/MavenI18nTest.java (rev 0)
+++ trunk/dna-maven-classloader/src/test/java/org/jboss/dna/maven/MavenI18nTest.java 2008-04-24 01:42:52 UTC (rev 106)
@@ -0,0 +1,16 @@
+/*
+ *
+ */
+package org.jboss.dna.maven;
+
+import org.jboss.dna.common.AbstractI18nTest;
+
+/**
+ * @author John Verhaeg
+ */
+public class MavenI18nTest extends AbstractI18nTest {
+
+ public MavenI18nTest() {
+ super(MavenI18n.class);
+ }
+}
Property changes on: trunk/dna-maven-classloader/src/test/java/org/jboss/dna/maven/MavenI18nTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java 2008-04-24 00:45:28 UTC (rev 105)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java 2008-04-24 01:42:52 UTC (rev 106)
@@ -2,7 +2,7 @@
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
+ * distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
@@ -21,6 +21,8 @@
*/
package org.jboss.dna.repository;
+import java.util.Locale;
+import java.util.Set;
import org.jboss.dna.common.i18n.I18n;
/**
@@ -28,74 +30,85 @@
*/
public final class RepositoryI18n {
- static {
- try {
- I18n.initialize(RepositoryI18n.class);
- } catch (final Exception err) {
- System.err.println(err);
- }
- }
+ public static I18n invalidStateString;
+ public static I18n serviceShutdowAndMayNotBeStarted;
+ public static I18n serviceShutdowAndMayNotBePaused;
+ public static I18n unableToFindRepositoryInJndi;
+ public static I18n errorProcessingEvents;
+ public static I18n errorFindingPropertyNameInPropertyAddedEvent;
+ public static I18n errorFindingPropertyNameInPropertyChangedEvent;
+ public static I18n errorFindingPropertyNameInPropertyRemovedEvent;
- public static I18n invalidStateString;
- public static I18n serviceShutdowAndMayNotBeStarted;
- public static I18n serviceShutdowAndMayNotBePaused;
- public static I18n unableToFindRepositoryInJndi;
- public static I18n errorProcessingEvents;
- public static I18n errorFindingPropertyNameInPropertyAddedEvent;
- public static I18n errorFindingPropertyNameInPropertyChangedEvent;
- public static I18n errorFindingPropertyNameInPropertyRemovedEvent;
+ public static I18n unableToObtainJsr94RuleAdministrator;
+ public static I18n errorUsingJsr94RuleAdministrator;
+ public static I18n unableToObtainJsr94ServiceProvider;
+ public static I18n errorAddingOrUpdatingRuleSet;
+ public static I18n errorRollingBackRuleSetAfterUpdateFailed;
+ public static I18n errorReadingRulesAndProperties;
+ public static I18n errorDeregisteringRuleSetBeforeUpdatingIt;
+ public static I18n errorRecreatingRuleSet;
+ public static I18n errorRemovingRuleSet;
+ public static I18n errorRemovingRuleSetUponShutdown;
+ public static I18n unableToFindRuleSet;
+ public static I18n errorExecutingRuleSetWithGlobalsAndFacts;
+ public static I18n unableToBuildRuleSetRegularExpressionPattern;
- public static I18n unableToObtainJsr94RuleAdministrator;
- public static I18n errorUsingJsr94RuleAdministrator;
- public static I18n unableToObtainJsr94ServiceProvider;
- public static I18n errorAddingOrUpdatingRuleSet;
- public static I18n errorRollingBackRuleSetAfterUpdateFailed;
- public static I18n errorReadingRulesAndProperties;
- public static I18n errorDeregisteringRuleSetBeforeUpdatingIt;
- public static I18n errorRecreatingRuleSet;
- public static I18n errorRemovingRuleSet;
- public static I18n errorRemovingRuleSetUponShutdown;
- public static I18n unableToFindRuleSet;
- public static I18n errorExecutingRuleSetWithGlobalsAndFacts;
- public static I18n unableToBuildRuleSetRegularExpressionPattern;
+ public static I18n errorObtainingSessionToRepositoryWorkspace;
+ public static I18n errorWritingProblemsOnRuleSet;
- public static I18n errorObtainingSessionToRepositoryWorkspace;
- public static I18n errorWritingProblemsOnRuleSet;
+ public static I18n sequencingServiceName;
+ public static I18n unableToChangeExecutionContextWhileRunning;
+ public static I18n unableToStartSequencingServiceWithoutExecutionContext;
+ public static I18n errorWhileSequencingNode;
+ public static I18n errorInRepositoryWhileSequencingNode;
+ public static I18n errorFindingSequencersToRunAgainstNode;
+ public static I18n errorInRepositoryWhileFindingSequencersToRunAgainstNode;
+ public static I18n executionContextHasBeenClosed;
+ public static I18n sequencerTask;
+ public static I18n sequencerSubtask;
+ public static I18n unableToFindPropertyForSequencing;
+ public static I18n sequencingPropertyOnNode;
+ public static I18n writingOutputSequencedFromPropertyOnNodes;
- public static I18n sequencingServiceName;
- public static I18n unableToChangeExecutionContextWhileRunning;
- public static I18n unableToStartSequencingServiceWithoutExecutionContext;
- public static I18n errorWhileSequencingNode;
- public static I18n errorInRepositoryWhileSequencingNode;
- public static I18n errorFindingSequencersToRunAgainstNode;
- public static I18n errorInRepositoryWhileFindingSequencersToRunAgainstNode;
- public static I18n executionContextHasBeenClosed;
- public static I18n sequencerTask;
- public static I18n sequencerSubtask;
- public static I18n unableToFindPropertyForSequencing;
- public static I18n sequencingPropertyOnNode;
- public static I18n writingOutputSequencedFromPropertyOnNodes;
+ public static I18n errorReadingPropertiesFromContainerNode;
+ public static I18n requiredPropertyOnNodeWasExpectedToBeStringValue;
+ public static I18n optionalPropertyOnNodeWasExpectedToBeStringValue;
+ public static I18n requiredPropertyOnNodeWasExpectedToBeStringArrayValue;
+ public static I18n optionalPropertyOnNodeWasExpectedToBeStringArrayValue;
+ public static I18n requiredPropertyOnNodeCouldNotBeRead;
+ public static I18n optionalPropertyOnNodeCouldNotBeRead;
+ public static I18n requiredPropertyIsMissingFromNode;
+ public static I18n errorGettingRequiredPropertyFromNode;
+ public static I18n errorGettingOptionalPropertyFromNode;
+ public static I18n errorClosingBinaryStreamForPropertyFromNode;
+ public static I18n requiredNodeDoesNotExistRelativeToNode;
+ public static I18n errorGettingNodeRelativeToNode;
+ public static I18n unknownPropertyValueType;
- public static I18n errorReadingPropertiesFromContainerNode;
- public static I18n requiredPropertyOnNodeWasExpectedToBeStringValue;
- public static I18n optionalPropertyOnNodeWasExpectedToBeStringValue;
- public static I18n requiredPropertyOnNodeWasExpectedToBeStringArrayValue;
- public static I18n optionalPropertyOnNodeWasExpectedToBeStringArrayValue;
- public static I18n requiredPropertyOnNodeCouldNotBeRead;
- public static I18n optionalPropertyOnNodeCouldNotBeRead;
- public static I18n requiredPropertyIsMissingFromNode;
- public static I18n errorGettingRequiredPropertyFromNode;
- public static I18n errorGettingOptionalPropertyFromNode;
- public static I18n errorClosingBinaryStreamForPropertyFromNode;
- public static I18n requiredNodeDoesNotExistRelativeToNode;
- public static I18n errorGettingNodeRelativeToNode;
- public static I18n unknownPropertyValueType;
+ public static I18n pathExpressionIsInvalid;
+ public static I18n pathExpressionMayNotBeBlank;
+ public static I18n pathExpressionHasInvalidSelect;
+ public static I18n pathExpressionHasInvalidMatch;
- public static I18n pathExpressionIsInvalid;
- public static I18n pathExpressionMayNotBeBlank;
- public static I18n pathExpressionHasInvalidSelect;
- public static I18n pathExpressionHasInvalidMatch;
+ public static I18n invalidRepositoryNodePath;
- public static I18n invalidRepositoryNodePath;
+ static {
+ try {
+ I18n.initialize(RepositoryI18n.class);
+ } catch (final Exception err) {
+ System.err.println(err);
+ }
+ }
+ public static Set<Locale> getLocalizationProblemLocales() {
+ return I18n.getLocalizationProblemLocales(RepositoryI18n.class);
+ }
+
+ public static Set<String> getLocalizationProblems() {
+ return I18n.getLocalizationProblems(RepositoryI18n.class);
+ }
+
+ public static Set<String> getLocalizationProblems( Locale locale ) {
+ return I18n.getLocalizationProblems(RepositoryI18n.class, locale);
+ }
}
Added: trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryI18nTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryI18nTest.java (rev 0)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryI18nTest.java 2008-04-24 01:42:52 UTC (rev 106)
@@ -0,0 +1,13 @@
+package org.jboss.dna.repository;
+
+import org.jboss.dna.common.AbstractI18nTest;
+
+/**
+ * @author John Verhaeg
+ */
+public class RepositoryI18nTest extends AbstractI18nTest {
+
+ public RepositoryI18nTest() {
+ super(RepositoryI18n.class);
+ }
+}
Property changes on: trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryI18nTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
16 years
DNA SVN: r105 - in trunk/dna-common/src: main/java/org/jboss/dna/common/i18n and 3 other directories.
by dna-commits@lists.jboss.org
Author: jverhaeg(a)redhat.com
Date: 2008-04-23 20:45:28 -0400 (Wed, 23 Apr 2008)
New Revision: 105
Added:
trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/CommonI18nTest.java
trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n_en.properties
trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n_fr.properties
Removed:
trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n.properties
Modified:
trunk/dna-common/src/main/java/org/jboss/dna/common/CommonI18n.java
trunk/dna-common/src/main/java/org/jboss/dna/common/i18n/I18n.java
trunk/dna-common/src/main/resources/org/jboss/dna/common/CommonI18n.properties
trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/I18nTest.java
Log:
DNA-27: Re-designed I18n to store text and instance-specific problems within instances. Corrected some synchronization- and exception-related bugs. Changed terminology related to localization. Supplied many more tests, including for other locales.
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/CommonI18n.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/CommonI18n.java 2008-04-22 20:42:49 UTC (rev 104)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/CommonI18n.java 2008-04-24 00:45:28 UTC (rev 105)
@@ -21,6 +21,8 @@
*/
package org.jboss.dna.common;
+import java.util.Locale;
+import java.util.Set;
import org.jboss.dna.common.i18n.I18n;
/**
@@ -29,17 +31,18 @@
*/
public final class CommonI18n {
- static {
- try {
- I18n.initialize(CommonI18n.class);
- } catch (final Exception err) {
- System.err.println(err);
- }
- }
-
// Make sure the following I18n.java-related fields are defined before all other fields to ensure a valid error message is
// produced in the event of a missing/duplicate/unused property
+ /**
+ * Parameters:
+ * <ol>
+ * <li>{@link I18n#id() ID}</li>
+ * <li>Number of supplied arguments</li>
+ * <li>Localized text before parameter substitution</li>
+ * <li>Localized text after parameter substitution</li>
+ * </ol>
+ */
public static I18n i18nArgumentsMismatchedParameter;
public static I18n i18nArgumentMismatchedParameters;
public static I18n i18nArgumentsMismatchedParameters;
@@ -52,7 +55,16 @@
public static I18n i18nFieldInvalidType;
public static I18n i18nFieldNotPublic;
public static I18n i18nFieldNotStatic;
- public static I18n i18nPropertiesFileNotFound;
+ public static I18n i18nLocalizationFileNotFound;
+ public static I18n i18nLocalizationProblems;
+
+ /**
+ * Parameters:
+ * <ol>
+ * <li>{@link I18n#id() Property}</li>
+ * <li>Localization file URL</li>
+ * </ol>
+ */
public static I18n i18nPropertyDuplicate;
public static I18n i18nPropertyMissing;
public static I18n i18nPropertyUnused;
@@ -90,4 +102,24 @@
public static I18n pathIsNotAbsolute;
public static I18n pathIsNotRelative;
public static I18n pathCannotBeNormalized;
+
+ static {
+ try {
+ I18n.initialize(CommonI18n.class);
+ } catch (final Exception err) {
+ System.err.println(err);
+ }
+ }
+
+ public static Set<Locale> getLocalizationProblemLocales() {
+ return I18n.getLocalizationProblemLocales(CommonI18n.class);
+ }
+
+ public static Set<String> getLocalizationProblems() {
+ return I18n.getLocalizationProblems(CommonI18n.class);
+ }
+
+ public static Set<String> getLocalizationProblems( Locale locale ) {
+ return I18n.getLocalizationProblems(CommonI18n.class, locale);
+ }
}
Modified: trunk/dna-common/src/main/java/org/jboss/dna/common/i18n/I18n.java
===================================================================
--- trunk/dna-common/src/main/java/org/jboss/dna/common/i18n/I18n.java 2008-04-22 20:42:49 UTC (rev 104)
+++ trunk/dna-common/src/main/java/org/jboss/dna/common/i18n/I18n.java 2008-04-24 00:45:28 UTC (rev 105)
@@ -27,21 +27,22 @@
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Collections;
-import java.util.HashMap;
+import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
+import java.util.Set;
+import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArraySet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import net.jcip.annotations.Immutable;
import net.jcip.annotations.ThreadSafe;
import org.jboss.dna.common.CommonI18n;
import org.jboss.dna.common.SystemFailureException;
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.common.util.ClassUtil;
-import org.jboss.dna.common.util.HashCode;
/**
* Manages the initialization of internationalization (i18n) files, substitution of values within i18n message placeholders, and
@@ -56,37 +57,68 @@
private static final Pattern PARAMETER_COUNT_PATTERN = Pattern.compile("\\{(\\d+)\\}");
private static final Object[] EMPTY_ARGUMENTS = new Object[] {};
private static final LocalizationRepository DEFAULT_LOCALIZATION_REPOSITORY = new ClasspathLocalizationRepository();
- private static final ConcurrentMap<Localization, Map<String, String>> LOCALIZATION_2_ID_2_ERROR_MAP = new ConcurrentHashMap<Localization, Map<String, String>>();
- private static final ConcurrentMap<Localization, Map<String, String>> LOCALIZATION_2_ID_2_TEXT_MAP = new ConcurrentHashMap<Localization, Map<String, String>>();
+ /**
+ * The first level of this map indicates whether an i18n class has been localized to a particular locale. The second level
+ * contains any problems encountered during localization.
+ */
+ static final ConcurrentMap<Locale, Map<Class, Set<String>>> LOCALE_TO_CLASS_TO_PROBLEMS_MAP = new ConcurrentHashMap<Locale, Map<Class, Set<String>>>();
+
private static LocalizationRepository localizationRepository = DEFAULT_LOCALIZATION_REPOSITORY;
/**
- * @param i18nClass An internalization class for which errors should be returned.
- * @return The errors encountered while initializing the specified internationalization class for the default locale mapped to
- * the applicable internalization IDs; never <code>null</code>.
+ * Note, calling this method will <em>not</em> trigger localization of the supplied internationalization class.
+ *
+ * @param i18nClass The internalization class for which localization problem locales should be returned.
+ * @return The locales for which localization problems were encountered while localizing the supplied internationalization
+ * class; never <code>null</code>.
*/
- public static Map<String, String> getErrorsForDefaultLocale( Class i18nClass ) {
- return getErrorsForLocale(i18nClass, null);
+ public static Set<Locale> getLocalizationProblemLocales( Class i18nClass ) {
+ ArgCheck.isNotNull(i18nClass, "i18nClass");
+ Set<Locale> locales = new HashSet<Locale>(LOCALE_TO_CLASS_TO_PROBLEMS_MAP.size());
+ for (Entry<Locale, Map<Class, Set<String>>> localeEntry : LOCALE_TO_CLASS_TO_PROBLEMS_MAP.entrySet()) {
+ for (Entry<Class, Set<String>> classEntry : localeEntry.getValue().entrySet()) {
+ if (!classEntry.getValue().isEmpty()) {
+ locales.add(localeEntry.getKey());
+ break;
+ }
+ }
+ }
+ return locales;
}
/**
- * @param i18nClass An internalization class for which errors should be returned.
- * @param locale The locale for which errors should be returned. If <code>null</code>, errors for the the default locale
- * will be returned.
- * @return The errors encountered while initializing the specified internationalization class for the specified locale mapped
- * to the applicable internalization IDs; never <code>null</code>.
+ * Note, calling this method will <em>not</em> trigger localization of the supplied internationalization class.
+ *
+ * @param i18nClass The internalization class for which localization problems should be returned.
+ * @return The localization problems encountered while localizing the supplied internationalization class to the default
+ * locale; never <code>null</code>.
*/
- public static Map<String, String> getErrorsForLocale( Class i18nClass,
- Locale locale ) {
+ public static Set<String> getLocalizationProblems( Class i18nClass ) {
+ return getLocalizationProblems(i18nClass, null);
+ }
+
+ /**
+ * Note, calling this method will <em>not</em> trigger localization of the supplied internationalization class.
+ *
+ * @param i18nClass The internalization class for which localization problems should be returned.
+ * @param locale The locale for which localization problems should be returned. If <code>null</code>, the default locale
+ * will be used.
+ * @return The localization problems encountered while localizing the supplied internationalization class to the supplied
+ * locale; never <code>null</code>.
+ */
+ public static Set<String> getLocalizationProblems( Class i18nClass,
+ Locale locale ) {
ArgCheck.isNotNull(i18nClass, "i18nClass");
- Map<String, String> errors = LOCALIZATION_2_ID_2_ERROR_MAP.get(new Localization(
- locale == null ? Locale.getDefault() : locale,
- i18nClass));
- if (errors == null) {
- errors = Collections.emptyMap();
+ Map<Class, Set<String>> classToProblemsMap = LOCALE_TO_CLASS_TO_PROBLEMS_MAP.get(locale == null ? Locale.getDefault() : locale);
+ if (classToProblemsMap == null) {
+ return Collections.emptySet();
}
- return errors;
+ Set<String> problems = classToProblemsMap.get(i18nClass);
+ if (problems == null) {
+ return Collections.emptySet();
+ }
+ return problems;
}
/**
@@ -100,18 +132,19 @@
}
/**
- * Set the repository of localized messages. If null, a {@link ClasspathLocalizationRepository} instance that uses this class
- * loader will be used.
+ * Set the repository of localized messages. If <code>null</code>, a {@link ClasspathLocalizationRepository} instance that
+ * uses this class loader will be used.
*
- * @param localizationRepository the localization repository to use; may be null if the default repository should be used.
+ * @param localizationRepository the localization repository to use; may be <code>null</code> if the default repository
+ * should be used.
*/
public static void setLocalizationRepository( LocalizationRepository localizationRepository ) {
I18n.localizationRepository = localizationRepository != null ? localizationRepository : DEFAULT_LOCALIZATION_REPOSITORY;
}
/**
- * Initializes the internationalization fields declared on the specified class. Internationalization fields must be public,
- * static, not final, and of type <code>I18n</code>. The specified class must not be an interface (of course), but has no
+ * Initializes the internationalization fields declared on the supplied class. Internationalization fields must be public,
+ * static, not final, and of type <code>I18n</code>. The supplied class must not be an interface (of course), but has no
* restrictions as to what class it may extend or what interfaces it must implement.
*
* @param i18nClass A class declaring one or more public, static, non-final fields of type <code>I18n</code>.
@@ -122,82 +155,98 @@
throw new IllegalArgumentException(CommonI18n.i18nClassInterface.text(i18nClass.getName()));
}
- // Find all public static non-final String fields in the specified class and instantiate an I18n object for each.
- try {
- for (Field fld : i18nClass.getDeclaredFields()) {
+ synchronized (i18nClass) {
+ // Find all public static non-final String fields in the supplied class and instantiate an I18n object for each.
+ try {
+ for (Field fld : i18nClass.getDeclaredFields()) {
- // Ensure field is of type I18n
- if (fld.getType() == I18n.class) {
+ // Ensure field is of type I18n
+ if (fld.getType() == I18n.class) {
- // Ensure field is not final
- if ((fld.getModifiers() & Modifier.FINAL) == Modifier.FINAL) {
- throw new SystemFailureException(CommonI18n.i18nFieldFinal.text(fld.getName(), i18nClass));
- }
+ // Ensure field is public
+ if ((fld.getModifiers() & Modifier.PUBLIC) != Modifier.PUBLIC) {
+ throw new SystemFailureException(CommonI18n.i18nFieldNotPublic.text(fld.getName(), i18nClass));
+ }
- // Ensure field is public
- if ((fld.getModifiers() & Modifier.PUBLIC) != Modifier.PUBLIC) {
- throw new SystemFailureException(CommonI18n.i18nFieldNotPublic.text(fld.getName(), i18nClass));
- }
+ // Ensure field is static
+ if ((fld.getModifiers() & Modifier.STATIC) != Modifier.STATIC) {
+ throw new SystemFailureException(CommonI18n.i18nFieldNotStatic.text(fld.getName(), i18nClass));
+ }
- // Ensure field is static
- if ((fld.getModifiers() & Modifier.STATIC) != Modifier.STATIC) {
- throw new SystemFailureException(CommonI18n.i18nFieldNotStatic.text(fld.getName(), i18nClass));
- }
+ // Ensure field is not final
+ if ((fld.getModifiers() & Modifier.FINAL) == Modifier.FINAL) {
+ throw new SystemFailureException(CommonI18n.i18nFieldFinal.text(fld.getName(), i18nClass));
+ }
- // Ensure we can access field even if it's in a private class
- ClassUtil.makeAccessible(fld);
+ // Ensure we can access field even if it's in a private class
+ ClassUtil.makeAccessible(fld);
- // Initialize field. Do this every time the class is initialized (or re-initialized)
- fld.set(null, new I18n(fld.getName(), i18nClass));
+ // Initialize field. Do this every time the class is initialized (or re-initialized)
+ fld.set(null, new I18n(fld.getName(), i18nClass));
+ }
}
+
+ // Remove all entries for the supplied i18n class to indicate it has not been localized.
+ for (Entry<Locale, Map<Class, Set<String>>> entry : LOCALE_TO_CLASS_TO_PROBLEMS_MAP.entrySet()) {
+ entry.getValue().remove(i18nClass);
+ }
+ } catch (IllegalAccessException err) {
+ // If this happens, it will happen with the first field visited in the above loop
+ throw new IllegalArgumentException(CommonI18n.i18nClassNotPublic.text(i18nClass));
}
- } catch (IllegalAccessException err) {
- throw new IllegalArgumentException(CommonI18n.i18nClassNotPublic.text(i18nClass.getName()));
}
}
/**
- * Synchronized on the locale being loaded (this blocks loading all other locales, but not reads for existing locales)
+ * Synchronized on the supplied internalization class.
*
- * @param i18nClass The internalization class being initialized
- * @param localization
- * @return
+ * @param i18nClass The internalization class being localized
+ * @param locale The locale to which the supplied internationalization class should be localized.
*/
- private synchronized static Map<String, String> initializeIdToTextMap( final Localization localization ) {
- Map<String, String> id2TextMap = new HashMap<String, String>();
-
- // Put in the new map and see if there's already one there ...
- Map<String, String> existingId2TextMap = LOCALIZATION_2_ID_2_TEXT_MAP.putIfAbsent(localization, id2TextMap);
- // If there is already an existing map, then someone beat us to the punch and there's nothing to do ...
- if (existingId2TextMap != null) {
- return existingId2TextMap;
+ private static void localize( final Class i18nClass,
+ final Locale locale ) {
+ assert i18nClass != null;
+ assert locale != null;
+ // Create a class-to-problem map for this locale if one doesn't exist, else get the existing one.
+ Map<Class, Set<String>> classToProblemsMap = new ConcurrentHashMap<Class, Set<String>>();
+ Map<Class, Set<String>> existingClassToProblemsMap = LOCALE_TO_CLASS_TO_PROBLEMS_MAP.putIfAbsent(locale,
+ classToProblemsMap);
+ if (existingClassToProblemsMap != null) {
+ classToProblemsMap = existingClassToProblemsMap;
}
- // We're the first to put in the map for this locale, so populate the one we created...
-
- // Get the URL to the localization properties file ...
- final LocalizationRepository repos = getLocalizationRepository();
- final String bundleName = localization.i18nClass.getName();
- URL url = null;
- Locale locale = new Locale(localization.language, localization.country, localization.variant);
- url = repos.getLocalizationBundle(bundleName, locale);
-
- // Try the default locale (if it is different than the supplied locale) ...
- if (url == null) {
- // Nothing was found, so try the default locale
- Locale defaultLocale = Locale.getDefault();
- if (!defaultLocale.equals(locale)) {
- url = repos.getLocalizationBundle(bundleName, defaultLocale);
+ // Check if already localized outside of synchronization block for 99% use-case
+ if (classToProblemsMap.get(i18nClass) != null) {
+ return;
+ }
+ synchronized (i18nClass) {
+ // Return if the supplied i18n class has already been localized to the supplied locale, despite the check outside of
+ // the synchronization block (1% use-case), else create a class-to-problems map for the class.
+ Set<String> problems = classToProblemsMap.get(i18nClass);
+ if (problems == null) {
+ problems = new CopyOnWriteArraySet<String>();
+ classToProblemsMap.put(i18nClass, problems);
+ } else {
+ return;
}
- }
-
- String bundleMsg = null;
- if (url == null) {
- // Record no variant of the i18n properties file for the specified class found
- bundleMsg = CommonI18n.i18nPropertiesFileNotFound.text(bundleName);
- } else {
+ // Get the URL to the localization properties file ...
+ final LocalizationRepository repos = getLocalizationRepository();
+ final String localizationBaseName = i18nClass.getName();
+ URL url = repos.getLocalizationBundle(localizationBaseName, locale);
+ if (url == null) {
+ // Nothing was found, so try the default locale
+ Locale defaultLocale = Locale.getDefault();
+ if (!defaultLocale.equals(locale)) {
+ url = repos.getLocalizationBundle(localizationBaseName, defaultLocale);
+ }
+ // Return if no applicable localization file could be found
+ if (url == null) {
+ problems.add(CommonI18n.i18nLocalizationFileNotFound.text(localizationBaseName));
+ return;
+ }
+ }
// Initialize i18n map
- final Map<String, String> finalMap = id2TextMap;
final URL finalUrl = url;
+ final Set<String> finalProblems = problems;
Properties props = new Properties() {
@Override
@@ -207,23 +256,28 @@
String text = (String)value;
try {
- Field fld = localization.i18nClass.getDeclaredField(id);
+ Field fld = i18nClass.getDeclaredField(id);
if (fld.getType() != I18n.class) {
// Invalid field type
- mapErrorMessage(localization, id, CommonI18n.i18nFieldInvalidType.text(id,
- finalUrl,
- getClass().getName()));
+ finalProblems.add(CommonI18n.i18nFieldInvalidType.text(id, finalUrl, getClass().getName()));
+ } else {
+ I18n i18n = (I18n)fld.get(null);
+ if (i18n.localeToTextMap.putIfAbsent(locale, text) != null) {
+ // Duplicate id encountered
+ String prevProblem = i18n.localeToProblemMap.putIfAbsent(locale,
+ CommonI18n.i18nPropertyDuplicate.text(id,
+ finalUrl));
+ assert prevProblem == null;
+ }
}
} catch (NoSuchFieldException err) {
// No corresponding field exists
- mapErrorMessage(localization, id, CommonI18n.i18nPropertyUnused.text(id, finalUrl));
+ finalProblems.add(CommonI18n.i18nPropertyUnused.text(id, finalUrl));
+ } catch (IllegalAccessException notPossible) {
+ // Would have already occurred in initialize method, but allowing for the impossible...
+ finalProblems.add(notPossible.getMessage());
}
- if (finalMap.put(id, text) != null) {
- // Duplicate id encountered
- mapErrorMessage(localization, id, CommonI18n.i18nPropertyDuplicate.text(id, finalUrl));
- }
-
return null;
}
};
@@ -232,38 +286,29 @@
InputStream propStream = url.openStream();
try {
props.load(propStream);
+ // Check for uninitialized fields
+ for (Field fld : i18nClass.getDeclaredFields()) {
+ if (fld.getType() == I18n.class) {
+ try {
+ I18n i18n = (I18n)fld.get(null);
+ if (i18n.localeToTextMap.get(locale) == null) {
+ i18n.localeToProblemMap.put(locale, CommonI18n.i18nPropertyMissing.text(fld.getName(), url));
+ }
+ } catch (IllegalAccessException notPossible) {
+ // Would have already occurred in initialize method, but allowing for the impossible...
+ finalProblems.add(notPossible.getMessage());
+ }
+ }
+ }
} finally {
propStream.close();
}
} catch (IOException err) {
- bundleMsg = err.getMessage();
+ finalProblems.add(err.getMessage());
}
}
-
- // Check for uninitialized fields
- for (Field fld : localization.i18nClass.getDeclaredFields()) {
- if (fld.getType() == I18n.class && id2TextMap.get(fld.getName()) == null) {
- mapErrorMessage(localization,
- fld.getName(),
- bundleMsg == null ? CommonI18n.i18nPropertyMissing.text(fld.getName(), url) : bundleMsg);
- }
- }
-
- return id2TextMap;
}
- static void mapErrorMessage( Localization localization,
- String id,
- String message ) {
- Map<String, String> id2ErrorMap = new ConcurrentHashMap<String, String>();
- Map<String, String> existingId2ErrorMap = LOCALIZATION_2_ID_2_ERROR_MAP.putIfAbsent(localization, id2ErrorMap);
- if (existingId2ErrorMap != null) {
- id2ErrorMap = existingId2ErrorMap;
- }
- message = id2ErrorMap.put(id, message);
- assert message == null;
- }
-
/**
* Substitute the arguments into the message, ensuring that the number of arguments matches the number of parameters in the
* text.
@@ -299,25 +344,32 @@
}
}
if (err || argCount < arguments.length) {
- I18n msg = null;
+ String msg = null;
if (id != null) {
if (arguments.length == 1) {
- msg = CommonI18n.i18nArgumentMismatchedParameters;
+ msg = CommonI18n.i18nArgumentMismatchedParameters.text(id, argCount, text, newText.toString());
} else if (argCount == 1) {
- msg = CommonI18n.i18nArgumentsMismatchedParameter;
+ msg = CommonI18n.i18nArgumentsMismatchedParameter.text(arguments.length, id, text, newText.toString());
} else {
- msg = CommonI18n.i18nArgumentsMismatchedParameters;
+ msg = CommonI18n.i18nArgumentsMismatchedParameters.text(arguments.length,
+ id,
+ argCount,
+ text,
+ newText.toString());
}
- throw new IllegalArgumentException(msg.text(arguments.length, id, argCount, text, newText.toString()));
+ throw new IllegalArgumentException(msg);
}
if (arguments.length == 1) {
- msg = CommonI18n.i18nReplaceArgumentMismatchedParameters;
+ msg = CommonI18n.i18nReplaceArgumentMismatchedParameters.text(argCount, text, newText.toString());
} else if (argCount == 1) {
- msg = CommonI18n.i18nReplaceArgumentsMismatchedParameter;
+ msg = CommonI18n.i18nReplaceArgumentsMismatchedParameter.text(arguments.length, text, newText.toString());
} else {
- msg = CommonI18n.i18nReplaceArgumentsMismatchedParameters;
+ msg = CommonI18n.i18nReplaceArgumentsMismatchedParameters.text(arguments.length,
+ argCount,
+ text,
+ newText.toString());
}
- throw new IllegalArgumentException(msg.text(arguments.length, argCount, text, newText.toString()));
+ throw new IllegalArgumentException(msg);
}
matcher.appendTail(newText);
@@ -337,8 +389,10 @@
return replaceParameters(null, text, arguments);
}
- final String id;
+ private final String id;
private final Class i18nClass;
+ final ConcurrentHashMap<Locale, String> localeToTextMap = new ConcurrentHashMap<Locale, String>();
+ final ConcurrentHashMap<Locale, String> localeToProblemMap = new ConcurrentHashMap<Locale, String>();
private I18n( String id,
Class i18nClass ) {
@@ -346,23 +400,84 @@
this.i18nClass = i18nClass;
}
+ /**
+ * @return This internationalization object's ID, which will match both the name of the relevant static field in the
+ * internationalization class and the relevant property name in the associated localization files.
+ */
+ public String id() {
+ return id;
+ }
+
+ /**
+ * @return <code>true</code> if a problem was encountered while localizing this internationalization object to the default
+ * locale.
+ */
+ public boolean hasProblem() {
+ return (problem() != null);
+ }
+
+ /**
+ * @param locale The locale for which to check whether a problem was encountered.
+ * @return <code>true</code> if a problem was encountered while localizing this internationalization object to the supplied
+ * locale.
+ */
+ public boolean hasProblem( Locale locale ) {
+ return (problem(locale) != null);
+ }
+
+ /**
+ * @return The problem encountered while localizing this internationalization object to the default locale, or
+ * <code>null</code> if none was encountered.
+ */
+ public String problem() {
+ return problem(null);
+ }
+
+ /**
+ * @param locale The locale for which to return the problem.
+ * @return The problem encountered while localizing this internationalization object to the supplied locale, or
+ * <code>null</code> if none was encountered.
+ */
+ public String problem( Locale locale ) {
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
+ localize(i18nClass, locale);
+ // Check for field/property error
+ String problem = localeToProblemMap.get(locale);
+ if (problem != null) {
+ return problem;
+ }
+ // Check if text exists
+ if (localeToTextMap.get(locale) != null) {
+ // If so, no problem exists
+ return null;
+ }
+ // If we get here, which will be at most once, there was at least one global localization error, so just return a message
+ // indicating to look them up.
+ problem = CommonI18n.i18nLocalizationProblems.text(i18nClass, locale);
+ localeToProblemMap.put(locale, problem);
+ return problem;
+ }
+
private String rawText( Locale locale ) {
assert locale != null;
- Map<String, String> id2TextMap = null;
- final Localization localization = new Localization(locale, i18nClass);
- id2TextMap = LOCALIZATION_2_ID_2_TEXT_MAP.get(localization);
- if (id2TextMap == null) {
- id2TextMap = initializeIdToTextMap(localization);
+ localize(i18nClass, locale);
+ // Check if text exists
+ String text = localeToTextMap.get(locale);
+ if (text != null) {
+ return text;
}
-
- return id2TextMap.get(id);
+ // If not, there was a problem, so throw it within an exception so upstream callers can tell the difference between normal
+ // text and problem text.
+ throw new SystemFailureException(problem(locale));
}
/**
- * Get the internationalized text localized to the {@link Locale#getDefault() current (default) locale}, replacing the
- * parameters in the text with those supplied.
+ * Get the localized text for the {@link Locale#getDefault() current (default) locale}, replacing the parameters in the text
+ * with those supplied.
*
- * @param arguments the arguments for the parameter replacement; may be null or empty
+ * @param arguments the arguments for the parameter replacement; may be <code>null</code> or empty
* @return the localized text
*/
public String text( Object... arguments ) {
@@ -370,28 +485,20 @@
}
/**
- * Get the internationalized text localized to the supplied locale, replacing the parameters in the text with those supplied.
+ * Get the localized text for the supplied locale, replacing the parameters in the text with those supplied.
*
- * @param locale the locale, or null if the {@link Locale#getDefault() current (default) locale} should be used
- * @param arguments the arguments for the parameter replacement; may be null or empty
+ * @param locale the locale, or <code>null</code> if the {@link Locale#getDefault() current (default) locale} should be used
+ * @param arguments the arguments for the parameter replacement; may be <code>null</code> or empty
* @return the localized text
*/
public String text( Locale locale,
Object... arguments ) {
- if (locale == null) {
- locale = Locale.getDefault();
+ try {
+ String rawText = rawText(locale == null ? Locale.getDefault() : locale);
+ return replaceParameters(id, rawText, arguments);
+ } catch (SystemFailureException err) {
+ return '<' + err.getMessage() + '>';
}
- String rawText = rawText(locale);
- if (rawText == null) {
- Map<String, String> id2ErrorMap = LOCALIZATION_2_ID_2_ERROR_MAP.get(new Localization(locale, i18nClass));
- if (id2ErrorMap != null) {
- String msg = id2ErrorMap.get(id);
- if (msg != null) {
- return '<' + msg + '>';
- }
- }
- }
- return replaceParameters(id, rawText, arguments);
}
/**
@@ -399,71 +506,10 @@
*/
@Override
public String toString() {
- return rawText(Locale.getDefault());
- }
-
- @Immutable
- private static class Localization {
-
- final String language;
- final String country;
- final String variant;
- final Class i18nClass;
-
- Localization( Locale locale,
- Class i18nClass ) {
- this.language = locale.getLanguage();
- this.country = locale.getCountry();
- this.variant = locale.getVariant();
- this.i18nClass = i18nClass;
+ try {
+ return rawText(Locale.getDefault());
+ } catch (SystemFailureException err) {
+ return '<' + err.getMessage() + '>';
}
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see java.lang.Object#hashCode()
- */
- @Override
- public int hashCode() {
- return HashCode.compute(country, i18nClass, language, variant);
- }
-
- /**
- * <p>
- * {@inheritDoc}
- * </p>
- *
- * @see java.lang.Object#equals(java.lang.Object)
- */
- @Override
- public boolean equals( Object obj ) {
- if (this == obj) return true;
- if (obj == null) return false;
- if (getClass() != obj.getClass()) return false;
- Localization other = (Localization)obj;
- if (country == null) {
- if (other.country != null) return false;
- } else if (!country.equals(other.country)) {
- return false;
- }
- if (i18nClass == null) {
- if (other.i18nClass != null) return false;
- } else if (!i18nClass.equals(other.i18nClass)) {
- return false;
- }
- if (language == null) {
- if (other.language != null) return false;
- } else if (!language.equals(other.language)) {
- return false;
- }
- if (variant == null) {
- if (other.variant != null) return false;
- } else if (!variant.equals(other.variant)) {
- return false;
- }
- return true;
- }
}
}
Modified: trunk/dna-common/src/main/resources/org/jboss/dna/common/CommonI18n.properties
===================================================================
--- trunk/dna-common/src/main/resources/org/jboss/dna/common/CommonI18n.properties 2008-04-22 20:42:49 UTC (rev 104)
+++ trunk/dna-common/src/main/resources/org/jboss/dna/common/CommonI18n.properties 2008-04-24 00:45:28 UTC (rev 105)
@@ -1,21 +1,22 @@
# Make sure the following I18n.java-related properties are defined before all other properties to ensure a valid error message is
# produced in the event of a missing/duplicate/unused property
-i18nArgumentsMismatchedParameter = {0} arguments were specified for internationalization object "{1}", but {2} parameter is required: "{3}" => "{4}"
-i18nArgumentMismatchedParameters = {0} argument was specified for internationalization object "{1}", but {2} parameters are required: "{3}" => "{4}"
-i18nArgumentsMismatchedParameters = {0} arguments were specified for internationalization object "{1}", but {2} parameters are required: "{3}" => "{4}"
-i18nReplaceArgumentsMismatchedParameter = {0} arguments were specified, but {1} parameter is required: "{2}" => "{3}"
-i18nReplaceArgumentMismatchedParameters = {0} argument was specified, but {1} parameters are required: "{2}" => "{3}"
-i18nReplaceArgumentsMismatchedParameters = {0} arguments were specified, but {1} parameters are required: "{2}" => "{3}"
-i18nClassInterface = Class {0} must not be an interface.
-i18nClassNotPublic = Class {0} must be public.
+i18nArgumentsMismatchedParameter = {0} arguments were supplied to internationalization object "{1}", but 1 parameter is required: "{2}" => "{3}"
+i18nArgumentMismatchedParameters = 1 argument was supplied to internationalization object "{0}", but {1} parameters are required: "{2}" => "{3}"
+i18nArgumentsMismatchedParameters = {0} arguments were supplied to internationalization object "{1}", but {2} parameters are required: "{3}" => "{4}"
+i18nReplaceArgumentsMismatchedParameter = {0} arguments were supplied, but 1 parameter is required: "{1}" => "{2}"
+i18nReplaceArgumentMismatchedParameters = 1 argument was supplied, but {0} parameters are required: "{1}" => "{2}"
+i18nReplaceArgumentsMismatchedParameters = {0} arguments were supplied, but {1} parameters are required: "{2}" => "{3}"
+i18nClassInterface = Internationalization class {0} must not be an interface.
+i18nClassNotPublic = Internationalization {0} must be public.
i18nFieldFinal = Internationalization field "{0}" in {1} must not be final.
i18nFieldInvalidType = Internationalization field "{0}" in {1} must be of type {2}.
i18nFieldNotPublic = Internationalization field "{0}" in {1} must be public.
i18nFieldNotStatic = Internationalization field "{0}" in {1} must be static.
-i18nPropertiesFileNotFound = No variant of the localization file for "{0}" could be found.
+i18nLocalizationFileNotFound = No variant of the localization file for "{0}" could be found.
+i18nLocalizationProblems = Problems were encountered while localizing internationalization {0} to locale "{1}"
i18nPropertyDuplicate = Duplicate property values were found for property "{0}" in localization file "{1}";
-i18nPropertyMissing = Missing property "{0}" in localization file {1}.
+i18nPropertyMissing = Missing property "{0}" in localization file "{1}".
i18nPropertyUnused = An unused property, "{0}", was found in localization file "{1}".
# Core-related fields
Added: trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/CommonI18nTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/CommonI18nTest.java (rev 0)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/CommonI18nTest.java 2008-04-24 00:45:28 UTC (rev 105)
@@ -0,0 +1,23 @@
+/*
+ *
+ */
+package org.jboss.dna.common.i18n;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import java.util.Locale;
+import org.jboss.dna.common.CommonI18n;
+import org.junit.Test;
+
+/**
+ * @author John Verhaeg
+ */
+public class CommonI18nTest {
+
+ @Test
+ public void shouldNotHaveLocalizationProblems() {
+ for (Locale locale : CommonI18n.getLocalizationProblemLocales()) {
+ assertThat(CommonI18n.getLocalizationProblems(locale).isEmpty(), is(true));
+ }
+ }
+}
Property changes on: trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/CommonI18nTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/I18nTest.java
===================================================================
--- trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/I18nTest.java 2008-04-22 20:42:49 UTC (rev 104)
+++ trunk/dna-common/src/test/java/org/jboss/dna/common/i18n/I18nTest.java 2008-04-24 00:45:28 UTC (rev 105)
@@ -28,6 +28,13 @@
import static org.hamcrest.core.IsNull.notNullValue;
import static org.hamcrest.core.IsNull.nullValue;
import static org.junit.Assert.assertThat;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
import org.jboss.dna.common.CommonI18n;
import org.jboss.dna.common.SystemFailureException;
import org.junit.Before;
@@ -39,222 +46,409 @@
*/
public final class I18nTest {
- @Before
- public void beforeEach() {
- I18n.initialize(TestI18n.class);
- }
+ @Before
+ public void beforeEach() throws Exception {
+ clearFields(TestI18n.class);
+ clearFields(TestI18nDuplicateProperty.class);
+ clearFields(TestI18nFinal.class);
+ clearFields(TestI18nFinalField.class);
+ clearFields(TestI18nInterface.class);
+ clearFields(TestI18nMissingLocalization.class);
+ clearFields(TestI18nMissingProperty.class);
+ clearFields(TestI18nNotPublicField.class);
+ clearFields(TestI18nNotStaticField.class);
+ clearFields(TestI18nPrivate.class);
+ clearFields(TestI18nUnusedProperty.class);
+ for (Entry<Locale, Map<Class, Set<String>>> localeToMapEntry : I18n.LOCALE_TO_CLASS_TO_PROBLEMS_MAP.entrySet()) {
+ for (Iterator<Entry<Class, Set<String>>> iter = localeToMapEntry.getValue().entrySet().iterator(); iter.hasNext();) {
+ if (iter.next().getKey() != CommonI18n.class) {
+ iter.remove();
+ }
+ }
+ }
+ }
- @Test( expected = IllegalArgumentException.class )
- public void getErrorsForDefaultLocaleShouldFailIfClassIsNull() {
- I18n.getErrorsForDefaultLocale(null);
+ private void clearFields( Class i18nClass ) throws Exception {
+ for (Field fld : i18nClass.getDeclaredFields()) {
+ if (fld.getType() == I18n.class && (fld.getModifiers() & Modifier.PUBLIC) == Modifier.PUBLIC
+ && (fld.getModifiers() & Modifier.STATIC) == Modifier.STATIC
+ && (fld.getModifiers() & Modifier.FINAL) != Modifier.FINAL) {
+ fld.set(null, null);
+ }
+ }
}
- @Test
- public void getErrorsForLocaleShouldAllNullLocale() {
- I18n.getErrorsForLocale(TestI18n.class, null);
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToGetLocalizationProblemLocalesIfNoClassSupplied() {
+ I18n.getLocalizationProblemLocales(null);
}
@Test
- public void getErrorsForDefaultLocaleShouldNotReturnNull() {
- assertThat(I18n.getErrorsForDefaultLocale(TestI18n.class), notNullValue());
+ public void shouldNeverReturnNullWhenGettingLocalizationProblemLocales() {
+ assertThat(I18n.getLocalizationProblemLocales(TestI18n.class), notNullValue());
}
- @Test( expected = IllegalArgumentException.class )
- public void initializeShouldFailIfClassIsNull() {
- I18n.initialize(null);
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToGetLocalizationProblemsForDefaultLocaleIfNoClassSupplied() {
+ I18n.getLocalizationProblems(null);
+ }
- @Test
- public void initializeShouldSkipNonI18nFields() {
- assertThat(TestI18n.nonI18n, is(nullValue()));
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToGetLocalizationProblemsForSuppliedLocaleIfNoClassSupplied() {
+ I18n.getLocalizationProblems(null, Locale.US);
+ }
- @Test( expected = SystemFailureException.class )
- public void initializeShouldFailIfI18nFieldIsFinal() {
- try {
- I18n.initialize(TestI18nFinalField.class);
- } catch (SystemFailureException err) {
- assertThat(err.getMessage(), is(CommonI18n.i18nFieldFinal.text("testMessage", TestI18nFinalField.class)));
- System.err.println(err);
- throw err;
- }
- }
+ @Test
+ public void shouldNeverReturnNullWhenGettingLocalizationProblemsForDefaultLocale() {
+ assertThat(I18n.getLocalizationProblems(TestI18n.class), notNullValue());
+ }
- @Test( expected = RuntimeException.class )
- public void initializeShouldFailIfI18nFieldIsNotPublic() {
- try {
- I18n.initialize(TestI18nNotPublicField.class);
- } catch (RuntimeException err) {
- assertThat(err.getMessage(), is(CommonI18n.i18nFieldNotPublic.text("testMessage", TestI18nNotPublicField.class)));
- System.err.println(err);
- throw err;
- }
- }
+ @Test
+ public void shouldNeverReturnNullWhenGettingLocalizationProblemsForSuppliedLocale() {
+ assertThat(I18n.getLocalizationProblems(TestI18n.class, Locale.US), notNullValue());
+ }
- @Test( expected = RuntimeException.class )
- public void initializeShouldFailIfI18nFieldIsNotStatic() {
- try {
- I18n.initialize(TestI18nNotStaticField.class);
- } catch (RuntimeException err) {
- assertThat(err.getMessage(), is(CommonI18n.i18nFieldNotStatic.text("testMessage", TestI18nNotStaticField.class)));
- System.err.println(err);
- throw err;
- }
- }
+ @Test
+ public void shouldNotHaveLocalizationProblemsAfterInitializationButBeforeLocalization() {
+ I18n.initialize(TestI18nUnusedProperty.class);
+ assertThat(I18n.getLocalizationProblems(TestI18nUnusedProperty.class, null).isEmpty(), is(true));
+ assertThat(I18n.getLocalizationProblemLocales(TestI18nUnusedProperty.class).isEmpty(), is(true));
+ }
- @Test
- public void initializeShouldAllowFinalClass() {
- I18n.initialize(TestI18nFinal.class);
- }
+ @Test
+ public void shouldGetLocalizationProblemsForDefaultLocaleIfNoLocaleSupplied() {
+ I18n.initialize(TestI18nUnusedProperty.class);
+ TestI18nUnusedProperty.testMessage.text("test");
+ assertThat(I18n.getLocalizationProblems(TestI18nUnusedProperty.class, null).isEmpty(), is(false));
+ }
- @Test
- public void initializeShouldAllowPrivateClasses() {
- I18n.initialize(TestI18nPrivate.class);
- assertThat(TestI18nPrivate.testMessage, instanceOf(I18n.class));
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToInitializeIfNoClassSupplied() {
+ I18n.initialize(null);
+ }
- @Test
- public void initializeShouldAssignI18nInstanceToI18nFields() {
- assertThat(TestI18n.testMessage, instanceOf(I18n.class));
- }
+ @Test( expected = SystemFailureException.class )
+ public void shouldFailToInitializeFinalI18nField() {
+ try {
+ I18n.initialize(TestI18nFinalField.class);
+ } catch (SystemFailureException err) {
+ assertThat(err.getMessage(), is(CommonI18n.i18nFieldFinal.text("testMessage", TestI18nFinalField.class)));
+ System.err.println(err);
+ throw err;
+ }
+ }
- @Test( expected = IllegalArgumentException.class )
- public void initializeShouldFailIfClassIsInterface() {
- try {
- I18n.initialize(TestI18nInterface.class);
- } catch (IllegalArgumentException err) {
- assertThat(err.getMessage(), is(CommonI18n.i18nClassInterface.text(TestI18nInterface.class.getName())));
- System.err.println(err);
- throw err;
- }
- }
+ @Test( expected = SystemFailureException.class )
+ public void shouldFailToInitializeNonPublicI18nField() {
+ try {
+ I18n.initialize(TestI18nNotPublicField.class);
+ } catch (SystemFailureException err) {
+ assertThat(err.getMessage(), is(CommonI18n.i18nFieldNotPublic.text("testMessage", TestI18nNotPublicField.class)));
+ System.err.println(err);
+ throw err;
+ }
+ }
- @Test
- public void initializeShouldBeIdempotent() {
- I18n.initialize(TestI18n.class);
- }
+ @Test( expected = SystemFailureException.class )
+ public void shouldFailToInitializeNonStaticI18nField() {
+ try {
+ I18n.initialize(TestI18nNotStaticField.class);
+ } catch (SystemFailureException err) {
+ assertThat(err.getMessage(), is(CommonI18n.i18nFieldNotStatic.text("testMessage", TestI18nNotStaticField.class)));
+ System.err.println(err);
+ throw err;
+ }
+ }
- @Test
- public void i18nIdShouldMatchFieldName() throws Exception {
- assertThat(TestI18n.testMessage.id, is("testMessage"));
- }
+ @Test
+ public void shouldInitializeFinalClasses() {
+ I18n.initialize(TestI18nFinal.class);
+ assertThat(TestI18nFinal.testMessage, instanceOf(I18n.class));
+ }
- @Test
- public void i18nTextShouldHandleIfPropertyDuplicate() throws Exception {
- I18n.initialize(TestI18nDuplicateProperty.class);
- String text = TestI18nDuplicateProperty.testMessage.text("test");
+ @Test
+ public void shouldInitializePrivateClasses() {
+ I18n.initialize(TestI18nPrivate.class);
+ assertThat(TestI18nPrivate.testMessage, instanceOf(I18n.class));
+ }
+
+ @Test
+ public void shouldInitializeI18nFields() {
+ I18n.initialize(TestI18n.class);
+ assertThat(TestI18n.testMessage, instanceOf(I18n.class));
+ }
+
+ @Test
+ public void shouldNotInitializeNonI18nFields() {
+ I18n.initialize(TestI18n.class);
+ assertThat(TestI18n.nonI18n, nullValue());
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToInitializeInterfaces() {
+ try {
+ I18n.initialize(TestI18nInterface.class);
+ } catch (IllegalArgumentException err) {
+ assertThat(err.getMessage(), is(CommonI18n.i18nClassInterface.text(TestI18nInterface.class.getName())));
+ System.err.println(err);
+ throw err;
+ }
+ }
+
+ @Test
+ public void shouldProvideIdempotentInitialization() {
+ I18n.initialize(TestI18n.class);
+ assertThat(TestI18n.testMessage1.text("test"), is("test"));
+ I18n.initialize(TestI18n.class);
+ assertThat(TestI18n.testMessage1.text("test"), is("test"));
+ }
+
+ @Test
+ public void shouldNotBeLocalizedAfterInitialization() {
+ I18n.initialize(TestI18nDuplicateProperty.class);
+ assertThat(TestI18nDuplicateProperty.testMessage.localeToTextMap.get(Locale.getDefault()), nullValue());
+ assertThat(TestI18nDuplicateProperty.testMessage.localeToProblemMap.get(Locale.getDefault()), nullValue());
+ }
+
+ @Test
+ public void shouldHaveIdThatMatchesFieldName() throws Exception {
+ I18n.initialize(TestI18n.class);
+ assertThat(TestI18n.testMessage.id(), is("testMessage"));
+ }
+
+ @Test
+ public void shouldNotBeLocalizedIfAskedForId() {
+ I18n.initialize(TestI18nDuplicateProperty.class);
+ TestI18nDuplicateProperty.testMessage.id();
+ assertThat(TestI18nDuplicateProperty.testMessage.localeToTextMap.get(Locale.getDefault()), nullValue());
+ assertThat(TestI18nDuplicateProperty.testMessage.localeToProblemMap.get(Locale.getDefault()), nullValue());
+ }
+
+ @Test
+ public void shouldBeLocalizedIfAskedIfHasProblem() {
+ I18n.initialize(TestI18nDuplicateProperty.class);
+ TestI18nDuplicateProperty.testMessage.hasProblem();
+ assertThat(TestI18nDuplicateProperty.testMessage.localeToTextMap.get(Locale.getDefault()), notNullValue());
+ assertThat(TestI18nDuplicateProperty.testMessage.localeToProblemMap.get(Locale.getDefault()), notNullValue());
+ }
+
+ @Test
+ public void shouldBeLocalizedIfAskedForProblem() {
+ I18n.initialize(TestI18nDuplicateProperty.class);
+ TestI18nDuplicateProperty.testMessage.problem();
+ assertThat(TestI18nDuplicateProperty.testMessage.localeToTextMap.get(Locale.getDefault()), notNullValue());
+ assertThat(TestI18nDuplicateProperty.testMessage.localeToProblemMap.get(Locale.getDefault()), notNullValue());
+ }
+
+ @Test
+ public void shouldBeLocalizedIfConvertedToString() {
+ I18n.initialize(TestI18nDuplicateProperty.class);
+ TestI18nDuplicateProperty.testMessage.toString();
+ assertThat(TestI18nDuplicateProperty.testMessage.localeToTextMap.get(Locale.getDefault()), notNullValue());
+ assertThat(TestI18nDuplicateProperty.testMessage.localeToProblemMap.get(Locale.getDefault()), notNullValue());
+ }
+
+ @Test
+ public void shouldContainAngleBracketedProblemInTextIfMissingLocalization() throws Exception {
+ I18n.initialize(TestI18nMissingLocalization.class);
+ String text = TestI18nMissingLocalization.testMessage.text();
+ assertThat(text,
+ is('<' + CommonI18n.i18nLocalizationProblems.text(TestI18nMissingLocalization.class, Locale.getDefault()) + '>'));
+ System.out.println("Text: " + text);
+ }
+
+ @Test
+ public void shouldHaveProblemIfMissingLocalization() throws Exception {
+ I18n.initialize(TestI18nMissingLocalization.class);
+ assertThat(TestI18nMissingLocalization.testMessage.hasProblem(), is(true));
+ String problem = TestI18nMissingLocalization.testMessage.problem();
+ assertThat(problem, is(CommonI18n.i18nLocalizationProblems.text(TestI18nMissingLocalization.class, Locale.getDefault())));
+ System.out.println("Problem: " + problem);
+ }
+
+ @Test
+ public void shouldHaveLocalicationProblemIfMissingLocalization() throws Exception {
+ I18n.initialize(TestI18nMissingLocalization.class);
+ TestI18nMissingLocalization.testMessage.text();
+ assertThat(I18n.getLocalizationProblems(TestI18nMissingLocalization.class).size(), is(1));
+ assertThat(I18n.getLocalizationProblems(TestI18nMissingLocalization.class).iterator().next(),
+ is(CommonI18n.i18nLocalizationFileNotFound.text(TestI18nMissingLocalization.class.getName())));
+ assertThat(I18n.getLocalizationProblemLocales(TestI18nMissingLocalization.class).size(), is(1));
+ assertThat(I18n.getLocalizationProblemLocales(TestI18nMissingLocalization.class).iterator().next(),
+ is(Locale.getDefault()));
+ }
+
+ @Test
+ public void shouldHaveTextIfPropertyDuplicate() throws Exception {
+ I18n.initialize(TestI18nDuplicateProperty.class);
+ String text = TestI18nDuplicateProperty.testMessage.text("test");
assertThat(text.charAt(0), not('<'));
- assertThat(I18n.getErrorsForDefaultLocale(TestI18nDuplicateProperty.class).size(), is(1));
- System.out.println(text);
- }
+ System.out.println("Text: " + text);
+ }
- @Test
- public void i18nTextShouldHandleIfPropertyMissing() throws Exception {
- I18n.initialize(TestI18nMissingProperty.class);
- String text = TestI18nMissingProperty.testMessage1.text();
+ @Test
+ public void shouldHaveProblemIfPropertyDuplicate() throws Exception {
+ I18n.initialize(TestI18nDuplicateProperty.class);
+ assertThat(TestI18nDuplicateProperty.testMessage.hasProblem(), is(true));
+ String problem = TestI18nDuplicateProperty.testMessage.problem();
+ assertThat(problem, notNullValue());
+ System.out.println("Problem: " + problem);
+ }
+
+ @Test
+ public void shouldNotHaveLocalicationProblemIfPropertyDuplicate() throws Exception {
+ I18n.initialize(TestI18nDuplicateProperty.class);
+ TestI18nDuplicateProperty.testMessage.text("test");
+ assertThat(I18n.getLocalizationProblems(TestI18nDuplicateProperty.class).isEmpty(), is(true));
+ assertThat(I18n.getLocalizationProblemLocales(TestI18nDuplicateProperty.class).isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldContainAngleBracketedProblemInTextIfPropertyMissing() throws Exception {
+ I18n.initialize(TestI18nMissingProperty.class);
+ String text = TestI18nMissingProperty.testMessage1.text("test");
assertThat(text.charAt(0), is('<'));
- assertThat(I18n.getErrorsForDefaultLocale(TestI18nDuplicateProperty.class).size(), is(1));
- System.out.println(text);
- }
+ System.out.println("Text: " + text);
+ }
- @Test
- public void i18nTextShouldHandleIfPropertyUnused() throws Exception {
- I18n.initialize(TestI18nUnusedProperty.class);
- String text = TestI18nUnusedProperty.testMessage.text("test");
- assertThat(text.charAt(0), not('<'));
- assertThat(I18n.getErrorsForDefaultLocale(TestI18nDuplicateProperty.class).size(), is(1));
- System.out.println(text);
- }
+ @Test
+ public void shouldHaveProblemIfPropertyMissing() throws Exception {
+ I18n.initialize(TestI18nMissingProperty.class);
+ assertThat(TestI18nMissingProperty.testMessage1.hasProblem(), is(true));
+ String problem = TestI18nMissingProperty.testMessage1.problem();
+ assertThat(problem, notNullValue());
+ System.out.println("Problem: " + problem);
+ }
- @Test
- public void i18nTextShouldMatchPropertiesFile() throws Exception {
- assertThat(TestI18n.testMessage.text(), is("Test Message"));
- }
+ @Test
+ public void shouldNotHaveLocalicationProblemIfPropertyMissing() throws Exception {
+ I18n.initialize(TestI18nMissingProperty.class);
+ TestI18nMissingProperty.testMessage1.text("test");
+ assertThat(I18n.getLocalizationProblems(TestI18nMissingProperty.class).isEmpty(), is(true));
+ assertThat(I18n.getLocalizationProblemLocales(TestI18nMissingProperty.class).isEmpty(), is(true));
+ }
- @Test( expected = IllegalArgumentException.class )
- public void i18nTextShouldFailIfTooFewArgumentsSpecified() throws Exception {
- try {
- TestI18n.testMessage1.text();
- } catch (IllegalArgumentException err) {
- assertThat(err.getMessage(), is(CommonI18n.i18nArgumentsMismatchedParameter.text(0, "testMessage1", 1, "{0}", "{0}")));
- System.err.println(err);
- throw err;
- }
- }
+ @Test
+ public void shouldHaveLocalicationProblemIfPropertyUnused() throws Exception {
+ I18n.initialize(TestI18nUnusedProperty.class);
+ TestI18nUnusedProperty.testMessage.text("test");
+ assertThat(I18n.getLocalizationProblems(TestI18nUnusedProperty.class).size(), is(1));
+ assertThat(I18n.getLocalizationProblemLocales(TestI18nUnusedProperty.class).size(), is(1));
+ assertThat(I18n.getLocalizationProblemLocales(TestI18nUnusedProperty.class).iterator().next(), is(Locale.getDefault()));
+ }
- @Test( expected = IllegalArgumentException.class )
- public void i18nTextShouldFailIfTooManyArgumentsSpecified() throws Exception {
- try {
- TestI18n.testMessage1.text("Test", "Message");
- } catch (IllegalArgumentException err) {
- assertThat(err.getMessage(), is(CommonI18n.i18nArgumentsMismatchedParameter.text(2, "testMessage1", 1, "{0}", "Test")));
- System.err.println(err);
- throw err;
- }
- }
+ @Test
+ public void shouldHaveTextMatchingLocalizationFilePropertyValue() throws Exception {
+ I18n.initialize(TestI18n.class);
+ assertThat(TestI18n.testMessage.text(), is("Test Message"));
+ }
- @Test
- public void i18nTextShouldContainArgumentsInRightOrder() throws Exception {
- assertThat(TestI18n.testMessage2.text("Test", "Message"), is("Message Test"));
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailIfTooFewArgumentsSuppliedToText() throws Exception {
+ I18n.initialize(TestI18n.class);
+ try {
+ TestI18n.testMessage1.text();
+ } catch (IllegalArgumentException err) {
+ assertThat(err.getMessage(), is(CommonI18n.i18nArgumentsMismatchedParameter.text(0, "testMessage1", 1, "{0}", "{0}")));
+ System.err.println(err);
+ throw err;
+ }
+ }
- @Test
- public void i18nTextShouldAllowReuseOfArguments() throws Exception {
- assertThat(TestI18n.testMessage3.text("Test", "Message"), is("Message Test Message"));
- }
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailIfTooManyArgumentsSuppliedToText() throws Exception {
+ I18n.initialize(TestI18n.class);
+ try {
+ TestI18n.testMessage1.text("Test", "Message");
+ } catch (IllegalArgumentException err) {
+ assertThat(err.getMessage(),
+ is(CommonI18n.i18nArgumentsMismatchedParameter.text(2, "testMessage1", 1, "{0}", "Test")));
+ System.err.println(err);
+ throw err;
+ }
+ }
- public static class TestI18n {
+ @Test
+ public void shouldContainArgumentsInRightOrderInText() throws Exception {
+ I18n.initialize(TestI18n.class);
+ assertThat(TestI18n.testMessage2.text("Test", "Message"), is("Message Test"));
+ }
- public static I18n testMessage;
- public static I18n testMessage1;
- public static I18n testMessage2;
- public static I18n testMessage3;
- public static Object nonI18n;
- }
+ @Test
+ public void shouldAllowReuseOfArgumentsInText() throws Exception {
+ I18n.initialize(TestI18n.class);
+ assertThat(TestI18n.testMessage3.text("Test", "Message"), is("Message Test Message"));
+ }
- private static class TestI18nDuplicateProperty {
+ @Test
+ public void shouldContainLocaleSpecificText() {
+ I18n.initialize(TestI18n.class);
+ assertThat(TestI18n.testMessage.text(Locale.FRENCH), is("Message de Test"));
+ }
- public static I18n testMessage;
- }
+ @Test
+ public void shouldContainTextForDefaultLocaleIfMissingLocalizationForSuppliedLocale() {
+ I18n.initialize(TestI18n.class);
+ assertThat(TestI18n.testMessage.text(Locale.CHINESE), is("Test Message"));
+ }
- public static final class TestI18nFinal {
+ public static class TestI18n {
- public static I18n testMessage;
- }
+ public static I18n testMessage;
+ public static I18n testMessage1;
+ public static I18n testMessage2;
+ public static I18n testMessage3;
+ public static Object nonI18n;
+ }
- public static class TestI18nFinalField {
+ private static class TestI18nDuplicateProperty {
- public static final I18n testMessage = null;
- }
+ public static I18n testMessage;
+ }
- public static interface TestI18nInterface {
+ public static final class TestI18nFinal {
- I18n testMessage = null;
- }
+ public static I18n testMessage;
+ }
- private static class TestI18nMissingProperty {
+ public static class TestI18nFinalField {
- public static I18n testMessage;
- public static I18n testMessage1;
- }
+ public static final I18n testMessage = null;
+ }
- public static class TestI18nNotPublicField {
+ public static interface TestI18nInterface {
- static I18n testMessage;
- }
+ I18n testMessage = null;
+ }
- public static class TestI18nNotStaticField {
+ private static class TestI18nMissingProperty {
- public I18n testMessage;
- }
+ public static I18n testMessage;
+ public static I18n testMessage1;
+ }
- private static class TestI18nPrivate {
+ public static class TestI18nNotPublicField {
- public static I18n testMessage;
- }
+ static I18n testMessage;
+ }
- private static class TestI18nUnusedProperty {
+ public static class TestI18nNotStaticField {
- public static I18n testMessage;
- }
+ public I18n testMessage;
+ }
+
+ private static class TestI18nPrivate {
+
+ public static I18n testMessage;
+ }
+
+ private static class TestI18nUnusedProperty {
+
+ public static I18n testMessage;
+ }
+
+ private static class TestI18nMissingLocalization {
+
+ public static I18n testMessage;
+ }
}
Deleted: trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n.properties
===================================================================
--- trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n.properties 2008-04-22 20:42:49 UTC (rev 104)
+++ trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n.properties 2008-04-24 00:45:28 UTC (rev 105)
@@ -1,4 +0,0 @@
-testMessage = Test Message
-testMessage1 = {0}
-testMessage2 = {1} {0}
-testMessage3 = {1} {0} {1}
\ No newline at end of file
Copied: trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n_en.properties (from rev 100, trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n.properties)
===================================================================
--- trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n_en.properties (rev 0)
+++ trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n_en.properties 2008-04-24 00:45:28 UTC (rev 105)
@@ -0,0 +1,4 @@
+testMessage = Test Message
+testMessage1 = {0}
+testMessage2 = {1} {0}
+testMessage3 = {1} {0} {1}
\ No newline at end of file
Property changes on: trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n_en.properties
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n_fr.properties
===================================================================
--- trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n_fr.properties (rev 0)
+++ trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n_fr.properties 2008-04-24 00:45:28 UTC (rev 105)
@@ -0,0 +1,4 @@
+testMessage = Message de Test
+testMessage1 = {0}
+testMessage2 = {1} {0}
+testMessage3 = {1} {0} {1}
\ No newline at end of file
Property changes on: trunk/dna-common/src/test/resources/org/jboss/dna/common/i18n/I18nTest$TestI18n_fr.properties
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ text/plain
16 years