Package com.catify.processengine.core.services

Source Code of com.catify.processengine.core.services.NodeInstanceMediatorService

/**
* *******************************************************
* Copyright (C) 2013 catify <info@catify.com>
* *******************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*         http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.catify.processengine.core.services;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.transaction.annotation.Transactional;

import com.catify.processengine.core.data.model.NodeInstaceStates;
import com.catify.processengine.core.data.model.entities.FlowNodeInstance;
import com.catify.processengine.core.data.services.FlowNodeInstanceRepositoryService;

/**
* The NodeInstanceMediatorService handles all data access between the node
* services ({@link com.catify.processengine.core.nodes}) and their database
* representation ({@link com.catify.processengine.core.data.model.entities}).
* The NodeInstanceMediatorService can only access the database node that has
* been assigned to it at process start. For process wide access responsibility
* use {@link ProcessInstanceMediatorService}.
*
* @author christopher köster
*
*/
@Configurable
public class NodeInstanceMediatorService {

  static final Logger LOG = LoggerFactory
      .getLogger(NodeInstanceMediatorService.class);

  /** The flow node instance is cached to reduce the need for querying and act as a local cache. */
  private FlowNodeInstance nodeInstance;

  /** The unique process id. */
  private String uniqueProcessId;
 
  /** The unique flow node id. */
  private String uniqueFlowNodeId;

  @Autowired
  private FlowNodeInstanceRepositoryService flowNodeInstanceRepositoryService;

  /**
   * Instantiates a new node instance mediator service.
   */
  public NodeInstanceMediatorService() {
  }

  /**
   * Instantiates a new node instance mediator service.
   *
   * @param uniqueProcessId the unique process id
   * @param uniqueFlowNodeId the unique flow node id
   */
  @Autowired
  public NodeInstanceMediatorService(String uniqueProcessId,
      String uniqueFlowNodeId) {
    this.uniqueProcessId = uniqueProcessId;
    this.uniqueFlowNodeId = uniqueFlowNodeId;
  }

  /*
   * ##### begin of neo4j specific methods ##### (this should be an
   * implementation of an interface. see redmine #58)
   */

  /**
   * Persist any changes to the flow node instance to the db.
   */
  @Transactional //FIXME: need to test if transaction is needed
  public void persistChanges() {
    flowNodeInstanceRepositoryService.save(this.nodeInstance);
  }

  /**
   * Load a flow node instance from db.
   *
   * @param uniqueProcessId
   *            the unique process id
   * @param uniqueFlowNodeId
   *            the unique flow node id
   * @param instanceId
   *            the instance id
   * @return the neo4j flow node instance
   */
  private FlowNodeInstance loadFlowNodeInstance(String uniqueProcessId,
      String uniqueFlowNodeId, String processInstanceId) {
    // check if nodeInstance has already been loaded (eg. by another
    // operation) to avoid unnecessary db lookups
    if (this.nodeInstance == null
        || !this.nodeInstance.getHasInstanceRelationship()
            .getInstanceId().equals(processInstanceId)) {
     
      FlowNodeInstance flowNodeInstance = flowNodeInstanceRepositoryService.findFlowNodeInstance(
          uniqueProcessId, uniqueFlowNodeId, processInstanceId);
     
      LOG.debug(String.format(
          "Searching FlowNodeInstance in db with parameters: %s, %s, %s. Found: %s",
          uniqueProcessId, uniqueFlowNodeId, processInstanceId,
          flowNodeInstance));
     
      return flowNodeInstance;
    } else {
      return this.nodeInstance;
    }
  }

  /*
   * ##### end of neo4j specific methods #####
   */

  /**
   * Gets the node instance.
   *
   * @param instanceId
   *            the instance id
   * @return the node instance
   */
  public FlowNodeInstance getNodeInstance(String processInstanceId) {
    return loadFlowNodeInstance(this.uniqueProcessId,
        this.uniqueFlowNodeId, processInstanceId);
  }

  /**
   * Gets the state of a flow node instance.
   *
   * @param instanceId
   *            the instance id
   * @return the state
   */
  public String getNodeInstanceState(String processInstanceId) {
    this.nodeInstance = getNodeInstance(processInstanceId);

    if (this.nodeInstance == null) {
      return null;
    } else {
      return this.nodeInstance.getNodeInstanceState();
    }
  }

  /**
   * Gets the fired flows needed.
   *
   * @param instanceId
   *            the instance id
   * @return the fired flows needed
   */
  public int getIncomingFiredFlowsNeeded(String processInstanceId) {
    this.nodeInstance = getNodeInstance(processInstanceId);

    return this.nodeInstance.getIncomingFiredFlowsNeeded();
  }

  /**
   * Gets the sequence flows fired.
   *
   * @param instanceId
   *            the instance id
   * @return the sequence flows fired
   */
  public int getSequenceFlowsFired(String processInstanceId) {
    this.nodeInstance = getNodeInstance(processInstanceId);

    return this.nodeInstance.getFlowsFired();
  }

  /**
   * Sets the state of a flow node instance.
   *
   * @param state
   *            the new state
   */
  public void setState(String processInstanceId, String state) {
    this.nodeInstance = getNodeInstance(processInstanceId);

    if (stateTransistionSanityCheck(state)) {
      LOG.debug(String.format(
          "Setting state of graphId: %s from %s to %s (uniqueFlowNodeId:%s)",
          nodeInstance.getGraphId(),
          nodeInstance.getNodeInstanceState(), state,
          this.getUniqueFlowNodeId()));
      nodeInstance.setNodeInstanceState(state);
    }
  }
 
  /**
   * Checks if node instance is in "active state".
   *
   * @param processInstanceId the process instance id
   * @return true, if is active
   */
  public boolean isActive(String processInstanceId) {
    return this.getNodeInstanceState(processInstanceId).equals(NodeInstaceStates.ACTIVE_STATE);
  }
 
  /**
   * Shortcut to set "active state" for node.
   *
   * @param processInstanceId
   */
  public void setActive(String processInstanceId) {
    this.setState(processInstanceId, NodeInstaceStates.ACTIVE_STATE);
  }
 
  /**
   * Shortcut to set "passed state" for node.
   *
   * @param processInstanceId
   */
  public void setPassed(String processInstanceId) {
    this.setState(processInstanceId, NodeInstaceStates.PASSED_STATE);
  }
 
  /**
   * Shortcut to set "deactivated state" for node.
   *
   * @param processInstanceId
   */
  public void setDeactivated(String processInstanceId) {
    this.setState(processInstanceId, NodeInstaceStates.DEACTIVATED_STATE);
  }
 
  /**
   * Shortcut to set "inactive state" for node.
   *
   * @param processInstanceId
   */
  public void setInactive(String processInstanceId) {
    this.setState(processInstanceId, NodeInstaceStates.INACTIVE_STATE);
  }
 

  /**
   * Sets the fired flows needed.
   *
   * @param firedFlowsNeeded
   *            the new fired flows needed
   */
  public void setFiredFlowsNeeded(String processInstanceId,
      int firedFlowsNeeded) {
    this.nodeInstance = getNodeInstance(processInstanceId);

    LOG.debug(String.format("Setting firedFlowsNeeded of %s from %s to %s",
        nodeInstance, nodeInstance.getIncomingFiredFlowsNeeded(),
        firedFlowsNeeded));
    this.nodeInstance.setIncomingFiredFlowsNeeded(firedFlowsNeeded);
  }

  /**
   * Sets the sequence flows fired.
   *
   * @param flowsFired
   *            the new sequence flows fired
   */
  public void setSequenceFlowsFired(String processInstanceId, int flowsFired) {
    this.nodeInstance = getNodeInstance(processInstanceId);

    LOG.debug(String.format(
        "Setting sequenceFlowsFired of %s from %s to %s", nodeInstance,
        nodeInstance.getFlowsFired(), flowsFired));
    this.nodeInstance.setFlowsFired(flowsFired);
  }
 
  public void setNodeInstanceStartTime(String processInstanceId, Date nodeInstanceStart) {
    this.nodeInstance = getNodeInstance(processInstanceId);

    LOG.debug(String.format(
        "Setting start time of %s to %s", nodeInstance, nodeInstanceStart));
    this.nodeInstance.setNodeInstanceStartTime(nodeInstanceStart);
  }
 
  public Date getNodeInstanceStartTime(String processInstanceId) {
    this.nodeInstance = getNodeInstance(processInstanceId);

    return this.nodeInstance.getNodeInstanceStartTime();
  }
 
  public void setNodeInstanceEndTime(String processInstanceId, Date nodeInstanceEnd) {
    this.nodeInstance = getNodeInstance(processInstanceId);

    LOG.debug(String.format(
        "Setting end time of %s to %s", nodeInstance, nodeInstanceEnd));
    this.nodeInstance.setNodeInstanceEndTime(nodeInstanceEnd);
  }

  /**
   * Plausibility check of the transition from one state to another.
   *
   * @param newState
   *            the new state to be set
   * @return true, if successful, false if state should not be changed
   */
  private boolean stateTransistionSanityCheck(String newState) {
    if (this.nodeInstance.getNodeInstanceState().equals(newState)) {
      LOG.info(String
          .format("Cannot set node instance state. State of %s is already at %s",
              this.nodeInstance.getGraphId(),
              this.nodeInstance.getNodeInstanceState()));
      return false;

      // transition from INACTIVE_STATE to newState
    } else if (this.nodeInstance.getNodeInstanceState().equals(
        NodeInstaceStates.INACTIVE_STATE)) {
      if (newState.equals(NodeInstaceStates.ACTIVE_STATE)) {
        return true;
      } else if (newState.equals(NodeInstaceStates.PASSED_STATE)) {
        return true;
      } else {
        LOG.warn(String
            .format("stateTransistionSanityCheck failed. State of %s was at %s and should be set to %s",
                this.nodeInstance.getGraphId(),
                this.nodeInstance.getNodeInstanceState(),
                newState));
        return false;
      }

      // transition from ACTIVE_STATE to newState
    } else if (this.nodeInstance.getNodeInstanceState().equals(
        NodeInstaceStates.ACTIVE_STATE)) {
      if (newState.equals(NodeInstaceStates.PASSED_STATE)) {
        return true;
      } else if (newState.equals(NodeInstaceStates.DEACTIVATED_STATE)) {
        return true;
      } else {
        LOG.warn(String
            .format("stateTransistionSanityCheck failed. State of %s was at %s and should be set to %s",
                this.nodeInstance.getGraphId(),
                this.nodeInstance.getNodeInstanceState(),
                newState));
        return false;
      }

      // transition from PASSED_STATE to newState
    } else if (this.nodeInstance.getNodeInstanceState().equals(
        NodeInstaceStates.PASSED_STATE)) {
      LOG.warn(String
          .format("stateTransistionSanityCheck failed. State of %s was at %s and should be set to %s",
              this.nodeInstance.getGraphId(),
              this.nodeInstance.getNodeInstanceState(), newState));
      return false;

      // transition from DEACTIVATED_STATE to newState
    } else if (this.nodeInstance.getNodeInstanceState().equals(
        NodeInstaceStates.DEACTIVATED_STATE)) {
      LOG.warn(String
          .format("stateTransistionSanityCheck failed. State of %s was at %s and should be set to %s",
              this.nodeInstance.getGraphId(),
              this.nodeInstance.getNodeInstanceState(), newState));
      return false;

      // unhandled transitions
    } else {
      LOG.warn(String
          .format("stateTransistionSanityCheck failed. State of %s was at %s and should be set to %s",
              this.nodeInstance.getGraphId(),
              this.nodeInstance.getNodeInstanceState(), newState));
      return false;
    }

  }

  /**
   * Gets the unique process id.
   *
   * @return the unique process id
   */
  public String getUniqueProcessId() {
    return uniqueProcessId;
  }

  /**
   * Sets the unique process id.
   *
   * @param uniqueProcessId the new unique process id
   */
  public void setUniqueProcessId(String uniqueProcessId) {
    this.uniqueProcessId = uniqueProcessId;
  }

  /**
   * Gets the unique flow node id.
   *
   * @return the unique flow node id
   */
  public String getUniqueFlowNodeId() {
    return uniqueFlowNodeId;
  }

  /**
   * Sets the unique flow node id.
   *
   * @param uniqueFlowNodeId the new unique flow node id
   */
  public void setUniqueFlowNodeId(String uniqueFlowNodeId) {
    this.uniqueFlowNodeId = uniqueFlowNodeId;
  }

 
  /**
   * Checks if the node instance has been initialized.
   *
   * @return true, if is initialized
   */
  public boolean isInitialized(){
    return (this.nodeInstance != null);
  }
 
}
TOP

Related Classes of com.catify.processengine.core.services.NodeInstanceMediatorService

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.