Posts tagged "asset management"

Using Lists and Conditions in Correspondence Management to create complex template rules

The Correspondence Management Solution presents unique concepts of List and Condition assets (aka modules), to enable advanced correspondence template design. These asset types allow defining rules for content inclusion, that may be quite complex by using a combination of (nested) Lists and Conditions.

Lists

Lists are a great way to group content, i.e. Texts, Images, nested Lists and Conditions (read on, if you are new to Conditions) together into logical groups. For instance, when you wish to mandate the inclusion of a Text paragraph A with Text paragraph B, you could create List, and include Texts A and B within the List, marking them as mandatory content.

Apart from this, you could also set advanced Styles on Lists, so as to specify if and how the content should be bulleted or numbered, set indentation on individual content, and much more. You could also specify advanced rules for the List to control whether the List can accept more content than what is originally assigned to it (during correspondence creation), or whether content within it can be re-ordered, and so on.

Visit the official document to see how to work with Lists using the List Editor.

 

Conditions

Conditions are a great way to specify inclusion rules of content within a correspondence. One could define expressions on control variables (placeholders and/or Data Dictionary elements), such that appropriate content may be selected into the correspondence,  based on runtime values of these variables. Content may be Texts, Images, Lists or Conditions (thereby allowing deeply nested conditions).

Conditions are defined similar to SWITCH-CASE statements. Each expression has a result content associated with it. The first expression that evaluates to TRUE is chosen as the result and the content associated with it is included in the final correspondence.

Note that you can choose to return multiple content against an expression by wrapping (grouping) them within a List and then select the List as the result of that expression.

Visit the official document to see how to work with Conditions using the Condition Editor.

 

As you can see, Lists can be included within other Lists or Conditions and vice-versa. Thus allowing users to create complex rules for their templates, optionally combined with styles.

Understanding and Configuring the Correspondence Management Manage Assets interface

While the out-of-the-box experience of the Manage Assets interface will blow you away, it is worth noting that the interface itself is highly configurable, given that deployments of the Correspondence Management solution may need a different/customized look-n-feel of this interface, based on specific customer requirements.

The overall knitting of the UI components on the interface is done using the AMApplicationSkin.mxml which you can find in the CM Solution Template @ CorrespondenceManagementSolutionTemplate\ManageAssets\src\com\adobe\solutions\cmg\manage\skins\AMApplicationSkin.mxml.

Here’s a quick look at the high-level components:

 

 

 

 

 

 

While what’s shown on the Application Header (the various tab navigators) is largely governed by the (customizable) application’s skin (AMApplicationSkin), the rest of the UI components (i.e., which actions/buttons to be shown on the Application Toolbar, which columns to be shown in the Search Results Grid and which properties to be shown in the Advanced Search panel when searching) are driven by an XML definition, i.e. asset definition FMLs, which require almost no code changes to get yourself a customized UI experience. You will find these asset definition FMLs under /apps/solutions/cm/assetDefinitions in the CRX repository. See snapshot below:

 

 

 

 

 

 

 

 

 

 

 

Note that you will find two sets of FMLs there. Ones that are named [Asset type].fml and ones that are named [Asset type]-publish.fml – the former being the definitions used for the solution’s Author instance and the latter for the Publish instance.

The initial view of the Manage Assets interface lists all assets in the system. That is because the default view has all assets selected for search (“Search all assets” in the Advanced Search panel- see snapshot above). This view uses the Asset.fml descriptor as the UI definition/design. The same descriptor is used when searching for assets across multiple asset types. However, when searching for a specific type of asset (i.e., only Texts or only Conditions, and so on…), the descriptor for that asset type drives the UI definition/design. For example, when searching for Texts only (all other checkboxes deselected), the TextModule.fml drives how the interface looks like.

The FMLs are part of the CM Solution Template (@ CorrespondenceManagementSolutionTemplate\package-resources\apps\solutions\cm\assetDefinitions), and can be modified as required. Once modified, follow the steps to build and deploy the solution template for changes to take effect.

 

Understanding the Asset Definition descriptors (FMLs)

Now that we know the significance of these FMLs, let’s take a look at what’s in there…

The FML has a lot inside it, but we will only focus on what’s relevant towards the Manage Assets UI definition. Let’s take the TextModule.fml as an example here.

The first section of interest is the assetActions item, which defines what action buttons are available on the Application Toolbar when searching for Texts (only). Here’s how the section looks like for Texts:

 

 

 

 

Note the list of actions highlighted (within the grey boundary). Each <action> also defines the User Groups (names) who can perform that action (groupName=”…”),  whether the action is enabled by default or not (defaultEnabled=”…”), and other styling configurations such as the icons to be used in enabled or disabled states, tooltip and label (enabledIcon, disabledIcon, tooltip, label).

The next section of interest would be the various <property> tags. Here’s a snapshot of the name property for Texts:

 

 

 

The set of <property> tags define the properties/attributes that are part of that asset. Each <property> may define whether it is visible as a column in the Search Results Grid (note the visible attribute highlighted in RED), whether it is available as a searchable property in the Advanced Search panel (note the searchable attribute highlighted in GREEN), and other attributes such as the displayName, columnOrder, etc.

So, to add a column in the Manage Assets UI (in the Search Results Grid), you would need to add an additional <property> node for that property (if it does not exist already). Properties could either be one of the existing ones for the asset or a custom property added for that asset.

Overall, to configure the properties to be shown in the Search Results Grid and the Advanced Search panel, you may tweak existing properties and/or add/remove properties to the concerned FML.

 

This was a very generic description of such configurations. You may check out my post which adds a Tags column to the Manage Assets UI for all assets, as an example. You should also check out the public documentation which adds custom properties to assets and displays them on the Manage Assets interface.

Adding a new Tab to the Manage Assets interface

The Manage Assets user interface presents three main tabs for users to work with:

  • Assets :  This is the tab where the Correspondence Management assets are listed, can be searched for (based on basic/advanced search criteria), or acted upon using the various actions available in the toolbar.
  • Editors : This is the tab where the editor for an asset is presented (opens up), when opened for Edit or View or Copy or other such actions using the asset toolbar.
  • Admin : This tab is meant for users with administrator-like roles, wherein they can author the administrative assets, i.e. Data Dictionaries and Categories. The tab also allows users to export all assets in the system as an archive (ZIP), that can then be imported onto another system; thus allowing asset transport across systems.

While the above is available out-of-the-box, one can easily extend/customize the Manage Assets interface to introduce a new tab (alongside the above three tabs) that may be required to display a custom user interface (what’s displayed within the tab would be customer specific, based on the exact use case). We will see how…

Before you start with any customization(s) on the solution, ensure that you have correctly setup your development environment.

Once you have your development environment setup in your FlashBuilder, you will see a project ManageAssets in it. As the name suggests, this is the main flex project for the Manage Assets UI, and hence any client (flex) side customization to this user interface, would involve working with this project.

To start with, locate the file AMApplicationSkin.mxml. You will find it under src\com\adobe\solutions\cmg\manage\skins\AMApplicationSkin.mxml. This is the Skin file for the Manage Assets interface, where you will find the declaration for the above three tabs, as shown below:

 

 

 

 

 

We will add our new tab (named “My New Tab“) before the Assets tab by adding an additional Spark NavigatorContent (s:NavigatorContent) as shown below:

 

 

 

 

 

Note that for now we have specified the label for the tab (… label=”My New Tab” …) within the skin itself, for simplicity. This should ideally be externalized to the resource bundle, just as the other tabs’ labels are.

That’s it! Once done with the above change in the skin, re-build and deploy the solution, after which, when you open the Manage Assets UI (@ http://server:port/cm/manageassets.html), you will see this:

 

 

(our new tab indicated in RED)

Of course, our new tab does not have anything to show inside it and appears as an empty canvas at this time, because we haven’t added any view within it yet. However, that should be easy, as you now need to add standard Flex components within our additional NavigatorContent, depending upon what view you wish to show up within this tab. Additional code may be needed to implement the overall business use case, the extent of which would depend upon the complexity of the same.

Better search using asset tagging

Tagging has always been one of the classic approaches towards categorization of assets/objects, that allows a convenient way to ‘search’ for objects based on the associated tags, at a later point in time.

While the Correspondence Management Solution provides advanced search capabilities, wherein one can search over asset properties such as name, description, content, etc., users (customers) may want to associate custom tag(s) with an asset so that assets can then be more easily (and even, logically) searched using these tags.

Now, the obvious question…how to achieve this??

Here goes the answer…

As part of the various extensions points, the solution provides the capability to add custom attributes/properties to an asset, which can then be searched upon (and used in any other asset management workflows). We can leverage this aspect and add a custom property, say ‘tag’, to the desired asset types, which will be used to associate tags with any asset created of that type.

For details and samples around adding a custom attribute/property to an asset type, refer to the ADEP documentation.

Below are the key changes done (snippets) to enable tagging on Letter templates. The same can be applied on other asset types (Texts, Images, etc.) as well.

1. Here’s the addition to the Letter.fml that drives the Manage Assets UI look when searching for Letter Templates:

[Note: Letter.fml can be found in the Services project of the Solution Template]

<property name="tags" type="string">
<annotation name="DDS">
<item name="displayName">Tags</item>
     <item name="visible">true</item>
     <item name="searchable">true</item>
     <item name="columnOrder">11</item>
     <item name="searchRendererOrder">11</item>    
     <item name="searchPath">Letter.extendedProperties.tags</item>
     <item name="assetPropertyType">extended</item>
     <item name="extendedPropertyPath">Letter.extendedProperties.tags</item>
</annotation>
</property>

… which basically is adding a property named ‘tags‘ to the Manage Assets UI, such that it can appear in the Advanced Search, and as a column in the Letters view data grid. Note the entries in purple.

 

 

 

 

 

 

2. The new/extended Host Component for the Letter Editor that extends the out-of-the-box Host Component to add UI logic specific to our new attribute ‘tags':

 

 

 

 

 

 

 

3. A new Skin would be created for the Letter Editor that adds a Text Input to the Properties Editor where users can supply values for the applicable tags on a template:

 

 

 

 

 

 

 

…which basically, would lead to the Letter Editor showing up like this:
[note the additional text box for entering tags]

 

 

 

 

 

 

Users can now add comma-separated (you are free to use a different separator) tags when creating their Letter templates. Once added, these tags can be used to search for templates on the basis of these tags. See the below snapshot, where a search for templates with the tag ‘noida‘, lists the Letter template that was created with that tag.

 

 

 

 

 

 

 

As mentioned before, the above snippets just give you an idea of the capability and the necessary changes to get the desired results. There are other (though minor) changes needed as part of this customization, which are similar to the way custom attributes are added to an asset type in general. So, please refer to that documentation for comprehensive steps and details.

Also, you could implement more complex logic within your customized solution to further enhance tagging on assets.

Transporting assets across systems/environments in CM 3.0

Correspondence Management Solution 3.0 provides this great ability to transport, via an intuitive user interface, not just the entire set of assets across environments, but also selective assets. This is one of the uber cool enhancements from how the same is achieved in the previous version of the solution, where this was somewhat limited and cumbersome.

Right from the Manage Assets user interface itself, you can now select any asset or set of (possibly related) assets, that you wish to take over or move to another environment (or physical server), and export them as a ZIP. This ZIP can then be imported over to the desired target system, and voila!…you’ll have your assets in place. Indeed! it is as simple as this.

Please take a moment to read through the published documentation to guide you through the step by step process.

Publishing assets in the Correspondence Management Solution 3.0

The Correspondence Management Solution 3.0 introduces the concept of publishing assets, and deprecates the concept of activation (which was used in the 2.5.x version of the solution).

The solution is typically configured on two separate (ADEP Experience Server) instances – an Author instance and a Publish instance (see the installation and configuration documentation on how to configure the solution over the two instances).

The Author instance is one on which assets/templates are created and managed (using the Manage Assets interface). One can also Preview the Letter templates created on the Author instance, which launches the Create Correspondence interface in a document preview mode.

The Publish instance is one on which the final correspondence is created by agents (using the Create Correspondence interface), using the designed letter templates and published assets. The Manage Assets interface is also available on this instance, but with restricted actions.

Once done with the asset authoring, they must be marked Ready to Publish, indicating the same to the persona (which would typically be different from the one creating/editing the asset) responsible for publishing the asset, who can then go ahead and publish the asset. Note that when publishing an asset, all assets related to this asset should be in Published or Ready To Publish state. Assets that are in Ready To Publish state are published automatically, while the ones that are already Published, are ignored. If any related asset is in a Modified state, the publish operation is aborted, and hence cannot proceed until all related assets are marked Ready to Publish. The understanding behind this behavior is that there could be different persona involved in creation of various related assets, and it is essential that each one of them marks the respective asset ready to publish (indicating completion) before they can really be published.

Here’s a state diagram for various asset states, and how they transition on various actions:

On publishing an asset, a new version of the asset gets created on the Author instance, and the asset is immediately ‘replicated’ over to the Publish instance, which always has a single (head) version of an asset.

Also note that any related Data dictionaries are not published automatically when assets that use it are published. You are required to explicitly publish data dictionaries.

Read more on asset publishing and versioning here.

Transporting assets in Adobe Correspondence Management Solution Accelerator (CMSA) 2.5

Transporting assets in the Correspondence Management Solution Accelerator 2.5  across systems is a common requirement and a frequent activity.

Exporting assets from the source system

CMSA being based on LiveCycle Content Services as the content repository, assets are exported as an ACP from the source system using steps documented in the CMSA guide. Such an exported ACP will contain ALL assets on the source system, and their relationships.

Importing assets to the target system

Importing assets (ACP exported above) on the target system will be largely driven by the intention, and desired behavior.

If the intention is to *create a replica of the source system* (and ignore whatever is on the target system), then perform the following on the target system:

  1. Delete DataStore (under Company Home).
  2. Ensure to delete the same from Deleted Itemsas well. To do so :
    1. Go to User Profile.
    2. Click Manage Deleted Items
    3. Click Show All
    4. Click Delete Listed Items
    5. Click Yes
  3. Delete files within Models (under Company Home > Data Dictionary).
    1. DO NOT delete the Models space itself.
  4. Delete files within lcc_persistence (under Company Home)
  5. Restart your server
  6. Bootstrap CMSA (http://server:port/cmsa/Bootstrap)
  7. Use the Import Utility to import the source system’s ACP
    1. “importWithDD” or “importWithoutDD” would depend on which Data Dictionaries do you wish to honor. The ones from the source system (use ‘importWithDD’) or the ones on the target system (use ‘importWithoutDD’).
  8. Restart your server

However, if the intention is to *keep the existing assets* and import whatever is in the ACP from the source system, then you should IGNORE steps 1. to 6., and simply execute step 7. (i.e., “Use the Import Utility to import the source system’s ACP”) and 8.

It is important to note that in such cases there could be a possibility of duplicate assets in the system, if the source and target systems contain assets by the same ‘name’; since we enforce the uniqueness in asset names via the CMSA interface only, but here we are directly importing assets onto the repository (bypassing the solution’s constraints).  

Creating Text using the Correspondence Management APIs

While the classic way of creating Text in the Correspondence Management SA is using the Text Editor UI component, one may also want to create one or more Text modules using an API.

Following are the objects/services involved in creation of a Text Module using the APIs:

Here’s a sample of how to use these:

Creating the Text Module instance

TextModule tm = new TextModule(); // no-arg constructor
text.setName(textModuleName);
text.setDesc(description); // a meaningful description of the Text
text.setComment(comment); // a comment associated with the Text
text.setLcat(subCategory); // 'subCategory' is the SubCategory for the Text, and is of type 'com.adobe.icc.dbforms.obj.Category'
text.setUcat(category); // 'category' is the main Category for the Text, and is of type 'com.adobe.icc.dbforms.obj.Category'
text.setDataDictionaryRef(dataDictionaryName); // Name of the Data Dictionary used in this Text, if any.
text.setTBXXML(tbxXMLString); // tbxXMLString is a well-formed XML, that should comply to the expectations of a Text Module XML format. You could import/read this XML from a file using any of the standard java File reading utilities. It should have details such as the Text's plain text content, flash-html text content, xfa-xhtml content, etc. See the description on the TextModule API for more...

Here’s a sample XML that could be provided:

<content>
<guid/>
<name>text_test</name>
<desc>the description</desc>
<plainText>This is a paragraph with a variable: {^var^}</plainText>
<flashRichText><TEXTFORMAT LEADING="2" TABSTOPS="36,72,108,144,180,216,252,288,324,360,396,432,468,504,540,576,612,648,684,720"> <P ALIGN="LEFT"><FONT FACE="Times New Roman" SIZE="12" COLOR="#000000" LETTERSPACING="0" KERNING="0"> This is a paragraph with a variable: {^var^}</FONT></P></TEXTFORMAT>
</flashRichText>
<xfaXhtml><body xfa:APIVersion="2.4.5277.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/"> <p xml:space="preserve" style="text-align:left"><span style="letter-spacing: 0px; color: #000000; font-size: 12px; font-family: Times New Roman; xfa-spacerun:yes"> This is a paragraph with a variable: {^var^}</span></p></body>
</xfaXhtml>
</content>

The TextModule object API also exposes a comprehensive constructor that could be used to create a Text Module.

Persisting the Text Module instance

Now, once you have defined the above ‘text‘ object, you can persist that using the DataModuleService APIs. Here’s how:

DataModule dm = dataModuleService.createDataModule(text); // the returned 'dm' is the persisted Text module. you may further cast this into a 'TextModule'.

Managing the Text Module instance

You could also perform other actions  such as activate, update, etc. on the created Text (or already existing Texts) using the DataModuleService APIs such as activateDataModule(DataModule), updateDataModule(dataModule), etc. Please refer to the DataModuleService API docs for more.

See here for a comprehensive list of the CMSA documentation.

Retrieving latest ACTIVE asset in the Correspondence Management Solution Accelerator

The Correspondence Management Solution Accelerator involves the concept of activating and versioning assets; if an Active asset is chosen for EDIT, you are prompted to create an Inactive copy of the asset which can then be edited. You can edit that Inactive copy and finally Activate it once completed with the editing. This Inactive copy now becomes the Active version, and the original version will be Archived. This process may continue as the asset is edited (and activated) again and again, thereby creating multiple versions of the asset in the system.

However, at any given time, there will only be a single ACTIVE version of the asset in the system (others being in ARCHIVE state). Hence, often may arise, due to various customization requirement, the need to search for this latest ACTIVE version for a given asset in the system. The Asset Composer Building Block provides APIs to easily achieve this.

Here’s an example to fetch the latest ACTIVE version of a given Letter (identified by its name) in the system:

// Build the Query object
Query qry = new Query();
Statement st1 = new Statement();
Statement st2 = new Statement();

// Set the statement attribute 'name'
// and value to name of the Letter
st1.setAttributeName("name");
st1.setOperator(Operator.EQUALS);
st1.setAttributeValue(letterName);

// Set the statement attribute name value to state
// and value to 'ACTIVE'
st2.setAttributeName("state");
st2.setOperator(Operator.EQUALS);
st2.setAttributeValue(DBConstants.ACTIVE);

// building query
qry.addStatement(st1);
qry.addStatement(st2);

List letterList;

try {
// fetching the Letter with the query constructed above
// must have an instance of the LetterService here (may be via Spring Dependency injection).
letterList = letterService.getAllLetters(qry);

String letterId = letterList.get(0).getId();
// Obtaining Form object, as getAllLetters query does not return
// 'full' form object
Letter letter = letterService.getLetter(letterId);

} catch (Exception e) {
// handle exception
}

Re-Activating old, archived assets in the Correspondence Management Solution Accelerator

The Manage Assets user interface of the  Correspondence Management Solution Accelerator allows various operations on assets, such as Create New, Active, Edit, Delete etc. When an asset (that should be in Inactive state) is Activated, any existing Active asset by the same name is Archived and this asset becomes the new Active asset (with an incremented version number; thus creating a new version of the asset).

Now, there could be a need to re-Activate the previous (now archived) version of that asset. The Manage Assets UI does not (out-of-the-box) allow you to do so (these actions are disabled on the UI, and the APIs also restrict the same). However, there are set of server side APIs that you could use/invoke to achieve the same (perhaps, configuring it as a custom Action on the Manage Assets UI, that in-turn invokes a custom service/operation which wraps the below steps/functionality).

Here are the (logical) steps that you’d need to take to be able to do so:

  1. Firstly, move any existing Active version to Archive, since you are not allowed to have multiple Active versions of the same asset. Obviously, this Active version MUST NOT be in use by any other asset.
  2. Fetch and Update the (archived) version of the asset object (that you wish to activate), setting its state to “Active” and version to “[version of the previous active asset] + 1″.

In terms of API calls, here is what you’d do/invoke (refer the API listing for details on usage of these APIs):

  1. Fetch the latest available Active asset object (if you already do not have that) — you could use the getAll[Asset-type]() like APIs to search for such an object (Asset-type being either DataModule, Letter, Form, etc., depending upon the asset that you are working on). For example, to fetch the current Active version of a Letter, you could use the LetterService.getAllLetters(Query query) API (building the appropriate Query for this).
  2. Delete the object fetched in (step 1) above, using the delete[Asset-type]() like APIs; this will move the current Active asset to Archive. For example, to delete/archive the current Active version of a Letter, you could use the LetterService.deleteLetter(String letterID) API (where letterID is the ID of the asset to be deleted).
  3. Fetch the asset object that you wish to (re)activate — again, searching for it using the getAll[Asset-type]() like APIs, as mentioned above. You’ll need to retrieve the full object by invoking the corresponding get[Asset-type]() API; for instance, LetterService.getLetter(String letterID) if you are working with Letters (where letterID is the ID of the Letter that you have searched for).
  4. Set the state of the object fetched in (step 3) to Active, using the Asset.setState(DBConstants.STATE_ACTIVE) API.
  5. Set the version of the object fetched in (step 3) to ([version of object fetched in (step 1)] + 1)
  6. Then, update this (state and version modified) object using the update[Asset-type]() like API; for instance, LetterService.updateLetter(Letter letter).

One important point to be noted here is that it is not advisable to (re)Activate an asset that in-turn uses/references other Archive assets (reason being, the Manage Assets UI does not allow you to work with or use/select/de-select Archived assets when authoring an asset; so, it may be difficult for you to work with (EDIT, in particular) such assets on the Manage Assets UI). Hence, one should first (re)activate the dependent assets (using the above steps) and then (re)activate the parent asset.