Package org.jbpm.pvm.impl

Source Code of org.jbpm.pvm.impl.NodeImpl

/*
* 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.pvm.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jbpm.PvmException;
import org.jbpm.pvm.Activity;
import org.jbpm.pvm.Node;
import org.jbpm.pvm.Transition;
import org.jbpm.wire.Descriptor;

/**
* @author Tom Baeyens
*/
public class NodeImpl extends CompositeElementImpl implements Node {

  private static final long serialVersionUID = 1L;
   
  protected ObjectReference<Activity> behaviourReference;
  protected List<TransitionImpl> outgoingTransitions;
  protected List<TransitionImpl> incomingTransitions;
  protected TransitionImpl defaultTransition;
  protected NodeImpl parentNode;
  protected boolean isExecutionAsync;
  protected boolean isSignalAsync;
  protected boolean isLeaveAsync;
  protected boolean isPreviousNeeded;
 
  transient protected Map<String, TransitionImpl> outgoingTransitionsMap;

  /**
   * Use {@link ProcessDefinitionImpl#createNode()} or {@link NodeImpl#createNode()} instead.
   */
  public NodeImpl() {
    super();
  }
 
  // specialized node containment methods /////////////////////////////////////
 
  public NodeImpl addNode(NodeImpl node) {
    node.setParentNode(this);
    super.addNode(node);
    return node;
  }
 
  public Node findNode(String nodeName) {
    if (nodeName==null) {
      if (name==null) {
        return this;
      }
    } else if (nodeName.equals(name)) {
      return this;
    }
    return super.findNode(nodeName);
  }

  // leaving transitions //////////////////////////////////////////////////////

  /**
   * creates a transition from this node to the given
   * destination node. Also the transition pointers to source and destination
   * node will be set appropriatly.
   * @throws NullPointerException if destination is null.
   */
  public Transition createOutgoingTransition(NodeImpl destination) {
    return createOutgoingTransition(destination, null);
  }

  /**
   * creates a transition with the given name from this node to the given
   * destination node. Also the transition pointers to source and destination
   * node will be set appropriatly.
   * @param transitionName may be null.
   * @throws NullPointerException if destination is null.
   */
  public TransitionImpl createOutgoingTransition(NodeImpl destination, String transitionName) {
    // create a new transition
    TransitionImpl transition = new TransitionImpl();
    transition.setName(transitionName);
   
    // wire it between the source and destination
    addOutgoingTransition(transition);
    if (destination!=null) {
      destination.addIncomingTransition(transition);
    }

    // if there is no default transition yet
    if (defaultTransition==null) {
      // make this the default outgoing transition
      defaultTransition = transition;
    }
   
    return transition;
  }

  /**
   * adds the given transition as a leaving transition to this node.
   * Also the source of the transition is set to this node.
   * Adding a transition that is already contained in the leaving
   * transitions has no effect.
   * @return the added transition.
   * @throws NullPointerException if transition is null.
   */
  public Transition addOutgoingTransition(TransitionImpl transition) {
    transition.setSource(this);
   
    if (outgoingTransitions==null) {
      outgoingTransitions = new ArrayList<TransitionImpl>();
    }
    if (! outgoingTransitions.contains(transition)) {
      outgoingTransitions.add(transition);
    }
    outgoingTransitionsMap = null;
    return transition;
  }
 
  /**
   * removes the given transition from the leaving transitions.
   * Also the transition's source will be nulled.
   * This method will do nothing if the transition is null or if
   * the given transition is not in the list of this node's leaving
   * transitions.
   * In case this is the transition that was in the
   * outgoingTransitionsMap and another transition exists with the same
   * name, that transition (the first) will be put in the
   * outgoingTransitionsMap as a replacement for the removed transition.
   * If the transition is actually removed from the list of
   * leaving transitions, the transition's source will be nulled.
   */
  public boolean removeOutgoingTransition(TransitionImpl transition) {
    if ( (transition!=null)
         && (outgoingTransitions!=null)
       ) {
      boolean isRemoved = outgoingTransitions.remove(transition);
      if (isRemoved) {
        transition.setSource(null);
        if (outgoingTransitions.isEmpty()) {
          outgoingTransitions = null;
        }
        outgoingTransitionsMap = null;
      }
      return isRemoved;
    }
    return false;
  }

  /** the first leaving transition with the given name or null of no
   * such leaving transition exists.
   */
  public TransitionImpl getOutgoingTransition(String transitionName) {
    return (getOutgoingTransitionsMap()!=null ? outgoingTransitionsMap.get(transitionName) : null);
  }
 
  /** searches for the given transitionName in this node and then up the
   * parent chain. Returns null if no such transition is found. */
  public TransitionImpl findOutgoingTransition(String transitionName) {
    TransitionImpl transition = getOutgoingTransition(transitionName);
    if (transition!=null) {
      return transition;
    }
    if (parentNode!=null) {
      return parentNode.findOutgoingTransition(transitionName);
    }
    return null;
  }
 
  /** searches for the default transition in this node and then up the
   * parent chain. Returns null if no such transition is found. */
  public TransitionImpl findDefaultTransition() {
    if (defaultTransition!=null) {
      return defaultTransition;
    }
    if (parentNode!=null) {
      return parentNode.findDefaultTransition();
    }
    return null;
  }

 
  /** the list of leaving transitions.
   * Beware: the actual member is returned.  No copy is made.
   */
  public List<Transition> getOutgoingTransitions() {
    return (List) outgoingTransitions;
  }

  /** indicates if a leaving transition with the given transitionName exists. */
  public boolean hasOutgoingTransition(String transitionName) {
    return (getOutgoingTransition(transitionName)!=null);
  }

  /** indicates if this node has leaving transitions */
  public boolean hasOutgoingTransitions() {
    return ((outgoingTransitions!=null) && (!outgoingTransitions.isEmpty()));
  }

  /** sets the outgoingTransitions to the given list of outgoingTransitions.
   * A copy of the collection is made.  Also the outgoingTransitionsMap will
   * be updated and the source of all the transitions in the given list will
   * be set to this node.
   * In case there was a leaving transitions list present, these transition's
   * source will be nulled.
   */
  public void setOutgoingTransitions(List<TransitionImpl> outgoingTransitions) {
    if (this.outgoingTransitions!=null) {
      for (TransitionImpl removedTransition: this.outgoingTransitions) {
        removedTransition.setSource(null);
      }
    }
    if (outgoingTransitions!=null) {
      this.outgoingTransitions = new ArrayList<TransitionImpl>(outgoingTransitions);
      for (TransitionImpl addedTransition: outgoingTransitions) {
        addedTransition.setSource(this);
      }
    } else {
      this.outgoingTransitions = null;
    }
    this.outgoingTransitionsMap = null;
  }

  /** the leaving transitions, keyed by transition name.  If a transition with
   * the same name occurs mutltiple times, the first one is returned.
   * Leaving transitions with a null value for their name are not included
   * in the map.
   * Beware: the actual member is returned.  No copy is made.
   */
  public Map<String, Transition> getOutgoingTransitionsMap() {
    if(outgoingTransitionsMap == null){
      this.outgoingTransitionsMap = getTransitionsMap(outgoingTransitions);
    }
    return (Map) outgoingTransitionsMap;
  }

  // arriving transitions /////////////////////////////////////////////////////
 
  /**
   * adds the given transition as an arriving transition to this node.
   * Also the source of the transition is set to this node.
   * @return the added transition.
   * @throws NullPointerException if transition is null.
   */
  public Transition addIncomingTransition(TransitionImpl transition) {
    transition.setDestination(this);
    if (incomingTransitions==null) {
      incomingTransitions = new ArrayList<TransitionImpl>();
    }
    incomingTransitions.add(transition);
    return transition;
  }

  /** removes the given transition if it is contained in the arriving
   * transitions of this node.  If this transition was actually removed,
   * its destination pointer is nulled.
   * @return true if a transition was removed.
   */
  public boolean removeIncomingTransition(TransitionImpl transition) {
    if ( (transition!=null)
         && (incomingTransitions!=null)
         && (incomingTransitions.remove(transition))
       ) {
      transition.setDestination(null);
      if (incomingTransitions.isEmpty()) {
        incomingTransitions = null;
      }
      return true;
    }
    return false;
  }

  /** the list of arriving transitions.
   * Beware: the actual member is returned.  No copy is made.
   */
  public List<Transition> getIncomingTransitions() {
    return (List) incomingTransitions;
  }

  /** indicates if this node has arriving transitions */
  public boolean hasIncomingTransitions() {
    return ((incomingTransitions!=null) && (!incomingTransitions.isEmpty()));
  }


  /** sets the incomingTransitions to the given list of incomingTransitions.
   * A copy of the collection is made.  Also the destination of all the transitions
   * in the given list will be set to this node.
   * In case there was an arriving transitions list present, these transition's
   * destination will be nulled.
   */
  public void setIncomingTransitions(List<TransitionImpl> incomingTransitions) {
    if (this.incomingTransitions!=null) {
      for (TransitionImpl removedTransition: this.incomingTransitions) {
        removedTransition.setDestination(null);
      }
    }
    if (incomingTransitions!=null) {
      this.incomingTransitions = new ArrayList<TransitionImpl>(incomingTransitions);
      for (TransitionImpl addedTransition: incomingTransitions) {
        addedTransition.setDestination(this);
      }
    } else {
      this.incomingTransitions = null;
    }
  }


  // behaviour ////////////////////////////////////////////////////////////////

  /** sets the given activity as the behaviour for this node.
   * An object reference for the given activity is created. */
  public void setBehaviour(Activity activity) {
    behaviourReference = new ObjectReference<Activity>(activity);
  }

  /** sets the activity that can be created from the given descriptor as the
   * behaviour for this node.   It is assumed that the descriptor will
   * create an {@link Activity}
   * An object reference for the given descriptor is created. */
  public void setBehaviour(Descriptor descriptor) {
    behaviourReference = new ObjectReference<Activity>(descriptor);
  }

  /** sets the expression behaviour for this node.  The evaluation of the
   * expression will replace the {@link Activity#execute(org.jbpm.pvm.Execution) Activity's execute method}.
   * An object reference for the given descriptor is created. */
  public void setBehaviour(String expression) {
    behaviourReference = new ObjectReference<Activity>(expression);
  }

  public ObjectReference<Activity> getBehaviourReference() {
    return behaviourReference;
  }
 
  public void setBehaviourReference(ObjectReference<Activity> behaviourReference) {
    this.behaviourReference = behaviourReference;
  }

  public Activity getBehaviour() {
    Activity behaviour = ( behaviourReference!=null ? behaviourReference.get() : null);
    if (behaviour==null) {
      throw new PvmException("no behaviour on "+this);
    }
    return behaviour;
  }

  // various helper methods ///////////////////////////////////////////////////
 
  private static Map<String, TransitionImpl> getTransitionsMap(List<TransitionImpl> transitions) {
    Map<String, TransitionImpl> map = null;
    if (transitions!=null) {
      map = new HashMap<String, TransitionImpl>();
      for (TransitionImpl transition: transitions) {
        if (! map.containsKey(transition.getName())) {
          map.put(transition.getName(), transition);
        }
      }
    }
    return map;
  }
 
  static Map<String, NodeImpl> getNodesMap(List<NodeImpl> nodes) {
    Map<String, NodeImpl> map = null;
    if (nodes!=null) {
      map = new HashMap<String, NodeImpl>();
      for (NodeImpl node: nodes) {
        if (node.getName()!=null) {
          if (! map.containsKey(node.getName())) {
            map.put(node.getName(), node);
          }
        }
      }
    }
    return map;
  }

  public String toString() {
    if (name!=null) return "node("+name+")";
    if (dbid!=0) return "node("+dbid+")";
    return "node("+System.identityHashCode(this)+")";
  }

  /** collects the full stack of parent in a list.  This node is the
   * first element in the chain.  The process definition will be the last element.
   * the chain will never be null. */
  public List<ObservableElementImpl> getParentChain() {
    List<ObservableElementImpl> chain = new ArrayList<ObservableElementImpl>();
    ObservableElementImpl processElement = this;
    while (processElement!=null) {
      chain.add(processElement);
      processElement = processElement.getParent();
    }
    return chain;
  }

  // getters and setters //////////////////////////////////////////////////////
 
  public ObservableElementImpl getParent() {
    return (parentNode!=null ? parentNode : processDefinition);
  }
 
  public String getName() {
    return name;
  }
  public void setName(String name) {
    // if there is no processDefinition associated with this node
    if (processDefinition==null) {
      // it s just a setter
      this.name = name;

    } else { // otherwise
      // make sure the processDefinition's activitiesMap remains up to date
      if (this.name!=null) {
        processDefinition.removeNode(this);
      }
      this.name = name;
      if (name!=null) {
        processDefinition.addNode(this);
      }
    }
  }
  public TransitionImpl getDefaultTransition() {
    return defaultTransition;
  }
  public void setDefaultTransition(TransitionImpl defaultTransition) {
    this.defaultTransition = defaultTransition;
  }
  public NodeImpl getParentNode() {
    return parentNode;
  }
  public void setParentNode(NodeImpl parentNode) {
    this.parentNode = parentNode;
  }
  public boolean isExecutionAsync() {
    return isExecutionAsync;
  }
  public boolean isSignalAsync() {
    return isSignalAsync;
  }
  public void setSignalAsync(boolean isSignalAsync) {
    this.isSignalAsync = isSignalAsync;
  }
  public void setExecutionAsync(boolean isExecutionAsync) {
    this.isExecutionAsync = isExecutionAsync;
  }
  public boolean isLeaveAsync() {
    return isLeaveAsync;
  }
  public void setLeaveAsync(boolean isLeaveAsync) {
    this.isLeaveAsync = isLeaveAsync;
  }
  public boolean isPreviousNeeded() {
    return isPreviousNeeded;
  }
  public void setPreviousNeeded(boolean isPreviousNeeded) {
    this.isPreviousNeeded = isPreviousNeeded;
  }
}
TOP

Related Classes of org.jbpm.pvm.impl.NodeImpl

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.