Package org.jbpm.jpdl.internal.xml

Source Code of org.jbpm.jpdl.internal.xml.JpdlParser

/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jbpm.jpdl.internal.xml;

import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

import org.jbpm.api.JbpmException;
import org.jbpm.api.activity.ActivityBehaviour;
import org.jbpm.api.listener.EventListener;
import org.jbpm.api.model.Event;
import org.jbpm.internal.log.Log;
import org.jbpm.jpdl.internal.activity.JpdlBinding;
import org.jbpm.jpdl.internal.activity.MailListener;
import org.jbpm.jpdl.internal.model.JpdlProcessDefinition;
import org.jbpm.pvm.internal.email.impl.MailProducerImpl;
import org.jbpm.pvm.internal.email.impl.MailTemplate;
import org.jbpm.pvm.internal.email.impl.MailTemplateRegistry;
import org.jbpm.pvm.internal.email.spi.MailProducer;
import org.jbpm.pvm.internal.env.EnvironmentImpl;
import org.jbpm.pvm.internal.model.ActivityCoordinatesImpl;
import org.jbpm.pvm.internal.model.ActivityImpl;
import org.jbpm.pvm.internal.model.CompositeElementImpl;
import org.jbpm.pvm.internal.model.Continuation;
import org.jbpm.pvm.internal.model.EventImpl;
import org.jbpm.pvm.internal.model.EventListenerReference;
import org.jbpm.pvm.internal.model.ObservableElementImpl;
import org.jbpm.pvm.internal.model.ProcessDefinitionImpl;
import org.jbpm.pvm.internal.model.ScopeElementImpl;
import org.jbpm.pvm.internal.model.TimerDefinitionImpl;
import org.jbpm.pvm.internal.model.TransitionImpl;
import org.jbpm.pvm.internal.model.VariableDefinitionImpl;
import org.jbpm.pvm.internal.model.VariableOutDefinitionImpl;
import org.jbpm.pvm.internal.model.VariableOutDefinitionSet;
import org.jbpm.pvm.internal.repository.DeploymentImpl;
import org.jbpm.pvm.internal.task.AssignableDefinitionImpl;
import org.jbpm.pvm.internal.task.SwimlaneDefinitionImpl;
import org.jbpm.pvm.internal.task.TaskDefinitionImpl;
import org.jbpm.pvm.internal.util.XmlUtil;
import org.jbpm.pvm.internal.wire.Descriptor;
import org.jbpm.pvm.internal.wire.WireContext;
import org.jbpm.pvm.internal.wire.binding.MailTemplateBinding;
import org.jbpm.pvm.internal.wire.binding.ObjectBinding;
import org.jbpm.pvm.internal.wire.descriptor.ObjectDescriptor;
import org.jbpm.pvm.internal.wire.usercode.UserCodeReference;
import org.jbpm.pvm.internal.wire.xml.WireParser;
import org.jbpm.pvm.internal.xml.Bindings;
import org.jbpm.pvm.internal.xml.Parse;
import org.jbpm.pvm.internal.xml.Parser;
import org.jbpm.pvm.internal.xml.ProblemImpl;
import org.w3c.dom.Element;

/**
* @author Tom Baeyens
*/
public class JpdlParser extends Parser {
 
  private static final Log log = Log.getLog(JpdlParser.class.getName());

  public static final String NAMESPACE_JPDL_40 = "http://jbpm.org/4.0/jpdl";
  public static final String NAMESPACE_JPDL_42 = "http://jbpm.org/4.2/jpdl";
  public static final String NAMESPACE_JPDL_43 = "http://jbpm.org/4.3/jpdl";

  public static final String CURRENT_VERSION_JBPM = "4.3";
  public static final String CURRENT_VERSION_NAMESPACE = "http://jbpm.org/"+CURRENT_VERSION_JBPM+"/jpdl";
  public static final String CURRENT_VERSION_PROCESS_LANGUAGE_ID = "jpdl-"+CURRENT_VERSION_JBPM;
 
  public static final List<String> SCHEMA_RESOURCES = new ArrayList<String>();
  static {
    SCHEMA_RESOURCES.add("jpdl-4.0.xsd");
    SCHEMA_RESOURCES.add("jpdl-4.2.xsd");
    SCHEMA_RESOURCES.add("jpdl-4.3.xsd");
  }

  public static final WireParser wireParser = WireParser.getInstance();
  public static final ObjectBinding objectBinding = ObjectBinding.INSTANCE;

  // array elements are mutable, even when final
  // never make a static array public
  static final String[] DEFAULT_BINDING_RESOURCES = {
    "jbpm.jpdl.bindings.xml",
    "jbpm.user.bindings.xml"
  };

  static JpdlBindingsParser jpdlBindingsParser = new JpdlBindingsParser();

  public static final String CATEGORY_ACTIVITY = "activity";
  public static final String CATEGORY_EVENT_LISTENER = "eventlistener";

  public JpdlParser() {
    initialize();
    parseBindings();
    setSchemaResources(SCHEMA_RESOURCES);
  }

  protected void parseBindings() {
    this.bindings = new Bindings();

    for (String activityResource: DEFAULT_BINDING_RESOURCES) {
      Enumeration<URL> resourceUrls = getResources(activityResource);
      if (resourceUrls.hasMoreElements()) {
        while (resourceUrls.hasMoreElements()) {
          URL resourceUrl = resourceUrls.nextElement();
          log.trace("loading jpdl bindings from resource: "+resourceUrl);
          jpdlBindingsParser.createParse()
            .setUrl(resourceUrl)
            .contextMapPut(Parse.CONTEXT_KEY_BINDINGS, bindings)
            .execute()
            .checkErrors("jpdl bindings from "+resourceUrl.toString());
        }
      } else {
        log.trace("skipping unavailable jpdl activities resource: "+activityResource);
      }
    }
  }

  protected Enumeration<URL> getResources(String resourceName) {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    Enumeration<URL> resourceUrls;
    try {
      resourceUrls = classLoader.getResources(resourceName);
    } catch (Exception e) {
      throw new JbpmException("couldn't get resource urls for "+resourceName, e);
    }
    return resourceUrls;
  }

  public Object parseDocumentElement(Element documentElement, Parse parse) {
    List<ProcessDefinitionImpl> processDefinitions = new ArrayList<ProcessDefinitionImpl>();
   
    JpdlProcessDefinition processDefinition = instantiateNewJpdlProcessDefinition();
   
    processDefinitions.add(processDefinition);
   
    parse.contextStackPush(processDefinition);
    try {
      // process attribues
      String name = XmlUtil.attribute(documentElement, "name", true, parse);
      processDefinition.setName(name);

      // make the process language version available for bindings
      // to allow for specific parsing behaviour per version
     
      // first check if the langid is available as a deployment property
      DeploymentImpl deployment = (DeploymentImpl) parse.contextMapGet(Parse.CONTEXT_KEY_DEPLOYMENT);
      if (deployment!=null) {
        String processLanguageId = deployment.getProcessLanguageId(name);
        if (processLanguageId==null) {
          // if it is not available as a deployment property, check if the
          // jpdlparser attribute specifies a specific jpdl version.
          // this is the case for certain compatibility tests in our test suite
          String jpdlParser = XmlUtil.attribute(documentElement, "jpdlparser");
          if (jpdlParser!=null) {
            processLanguageId = "jpdl-"+jpdlParser;

          } else {
            // if none of the above, check if this is a parser test run for a specific verion
            // specify the jpdltestversion with "mvn -Djpdlparser=jpdl-4.3 clean install"
            // that way, the whole test suite will be use the specified parser
            jpdlParser = System.getProperty("jpdlparser");
            if (jpdlParser!=null) {
              processLanguageId = "jpdl-"+jpdlParser;

            } else {
              // if this process has a namespace, then use the namespace
              // to see what jpdl parser version should be used
              String namespaceUri = documentElement.getNamespaceURI();
              if (namespaceUri!=null) {
                processLanguageId = "jpdl-"+namespaceUri.substring(16, 19);

              } else {
                // if none of the above, just deploy it as the current library version
                processLanguageId = CURRENT_VERSION_PROCESS_LANGUAGE_ID;
              }
            }
          }
          // saving the process language will make sure that 
          // the right parser version is used after an upgrade of jbpm
          // as the old format xml will still be in the db
          deployment.setProcessLanguageId(name, processLanguageId);
        }
        parse.contextMapPut(Parse.CONTEXT_KEY_PROCESS_LANGUAGE_ID, processLanguageId);
      }

      String packageName = XmlUtil.attribute(documentElement, "package");
      processDefinition.setPackageName(packageName);

      Integer version = XmlUtil.attributeInteger(documentElement, "version", false, parse);
      if (version!=null) {
        processDefinition.setVersion(version);
      }

      String key = XmlUtil.attribute(documentElement, "key", false, parse);
      if (key!=null) {
        processDefinition.setKey(key);
      }

      Element descriptionElement = XmlUtil.element(documentElement, "description");
      if (descriptionElement!=null) {
        String description = XmlUtil.getContentText(descriptionElement);
        processDefinition.setDescription(description);
      }
     
      UnresolvedTransitions unresolvedTransitions = new UnresolvedTransitions();
      parse.contextStackPush(unresolvedTransitions);
     
      // swimlanes
      List<Element> swimlaneElements = XmlUtil.elements(documentElement, "swimlane");
      for (Element swimlaneElement: swimlaneElements) {
        String swimlaneName = XmlUtil.attribute(swimlaneElement, "name", true, parse);
        if (swimlaneName!=null) {
          SwimlaneDefinitionImpl swimlaneDefinition =
              processDefinition.createSwimlaneDefinition(swimlaneName);
          parseAssignmentAttributes(swimlaneElement, swimlaneDefinition, parse);
        }
      }

      // on events
      parseOnEvents(documentElement, parse, processDefinition);
     
      // activities
      parseActivities(documentElement, parse, processDefinition);

      // bind activities to their destinations
      resolveTransitionDestinations(parse, processDefinition, unresolvedTransitions);

      // process migration information
      Element migrationElement = XmlUtil.element(documentElement, "migrate-instances");
      if (migrationElement != null) {
        MigrationHelper.parseMigrationDescriptor(migrationElement, parse, processDefinition);
      }

    } finally {
      parse.contextStackPop();
    }

    if (processDefinition.getInitial()==null) {
      parse.addProblem("no start activity in process", documentElement);
    }
   
    return processDefinitions;
  }

  protected JpdlProcessDefinition instantiateNewJpdlProcessDefinition() {
    return new JpdlProcessDefinition();
  }

  protected void resolveTransitionDestinations(Parse parse, JpdlProcessDefinition processDefinition, UnresolvedTransitions unresolvedTransitions) {
    for (UnresolvedTransition unresolvedTransition: unresolvedTransitions.list) {
      unresolvedTransition.resolve(processDefinition, parse);
    }
  }

  public void parseActivities(Element documentElement, Parse parse, CompositeElementImpl compositeElement) {
    List<Element> elements = XmlUtil.elements(documentElement);
    for (Element nestedElement : elements) {
      String tagName = XmlUtil.getTagLocalName(nestedElement);
      if ("on".equals(tagName)
          || "timer".equals(tagName)
          || "swimlane".equals(tagName)
          || "migrate-instances".equals(tagName)) continue;

      JpdlBinding activityBinding = (JpdlBinding) getBinding(nestedElement, CATEGORY_ACTIVITY);
      if (activityBinding == null) {
        log.debug("unrecognized activity: " + tagName);
        continue;
      }

      ActivityImpl activity = compositeElement.createActivity();
      parse.contextStackPush(activity);
      try {
        activity.setType(activityBinding.getTagName());
        activityBinding.parseName(nestedElement, activity, parse);
        parseTransitions(nestedElement, activity, parse);

        Element descriptionElement = XmlUtil.element(documentElement, "description");
        if (descriptionElement!=null) {
          String description = XmlUtil.getContentText(descriptionElement);
          activity.setDescription(description);
        }

        String continuationText = XmlUtil.attribute(nestedElement, "continue");
        if (continuationText!=null) {
          if ("async".equals(continuationText)) {
            activity.setContinuation(Continuation.ASYNCHRONOUS);
          } else if ("exclusive".equals(continuationText)) {
            activity.setContinuation(Continuation.EXCLUSIVE);
          }
        }

        Object parseResult = activityBinding.parse(nestedElement, parse, this);
        if (parseResult instanceof ActivityBehaviour) {
          ActivityBehaviour activityBehaviour = (ActivityBehaviour) parseResult;
          activity.setActivityBehaviour(activityBehaviour);
        } else {
          Descriptor activityBehaviourDescriptor = (Descriptor) parseResult;
          activity.setActivityBehaviourDescriptor(activityBehaviourDescriptor);
        }

        parseOnEvents(nestedElement, parse, activity);

        String g = XmlUtil.attribute(nestedElement, "g");
        if (g == null) continue;

        StringTokenizer stringTokenizer = new StringTokenizer(g, ",");
        ActivityCoordinatesImpl coordinates = null;
        if (stringTokenizer.countTokens() == 4) {
          try {
            int x = Integer.parseInt(stringTokenizer.nextToken());
            int y = Integer.parseInt(stringTokenizer.nextToken());
            int width = Integer.parseInt(stringTokenizer.nextToken());
            int height = Integer.parseInt(stringTokenizer.nextToken());
            coordinates = new ActivityCoordinatesImpl(x, y, width, height);
          } catch (NumberFormatException e) {
            coordinates = null;
          }
        }
        if (coordinates != null) {
          activity.setCoordinates(coordinates);
        } else {
          parse.addProblem("invalid coordinates g=\"" + g + "\" in " + activity, nestedElement);
        }
      } finally {
        parse.contextStackPop();
      }
    }
  }
 
  public TimerDefinitionImpl parseTimerDefinition(Element timerElement, Parse parse, ScopeElementImpl scopeElement) {
    TimerDefinitionImpl timerDefinition = scopeElement.createTimerDefinition();

    String duedate = XmlUtil.attribute(timerElement, "duedate");
    String duedatetime = XmlUtil.attribute(timerElement, "duedatetime");

    if (duedate!=null) {
      timerDefinition.setDueDateDescription(duedate);
     
    } else if (duedatetime!=null) {
      String dueDateTimeFormatText = (String) EnvironmentImpl.getFromCurrent("jbpm.duedatetime.format");
      if (dueDateTimeFormatText==null) {
        dueDateTimeFormatText = "HH:mm dd/MM/yyyy";
      }
      SimpleDateFormat dateFormat = new SimpleDateFormat(dueDateTimeFormatText);
      try {
        Date duedatetimeDate = dateFormat.parse(duedatetime);
        timerDefinition.setDueDate(duedatetimeDate);
      } catch (ParseException e) {
        parse.addProblem("couldn't parse duedatetime "+duedatetime, e);
      }
    } else {
      parse.addProblem("either duedate or duedatetime is required in timer", timerElement);
    }
   
    String repeat = XmlUtil.attribute(timerElement, "repeat");
    timerDefinition.setRepeat(repeat);
   
    return timerDefinition;
  }

  public void parseOnEvents(Element element, Parse parse, ScopeElementImpl scopeElement) {
    // event listeners
    List<Element> onElements = XmlUtil.elements(element, "on");
    for (Element onElement: onElements) {
      String eventName = XmlUtil.attribute(onElement, "event", true, parse);
      parseOnEvent(onElement, parse, scopeElement, eventName);

      Element timerElement = XmlUtil.element(onElement, "timer");
      if (timerElement!=null) {
        TimerDefinitionImpl timerDefinitionImpl = parseTimerDefinition(timerElement, parse, scopeElement);
        timerDefinitionImpl.setEventName(eventName);
      }
    }
  }

  public void parseOnEvent(Element element, Parse parse, ObservableElementImpl observableElement, String eventName) {
    if (eventName!=null) {
      EventImpl event = observableElement.getEvent(eventName);
      if (event==null) {
        event = observableElement.createEvent(eventName);
      }
     
      String continuationText = XmlUtil.attribute(element, "continue");
      if (continuationText!=null) {
        if ("async".equals(continuationText)) {
          event.setContinuation(Continuation.ASYNCHRONOUS);
        } else if ("exclusive".equals(continuationText)) {
          event.setContinuation(Continuation.EXCLUSIVE);
        }
      }

      for (Element eventListenerElement: XmlUtil.elements(element)) {
        JpdlBinding eventBinding = (JpdlBinding) getBinding(eventListenerElement, CATEGORY_EVENT_LISTENER);
        if (eventBinding!=null) {
          EventListenerReference eventListenerReference = null;
          Object parseResult = eventBinding.parse(eventListenerElement, parse, this);
          if (parseResult instanceof EventListener) {
            EventListener eventListener = (EventListener) parseResult;
            eventListenerReference = event.createEventListenerReference(eventListener);
          } else {
            Descriptor eventListenerDescriptor = (Descriptor) parseResult;
            eventListenerReference = event.createEventListenerReference(eventListenerDescriptor);
          }
         
          if (XmlUtil.attributeBoolean(eventListenerElement, "propagation", false, parse, false)) {
            eventListenerReference.setPropagationEnabled(true);
          }
         
          continuationText = XmlUtil.attribute(eventListenerElement, "continue");
          if (continuationText!=null) {
            if (observableElement instanceof ActivityImpl) {
              if (observableElement.getName()==null) {
                parse.addProblem("async continuation on event listener requires activity name", eventListenerElement);
              }
            } else if (observableElement instanceof TransitionImpl) {
              TransitionImpl transition = (TransitionImpl) observableElement;
              if (transition.getSource().getName()==null) {
                parse.addProblem("async continuation on event listener requires name in the transition source activity", eventListenerElement);
              }
            }
            if ("async".equals(continuationText)) {
              eventListenerReference.setContinuation(Continuation.ASYNCHRONOUS);
            } else if ("exclusive".equals(continuationText)) {
              eventListenerReference.setContinuation(Continuation.EXCLUSIVE);
            }
          }

        } else {
          String tagName = XmlUtil.getTagLocalName(eventListenerElement);
          if ( ! ( (observableElement instanceof TransitionImpl)
                   && ( "condition".equals(tagName)
                        || "timer".equals(tagName)
                      )
                 )
             ) {
            parse.addProblem("unrecognized event listener: "+tagName, null, ProblemImpl.TYPE_WARNING, eventListenerElement);
          }
        }
      }
    }
  }

  public void parseTransitions(Element element, ActivityImpl activity, Parse parse) {
    List<Element> transitionElements = XmlUtil.elements(element, "transition");
    UnresolvedTransitions unresolvedTransitions = parse.contextStackFind(UnresolvedTransitions.class);
    for (Element transitionElement: transitionElements) {
      String transitionName = XmlUtil.attribute(transitionElement, "name", false, parse);

      Element timerElement = XmlUtil.element(transitionElement, "timer");
      if (timerElement!=null) {
        TimerDefinitionImpl timerDefinitionImpl = parseTimerDefinition(timerElement, parse, activity);
        timerDefinitionImpl.setSignalName(transitionName);
      }
 
      TransitionImpl transition = activity.createOutgoingTransition();
      transition.setName(transitionName);
 
      unresolvedTransitions.add(transition, transitionElement);
     
      parseOnEvent(transitionElement, parse, transition, Event.TAKE);
    }
  }

  public void parseAssignmentAttributes(Element element, AssignableDefinitionImpl assignableDefinition, Parse parse) {
    Element descriptionElement = XmlUtil.element(element, "description");
    if (descriptionElement!=null) {
      String description = XmlUtil.getContentText(descriptionElement);
      assignableDefinition.setDescription(description);
    }
 
    Element assignmentHandlerElement = XmlUtil.element(element, "assignment-handler");
    if (assignmentHandlerElement!=null) {
      UserCodeReference assignmentHandlerReference = parseUserCodeReference(assignmentHandlerElement, parse);
      assignableDefinition.setAssignmentHandlerReference(assignmentHandlerReference);
    }
 
    String assigneeExpression = XmlUtil.attribute(element, "assignee");
    assignableDefinition.setAssigneeExpression(assigneeExpression);
   
    String assigneeExpressionLanguage = XmlUtil.attribute(element, "assignee-lang");
    assignableDefinition.setAssigneeExpressionLanguage(assigneeExpressionLanguage);
   
    String candidateUsersExpression = XmlUtil.attribute(element, "candidate-users");
    assignableDefinition.setCandidateUsersExpression(candidateUsersExpression);
   
    String candidateUsersExpressionLanguage = XmlUtil.attribute(element, "candidate-users-lang");
    assignableDefinition.setCandidateUsersExpressionLanguage(candidateUsersExpressionLanguage);
   
    String candidateGroupsExpression = XmlUtil.attribute(element, "candidate-groups");
    assignableDefinition.setCandidateGroupsExpression(candidateGroupsExpression);
   
    String candidateGroupsExpressionLanguage = XmlUtil.attribute(element, "candidate-groups-lang");
    assignableDefinition.setCandidateGroupsExpressionLanguage(candidateGroupsExpressionLanguage);
  }

  public TaskDefinitionImpl parseTaskDefinition(Element element, Parse parse, ScopeElementImpl scopeElement) {
    TaskDefinitionImpl taskDefinition = new TaskDefinitionImpl();
 
    String taskName = XmlUtil.attribute(element, "name");
    taskDefinition.setName(taskName);

    String form = XmlUtil.attribute(element, "form");
    taskDefinition.setFormResourceName(form);
   
    ProcessDefinitionImpl processDefinition = parse.contextStackFind(ProcessDefinitionImpl.class);
    if (processDefinition.getTaskDefinition(taskName)!=null) {
      parse.addProblem("duplicate task name "+taskName, element);
    } else {
      processDefinition.addTaskDefinitionImpl(taskDefinition);
    }

    String swimlaneName = XmlUtil.attribute(element, "swimlane");
    if (swimlaneName!=null) {
      JpdlProcessDefinition jpdlProcessDefinition = parse.contextStackFind(JpdlProcessDefinition.class);
      SwimlaneDefinitionImpl swimlaneDefinition = jpdlProcessDefinition.getSwimlaneDefinition(swimlaneName);
      if (swimlaneDefinition!=null) {
        taskDefinition.setSwimlaneDefinition(swimlaneDefinition);
      } else {
        parse.addProblem("swimlane "+swimlaneName+" not declared", element);
      }
    }
   
    parseAssignmentAttributes(element, taskDefinition, parse);
   
    // parse notification mail producer
    Element notificationElement = XmlUtil.element(element, "notification");
    if (notificationElement != null) {
      parseMailEvent(notificationElement, parse, scopeElement, Event.ASSIGN);
    }

    Element reminderElement = XmlUtil.element(element, "reminder");
    if (reminderElement != null) {
      parseMailEvent(reminderElement, parse, scopeElement, Event.REMIND);
      // associate timer to event
      TimerDefinitionImpl timerDefinition = parseTimerDefinition(reminderElement, parse, scopeElement);
      timerDefinition.setEventName(Event.REMIND);
    }

    return taskDefinition;
  }

  public List<VariableDefinitionImpl> parseVariableDefinitions(Element element, Parse parse, boolean initRequired) {
    List<VariableDefinitionImpl> variableDefinitions = new ArrayList<VariableDefinitionImpl>();
   
    for (Element inElement: XmlUtil.elements(element, "variable")) {
      VariableDefinitionImpl variableDefinition = new VariableDefinitionImpl();

      String name = XmlUtil.attribute(inElement, "name", true, parse);
      variableDefinition.setName(name);
     
      int sources = 0;
     
      String initExpr = XmlUtil.attribute(inElement, "init");
      if (initExpr!=null) {
        variableDefinition.setInitExpression(initExpr);
        sources++;
      }
     
      Element valueElement = XmlUtil.element(inElement);
      if (valueElement!=null) {
        Descriptor initValueDescriptor = (Descriptor) WireParser.getInstance().parseElement(valueElement, parse);
        variableDefinition.setInitDescriptor(initValueDescriptor);
        sources++;
      }

      if (initRequired && sources==0) {
        parse.addProblem("no init specified", inElement);
      }
      if (sources>1) {
        parse.addProblem("init attribute and init element are mutually exclusive on element variable", inElement);
      }
     
      variableDefinitions.add(variableDefinition);
    }

    return variableDefinitions;
  }

  public VariableOutDefinitionSet parseVariableOutDefinitionSet(Element element, Parse parse) {
    VariableOutDefinitionSet variableOutDefinitionSet = new VariableOutDefinitionSet();
   
    for (Element inElement: XmlUtil.elements(element, "out-variable")) {
      VariableOutDefinitionImpl variableOutDefinition = variableOutDefinitionSet.createVariableOutDefinition();

      String name = XmlUtil.attribute(inElement, "name", true, parse);
      variableOutDefinition.setName(name);
     
      String expression = XmlUtil.attribute(inElement, "init");
      if (expression!=null) {
        variableOutDefinition.setExpression(expression);
      }
    }

    return variableOutDefinitionSet;
  }

  public void parseMailEvent(Element element, Parse parse,
      ObservableElementImpl observableElement, String eventName) {
    // obtain assign event
    EventImpl event = observableElement.getEvent(eventName);
    if (event == null) {
      event = observableElement.createEvent(eventName);
    }
    // register event listener
    MailListener eventListener = new MailListener();
    EventListenerReference eventListenerRef = event.createEventListenerReference(eventListener);
    // set continuation mode
    String continuationText = XmlUtil.attribute(element, "continue");
    if ("async".equals(continuationText)) {
      eventListenerRef.setContinuation(Continuation.ASYNCHRONOUS);
    }
    else if ("exclusive".equals(continuationText)) {
      eventListenerRef.setContinuation(Continuation.EXCLUSIVE);
    }

    //https://jira.jboss.org/jira/browse/JBPM-2466
    String mailTemplateName = eventName;
    if (Event.ASSIGN.equals(eventName)) {
      mailTemplateName = "task-notification";
    } else if (Event.REMIND.equals(eventName)) {
      mailTemplateName = "task-reminder";
    }
   
    // associate mail producer to event listener
    MailProducer mailProducer = parseMailProducer(element, parse, mailTemplateName);
    eventListener.setMailProducer(mailProducer);
  }

  public MailProducer parseMailProducer(Element element, Parse parse, String defaultTemplateName) {
    // check whether the element is a generic object descriptor
    if (ObjectBinding.isObjectDescriptor(element)) {
      // TODO test custom mail producer
      ObjectDescriptor objectDescriptor = parseObjectDescriptor(element, parse);
      return (MailProducer) WireContext.create(objectDescriptor);
    }

    // parse the default producer
    MailProducerImpl mailProducer = new MailProducerImpl();
    mailProducer.setTemplate(parseMailTemplate(element, parse, defaultTemplateName));
    return mailProducer;
  }

  private MailTemplate parseMailTemplate(Element element, Parse parse,
      String defaultTemplateName) {
    if (element.hasAttribute("template")) {
      // fetch template from configuration
      return findTemplate(element, parse, element.getAttribute("template"));
    }
    if (!XmlUtil.isTextOnly(element)) {
      // parse inline template
      return MailTemplateBinding.parseMailTemplate(element, parse);
    }
    if (defaultTemplateName != null) {
      // fetch default template
      return findTemplate(element, parse, defaultTemplateName);
    }
    parse.addProblem("mail template must be referenced in the 'template' attribute "
        + "or specified inline", element);
    return null;
  }

  private MailTemplate findTemplate(Element element, Parse parse, String templateName) {
    MailTemplateRegistry templateRegistry = EnvironmentImpl.getFromCurrent(MailTemplateRegistry.class);
    if (templateRegistry != null) {
      MailTemplate template = templateRegistry.getTemplate(templateName);
      if (template != null) return template;
    }
    parse.addProblem("mail template not found: " + templateName, element);
    return null;
  }

  public UserCodeReference parseUserCodeReference(Element element, Parse parse) {
    UserCodeReference userCodeReference = new UserCodeReference();

    ObjectDescriptor objectDescriptor = parseObjectDescriptor(element, parse);
    userCodeReference.setDescriptor(objectDescriptor);
   
    if (objectDescriptor.getExpr()!=null) {
      // expressions are not cached by default
      userCodeReference.setCached(false);
    }

    Boolean isCached = XmlUtil.attributeBoolean(element, "cache", false, parse, null);
    if (isCached!=null) {
      userCodeReference.setCached(isCached.booleanValue());
    }

    return userCodeReference;
  }

  public ObjectDescriptor parseObjectDescriptor(Element element, Parse parse) {
    return (ObjectDescriptor) objectBinding.parse(element, parse, wireParser);
  }

  public Descriptor parseDescriptor(Element element, Parse parse) {
    return (Descriptor) wireParser.parseElement(element, parse);
  }

  public Set<String> getActivityTagNames() {
    return getBindings().getTagNames(CATEGORY_ACTIVITY);
  }
}
TOP

Related Classes of org.jbpm.jpdl.internal.xml.JpdlParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.