42 Asset API Tutorial

The purpose of this tutorial is to introduce the Asset API to the developer. It is meant to be a quick reference and not a substitute for the Oracle Fusion Middleware WebCenter Sites Java API Reference. Code samples throughout this tutorial illustrate how the Asset API is used.

This chapter contains the following sections:

42.1 Understanding the Asset API

The Asset API is a Java API used to access and manipulate WebCenter Sites assets. Its main purpose is to broaden the context in which assets can be handled. Its major features are the following:

  • The Asset API supports WebCenter Sites in a non-servlet context.

    Prior to the Asset API, WebCenter Sites exposed primary interfaces for programming in the form of tags (both in XML and JSP), used as the means for creating web pages and applications. In this sense, WebCenter Sites was tightly built around the servlet model and was not usable in other contexts, such as standalone Java programs (EJB, for example). Therefore, there was a need to create an API that could be used anywhere, regardless of the servlet framework.

  • The Asset API unifies the retrieval, creation, and modification of the two asset families: basic and flex.

    • The Asset API represents both asset families with AssetData and AttributeData.

    • The Asset API uses generic Condition and Query objects for both flex and basic assets.

  • The Asset API supports the creation and editing of basic assets, flex assets, and flex parent assets in the form of Java objects.

    Note:

    The Asset API does not log any dependencies other than the asset that is being loaded.

42.2 Primary Interfaces

The Asset API provides access to data as well as definitions for WebCenter Sites assets:

  • Package com.fatwire.assetapi.data contains classes that are useful in reading data.

  • Classes under com.fatwire.assetapi.def are for asset definitions.

  • Package com.fatwire.assetapi.query contains constructs necessary for building a Query. For further details, see the Oracle Fusion Middleware WebCenter Sites Java API Reference.

The Asset API defines the following primary interfaces:

  • Session: The primary entry point into WebCenter Sites from the API. One has to obtain a session to be able to do anything at all in the Asset API.

  • AssetDataManager: A manager for reading asset data. Developers can query for information here, as well as look up asset associations and other information.

  • AssetTypeDefManager: A manager for reading an asset type's definition. 'Definition' is a loaded term in WebCenter Sites where flex assets are concerned. Here it is used in the generic sense, as something that defines the structure of an asset type. As a result, basic asset types also have a definition.

  • AssetData: An asset's data; basically a collection of AttributeData instances and other information about the asset itself.

  • AssetId: The asset type-id combination.

  • DimensionableAssetManager: A manager that supports multilingual assets by retrieving translations of any given asset.

42.3 Getting Started

42.4 Asset API Read

With this brief background, let's start writing some code based on FSII data.

This section contains the following topics:

42.4.1 A Simple Example: Reading Field Values

Let's try to read all the values of the FSIIHeadline field in FSII Articles. These are the steps to follow:

  1. Get a session.

  2. Get a handle to AssetDataManager.

  3. Build a query.

  4. Perform 'read' and print the results.

Here is the code that implements these steps (in a jsp element):

<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<%@ page import="java.util.*"%>
<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
AssetDataManager mgr =(AssetDataManager) ses.getManager( AssetDataManager.class.getName() );
Query q = new SimpleQuery("Content_C", "FSII Article", null, Collections.singletonList("FSIIHeadline") );
for( AssetData data : mgr.read( q ) )
{
out.println( data.getAttributeData("FSIIHeadline").getData() );
out.println( "<br/>" );
}
%>
</cs:ftcs>
  1. SessionFactory.newSession() builds a session for a given user. From that point on, all data that is read using this session instance is based on the user's ACL permissions. You could also simply call newSession( null, null ) and get a Session that belongs to DefaultReader, an assumed user. CS-powered web applications generally run as this user at runtime. However, if the user name and password are specified and happen to be incorrect, you will get an exception.

  2. Using the session, get a handle to AssetDataManager.getManager. (The AssetDataManager.class.getName() method does this.)

  3. A Query represents results that are based on the user's search criteria. In this example, we are using a simple version of Query, where we specify the asset type (Content_C) subtype (FSII Article) and the list of attributes to be returned (just FSIIHeadline in this case). We want all assets; therefore the third parameter (which takes Condition instance) is null. We will see how to use Conditions later on in Section 42.4.5, "Complex Query."

  4. The read() method of AssetDataManager returns an Iterable over AssetData. Each piece of asset data contains an instance of AttributeData against an attribute name. AttributeData.getData() returns the real data of the attribute itself.

42.4.2 Reading AssetId

What if we wanted to know the id's of all these assets? AssetData.getAssetId() returns an AssetId instance.

The code in Section 42.4.1, "A Simple Example: Reading Field Values" can be modified, as shown below, to print AssetId:


for( AssetData data : mgr.read( q ) )
{
AssetId id = data.getAssetId();
out.println( data.getAttributeData("FSIIHeadline").getData() + " id=" + id );
out.println( "<br/>" );
}

The code above prints the following lines (note that AssetId is a composite, it contains the id number as well as type. AssetId.getId() and AssetId.getType() return id and type separately:

AudioCo. America Announces H300 series id=Content_C:1114083739888 
AudioCo. New Portable Media Player Offers Full Video Experience id=Content_C:1114083739926
AudioCo.'s First Under Water MP3 Player id=Content_C:1114083739951
...

42.4.3 Reading Attributes Given the Asset ID

What if we already have an asset id, by some means? (Either passed into a template or acquired programmatically.) How can we read attributes of that? Let's consider an AssetId (Content_C:1114083739888, for example, as shown in the code used in Section 42.4.2, "Reading AssetId" and attempt to print the name, description, and FSIIBody. The following code does this:

<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<%@ page import="java.util.*"%>
<%@ page import="com.openmarket.xcelerate.asset.*"%>
<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
AssetDataManager mgr =(AssetDataManager) ses.getManager( AssetDataManager.class.getName() );
AssetId id = new AssetIdImpl( "Content_C", 1114083739888L );
List attrNames = new ArrayList();
attrNames.add( "name" );
attrNames.add( "description" );
attrNames.add( "FSIIBody" );

AssetData data = mgr.readAttributes( id, attrNames );
AttributeData attrDataName = data.getAttributeData( "name" );
AttributeData attrDataDescr = data.getAttributeData( "description" );
AttributeData attrDataBody = data.getAttributeData("FSIIBody");

out.println( "name:" + attrDataName.getData() );
out.println( "<br/>" );
out.println( "description:" + attrDataDescr.getData() );
out.println( "<br/>" );
out.println( "FSII Body:" + attrDataBody.getData() );
out.println( "<br/>" );
%>
</cs:ftcs>

Here, we are indicating which attributes to read for a given id. As you can see, you can specify basic fields (such as name, description) as well as flex attributes; both are treated as attributes.

Alternatively, you can load all attributes for a given id by using AssetDataManager.read( List<AssetId> ids). The following code demonstrates how this is done for a single AssetId:

<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<%@ page import="java.util.*"%>
<%@ page import="com.openmarket.xcelerate.asset.*"%>
<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
AssetDataManager mgr =(AssetDataManager) ses.getManager( AssetDataManager.class.getName() );
AssetId id = new AssetIdImpl( "Content_C", 1114083739888L );

Iterable<AssetData> dataItr = mgr.read( Collections.singletonList( id ) );

for( AssetData data : dataItr )
{
for(AttributeData atrData : data.getAttributeData() )
{
out.println( "<br/>" );
out.println( "attribute name:" + atrData.getAttributeName() );
out.println( "data: " + atrData.getData() );
}
}
%>
</cs:ftcs>

42.4.4 Query

A Query specifies the criteria based on which data is looked up. What if we want to look up a product whose SKU is iAC-008? The code below does this and prints the name and id:

<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<%@ page import="java.util.*"%>
<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
AssetDataManager mgr = (AssetDataManager) ses.getManager( AssetDataManager.class.getName() );
Condition c = ConditionFactory.createCondition( "FSIISKU", OpTypeEnum.EQUALS, "iAC-008" );
Query query = new SimpleQuery( "Product_C", "FSII Product", c, Collections.singletonList( "name" ) );

for( AssetData data : mgr.read( query ) )
{
AttributeData attrData = data.getAttributeData( "name" );
out.println( "name:" + attrData.getData() );
out.println( "<br/>" );
out.println( "id:" + data.getAssetId() );
}
%>
</cs:ftcs>

Query consists of a Condition, set of Attributes to be returned, and a SortOrder. The example above uses a condition that is built on the FSIISKU attribute value being EQUAL to iAC-008. Just as we did in the previous example, we pass in the list of attribute names we want to be returned in the resulting collection of AssetData.

There are some considerations as to what types of attributes can be queried and how. See Section 42.6.2, "Query Types" for a complete discussion of different query algorithms. In short, some types of queries are possible with one algorithm, but not with the other. Note that this is exactly the behavior we have in the Asset family of tags and AssetSet family of tags. To illustrate this point, say we want to read all products whose price (FSIIPrice) is greater than 179.

FSIIPrice is of type MONEY. Consulting Table 42-2 in Section 42.6.3, "Data Types and Valid Query Operations," we see that the GREATER_THAN operation is allowed for this data type only in the basic/generic algorithm. The following code uses that algorithm to get all products whose price is greater than 179. The choice of query algorithm is made by the highlighted line in the code below:

<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<%@ page import="java.util.*"%>

<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
        AssetDataManager mgr = (AssetDataManager) ses.getManager( AssetDataManager.class.getName() );
Condition c = ConditionFactory.createCondition( "FSIIPrice", OpTypeEnum.GREATER_THAN, 179.0f );
Query query = new SimpleQuery( "Product_C", "FSII Product", c, Arrays.asList( "name", "FSIIPrice" ) );
query.getProperties().setIsBasicSearch( true );

for( AssetData data : mgr.read( query ) )
{
AttributeData name = data.getAttributeData( "name" );
AttributeData price = data.getAttributeData( "FSIIPrice" );

out.println( "name:" + name.getData() );
out.println( "id:" + data.getAssetId() );
out.println( "price:" + price.getData() );

out.println( "<br/>" );
}
%>
</cs:ftcs>

42.4.5 Complex Query

A complex query can be achieved through nested Conditions. According to the choice of query algorithm, we are subjected to the constraints listed in Section 42.6.2, "Query Types."

The following code retrieves all the Product_C assets whose FSIIPrice attribute is greater than 179.0 and/or whose names are like "FSII":

<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<%@ page import="java.util.*"%>
<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
AssetDataManager mgr = (AssetDataManager) ses.getManager( AssetDataManager.class.getName() );
Condition c1 = ConditionFactory.createCondition( "FSIIPrice", OpTypeEnum.GREATER_THAN, 179.0f );
Condition c2 = ConditionFactory.createCondition( "name", OpTypeEnum.LIKE, "FSII" );
Condition c = c1.and( c2 ); // c1.or( c2 );

Query query = new SimpleQuery( "Product_C", "FSII Product", c, Arrays.asList( "name", "FSIIPrice" ) );
query.getProperties().setIsBasicSearch( true );

for( AssetData data : mgr.read( query ) )
{
AttributeData name = data.getAttributeData( "name" );
AttributeData price = data.getAttributeData( "FSIIPrice" );

out.println( "name:" + name.getData() );
out.println( "id:" + data.getAssetId() );
out.println( "price:" + price.getData() );

out.println( "<br/>" );
}
%>
</cs:ftcs>

42.4.6 Sorting

What if we wanted to retrieve the results sorted by price? The following code does that, by specifying a SortOrder, ascending in this example. To reverse the sort order, change true to false in the highlighted line of the code below:

<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<%@ page import="java.util.*"%>
<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
        AssetDataManager mgr = (AssetDataManager) ses.getManager( AssetDataManager.class.getName() );

SortOrder so = new SortOrder( "FSIIPrice", true );
Query query = new SimpleQuery( "Product_C", "FSII Product", 
null, Collections.singletonList( "FSIIPrice" ), Collections.singletonList( so ) );

for( AssetData data : mgr.read( query ) )
{
AttributeData price = data.getAttributeData( "FSIIPrice" );

out.println( "id:" + data.getAssetId() );
out.println( "price:" + price.getData() );

out.println( "<br/>" );
}
%>
</cs:ftcs>

The above code sorts and prints asset ids and price in the ascending order of FSIIPrice,

id:Product_C:1114083739851 price:89.99
id:Product_C:1114083739757 price:99.95
id:Product_C:1114083739696 price:129.99
id:Product_C:1114083739301 price:129.99
id:Product_C:1114083739471 price:179.95
id:Product_C:1114083739350 price:189.95
id:Product_C:1114083739225 price:399.99
id:Product_C:1114083739596 price:899.95
id:Product_C:1114083739804 price:1399.99
id:Product_C:1114083739549 price:3799.95
id:Product_C:1114083739663 price:6999.99

42.4.7 Reading BlobObject

The Asset API defines a special class to represent file type of data, data that is stored as a binary file. For example, the FSIIDocumentFile attribute in FirstSiteII is of type blob. The following code reads FSIIDocumentFile from all Document_C instances and prints the asset id, file name, and file size.

<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<%@ page import="java.util.*"%>
<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
AssetDataManager mgr = (AssetDataManager) ses.getManager( AssetDataManager.class.getName() );

Query query = new SimpleQuery( "Document_C", "FSII Document", null, Collections.singletonList( "FSIIDocumentFile" ) );

for( AssetData data : mgr.read( query ) )
{
AttributeData docAttr = data.getAttributeData("FSIIDocumentFile");
BlobObject fileObj = (BlobObject)docAttr.getData();
byte [] d = new byte[fileObj.getBinaryStream().available()];
fileObj.getBinaryStream().read(d);

out.println( "id:" + data.getAssetId() );
out.println( "file name:" + fileObj.getFilename() );
out.println( "file size:" + d.length );

out.println( "<br/>" );
}
%>
</cs:ftcs>

42.4.8 Retrieving Multi-Valued Attributes

The Asset API supports multi-valued attributes in the same way it supports single-valued attributes. AttributeData contains a companion method, getDataAsList() to retrieve multiple values. The following code attempts to print data contained in FSIIKeyword, a multi-valued attribute.

Note:

Because sample data that ships with FirstSiteII does not have data for the FSIIKeyword attribute, this sample code does not print any keywords. Before running this code, edit some of the FSIIDocument instances to add data for this attribute.

<%@ page import="com.fatwire.system.*"%> 
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<%@ page import="java.util.*"%>
<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
AssetDataManager mgr = (AssetDataManager) ses.getManager( AssetDataManager.class.getName() );

Query query = new SimpleQuery( "Document_C", "FSII Document", 
null, Collections.singletonList( "FSIIKeyword" ) );

for( AssetData data : mgr.read( query ) )
{
AttributeData attrData = data.getAttributeData( "FSIIKeyword" );
List retData = attrData.getDataAsList();
out.println( "id:" + data.getAssetId() );

for( Object o : retData )
{
out.println( "data:" + o );
}

out.println( "<br/>" );
}
%>
</cs:ftcs>

42.4.9 Multilingual Assets: Retrieving Translations

The Asset API also provides interfaces and methods to deal with multilingual assets. Basically, you have methods in DimensionableAssetManager to handle multilingual assets. They deal with getting all the locales for a given asset and specific translation of an asset.

The following example first retrieves the translations for asset Page: 1118867611403 by using the getRelatives method in DimensionableAssetManager with group set to Locale, and then it uses the getRelative method to get the fr_FR translation of the asset.

<%@ page import="com.fatwire.system.*"%> 
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.mda.DimensionableAssetManager"%>
<%@ page import="com.openmarket.xcelerate.asset.*"%>
<%@ page import="java.util.*"%>

<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
DimensionableAssetManager mgr = (DimensionableAssetManager)ses.getManager(DimensionableAssetManager.class.getName());

AssetId page_asset = new AssetIdImpl("Page", 1118867611403L);

for( AssetId id : mgr.getRelatives( page_asset, null, "Locale" ))
{
out.println( id );
}
out.println( "<br/>" );

AssetId fr_translation = mgr.getRelative( page_asset, "fr_FR" );
out.println( fr_translation );

%>
</cs:ftcs>

42.4.10 Reading Asset and Attribute Definitions

In addition to asset data, APIs also provide access to their definitions. Information such as the attributes that make up an asset definition, type of each attribute, etc. can be obtained through a manager called AssetTypeDefManager. The following example attempts to read all definition information from Document_C and print it to the browser.

<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.def.*"%>
<%@ page import="java.util.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
        AssetTypeDefManager mgr = (AssetTypeDefManager) ses.getManager( AssetTypeDefManager.class.getName() );

AssetTypeDef defMgr = mgr.findByName( "Document_C", "FSII Document" );

out.println( "Asset type description: " + defMgr.getDescription() );
out.println( "<br/>" );

for( AttributeDef attrDef : defMgr.getAttributeDefs() )
{
out.println( "Attribute name: " + attrDef.getName() );
out.println( "Attribute description: " + attrDef.getDescription() );
out.println( "is required: " + attrDef.isDataMandatory() );
out.println( "Attribute type: " + attrDef.getType() );
out.println( "<br/>" );
}

%>
</cs:ftcs>

42.4.11 Reading Key-Value Mappings

The Asset API provides access to a given CSElement or Template's key-value mapping pairs. The following example reads all mapping pairs from a CSElement:

<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<%@ page import="java.util.*"%>
<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
AssetDataManager mgr = (AssetDataManager)(ses.getManager(AssetDataManager.class.getName()));
Condition c = ConditionFactory.createCondition("name", OpTypeEnum.LIKE, "FSIICommon/Nav/LocaleForm");
Query query = new SimpleQuery("CSElement", null, c, null);
query.getProperties().setReadAll(true);
for (AssetData data : mgr.read(query))
{
   List<AttributeData>  mappingArray = (List<AttributeData>)data.getAttributeData("Mapping"). getData();
   for (int i=0; i<mappingArray.size(); i++)
   {
      HashMap mappingMap = (HashMap)mappingArray.get(i).getData();
      String key = (String)((AttributeData)mappingMap.get("key")).getData();
      String type =(String)((AttributeData)mappingMap.get("type")).getData();                   
      String value = (String)((AttributeData)mappingMap.get("value")).getData();
      String siteid = (String)((AttributeData)mappingMap.get("siteid")).getData();     

      out.println("Mapping Entry #"+String.valueOf(i+1));
      out.println("<br/>");
      out.println("Key: "+key);
      out.println("Type: "+type);

out.println("Value: "+value);

      out.println("Siteid: "+siteid);
      out.println("<br/>");
   }
}
%>
</cs:ftcs>

42.5 Asset API Write

The Asset API supports write operations on basic assets and selected types of flex assets. The supported write operations are asset creation, modification, and deletion. The supported assets are basic assets, flex assets, and flex parents. All other asset types are not currently supported: Flex Parent Definition, Flex Asset Definition, Flex Filter, and Flex Attribute. An UnsupportedOperationException will be thrown if any write operation (insert or update) is attempted on those asset types.

This section contains the following topics:

42.5.1 Creating New Assets

Asset API uses the AssetDataManager.insert( List<AssetData> data ) method to create a new asset in WebCenter Sites. The method takes in a list of AssetData and uses these AssetData to create new assets in WebCenter Sites. If successful, the method will populate the passed in AssetData with the IDs of the newly created assets.

Creating a New Flex Asset

Asset API is able to create a new flex asset by combining the AssetDataManager.newAssetData method and insert method. The newAssetData method will return an empty AssetData with all the AttributeData objects populated with null or empty List/Collection. The flextemplateid (for flex assets) or flexgroupid (for flex parents) will be automatically populated if the correct subtype is specified.

<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<%@ page import="com.openmarket.xcelerate.asset.AssetIdImpl"%>
<%@ page import="java.util.*"%>
<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
AssetDataManager adm = (AssetDataManager) ses.getManager( AssetDataManager.class.getName() );
        MutableAssetData d = adm.newAssetData( "Content_C", "FSII Article" );
        d.getAttributeData( "name" ).setData( New Content" );
        d.getAttributeData( "FSIIHeadline" ).setData( "headline" );
        d.getAttributeData( "FSIIAbstract" ).setData( "abstract" );
        d.getAttributeData( "FSIIBody" ).setData( "body" );
        d.getAttributeData( "Publist" ).setData( Arrays.asList( "FirstSiteII" ) );
        d.setParents( Arrays.<AssetId>asList( new AssetIdImpl( "Content_P", 1112192431478L)) );
        adm.insert( Arrays.<AssetData>asList( d ));
        out.println( d.getAssetId() );        
%>
</cs:ftcs>

Create a New Basic Asset

Asset API is also capable of creating new basic assets.

<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<%@ page import="java.util.*"%>
<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
AssetDataManager adm = (AssetDataManager) ses.getManager( AssetDataManager.class.getName() );
        MutableAssetData d = adm.newAssetData( "HelloArticle", "" );
        d.getAttributeData( "name" ).setData( New Hello Article" );
        d.getAttributeData( "headline" ).setData( "headline" );
        d.getAttributeData( "byline" ).setData( "abstract" );
        d.getAttributeData( "category" ).setData( "g" );
        BlobObject b = new BlobObjectImpl( "filename.txt", null, "body".getBytes() );
        d.getAttributeData( "urlbody" ).setData( b );
        d.getAttributeData( "Publist" ).setData( Arrays.asList( "HelloAssetWorld" ) );
        adm.insert( Arrays.<AssetData>asList( d ));
        out.println( d.getAssetId() );
%>
</cs:ftcs>

42.5.2 Updating Existing Assets

Another operation that Asset API supports, in addition to insert, is update. Similar to insert, update will save the data from AssetData into WebCenter Sites, but to an existing asset. If the asset does not exist, update will throw an exception.

<%@ page import="com.openmarket.xcelerate.asset.AssetIdImpl"%>
<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<%@ page import="java.util.*"%>
<cs:ftcs>
<%
Session ses = SessionFactory.getSession();
AssetDataManager adm = (AssetDataManager) ses.getManager( AssetDataManager.class.getName() );
Iterable<AssetData> assets = adm.read( Arrays.<AssetId>asList( new AssetIdImpl( "HelloArticle", 1238171255471L), new AssetIdImpl( "Content_C", 1238171254486L)) );
        List<AssetData> sAssets = new ArrayList<AssetData>();
        for ( AssetData a : assets )
        {
            sAssets.add( a );
            a.getAttributeData( "name" ).setData( "Changed Name" );
        }
        adm.update( sAssets ); 
%>
</cs:ftcs>

42.5.3 Deleting Existing Assets

AssetAPI also supports deletion of assets from WebCenter Sites. In the following example, after removing all the references to the two assets, adm.delete will be able to delete both assets from WebCenter Sites. An exception will be thrown if an asset is referenced by other assets, or if the asset is invalid. The delete process will stop when an exception is thrown.

<%@ page import="com.openmarket.xcelerate.asset.AssetIdImpl"%>
<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.assetapi.query.*"%>
<%@ page import="java.util.*"%>
<cs:ftcs>
<%
 Session ses = SessionFactory.getSession();
 AssetDataManager adm = (AssetDataManager) ses.getManager( AssetDataManager.class.getName() );
 adm.delete( Arrays.<AssetId>asList( new AssetIdImpl( "HelloArticle", 1238171255471L), new AssetIdImpl( "Content_C", 1238171254486L)) );
%>
</cs:ftcs>

42.5.4 Multilingual Assets

Asset API supports the creation of multilingual assets. Creation of the assets requires a two-step process. First, the asset is created and saved. Next, locale information is added. The following example creates a new Content_C asset and sets the locale to en_US.

<%@ page import="com.fatwire.system.*"%>
<%@ page import="com.fatwire.assetapi.data.*"%>
<%@ page import="com.fatwire.mda.*"%>
<%@ page import="com.fatwire.mda.DimensionableAssetInstance.
                 DimensionParentRelationship"%>
<%@ page import="java.util.*"%>
<%@ page import="com.openmarket.xcelerate.asset.*"%>
<%@ page import="com.openmarket.xcelerate.common.*"%>
<cs:ftcs>

<%
Session ses = SessionFactory.getSession();

AssetDataManager adm = (AssetDataManager) ses.getManager( AssetDataManager.class.getName() );
MutableAssetData d = adm.newAssetData( "Content_C", "FSII Article" );
d.getAttributeData( "name" ).setData( New Content" );
d.getAttributeData( "FSIIHeadline" ).setData( "headline" );
d.getAttributeData( "FSIIAbstract" ).setData( "abstract" );
d.getAttributeData( "FSIIBody" ).setData( "body" );
d.getAttributeData( "Publist" ).setData( Arrays.asList( "FirstSiteII" ) );
d.setParents( Arrays.<AssetId>asList( new AssetIdImpl( "Content_P", 1112192431478L)) );
adm.insert( Arrays.<AssetData>asList( d ));
DimensionManager dam = (DimensionManager)ses.getManager(DimensionManager.class.getName());
Dimension dim = dam.loadDimension("en_US");
d.getAttributeData("Dimension") .setData(Arrays.asList(new Dimension[]{dim}));
DimensionParentRelationship dpr = new DimParentRelationshipImpl("Locale", d.getAssetId());
d.getAttributeData("Dimension-parent").setData(Arrays.asList(new DimensionParentRelationship[]{dpr}));
adm.update( Arrays.<AssetData>asList( d ));
%>
</cs:ftcs>

42.6 Development Strategies

This section discusses data types and attribute data (maps WebCenter Sites data types to Java types) as well as query types (compares types of queries, their usage, and supported operations).

This section contains the following topics:

42.6.1 Data Types and Attribute Data

AttributeData contains information about the data type (WebCenter Sites specific type) and the actual data. The types are defined by AttributeTypeEnum. AttributeData.getData() and AttributeData.getDataAsList() return data objects of a specific Java type. Here is a map of WebCenter Sites types and their corresponding Java types.

Table 42-1 WebCenter Sites Data Types and Java Types

WebCenter Sites Data Type Java Type

INT

Integer

FLOAT

Double

STRING

String

DATE

Date

MONEY

Double

LONG

Long

LARGE_TEXT

String

ASSET

AssetId

BLOB

BlobObject


42.6.2 Query Types

Using the Asset API, you can perform two kinds of queries: generic/basic and flex.

There are two different algorithms, one using the generic asset infrastructure (generic/basic query), and the other using AssetSets and Search States (flex query). Note that it is possible to use the generic/basic query for flex assets as well as basic assets; flex query, however, works only for flex assets.

Each of these algorithms has its advantages and disadvantages. The Asset API seeks to unify the querying mechanism and eventually let the API user not be concerned about the choice of algorithm. However, at the present time as there is no equivalence between these algorithms, the user needs to specify if she wants to use a specific feature, offered by one of the two.

QueryProperties.setIsBasicSearch( true ) sets the query algorithm to generic/basic search for this query. It is set to false by default. For basic assets, the setting does not matter.

Which Type of Query to Choose? Very simply put, if you want to look for basic attributes of a flex asset, use the basic. Otherwise use the default. This will work for most queries one generally encounters. Things are a bit more subtle than that. Given below are other considerations against each type of query.

Basic/Generic Query

  • Cannot search on flex attributes if you do not specify subtype.

  • Cannot search on a flex attribute that is not in the flex definition.

  • Cannot sort on a flex attribute.

  • Case sensitivity is not guaranteed (depends on the database).

  • Only the AND operation is allowed between different fields (name=name1 AND description=descr1 is allowed, but name=name1 AND name=name2 is not).

  • Only OR is allowed for two conditions involving the same field name. The OR condition does not work on flex attributes.

Flex Query

  • Cannot have basic attributes in the condition (id, name, description, etc.).

  • Cannot sort by basic attributes.

  • Flex query works without a subtype being specified. The search applies to data of all subtypes.

  • Can use only the following operands in the condition; LIKE, EQUALS, BETWEEN, and RICHTEXT.

42.6.3 Data Types and Valid Query Operations

Depending on the type of query being performed, there are further restrictions on what type of operation is allowed for a given data type.

In general, a flex type query (which is the default for flex assets) allows only the following OpTypeEnums; LIKE, EQUALS, BETWEEN, and RICHTEXT. Note that these are the same operations available from AssetSet/SearchState tags.

If you want to use other OpTypeEnums, you have to use basic/generic query (by setting QueryProperties.setIsBasicSearch( true )). Such a query, of course, has to adhere to the basic query rules above.

Here is the allowed set of operations per data type (single-valued or multi-valued) for a basic/generic query.

Table 42-2 Allowed Set of Operations

Data Type EQUALS NOT_EQUALS LIKE GREATER LESSTHAN BETWEEN RICHTEXT

INT

Y

Y

N

Y

Y

N

FLOAT

Y

Y

N

Y

Y

N

STRING

Y

Y

Y

Y

Y

N

DATE

Y

Y

N

Y

Y

N

MONEY

Y

Y

N

Y

Y

N

LONG

Y

Y

N

Y

Y

N

LARGE_TEXT

N

N

Y

N

N

N

ASSET

Y

Y

N

N

N

N

BLOB

N

N

N

N

N

N


And here is the allowed set of operations per data type (single-valued or multi-valued) for the flex type query.

Table 42-3 Allowed Set of Operations per Data Type

Data Type EQUALS NOT_EQUALS LIKE GREATER LESS THAN BETWEEN RICHTEXT

INT

Y

N

Y

N

FLOAT

Y

N

Y

N

STRING

Y

Y

Y

N

DATE

Y

N

Y

N

MONEY

Y

N

Y

N

LONG

Y

N

Y

N

LARGE_TEXT

N

Y

N

Y

ASSET

Y

N

Y

N

BLOB

N

N

N

Y


42.7 Optional: Setting Up to Use the Asset API from Standalone Java Programs

Although this tutorial shows usage of the Asset API from JSP templates, it is possible to use the API from a standalone Java program, as well. In order to do this, you can set up a single database connection or a connection pool (outside WebCenter Sites).

Note:

In the steps below, we assume that all components are local to your WebCenter Sites installation.

Before setting up a single database connection or pool

  1. Make sure the following files are in the classpath of your Java program:

    • javaee.jar and tools.jar (both are available in JDK 1.5 and higher versions).

    • ServletRequest.properties. This file can be copied from the WEB-INF/classes folder.

    • wem_sso.xml, given that your WebCenter Sites installation has WEM installed and single sign-on (in futuretense.ini) is set to true. The wem_sso.xml file can be copied from the WEB-INF/classes folder.

    • All of WebCenter Sites's binary files (jar files in the WEB-INF/lib folder).

  2. Continue with the steps in one of the following sections:

To set up a single database connection

  1. Set the following system properties for your Java program:

    cs.dburl=<JDBC_URL_to_connect_to_DB>
    cs.dbdriver=<driverClass>
    cs.dbuid=<dbUserName>
    cs.dbpwd=<dbPassword>
    
  2. Locate the WebCenter Sites installation folder and pass its name as a JVM argument:

    -Dcs.installDir=<install_dir>
    

To set up a database connection pool

  1. Add the following jar files to the classpath: commons-dbcp.jar (which ships with WebCenter Sites) and commons-pool.jar (available from the Apache website).

  2. Create the property file with the same name as your data source:

    Note the following:

    • The name of the data source is the value of the cs.dsn property (in futuretense.ini).

    • The value of cs.dbconnpicture (also in futuretense.ini) must refer to cs.dsn (the combination of cs.dbconnpicture and cs.dsn must yield a valid resource).

      For example, the combination of

      cs.dsn= csDataSource and

      cs.dbconnpicture= java\:comp/env/$dsn

      yields a valid resource:

      java:/csDataSource

      Therefore, you would name the property file csDataSource.properties (the value of cs.dsn).

    • When creating the property file, make sure to place it in the classpath of your Java program.

  3. When the property file is created, add the following keys to the file:

    driver=<driverClass>
    url=<JDBC_URL_to_connect_to_DB>
    maxconnections=<number_of_connections_to_pool>
    user=<dbUserName>
    password=<dbPassword>
    
  4. Locate the WebCenter Sites installation folder and pass its name as a JVM argument:

    -Dcs.installDir=<install_dir>