Package de.danet.an.workflow.domain

Source Code of de.danet.an.workflow.domain.DefaultProcessDefinition$SAXExtAttrHandler

/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* $Id: DefaultProcessDefinition.java 2942 2009-02-18 23:12:12Z mlipp $
*/

package de.danet.an.workflow.domain;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.io.StringReader;
import java.io.StringWriter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXHandler;
import org.jdom.output.SAXOutputter;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import de.danet.an.util.sax.DelegatingHandler;
import de.danet.an.util.sax.HandlerStack;
import de.danet.an.util.sax.StackedHandler;
import de.danet.an.util.sax.XmlnsUrisPatcher;

import de.danet.an.workflow.util.SAXEventBufferImpl;
import de.danet.an.workflow.util.XPDLUtil;

import de.danet.an.workflow.omgcore.ProcessDataInfo;

import de.danet.an.workflow.api.Application;
import de.danet.an.workflow.api.FormalParameter;
import de.danet.an.workflow.api.ImportException;
import de.danet.an.workflow.api.InvalidIdException;
import de.danet.an.workflow.api.Participant;
import de.danet.an.workflow.api.ProcessDefinition;
import de.danet.an.workflow.api.SAXEventBuffer;

/**
* This class represents a process definitions with
* the root tag ProcessDefinition. It converts the input to the
* respective objects in the process definition database.
*/
public class DefaultProcessDefinition
    implements ProcessDefinition, Serializable {

    /**
     * logger of this class.
     */
    static final org.apache.commons.logging.Log logger
  = org.apache.commons.logging.LogFactory
  .getLog(DefaultProcessDefinition.class);

    private static Properties overridesCache = null;
   
    private final String packagePath = "/{" + XPDLUtil.XPDL_NS + "}Package";
    private final String processPath = packagePath
  + "/{" + XPDLUtil.XPDL_NS + "}WorkflowProcesses"
  + "/{" + XPDLUtil.XPDL_NS + "}WorkflowProcess";
    private final String applRelPath
  = "/{" + XPDLUtil.XPDL_NS + "}Applications"
  + "/{" + XPDLUtil.XPDL_NS + "}Application";
    private final String extAttrRelPath
  = "/{" + XPDLUtil.XPDL_NS + "}ExtendedAttributes"
  + "/{" + XPDLUtil.XPDL_NS + "}ExtendedAttribute";

    /*
     * Implementation hint: this class is used as return value of a
     * remote method call. Therefore care should be taken to keep the
     * amount of data transfered (i.e. the number of non-transient
     * attributes) small. Any information derived from the process
     * description should be cached in transient attributes.
     */

    // name of the workflow process
    private String packageId = null;

    // name of the workflow process
    private String processId = null;

    // name of the workflow process
    private String packageName = null;

    // name of the workflow process
    private String processName = null;

    // the process description as SAX events.
    // this is the primary representation.
    private SAXEventBufferImpl procDef = null;

    // the representation of process header date and package header data
    private transient ProcessHeaderData processHeader = null;

    // the context information of the process
    private transient ProcessDataInfo contextSignature = null;

    /** The result signature cache. */
    private transient ProcessDataInfo resultSignature = null;

    /** The formal parameters of the process. */
    private transient FormalParameter[] formalParams;

    /** The defined applications. */
    private transient Map applications = null;

    /** The defined participants. */
    private transient Map participants = null;

    /** The remove closed process extended attribute. */
    private transient Integer cleanupMode = null;

    /** The audit state change events only extended attribute. */
    private transient Integer auditEventSelection = null;

    /** The audit state change events only extended attribute. */
    private transient Boolean storeAuditEvents = null;

    /**
     * This class defines the elements of package header.
     */
    public static class DefaultPackageHeader
  implements ProcessDefinition.PackageHeaderData, Serializable {
 
  private String xpdlVersion = null;
  private String vendor = null;
  private String created = null;
  private String description = null;
  private String documentation = null;
  private String priorityUnit = null;
  private String costUnit = null;

  /**
   * Version of the process definition specification.
   * @return the version.
   */
  public String xpdlVersion () {
      return xpdlVersion;
  }

  /**
   * Defines the origin of this model definition
   * and contains vendor's name, vendor's product name
   * and product's release number.
   * @return the vendor.
   */
  public String vendor () {
      return vendor;
  }

  /**
   * Creation date of package definition.
   * @return the created time.
   */
  public String created () {
      return created;
  }

  /**
   * Short description of the package definition.
   * @return the description.
   */
  public String description () {
      return description;
  }

  /**
   * Operating system specific path and -filename
   * of help file/description file.
   * @return the documentation.
   */
  public String documentation () {
      return documentation;
  }

  /**
   * Units used in simulation data.
   * @return the priority unit.
   */
  public String priorityUnit () {
      return priorityUnit;
  }
 
  /**
   * Units used in simulation data.
   * @return the cost unit.
   */
  public String costUnit () {
      return costUnit;
  }

  /**
   * A helper class that can be used to initialize this class
   * from SAX events.
   */
  public class SAXInitializer extends StackedHandler {
      /**
       * Receive notification of the end of an element.
       *
       * @param uri the Namespace URI, or the empty string if the
       * element has no Namespace URI or if Namespace processing is not
       * being performed.
       * @param loc the local name (without prefix), or the empty string
       * if Namespace processing is not being performed.
       * @param raw the raw XML 1.0 name (with prefix), or the empty
       * string if raw names are not available.
       * @throws SAXException not thrown.
       */
      public void endElement(String uri, String loc, String raw)
    throws SAXException {
    if (loc.equals ("XPDLVersion")) {
        xpdlVersion = text ();
    } else if (loc.equals ("Vendor")) {
        vendor = text ();
    } else if (loc.equals ("Created")) {
        created = text ();
    } else if (loc.equals ("Description")) {
        description = text ();
    } else if (loc.equals ("Documentation")) {
        documentation = text ();
    } else if (loc.equals ("PriorityUnit")) {
        priorityUnit = text ();
    } else if (loc.equals ("CostUnit")) {
        costUnit = text ();
    }
      }
  }

  /**
   * Return a handler that can be used to initialize an object
   * from SAX events.
   * @return the handler.
   */
  StackedHandler saxInitializer () {
      return new SAXInitializer ();
  }
    }

    /**
     * This class defines the elements of the process header.
     */
    public static class DefaultProcessHeader
  implements ProcessHeaderData, Serializable  {

  private String created = null;
  private String description = null;
  private String priority = null;
  private String limit = null;
  private String validFrom = null;
  private String validTo = null;
  private String timeEstimationWaiting = null;
  private String timeEstimationWorking = null;
  private String timeEstimationDuration = null;
  private String author = null;
  private String codepage = null;
  private String countrykey = null;
  private String publicationStatus = null;
  private List responsibles = null;
  private String version = null;
  private PackageHeaderData packageHeader;

  /**
   * Default constructor.
   */
  public DefaultProcessHeader() {
      packageHeader = new DefaultPackageHeader();
  }

  /**
   * Dreation date of the process definition.
   * @return the created information.
   */
  public String created () {
      return created;
  }

  /**
   * Short description of the process definition.
   * @return the description.
   */
  public String description () {
      return description;
  }

  /**
   * Priority of the process type.
   * @return the priority.
   */
  public String priority () {
      return priority;
  }

  /**
   * Expected duration for time management purposes in units
   * of duration unit (duration unit does not present in this class).
   * @return the limit.
   */
  public String limit () {
      return limit;
  }

  /**
   * Date that the workflow process definition is active from.
   * @return the valid from date.
   */
  public String validFrom () {
      return validFrom;
  }

  /**
   * Date at witch the process definition becomes valid.
   * @return the valid to date.
   */
  public String validTo () {
      return validTo;
  }

  /**
   * Describes the amount of time the performer of the activity
   * needs to perform the task.
   * @return the estimated time.
   */
  public String timeEstimationWaiting () {
      return timeEstimationWaiting;
  }

  /**
   * Describes the amount of time the performer of the activity
   * needs to perform the task.
   * @return the estimated time.
   */
  public String timeEstimationWorking () {
      return timeEstimationWorking;
  }

  /**
   * Describes the amount of time the performer of the activity
   * needs to perform the task.
   * @return the estimated time.
   */
  public String timeEstimationDuration () {
      return timeEstimationDuration;
  }

  /**
   * Name of the author of this workflow process definition.
   * @return the author.
   */
  public String author () {
      return author;
  }

  /**
   * Describes the version of this workflow process definition.
   * @return the version.
   */
  public String version() {
      return version;
  }

  /**
   * Describes the codepage used for the text parts.
   * @return the codepage.
   */
  public String codepage() {
      return codepage;
  }
 
  /**
   * Describes the country code based on ISO 3166. It could
   * be either the three digits country code number, or the
   * two alpha characters country codes.
   * @return the country code.
   */
  public String countrykey() {
      return countrykey;
  }

  /**
   * Describes the status of the Workflow Process Definition.
   * @return the status.
   */
  public String publicationStatus() {
      return publicationStatus;
  }

  /**
   * Describes the responsible Workflow participant(s). It is assumed
   * that the responsible is the supervisor during the execution
   * of the process.
   * @return the list of responsible Workflow participant in String.
   */
  public List responsibles() {
      return responsibles;
  }

  /**
   * The elements of package header.
   * @return the package header.
   */
  public PackageHeaderData packageHeader () {
      return packageHeader;
  }

  /**
   * A helper class that can be used to initialize this class
   * from SAX events.
   */
  public class SAXInitializer extends StackedHandler {
      /**
       * Receive notification of the beginning of an element.
       *
       * @param uri the Namespace URI, or the empty string if the
       * element has no Namespace URI or if Namespace processing is not
       * being performed.
       * @param loc the local name (without prefix), or the empty string
       * if Namespace processing is not being performed.
       * @param raw the raw XML 1.0 name (with prefix), or the empty
       * string if raw names are not available.
       * @param a the attributes attached to the element. If there are
       * no attributes, it shall be an empty Attributes object.
       * @throws SAXException not thrown.
       */
      public void startElement
    (String uri, String loc, String raw, Attributes a)
    throws SAXException {
    if (loc.equals ("RedefinableHeader")) {
        publicationStatus = a.getValue("PublicationStatus");
    } else if (loc.equals ("Responsibles")) {
        responsibles = new ArrayList();
    }
      }
      /**
       * Receive notification of the end of an element.
       *
       * @param uri the Namespace URI, or the empty string if the
       * element has no Namespace URI or if Namespace processing is not
       * being performed.
       * @param loc the local name (without prefix), or the empty string
       * if Namespace processing is not being performed.
       * @param raw the raw XML 1.0 name (with prefix), or the empty
       * string if raw names are not available.
       * @throws SAXException not thrown.
       */
      public void endElement(String uri, String loc, String raw)
    throws SAXException {
    if (loc.equals ("Created")) {
        created = text ();
    } else if (loc.equals ("Description")) {
        description = text ();
    } else if (loc.equals ("Priority")) {
        priority = text ();
    } else if (loc.equals ("Limit")) {
        limit = text ();
    } else if (loc.equals ("ValidFrom")) {
        validFrom = text ();
    } else if (loc.equals ("ValidTo")) {
        validTo = text ();
    } else if (loc.equals ("WaitingTime")) {
        timeEstimationWaiting = text ();
    } else if (loc.equals ("WorkingTime")) {
        timeEstimationWorking = text ();
    } else if (loc.equals ("Duration")) {
        timeEstimationDuration = text ();
    } else if (loc.equals ("Author")) {
        author = text ();
    } else if (loc.equals ("Version")) {
        version = text ();
    } else if (loc.equals ("Codepage")) {
        codepage = text ();
    } else if (loc.equals ("Countrykey")) {
        countrykey = text ();
    } else if (loc.equals ("Responsible")) {
        responsibles.add(text());
    }
      }
  }

  /**
   * Return a handler that can be used to initialize an object
   * from SAX events.
   * @return the handler.
   */
  StackedHandler saxInitializer () {
      return new SAXInitializer ();
  }
    }
   
    /**
     * Construct a new <code>DefaultProcessDefinition</code> from a
     * JDOM document.
     *
     * @param processDefinition parsed process definition
     * as <code>Document</code>.
     * @throws JDOMException If an error occurs.
     * @throws ImportException if the XPDL is not correct.
     */
    public DefaultProcessDefinition (Document processDefinition)
  throws JDOMException, ImportException {
  try {
      SAXOutputter outputter = new SAXOutputter();
      procDef = new SAXEventBufferImpl ();
      outputter.setContentHandler(procDef);
      outputter.setLexicalHandler(procDef);
      outputter.output (processDefinition);
  } catch (JDOMException e) {
      String s = "Cannot get XPDL from DOM: " + e.getMessage();
      logger.error (s, e);
      throw new IllegalArgumentException (s);
  }
  init ();
    }

    /**
     * Construct a new <code>DefaultProcessDefinition</code> from an
     * XPDL Document.<P>
     *
     * This constructor assumes that XPDL has been verified before, i.e.
     * it parses the process definition with verification turned off.
     *
     * @param xpdl String representation of the process definition
     * @throws IOException If an error occurs.
     * @throws ImportException if the XPDL is not correct.
     */
    public DefaultProcessDefinition (String xpdl)
  throws IOException, ImportException {
  try {
      SAXParserFactory pf = SAXParserFactory.newInstance();
      pf.setValidating (false);
      pf.setNamespaceAware (true);
      pf.setFeature
    ("http://xml.org/sax/features/namespace-prefixes", true);
      XMLReader reader = null;
      try {
    pf.setFeature
        ("http://xml.org/sax/features/xmlns-uris", true);
    SAXParser parser = pf.newSAXParser();
    reader = parser.getXMLReader();
      } catch (SAXException e) {
    SAXParser parser = pf.newSAXParser();
    reader = new XmlnsUrisPatcher (parser.getXMLReader());
      }
      procDef = new SAXEventBufferImpl ();
      reader.setContentHandler(procDef);
      // Parse the file
      InputSource inSrc = new InputSource(new StringReader(xpdl));
      reader.parse (inSrc);
      init ();
  } catch (SAXException e) {
      String s = "Cannot read XPDL: " + e.getMessage();
      logger.error (s, e);
      throw new IOException (s);
  } catch (ParserConfigurationException e) {
      String s = "Cannot read XPDL: " + e.getMessage();
      logger.fatal (s, e);
      throw new IllegalStateException (s);
  }
    }

    private void writeObject(ObjectOutputStream oos)
        throws IOException {
        oos.defaultWriteObject();
        // OverridesCache cannot be initialized on client side
        oos.writeObject(overridesCache);
    }

    private void readObject (ObjectInputStream stream)
  throws IOException, ClassNotFoundException {
  stream.defaultReadObject();
  overridesCache = (Properties)stream.readObject();
  init ();
    }

    private Properties overrides() {
        synchronized (DefaultProcessDefinition.class) {
            if (overridesCache == null) {
                overridesCache = new Properties();
                InputStream is = Thread.currentThread()
                    .getContextClassLoader().getResourceAsStream
                        ("de.danet.an.workflow.ToolAgentOverrides.properties");
                if (is != null) {
                    try {
                        overridesCache.load(is);
                    } catch (IOException e) {
                        logger.error("Problem reading de.danet.an.workflow."
                                     + "ToolAgentOverrides.properties: "
                                     + e.getMessage(), e);
                    }
                }
            }
        }
        return overridesCache;
    }
   
    private class MyDelegatingHandler extends DelegatingHandler {
  private ApplicationDefinition applDef = null;
  // Add some "on the fly" handling
  public void startElement
      (String uri, String loc, String raw, Attributes a)
      throws SAXException {
      super.startElement (uri, loc, raw, a);
      String curPath = currentPath ();
      if (curPath.equals (packagePath)) {
    packageId = a.getValue("Id");
    packageName = a.getValue("Name");
      } else if (curPath.equals (processPath)) {
    processId = a.getValue("Id");
    processName = a.getValue("Name");
      } else if (curPath.equals (packagePath + applRelPath)
           || (curPath.equals (processPath + applRelPath))) {
    applDef = new ApplicationDefinition ();
    getStack().push (applDef.saxInitializer());
      }
  }

  public void endElement (String uri, String loc, String raw)
      throws SAXException {
      if (applDef != null) {
    applications.put (applDef.id(), applDef);
    applDef = null;
      } else if (uri.equals (XPDLUtil.XPDL_NS)
           && loc.equals ("Participant")) {
    Participant p = (Participant)
        getStack().removeContextData ("Participant");
    participants.put (p.getId(), p);
      }
  }
    }

    /**
     * Initialize this <code>DefaultProcessDefinition</code> from the
     * SAX events.
     */
    private void init () {
  formalParams = new FormalParameter[0];

  final String dfRelPath = "/{" + XPDLUtil.XPDL_NS + "}DataFields";
  final String partiRelPath
      = "/{" + XPDLUtil.XPDL_NS + "}Participants"
      + "/{" + XPDLUtil.XPDL_NS + "}Participant";
  try {
      DelegatingHandler dh = new MyDelegatingHandler ();
      processHeader = new DefaultProcessHeader();
      dh.addHandler
    (packagePath + "/{" + XPDLUtil.XPDL_NS + "}PackageHeader",
     ((DefaultPackageHeader)processHeader.packageHeader())
     .saxInitializer());
      dh.addHandler
    (processPath + "/{" + XPDLUtil.XPDL_NS + "}ProcessHeader",
     ((DefaultProcessHeader)processHeader).saxInitializer());
      dh.addHandler
    (packagePath + "/{" + XPDLUtil.XPDL_NS + "}RedefinableHeader",
     ((DefaultProcessHeader)processHeader).saxInitializer());
      dh.addHandler
    (processPath + "/{" + XPDLUtil.XPDL_NS + "}RedefinableHeader",
     ((DefaultProcessHeader)processHeader).saxInitializer());
      StackedHandler dfh = new SAXDataFieldHandler ();
      contextSignature = new DefaultProcessDataInfo();
      dh.addHandler (packagePath + dfRelPath, dfh);
      dh.addHandler (processPath + dfRelPath, dfh);
      resultSignature = new DefaultProcessDataInfo();
      dh.addHandler
    (processPath + "/{" + XPDLUtil.XPDL_NS + "}FormalParameters",
     new SAXFormalParameterHandler ());
      participants = new HashMap();
      dh.addHandler (packagePath + partiRelPath,
         DefaultParticipant.SAXInitializer.class);
      dh.addHandler (processPath + partiRelPath,
         DefaultParticipant.SAXInitializer.class);
      StackedHandler extAttrHandler = new SAXExtAttrHandler ();
      dh.addHandler (packagePath + extAttrRelPath, extAttrHandler);
      dh.addHandler (processPath + extAttrRelPath, extAttrHandler);
      applications = new HashMap ();
      HandlerStack hs = new HandlerStack (dh);
      procDef.emit(hs.contentHandler(), null);
      for (Iterator i = applications().iterator(); i.hasNext();) {
          ApplicationDefinition applDef
              = (ApplicationDefinition)i.next();
                postfixApplicationDefinition(applDef);
      }
  } catch (SAXException e) {
      String s = "Cannot initialize: " + e.getMessage ();
      logger.error (s, e);
      throw new IllegalStateException (s);
  }
    }

    /**
     * @param applDef
     */
    private void postfixApplicationDefinition(ApplicationDefinition applDef) {
        if (applDef.handler() == null) {
            String fallbackHandler = null;
            String classForHandler = null;
            String fallbacks = overrides()
                .getProperty("(Class)" + applDef.agentClassName());
            if (fallbacks != null) {
                String[] vals = fallbacks.split("#");
                fallbackHandler = vals[0];
                if (vals.length > 1) {
                    classForHandler = vals[1];
                }
            } else {
                String appPkgPrefix = packageId + "." + applDef.id();
                String appProcPrefix
                    = packageId + "." + processId + "." + applDef.id();
                fallbackHandler = overrides().getProperty
                    (appProcPrefix + ".FallbackHandler");
                classForHandler = overrides().getProperty
                    (appProcPrefix + ".ClassForFallbackHandler");
                if (fallbackHandler == null) {
                    fallbackHandler = overrides().getProperty
                        (appPkgPrefix + ".FallbackHandler");
                    classForHandler = overrides().getProperty
                        (appPkgPrefix + ".ClassForFallbackHandler");
                }
            }
            if (fallbackHandler != null) {
                if (logger.isDebugEnabled()) {
                    logger.debug ("Adding handler "
                                  + fallbackHandler + " in " + applDef);
                }
                applDef.updateHandler(fallbackHandler);
                if (classForHandler != null) {
                    if (logger.isDebugEnabled()) {
                        logger.debug ("Replacing agent class with "
                                      + classForHandler + " in " + applDef);
                    }
                    applDef.updateAgentClassName(classForHandler);
                }
            }
        }
    }

    /**
     * Helper class for retrieving the context info from the process
     * definition.
     */
    public class SAXDataFieldHandler extends StackedHandler {

  private String dfId = null;

  /**
   * Receive notification of the beginning of an element.
   *
   * @param uri the Namespace URI, or the empty string if the
   * element has no Namespace URI or if Namespace processing is not
   * being performed.
   * @param loc the local name (without prefix), or the empty string
   * if Namespace processing is not being performed.
   * @param raw the raw XML 1.0 name (with prefix), or the empty
   * string if raw names are not available.
   * @param a the attributes attached to the element. If there are
   * no attributes, it shall be an empty Attributes object.
   * @throws SAXException not thrown.
   */
  public void startElement
      (String uri, String loc, String raw, Attributes a)
      throws SAXException {
      if (loc.equals ("DataField")) {
    dfId = a.getValue("Id");
      } else if (loc.equals ("DataType")) {
    getStack().push (new XPDLUtil.SAXDataTypeHandler());
      }
  }

  /**
   * Receive notification of the end of an element.
   *
   * @param uri the Namespace URI, or the empty string if the
   * element has no Namespace URI or if Namespace processing is not
   * being performed.
   * @param loc the local name (without prefix), or the empty string
   * if Namespace processing is not being performed.
   * @param raw the raw XML 1.0 name (with prefix), or the empty
   * string if raw names are not available.
   * @throws SAXException not thrown.
   */
  public void endElement(String uri, String loc, String raw)
      throws SAXException {
      if (loc.equals ("DataField")) {
    Object dtc = removeContextData ("DataType");
    if (dtc == null) {
        logger.error ("Unknown data type in data field with id = \""
          + dfId + "\".");
        return;
    }
    contextSignature.put (dfId, dtc);
      }
  }
    }

    /**
     * Helper class for retrieving the formal parameter info from the process
     * definition.
     */
    public class SAXFormalParameterHandler extends StackedHandler {

  private String fpId = null;
  private int fpIdx = 0;
  private FormalParameter.Mode fpMode = null;
  private List fps = null;

  /**
   * Receive notification of the beginning of an element.
   *
   * @param uri the Namespace URI, or the empty string if the
   * element has no Namespace URI or if Namespace processing is not
   * being performed.
   * @param loc the local name (without prefix), or the empty string
   * if Namespace processing is not being performed.
   * @param raw the raw XML 1.0 name (with prefix), or the empty
   * string if raw names are not available.
   * @param a the attributes attached to the element. If there are
   * no attributes, it shall be an empty Attributes object.
   * @throws SAXException not thrown.
   */
  public void startElement
      (String uri, String loc, String raw, Attributes a)
      throws SAXException {
      if (loc.equals ("FormalParameters")) {
    fps = new ArrayList ();
      } else if (loc.equals ("FormalParameter")) {
    fpId = a.getValue("Id");
    fpMode = FormalParameter.Mode.fromString(a.getValue("Mode"));
      } else if (loc.equals ("DataType")) {
    getStack().push (new XPDLUtil.SAXDataTypeHandler());
      }
  }

  /**
   * Receive notification of the end of an element.
   *
   * @param uri the Namespace URI, or the empty string if the
   * element has no Namespace URI or if Namespace processing is not
   * being performed.
   * @param loc the local name (without prefix), or the empty string
   * if Namespace processing is not being performed.
   * @param raw the raw XML 1.0 name (with prefix), or the empty
   * string if raw names are not available.
   * @throws SAXException not thrown.
   */
  public void endElement(String uri, String loc, String raw)
      throws SAXException {
      if (loc.equals ("FormalParameter")) {
    Object dtc = removeContextData ("DataType");
    if (dtc == null) {
        logger.error ("Unknown data type in formal parameter "
          + "with id = \"" + fpId + "\".");
        return;
    }
    if (fpMode != FormalParameter.Mode.IN) {
        resultSignature.put (fpId, dtc);
    }
    contextSignature.put (fpId, dtc);
    fps.add (new FormalParameter
       (fpId, Integer.toString(fpIdx++), fpMode, dtc));
      } else if (loc.equals ("FormalParameters")) {
    formalParams = (FormalParameter[])
        fps.toArray(new FormalParameter[fps.size()]);
      }
  }
    }

    /**
     * Helper class for retrieving extended attributes from the process
     * definition.
     */
    public class SAXExtAttrHandler extends StackedHandler {

  private String waitingFor = null;
  private String valueAttr = null;

  /**
   * Receive notification of the beginning of an element.
   *
   * @param uri the Namespace URI, or the empty string if the
   * element has no Namespace URI or if Namespace processing is not
   * being performed.
   * @param loc the local name (without prefix), or the empty string
   * if Namespace processing is not being performed.
   * @param raw the raw XML 1.0 name (with prefix), or the empty
   * string if raw names are not available.
   * @param a the attributes attached to the element. If there are
   * no attributes, it shall be an empty Attributes object.
   * @throws SAXException not thrown.
   */
  public void startElement
      (String uri, String loc, String raw, Attributes a)
      throws SAXException {
      waitingFor = a.getValue ("Name");
      if (waitingFor == null) {
    waitingFor = "(unknown)";
      }
      valueAttr = a.getValue ("Value");
  }

  /**
   * Receive notification of the end of an element.
   *
   * @param uri the Namespace URI, or the empty string if the
   * element has no Namespace URI or if Namespace processing is not
   * being performed.
   * @param loc the local name (without prefix), or the empty string
   * if Namespace processing is not being performed.
   * @param raw the raw XML 1.0 name (with prefix), or the empty
   * string if raw names are not available.
   * @throws SAXException not thrown.
   */
  public void endElement(String uri, String loc, String raw)
      throws SAXException {
      if (waitingFor.equals ("RemoveClosedProcess")) {
    // note that for extended attributes process level values
    // preceed package level settings.
    if (cleanupMode != null) {
        return;
    }
    if (valueAttr == null) {
        valueAttr = getStack().text().trim();
    }
    cleanupMode = new Integer(REMOVE_AUTOMATIC);
    if (valueAttr.equals("MANUAL")) {
        cleanupMode = new Integer(REMOVE_MANUAL);
    } else if (valueAttr.equals("COMPLETED")) {
        cleanupMode = new Integer(REMOVE_COMPLETED);
    }
    return;
      }
      if (waitingFor.equals ("AuditEventSelection")) {
    // note that for extended attributes process level values
    // preceed package level settings.
    if (auditEventSelection != null) {
        return;
    }
    if (valueAttr == null) {
        valueAttr = getStack().text().trim();
    }
    if (valueAttr.equals ("AllEvents")) {
        auditEventSelection = new Integer
      (ProcessDefinition.AUDIT_SELECTION_ALL_EVENTS);
    }
    if (valueAttr.equals ("StateEventsOnly")) {
        auditEventSelection = new Integer
      (ProcessDefinition.AUDIT_SELECTION_STATE_EVENTS_ONLY);
    }
    if (valueAttr.equals ("ProcessClosedEventsOnly")) {
        auditEventSelection = new Integer
      (ProcessDefinition
       .AUDIT_SELECTION_PROCESS_CLOSED_EVENTS_ONLY);
    }
    if (valueAttr.equals ("NoEvents")) {
        auditEventSelection = new Integer
      (ProcessDefinition.AUDIT_SELECTION_NO_EVENTS);
    }
    return;
      }
      if (waitingFor.equals ("StoreAuditEvents")) {
    // note that for extended attributes process level values
    // preceed package level settings.
    if (storeAuditEvents != null) {
        return;
    }
    if (valueAttr == null) {
        valueAttr = getStack().text().trim();
    }
    storeAuditEvents
        = new Boolean (valueAttr.equalsIgnoreCase("true"));
    return;
      }
  }
    }

    /**
     * Return the id of the package.
     * @return id of the package in String.
     */
    public String packageId() {
  return packageId;
    }
   
    /**
     * Return the id of the process.
     * @return id of the process in String.
     */
    public String processId() {
  return processId;
    }
   
    /**
     * Return the name of the package.
     * @return name of the package in String.
     */
    public String packageName() {
  return packageName;
    }
   
    /**
     * Return the name of the process.
     * @return name of the process in String.
     */
    public String processName() {
  return processName;
    }
   
    /**
     * Return the name of the process manager.
     * @return name of the process manager as String.
     */
    public String mgrName() {
  return packageId + "/" + processId;
    }

    /**
     * Return the version of the process manager.
     * @return version of the process manager as String.
     */
    public String version() {
  return processHeader().version();
    }

    /**
     * Returns the meta information that describes the context for
     * this kind of process. Equivalent to calling {@link
     * de.danet.an.workflow.localcoreapi.WfProcessMgrLocal#contextSignature
     * <code>contextSignature</code>} on a process manager for this
     * kind of process.
     * @return the process meta information.
     * @see de.danet.an.workflow.localcoreapi.WfProcessMgrLocal#contextSignature
     */
    public ProcessDataInfo contextSignature() {
  return contextSignature;
    }

    /**
     * Returns the meta information that describes the result for this
     * kind of process. Equivalent to calling {@link
     * de.danet.an.workflow.localcoreapi.WfProcessMgrLocal#resultSignature
     * <code>resultSignature</code>} on a process manager for this
     * kind of process.<P>
     *
     * The implementation returns all formal IN or INOUT parameters.
     *
     * @return the process meta information.
     * @see de.danet.an.workflow.localcoreapi.WfProcessMgrLocal#resultSignature
     */
    public ProcessDataInfo resultSignature() {
  return resultSignature;
    }

    /**
     * Returns the meta information that describes the formal parameters
     * for this kind of process.
     * @return the process meta information.
     */
    public FormalParameter[] formalParameters() {
  return formalParams;
    }

    /**
     * Return the process definition as SAX event buffer.
     * @return the process definition
     */
    public SAXEventBuffer toSAX () {
  return procDef;
    }

    /**
     * Use XMLOutputter to transfer process definition presented as JDOM Tree
     * in String.
     * @return the process definition in String.
     */
    public String toXPDL() {
  try {
      TransformerFactory tf = TransformerFactory.newInstance();
      if (!tf.getFeature(SAXTransformerFactory.FEATURE)) {
    String s = "JAXP transformer factory does not support"
        + " a SAX transformer!";
    logger.fatal (s);
    throw new IllegalStateException (s);
      }
      TransformerHandler th
    = ((SAXTransformerFactory)tf).newTransformerHandler ();
      StringWriter out = new StringWriter ();
      th.setResult (new StreamResult(out));
      procDef.emit(th, th);
      return out.toString();
  } catch (SAXException e) {
      String s = "Error generating XPDL as string: " + e.getMessage ();
      logger.error (s, e);
      throw new IllegalStateException (s);
  } catch (TransformerConfigurationException e) {
      String s = "Error generating XPDL as string: " + e.getMessage ();
      logger.error (s, e);
      throw new IllegalStateException (s);
  }
    }
 
    /**
     * Return the process definition presented as JDOM document.
     *
     * @return the process definition presented as JDOM document.
     */
    public Document toJDOM () {
  try {
      SAXHandler sh = new SAXHandler ();
      procDef.emit(sh, sh);
      return sh.getDocument();
  } catch (SAXException e) {
      logger.error (e.getMessage(), e);
      throw new IllegalStateException
    ("Error generating XPDL as JDOM: " + e.getMessage());
  }
    }
   
    /** Return the process header data of this process definition.
     *
     * @return the process header data of this process definition.
     */
    public ProcessHeaderData processHeader() {
  return processHeader;
    }
   
    /**
     * Extracts all the applications definition in the package and
     * in this process and use it to generate a collection of
     * <code>ApplicationDefinition</code>.
     * @return a collection of <code>ApplicationDefinition</code>.
     */
    public Collection applications() {
  return applications.values();
    }

    /**
     * Find out the dedicated application using the given id.
     * @param id the given id of the application to be found.
     * @throws InvalidIdException If no such application be found
     * @return the dedicated application.
     */
    public Application applicationById (String id) throws InvalidIdException {
  Application a = (Application)applications.get (id);
  if (a == null) {
      throw new InvalidIdException ("No application with Id = " + id);
  }
  return a;
    }

    /**
     * Gets the participants for this process.
     * @return a collection of {@link Participant
     * <code>Participant</code>s} for this process.
     */
    public Collection participants() {
  return participants.values();
    }

    /**
     * Return the participant identified by the id.
     * @param id identity of the participant in string
     * @return a Participant object
     * @throws InvalidIdException if no participant with the given id exists.
     */   
    public Participant participantById(String id) throws InvalidIdException {
  Participant p = (Participant)participants.get (id);
  if (p == null) {
      throw new InvalidIdException ("No participant with Id = " + id);
  }
  return p;
    }

    /**
     * This method checks if the closed process should be removed. Parse the
     * process definition and find out if the extendAttribute with the name of
     * RemoveClosedProcess has the value of MANUAL, then return false; if it
     * has the value of AUTOMATIC, then return true. Default is true.
     * @return true if the closed process should be removed, otherwise false.
     */   
    public boolean removeClosedProcess() {
  return cleanupMode() == REMOVE_AUTOMATIC;
    }

    /**
     * This method checks if a closed process should be removed. Parse the
     * process definition and find out if the extendAttribute with the name of
     * RemoveClosedProcess has the value of <code>MANUAL</code>,
     * <code>AUTOMATIC</code> or <code>COMPLETED</code> and return the
     * corresponding constant. Default is to remove automatically, i.e.
     * {@link #REMOVE_AUTOMATIC <code>REMOVE_AUTOMATIC</code>}.
     * @return the cleanup mode.
     */   
    public int cleanupMode() {
        return cleanupMode == null ? REMOVE_AUTOMATIC
               : cleanupMode.intValue();
    }
   
    /**
     * This method the audit event filter for instances of this
     * process definition.
     * @return the audit event filter in effect.
     */   
    public int auditEventSelection() {
  return (auditEventSelection == null)
      ? ProcessDefinition.AUDIT_SELECTION_ALL_EVENTS
      : auditEventSelection.intValue();
    }

    /**
     * This method reports if audit events are written to the
     * database.
     * @return <code>true</code> if only state change events of the
     * process instance are audited.
     */
    public boolean storeAuditEvents() {
  return (storeAuditEvents == null)
      || storeAuditEvents.booleanValue ();
    }

    //
    // Additional methods provided by the domain class.
    //

   

    //
    // Some private helpers.
    //
   
    /**
     * Retrieves the value for the attribute "Id" of this element.
     * @return the value for the attribute or <code>null</code>, if
     * the attribute does not exist.
     * @param el element
     */
    private String getAttributeValue(Element el, String at) {
  return el != null ? el.getAttributeValue(at): null;
    }
}
TOP

Related Classes of de.danet.an.workflow.domain.DefaultProcessDefinition$SAXExtAttrHandler

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.