/** * */ package org.jbpm.identity.assignment; import java.util.ArrayList; import java.util.List; import net.conselldemallorca.helium.jbpm3.integracio.Jbpm3HeliumBridge; import net.conselldemallorca.helium.v3.core.api.dto.AreaDto; import net.conselldemallorca.helium.v3.core.api.dto.AreaMembreDto; import net.conselldemallorca.helium.v3.core.api.dto.CarrecDto; import net.conselldemallorca.helium.v3.core.api.dto.EntornDto; import net.conselldemallorca.helium.v3.core.api.dto.PersonaDto; import net.conselldemallorca.helium.v3.core.api.exception.NoTrobatException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jbpm.graph.exe.ExecutionContext; import org.jbpm.graph.exe.Token; import org.jbpm.taskmgmt.def.AssignmentHandler; import org.jbpm.taskmgmt.exe.Assignable; import org.jbpm.taskmgmt.exe.SwimlaneInstance; /** * Implementa el següent llenguatge i resol expressions per assignar * actors a tasques. Està agafat del component d'identitat que du el * JBPM per defecte. * * <pre>syntax : first-term --> next-term --> next-term --> ... --> next-term * * first-term ::= previous | * swimlane(swimlane-name) | * variable(variable-name) | * user(user-name) | * group(group-name) * * next-term ::= group(group-type) | * member(role-name) * </pre> * * @author Limit Tecnologies <limit@limit.es> */ public class HeliumExpressionAssignmentHandler implements AssignmentHandler { private static final long serialVersionUID = 1L; protected String expression; protected Long entornId; public HeliumExpressionAssignmentHandler() {} /** * @see AssignmentHandler#assign(Assignable, ExecutionContext) */ public void assign(Assignable assignable, ExecutionContext executionContext) { String expressio = getExpressio(); logger.debug("Expresió a analitzar: '" + expressio + "'"); String processInstanceId = new Long(executionContext.getProcessInstance().getId()).toString(); if (entornId == null) { // EntornDto entorn = Jbpm3HeliumBridge.getInstanceService().getEntornAmbProcessInstanceId(processInstanceId); EntornDto entorn = Jbpm3HeliumBridge.getInstanceService().getEntornActual(); if (entorn == null) throw new RuntimeException("No s'ha trobat l'entorn per la instància de procés " + processInstanceId); else entornId = entorn.getId(); } TermTokenizer tokenizer = new TermTokenizer(expressio); Object entitat = null; if (tokenizer.hasMoreTerms()) { entitat = resolPrimerTerme(entornId, tokenizer.nextTerm().trim(), executionContext); while (tokenizer.hasMoreTerms() && entitat != null) { entitat = resolSeguentTerme(entornId, entitat, tokenizer.nextTerm().trim(), executionContext); } } if (entitat == null) { throw new RuntimeException("L'expressió d'assignació '" + expressio + "' no ha produit cap resultat"); } else if (entitat instanceof PersonaDto) { PersonaDto p = (PersonaDto)entitat; while(p.getRelleu() != null){ p = getPersonaAmbCodi(p.getRelleu()); } assignable.setActorId(p.getCodi()); } else if (entitat instanceof AreaDto) { AreaDto a = (AreaDto)entitat; List<PersonaDto> persones = getPersonesAmbArea(entornId, a.getCodi()); String[] actors = new String[persones.size()]; int index = 0; for (PersonaDto p: persones) actors[index++] = p.getCodi(); assignable.setPooledActors(actors); } } public void setExpression(String expression) { this.expression = expression; } public void setEntornId(Long entornId) { this.entornId = entornId; } private Object resolPrimerTerme(Long entornId, String terme, ExecutionContext executionContext) { logger.debug("Analitzant primer terme: '" + terme + "'"); Object entitat = null; if (terme.equalsIgnoreCase("previous")) { //String userName = SecurityHelper.getAuthenticatedActorId(); String userName = Jbpm3HeliumBridge.getInstanceService().getUsuariCodiActual(); entitat = getPersonaAmbCodi(userName); } else if ((terme.startsWith("swimlane(")) && (terme.endsWith(")"))) { String swimlaneName = terme.substring(9, terme.length()-1).trim(); String userName = getSwimlaneActorId(swimlaneName, executionContext); entitat = getPersonaAmbCodi(userName); } else if ((terme.startsWith("variable(")) && (terme.endsWith(")")) ) { String variableNom = terme.substring(9, terme.length() - 1).trim(); Object valor = getVariable(variableNom, executionContext); if (valor == null) { throw new ExpressionAssignmentException("La variable '" + variableNom + "' és null"); } else if (valor instanceof String) { entitat = getPersonaAmbCodi((String)valor); if (entitat == null) entitat = getAreaAmbCodi(entornId, (String)valor); } else { entitat = valor; } } else if ( (terme.startsWith("user(")) && (terme.endsWith(")")) ) { String usuariNom = terme.substring(5, terme.length()-1).trim(); entitat = getPersonaAmbCodi(usuariNom); } else if ( (terme.startsWith("group(")) && (terme.endsWith(")")) ) { String grupNom = terme.substring(6, terme.length()-1).trim(); entitat = getAreaAmbCodi(entornId, grupNom); } else { throw new ExpressionAssignmentException("No s'ha pogut interpretar el primer terme de l'expressió '" + getExpressio() + "'"); } return entitat; } private Object resolSeguentTerme(Long entornId, Object entitat, String terme, ExecutionContext executionContext) { logger.debug("Analitzant següent terme: '" + terme + "'"); if ((terme.startsWith("member(")) && (terme.endsWith(")")) ) { String carrec = terme.substring(7, terme.length() - 1).trim(); AreaDto a = (AreaDto)entitat; entitat = getPersonaAmbAreaICarrec(entornId, a.getCodi(), carrec); if (entitat == null) throw new ExpressionAssignmentException("No hi ha cap usuari amb el carrec '" + carrec + "' a dins l'àrea '" + a.getNom() + "'"); } else { throw new ExpressionAssignmentException("No es pot interpretar el terme '" + terme + "' de la expressio '" + getExpressio() + "'"); } return entitat; } private PersonaDto getPersonaAmbCodi(String codi) { PersonaDto p = Jbpm3HeliumBridge.getInstanceService().getPersonaAmbCodi(codi); if (p == null) logger.warn("No s'ha pogut trobar la persona amb el codi \"" + codi + "\""); return p; } private AreaDto getAreaAmbCodi(Long entornId, String codi) { try { AreaDto area = Jbpm3HeliumBridge.getInstanceService().getAreaAmbEntornICodi( entornId, codi); if (area == null) logger.warn("No s'ha pogut trobar l'àrea amb el codi \"" + codi + "\""); return area; } catch (NoTrobatException ex) { logger.error("No s'ha pogut trobar l'entorn (id=" + entornId + ")", ex); return null; } } private List<PersonaDto> getPersonesAmbArea(Long entornId, String codi) { AreaDto area = getAreaAmbCodi(entornId, codi); List<PersonaDto> persones = new ArrayList<PersonaDto>(); if (area.getMembres() != null) { for (AreaMembreDto membre: area.getMembres()) { PersonaDto p = getPersonaAmbCodi(membre.getCodi()); if (p != null) persones.add(p); } } if (personesAmbAreaRecursiu() && area.getFills() != null) { for (AreaDto fill: area.getFills()) persones.addAll(getPersonesAmbArea(entornId, fill.getCodi())); } return persones; } private PersonaDto getPersonaAmbAreaICarrec( Long entornId, String areaCodi, String carrecCodi) { try { CarrecDto carrec = Jbpm3HeliumBridge.getInstanceService().getCarrecAmbEntornIAreaICodi(entornId, areaCodi, carrecCodi); if (carrec != null && carrec.getPersonaCodi() != null) return getPersonaAmbCodi(carrec.getPersonaCodi()); return null; } catch (NoTrobatException ex) { logger.error("No s'ha pogut trobar " + ex.getClass().getName() + " (id/codi=" + ex.getObjectId().toString() + ")", ex); return null; } } private String getSwimlaneActorId(String swimlaneName, ExecutionContext executionContext) { SwimlaneInstance swimlaneInstance = executionContext. getTaskMgmtInstance(). getSwimlaneInstance(swimlaneName); if (swimlaneInstance == null) throw new ExpressionAssignmentException("No s'ha trobat la instancia del swimlane '" + swimlaneName + "'"); return swimlaneInstance.getActorId(); } private Object getVariable(String variableName, ExecutionContext executionContext) { Token token = executionContext.getToken(); return executionContext.getContextInstance().getVariable(variableName, token); } private String getExpressio() { String expressio = expression; // lleva el tag <expression>...</expression> int indexInici = expressio.indexOf(">") + 1; int indexFi = expressio.lastIndexOf("<"); if (indexInici != -1 && indexFi != -1) return expressio.substring(indexInici, indexFi); return expressio; } private boolean personesAmbAreaRecursiu() { String esRecursiu = Jbpm3HeliumBridge.getInstanceService().getHeliumProperty("app.jbpm.identity.recursiu"); return "true".equalsIgnoreCase(esRecursiu); } private static final Log logger = LogFactory.getLog(HeliumExpressionAssignmentHandler.class); }