package org.imixs.marty.plugins;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.imixs.marty.ejb.ProfileService;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.WorkflowContext;
import org.imixs.workflow.engine.plugins.AbstractPlugin;
import org.imixs.workflow.exceptions.PluginException;
/**
* This plugin computes for each name field (prefix = 'nam') if the
* corresponding user profile contains a deputy. If so the deputy will be added
* into the name field.
*
* If a name Field (prafix = 'nam') is listed in the 'ignoreList' the field will
* be skipped. The ignoreList can include regular expressions and can be
* modified by a client.
*
* The plugin runs on all kinds of workitems and childworkitems.
*
* The Plugin should run after the TeamPlugin but before the ownerPlugin,
* approverPlugin and accessPlugin
*
* To avoid conflicts with the ApproverPlugin, the DeputyPlugin ignores fields
* ending with 'approvers' and 'approvedby'.
*
* @see https://github.com/imixs/imixs-marty/issues/130
*
*
* @author rsoika
*
*/
public class DeputyPlugin extends AbstractPlugin {
public static String PROFILESERVICE_NOT_BOUND = "PROFILESERVICE_NOT_BOUND";
ItemCollection workitem = null;
ProfileService profileService = null;
private String[] ignoreList = { "$creator", "$editor", "$lasteditor", "namcreator", "namcurrenteditor", "namlasteditor", "namowner", "nam+(?:[a-z0-9_]+)approvers",
"nam+(?:[a-z0-9_]+)approvedby" };
private static Logger logger = Logger.getLogger(DeputyPlugin.class.getName());
@Override
public void init(WorkflowContext actx) throws PluginException {
super.init(actx);
// lookup profile service EJB
String jndiName = "ejb/ProfileService";
InitialContext ictx;
try {
ictx = new InitialContext();
Context ctx = (Context) ictx.lookup("java:comp/env");
profileService = (ProfileService) ctx.lookup(jndiName);
} catch (NamingException e) {
throw new PluginException(MailPlugin.class.getName(), PROFILESERVICE_NOT_BOUND, "ProfileService not bound",
e);
}
}
/**
* iterate over all fields with the prefix nam...
*
* Skip if not a workitem
*
**/
@SuppressWarnings("unchecked")
@Override
public ItemCollection run(ItemCollection aworkItem, ItemCollection documentActivity) {
workitem = aworkItem;
// skip if the workitem is from a different type (for example Teams
// may not be processed by this plugin)
String type = workitem.getItemValueString("type");
if (!type.startsWith("workitem") && !type.startsWith("childworkitem"))
return workitem;
// iterate over name fields
Map<String, List<Object>> map = workitem.getAllItems();
for (String key : map.keySet()) {
if (matchIgnoreList(key))
continue;
// lookup deputies
logger.fine("[DeputyPlugin] lookup=" + key);
List<String> oldNameList = workitem.getItemValue(key);
List<String> newNameList = updateDeputies(oldNameList);
if (logger.isLoggable(Level.FINE)) {
logger.fine("[DeputyPlugin] new list=");
for (String aentry : newNameList) {
logger.fine(aentry);
}
}
// update field
workitem.replaceItemValue(key, newNameList);
}
return workitem;
}
/**
* This method updates a given list of names. For each name the method
* lookups a deputy. If a deputy is defined but not par of the list he will
* be added to the new list.
*
* @param sourceNameList
* - source list of names
* @return new list with all names plus deputies.
*/
@SuppressWarnings("unchecked")
private List<String> updateDeputies(List<String> sourceNameList) {
Vector<String> resultNameList = new Vector<String>();
resultNameList.addAll(sourceNameList);
// test for each entry if a deputy is defined
for (String aName : sourceNameList) {
// now lookup the deputies
ItemCollection profile = profileService.findProfileById(aName);
if (profile != null) {
List<String> deputyList = profile.getItemValue("namdeputy");
// if we found deputies - we need to add them to the list
for (String deputy : deputyList) {
if (deputy != null && !deputy.isEmpty() && resultNameList.indexOf(deputy) == -1) {
// add new entry
resultNameList.add(deputy);
}
}
}
}
return resultNameList;
}
public String[] getIgnoreList() {
return ignoreList;
}
public void setIgnoreList(String[] ignoreList) {
this.ignoreList = ignoreList;
}
/**
* This method returns true in case the given fieldName matches the
* IgnoreList. Regular expressions are supported by the IgnoreList.
*
* @param fieldName
* @return true if fieldName matches the ignoreList
*/
public boolean matchIgnoreList(String fieldName) {
if (fieldName == null)
return true;
if (!fieldName.toLowerCase().startsWith("nam")) {
return true;
}
for (String pattern : this.ignoreList) {
if (fieldName.toLowerCase().matches(pattern)) {
return true;
}
}
return false;
}
}