Archive for the ‘item’ Category

Datasources allow mainly to select things from drop-down lists in forms publisher forms and workflow forms.

Datasources are nothing but java classes that get executed when a form loads. The class must implement one of the following interfaces:

com.interwoven.datasource.ListDataSource;
com.interwoven.datasource.MapDataSource;
com.interwoven.datasource.SimpleDataSource;
com.interwoven.datasource.SortedValuesMapDataSource;

As part of the implementation, the class must therefore have an execute method which gets passed a DataSourceContext object. The return value and type vary depending of which datasource class you implement.

A SimpleDataSource implementation returns a single value. Forms publisher will use the value for example in a text field.

public String execute(String sessionId, String context, Map params) {
String datasource="value";
return(datasource);
}

A ListDataSource implementation will return a List of strings. Forms publisher will use the same value for the form’s value and label.

public List<String> execute(DataSourceContext context) {
List<String> datasource = new ArrayList<String>();
datasource.add(“value”);
return(datasource);
}

The context contains some information about the session id, the server context (the vpath of the current node) and the other custom parameters passed to the datasource.

A MapDataSource implementation will return map of strings. Forms publisher will use one value for the label and the other for the value. The key is the value string.

public Map<String, String> execute(DataSourceContext context) {
Map<String,String> datasource = new HashMap<String,String>();
datasource.put("value","label"); // make sure you convert numbers to proper strings
return(datasource);
}

The SortedMapDataSource implementation returns the same as a MapDataSource, except Forms Publisher will sort the results alphabetically.

public Map<String, String> execute(DataSourceContext context) {
Map<String, String> datasource = new HashMap<String, String>();
datasource.put("value", "label"); // make sure you convert numbers to proper strings
return (datasource);
}

In order to create a new datasource, we need to edit the local/config/DataSourceConfig.xml file. This file is an XML document which defines which datasources are available to the system as a whole.

For the example that follows, we will create a datasource that will allow a user to select an edition from the current branch. We need to add our datasource to the list by adding the following:

<datasource>
<name>Main Branch Editions</name>
<classname>com.acme.util.BranchEditionsDatasource</classname>
<param name="branch">/default/main</param>
</datasource>

We will build a class with that name as follows:

package com.acme.util;

import com.interwoven.cssdk.factory.CSLocalFactory;
import com.interwoven.cssdk.filesys.CSBranch;
import com.interwoven.cssdk.filesys.CSEdition;
import com.interwoven.cssdk.filesys.CSVPath;
import com.interwoven.datasource.core.DataSourceContext;
import com.interwoven.datasource.SortedValuesMapDataSource;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

public class BranchEditionsDataSource implements SortedValuesMapDataSource {

 public Map<String, String> execute(DataSourceContext context) {
 Map<String, String> parameters = context.getAllParameters();
 Map<String, String> datasource = new HashMap<String, String>();
 String sessionString = context.getSessionId();
 String configFilePath = "/apps/interwoven/teamsite/cssdk/cssdk.cfg";
 Properties localProperties = new Properties();
 localProperties.setProperty("cssdk.cfg.path", configFilePath);
 CSLocalFactory csLocalFactory = (CSLocalFactory) CSLocalFactory.getFactory(localProperties);
 CSClient client = null;

 try {
 client = csLocalFactory.getClient(sessionString, Locale.ENGLISH, "BranchEditionsDataSource", "localhost");
 if (client != null) {
 String branchParameter = parameters.get("branch");
 CSVPath branchVPath = null;
 if (branchParameter != null) {
 branchVPath = new CSVPath(branchParameter);
 } else {
 branchVPath = new CSVPath(context.getServerContext());
 }
 if (branchVPath != null) {
 branchVPath = branchVPath.getBranch(); // make sure we have a branch, really...
 CSBranch branch = client.getBranch(branchVPath, true);
 if (branch != null) {
 CSEdition[] editions = branch.getEditions(true, false, -1);
 for (CSEdition edition : editions) {
 datasource.put(edition.getVPath().toString(), edition.getName() + " - " +                                             edition.getDescription());
 }
 } else {
 throw new NullPointerException("branch is null");
 }
 } else {
 throw new NullPointerException("branch vpath is null");
 }
 } else {
 throw new NullPointerException("client is null");
 }
 } catch (Exception ex) {
 datasource = new HashMap<String, String>();
 datasource.put("error", "An error occured. Please contact your administrator");
 Logger.getLogger(BranchEditionsDataSource.class.getName()).log(Level.SEVERE, null, ex);
 }

 return (datasource);
 }
}

The context gives you all you need to connect to the local Teamsite server using the session id. From there, we can either grab the editions of the branch passed as a parameter or the current branch. You can also extend

com.interwoven.livesite.common.cssdk.datasource.AbstractDataSource.

This will give you the ability to grab the client with a simple method call of:

CSClient client=getClient(context);

You will have to use the parameters that the class expects to make the connection:

<param name="servername">teamsite</param>
<param>http://teamsite:80</param>
<param name="csFactory">com.interwoven.cssdk.factory.CSLocalFactory</param>

Once the class has been compiled into the toolkit, we can then tell out formspublisher item to use it.

we can use a “inline” element, with a Datasource “pseudo-command” (note that this is case sensitive). This works for text instances and select, radio and checkbox instances.

<select>
    <inline command="Datasource:executeComponent:Main Branch Editions" />
</select>

All you now need to do is check the work in the form’s drop down list..

Firefox for me has been the most customisable and because of this, it has given me the most enriched browsing experience.
I am a web developer amd the mutlitude of shortcuts I can use really saves me time. I bookmark and organise my boobmark with 1 click, and I have a lot of those. I get rid of annoying ads, added functionality to my search engines, added search engines to look for documentation quickly.
For me, it also renders HTML the way HTML is supposed to be rendered, which I cannot say the same for Microsoft Internet Explorer. Stay away from Microsoft on this one. And to top ot all up, I can create an add-on so that users visiting my site have an extra-rich experience. Linked-in did it, so can I.

For me the browser war is not just something that happens in the background. Whenever I see people, colleagues, who develop in IE and don’t make their site standard compatible, I cringe.  whenever I go to  company that insists that we must use IE as the de-facto company browser, I cringe. the reason I cringe is because if you had a car manufacturer produced a car so fuel inefficient, so clunky to drive and with a engine without 3rd gear, you wouldn’t want to drive it, would you? Now why the hell is this what most companies choose to do with their browsers is beyond me…

Some even elected to stay with IE6… I wouldn’t work for them.

maxlength is only valid for text instances, not textarea ones. The DTD of datacapture documents says so. Limiting the size can be done with a nice little regulare expressio. For example, limiting to 300 characters requires the following regular expression:

<textarea validation-regex="^.{0,300}$" required="t" rows="10" cols="90" wrap="virtual" />

The allowed element inside text, textarea, select, radio, checkbox, readonly and hidden works fine on datacapture forms within forms publisher. Whenever a workflow instantiation form uses the allowed element, it’s not using it to use the instance designed by it.

<item pathid=”somepath” name=”somepath”>
<text>
<allowed><cred role=”master” /></allowed>
</text>
<readonly />
</item>

This snippet of XML should have allowed masters to edit the field and anyone else would just be able to look at it without modifying it. Though this works fine in forms publisher, the workflow engine’s rendition does not concern itself with such authorisation.

Instead, formAPI has to be used. To find out the current user’s name, group and roles, we can use the IWDatacapture’s getUser(), getGroups() and getRoles() methods and show or hide the fields as we please.

getUser() returns the short username (not “Laurent Picquet” but “lpiquet”), getGroups() returns an array of group names the current user belongs to and getRoles() returns an array of roles the current user has in the the current branch (“admin,master” in my case).

var roles = IWDatacapture.getRoles();
 var isMaster=false;
 for (var i in roles){
 if (roles[i]=='master'){
 isMaster=true;
 }
 }
 prompt("isMaster",isMaster);

The workflow preProcessor has access to the workflow variables. For this, we can retrieve the list of global configurable variables and datasources.

/* Configurable variables, Datasource variable and System variables */ 
Iterator<String> workflowParametersIterator = workflow.getParams().keySet().iterator(); 
while (workflowParametersIterator.hasNext()) {
 String parameter = workflowParametersIterator.next();
 System.out.println(parameter + "=" + (String)workflow.getParams().get(parameter));
}
Variable Description
$IW_HOME the installation directory of the current teamsite implementation
$IW_USER the user name of the current user
$IW_AREAOWNER the user name of the owner of the current workarea
$IW_WFNAME the name of the workflow
$IW_SESSION the session id. Very usefull for creating a new client to teamsite, with the same user as the user starting the workflow.
$IW_WORKAREA the name of the current workarea
$IW_FILES the list of attached files
$IW_TIME the current time
$IW_BRANCH the name of the current branch
$IW_STORE the name of the current content store
$IW_SERVER the name of the current teamsite server
IW_PROCESS Indicating the kind of process (PreProcessorCommand)

You can also modify the value of your configurable variables BEFORE the workflow gets started, by adding to the map of keys and values, or modifyinmg specific keys.

workflow.getParams().put("someConfigVar", "someValue");

For select options, create only one variable and use a semi-colon as a separator. On the custom instantiation form, Add some formAPI code to split the value on “;”, loop through the result and add the option to another custom variable. Make the original variable hidden.

The following example retrieves a list of “inline resources” and lets the user decide if they should be included or not by the subsequent workflow:

/* loop through the inline resources (hidden) and add the options for the attached inline resources (visible select) */  
var inlineResourcesToAttachItem = IWDatacapture.getItem("/Config/inlineResourcesToAttach");  
var inlineResourcesValue = IWDatacapture.getItem("/Config/InlineResources").getValue();  
var inlineResources = inlineResourcesValue.split(";");  
for (var inlineResourceIndex in inlineResources){
 /* create a new option to add to the visible inline resources to attach, selected and defaultSelected false by default */
 var option = new Option(inlineResources[inlineResourceIndex],inlineResources[inlineResourceIndex],false, false);
 inlineResourcesToAttachItem.addOption(option);
}

If you need to get connected to teamsite in the preProcessor, you can use the following method:

String sessionString=(String) workflow.getParams().get("$IW_SESSION"); 
String configFilePath = "/apps/interwoven/teamsite/cssdk/cssdk.cfg"; 
Properties localProperties = new Properties(); 
localProperties.setProperty("cssdk.cfg.path", configFilePath); 
CSLocalFactory csLocalFactory = (CSLocalFactory) CSLocalFactory.getFactory(localProperties); 
CSClient client = null; 
try {
 client = csLocalFactory.getClient(sessionString, Locale.ENGLISH, "myPreProcessorNameGoesHere", "localhost"); 
} catch (CSException ex) {
     Logger.getLogger(ComPageDCRInlineResources.class.getName()).log(Level.SEVERE, null, ex); 
}