Generic CMS content items importer.

Importer can import content items from XML source, placing them at specified place in folder hierarchy. Importer expects XML input in format similar to output of DomainObjectTraversal, with some modifications. There is also possibility to start workflow on imported objects.

The basic XML input file has a structure like this:

    <?xml version="1.0" encoding="UTF-8"?>
    <import source="camden.aplaw.org.uk" xmlns="http://xmlns.redhat.com/waf/london/importer/1.0">
      <folder xmlns="http://www.arsdigita.com/cms/1.0" label="Root Folder " name="/" oid="[com.arsdigita.cms.Folder:{id=556}]">
       <folder label="one" name="one" oid="[com.arsdigita.cms.Folder:{id=4402}]">
         <folder label="Two Test" name="two-test" oid="[com.arsdigita.cms.Folder:{id=4407}]">
            <cms:item xmlns:cms="http://www.arsdigita.com/cms/1.0" oid="[com.arsdigita.cms.contenttypes.Article:{id=4412}]">
               <fileAttachments oid="[com.arsdigita.cms.contentassets.FileAttachment:{id=4448}]">
                  <name>Address.xsd</name>
                  <content file="content-4448-Address.xsd"/>
               </fileAttachments>
               <name>eeek</name>
               <type oid="[com.arsdigita.cms.ContentType:{id=144}]"/>
               <launchDate>Tue Dec 02 00:00:00 GMT 2003</launchDate>
               <title>Eeek</title>
               <textAsset oid="[com.arsdigita.cms.TextAsset:{id=4429}]">
                  <content>Edit text here</content>
               </textAsset>
               <imageCaptions oid="[com.arsdigita.cms.ArticleImageAssociation:{id=4439}]">
                  <caption>sdfdsfs</caption>
                  <imageAsset oid="[com.arsdigita.cms.ReusableImageAsset:{id=1734}]">
                     <name>5.jpg</name>
                     <mimeType oid="[com.arsdigita.cms.MimeType:{mimeType=image/jpeg}]">
                        <label>JPG image</label>
                        <mimeType>image/jpeg</mimeType>
                        <fileExtension>jpg</fileExtension>
                     </mimeType>
                     <height>768</height>
                     <width>512</width>
                     <content file="content-1734-5.jpg"/>
                  </imageAsset>
               </imageCaptions>
               <lead>sadfsd</lead>
               <dublinCore oid="[com.arsdigita.london.cms.dublin.DublinCoreItem:{id=4413}]">
                  <name>eeek-dublin-metadata</name>
                  <dcLanguage>en</dcLanguage>
               </dublinCore>
            </cms:item>
         </folder>
       </folder>
      </folder>
    </import>

### The `import` tag

This is the top-level element. Its mandatory attribute `source` identifies the source of import data. This is an arbitrary string used to track the objects already processed by importer. Whenever an imported object is persisted in database, new {@link RemoteOidMapping} record is stored along, with the value of `source` attribute being written to `system_id` column.

### The `folder` tag

Determines the position of imported object. The `folder` tag can be nested to an arbitrary level. Importer checks if the folder with the specified `name` (mandatory attribute) exists. If not, it will be created. Optional attribute `label` is used to provide folder's title (label).

### The `cms:item` tag

Denotes the start of a content item block. The mandatory attribute `oid` specifies the OID of the source item, not the target one. Importer has no control over OIDs assigned to objects created during import process.

However, `oid` is used to determine the correct object type for the imported object. Moreover, if the `defaultDomainClass` element is not specified, importer will try to create instance of Java class specified in the `oid` attribute. This must be held in mind when importing data from pre-Rickshaw source, or from any non-CCM source. In both cases, source OIDs must be adjusted to match the persistence object types present in target CCM instance.

Opening <cms:item> tag can contain several optional attributes. Here's what they are used for:

- `author`: if provided, the attribute value will be interpreted as email address. If a user with that email address does not already exist, it will be created with some random password that can be reset via password recovery facility. Workflow will be actived for the imported object, with all tasks being locked by said user.
- `indexItem`: if equals to `true`, the imported item will be set as the index item to the currently processed folder.
- `relabelFolder`: if equals to `true` and with `indexItem` set to `true` as well, the currently active folder will be relabeled after this item's title.

Any element underneath opening <cms:item> is expected to contain a persistence attribute. Simple persistence properties, like `name` or `title`, are being simply taken from bodies of corresponding XML elements. Role properties, however, represent domain objects and their opening tag has to include `oid` attribute, as per the reasons stated above. Keep in mind that OID mappings of role properties will also be stored via RemoteOidMapping facility, just like the mapping of the top-level content item.

### BLOB handling

Persistence properties that contain byte[] values can be imported in two ways:

- via external file: name of the file containing raw BLOB data can be specified via `file` XML attribute. If not provided, importer looks up a file named `objectID-propertyName.raw`. In both cases the file is expected to be in the lobDir, the directory specified by one of the importer invocation arguments.
- inline: the BLOB value, base64 encoded, can be specified in body of XML element if the `encoding="base64"` XML attribute is provided.

### Transaction handling and the `external` tag

When importing from XML source with no `external` XML tags, importer will open a single transaction and import all the content within its context. This can cause memory problems when import set is too big. Sometimes it's enough to have handful of large BLOBs to trigger infamous OutOfMemoryException. The recommended approach in this case is to split import data into several pieces which are concatenated together via `external` XML tag:

    <?xml version="1.0" encoding="UTF-8"?>
    <import source="camden.aplaw.org.uk" xmlns="http://xmlns.redhat.com/waf/london/importer/1.0">
    <folder xmlns="http://www.arsdigita.com/cms/1.0" label="Root Folder " name="/" oid="[com.arsdigita.cms.Folder:{id=556}]">
       <folder label="one" name="one" oid="[com.arsdigita.cms.Folder:{id=4402}]">
          <external source="one/eeek.xml"/>
       </folder>
       <folder label="Two Test" name="two-test" oid="[com.arsdigita.cms.Folder:{id=4407}]"/>
       <external source="sfsdfsdfs.xml"/>
       <external source="mpa-test.xml"/>
    </folder>
    </import>

In this case each file referenced in `external` tag will be processed in its own transaction. Each file included in this way is expected to contain a single `cms:item` block.

### Invoking from command line

Importer can be invoked via standalone command-line tool like this:

      ccm-run com.arsdigita.london.importer.cms.ItemImportTool \
          master-import.xml /dir/with/files/to/include /dir/containing/lobs