package de.tu_dresden.diplom.richter_mirko_mat2628335.common.context;

import org.apache.log4j.Logger;
import de.tu_dresden.diplom.richter_mirko_mat2628335.clients.evidence.ClientEvidenceManagerFactory;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.digestAgreement.IFDigestAgreementResponse;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.digestAgreement.IFDigestAgreementRequest;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.evidence.IFBodyEvidence;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.listener.event.*;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.listener.IFCommunicationInitiatedListener;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.listener.IFCommunicationClosedListener;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.listener.IFDigestAgreementInitiatedListener;
import de.tu_dresden.diplom.richter_mirko_mat2628335.common.listener.IFDigestAgreementClosedListener;

import java.util.*;

/**
 * The base-class for client- and service-contextManager providing base-functionality common to them.
 */
public abstract class BaseContextManager implements IFContextManager {

   private static final Logger logger = Logger.getLogger(BaseContextManager.class);

   /**
    * As base-class it is sometimes more usefull to log in the name of the
    * extending class. This logger is used for that.
    */
   private static Logger inhLogger = Logger.getLogger(BaseContextManager.class);

   /**
    * Monitor to write informations on digest agreements (running, completed etc.)
    */
   public static final Logger digestAgreementStateMonitor = Logger.getLogger("monitor.state.digestAgreement.client");

   /**
    * Monitor write informations on the communication-state in common
    */
   public static final Logger communicationStateMonitor = Logger.getLogger("monitor.state.communication.client");

   /**
    * ContextID -> IFBaseContextInfo
    */
   private Map registeredContextInfoObjects = null;

   /**
    * Map[IFClientContextInfo -> Map[NONCE2 -> CommunicationProcess]]
    */
   private Map registeredCommunicationProceses = null;

   private List communicationInitiatedListener = null;
   private List communicationClosedListener = null;
   private List digestAgreementInitiatedListener = null;
   private List digestAgreementClosedListener = null;

   /**
    * an instance of this type should not be created from outside the package
    */
   protected BaseContextManager() {
      if (getInheritedLogger() != null) {
         inhLogger = getInheritedLogger();
      }
      registeredContextInfoObjects = new HashMap();
      registeredCommunicationProceses = new IdentityHashMap();

      communicationInitiatedListener = new Vector();
      communicationClosedListener = new Vector();
      digestAgreementInitiatedListener = new Vector();
      digestAgreementClosedListener = new Vector();
   }

   /**
    * @see de.tu_dresden.diplom.richter_mirko_mat2628335.clients.context.IFClientContextManager#registerCommunicationStarted(de.tu_dresden.diplom.richter_mirko_mat2628335.common.context.IFCountingContext)
    */
   public synchronized boolean registerCommunicationStarted(IFCountingContext context) {
      final String fn = "[registerCommunicationStarted] ";
      boolean result = false;
      if (context != null && context.getCoordinationContext() != null && context.getStepContext() != null && getContext(context.getIdentification()) != null) {
         if (registerCommunicationProcess(new CommunicationProcess(context))) {
            logCommunicationStartedToMonitor(context, fn);
            CommunicationInitiatedEvent event = new CommunicationInitiatedEvent(context);
            fireCommunicationInitiatedEvent(event);
            result = true;
         } else {
            inhLogger.error(fn + "failed to register newly started communication: " + context);
         }
      } else {
         StringBuffer err = new StringBuffer("CHECK FOR PARAMS FAILED: ");
         if (context == null) {
            err.append("countingContext was NULL!");
         } else if (context.getCoordinationContext() == null) {
            err.append("coordinationContext was NULL!");
         } else if (context.getStepContext() == null) {
            err.append("stepContext was NULL!");
         } else if (getContext(context.getIdentification()) == null) {
            err.append("couldn't locate ClientContextInfo with contextID '" + context.getIdentification() + "'");
         }
         inhLogger.error(fn + err);
      }
      return result;
   }

   /**
    * Logs informtions when a communication has started.
    * @param context the context under that the communication run
    * @param fn the name of the logging method
    */
   private void logCommunicationStartedToMonitor(IFCountingContext context, final String fn) {
      if (communicationStateMonitor.isDebugEnabled()) {
         StringBuffer mon = new StringBuffer("registering newly started Communication\n");
         mon.append("\tContextID:\t").append(context.getIdentification()).append("\n");
         mon.append("\tNonce:\t\t").append(context.getStepContext().getNonce()).append("\n");
         if (context.getStepContext().getDependency() != null) {
            mon.append("\tDependency:\tNOT NULL\n");
         } else {
            mon.append("\tDependency:\tNULL\n");
         }
         communicationStateMonitor.debug(fn + mon);
      }
   }

   /**
    * Registers a new communication-process
    * @param process the process being registered.
    * @return true if success, false else
    */
   private boolean registerCommunicationProcess(CommunicationProcess process) {
      final String fn = "[registerCommunicationProcess] ";
      boolean result = false;
      IFCountingContext countingCtx = process.getCountingContext();
      IFContextInfo ctxInfo = getContext(countingCtx.getIdentification());
      if (ctxInfo != null) {
         Map nonce2CommunicationProcessMapping = (Map) registeredCommunicationProceses.get(ctxInfo);
         if (nonce2CommunicationProcessMapping == null) {
            nonce2CommunicationProcessMapping = new HashMap();
            registeredCommunicationProceses.put(ctxInfo, nonce2CommunicationProcessMapping);
         }
         if (nonce2CommunicationProcessMapping.containsKey(countingCtx.getStepContext().getNonce())) {
            inhLogger.warn(fn + "overwriting existing communicationProcess belonging to contextID '" + countingCtx.getIdentification() + " and Nonce '" + countingCtx.getStepContext().getNonce() + "''");
         }
         nonce2CommunicationProcessMapping.put(countingCtx.getStepContext().getNonce(), process);
         logRegisteredCommunicationProcessesToMonitor(fn);
         result = true;
      } else {
         inhLogger.error(fn + "couldn't locate the clientContextInfo with id '" + countingCtx.getIdentification() + "'");
      }
      return result;
   }

   /**
    * Searches for some communicationProcess if only the digestAgreement out of the request-phase
    * is known (Nonce->RequestHash)
    * @param contextID the context in which the agreement runs
    * @param resp the response that has been received from witness
    * @return the communicationProcess if found, NULL else
    */
   private CommunicationProcess getCommunicationProcessByRequestPhaseDigestAgreementResponse(String contextID, IFDigestAgreementResponse resp) {
      final String fn = "[getCommunicationProcessByRequestPhaseDigestAgreementResponse] ";
      CommunicationProcess result = null;
      if (contextID != null && contextID.length() > 0 && resp != null) {
         CommunicationProcess[] contextCommProcs = getCommunicationProcesses(contextID);
         boolean found = false;
         for (int i = 0; i < contextCommProcs.length; i++) {
            CommunicationProcess proc = contextCommProcs[i];
            if (proc.hasRequestPhaseDigestAgreementProcess() && proc.getRequestPhaseDigestAgreementProcess().getProcessIdentification().equals(resp.getAgreementReference())) {
               result = proc;
               found = true;
               break;
            }
         }
         if (!found) {
            inhLogger.warn(fn + "couldn't find a process belonging to contextID '" + contextID + "' and digestAgrementResponse '" + resp + "'");
            //logRegisteredCommunicationProcessesToMonitor(fn);
         }
      } else {
         StringBuffer err = new StringBuffer("CHECK FOR PARAMS FAILED: ");
         if (contextID == null) {
            err.append("contextID was NULL!");
         } else if (contextID.length() == 0) {
            err.append("contextID had ZWERO length!");
         } else if (resp == null) {
            err.append("digestAgrementResponse was NULL!");
         }
         inhLogger.error(fn + err);
      }
      return result;
   }

   /**
    * Searches for some communicationProcess if only the digestAgreement out of the response-phase
    * is known (Nonce->RequestHash->ResponseHash)
    * @param contextID the context in which the agreement runs
    * @param resp the response that has been received from witness
    * @return the communicationProcess if found, NULL else
    */
   private CommunicationProcess getCommunicationProcessByResponsePhaseDigestAgreementResponse(String contextID, IFDigestAgreementResponse resp) {
      final String fn = "[getCommunicationProcessByResponsePhaseDigestAgreementResponse] ";
      CommunicationProcess result = null;
      if (contextID != null && contextID.length() > 0 && resp != null) {
         CommunicationProcess[] contextCommProcs = getCommunicationProcesses(contextID);
         boolean found = false;
         for (int i = 0; i < contextCommProcs.length; i++) {
            CommunicationProcess proc = contextCommProcs[i];
            if (proc.hasResponsePhaseDigestAgreementProcess() && proc.getResponsePhaseDigestAgreementProcess().getProcessIdentification().equals(resp.getAgreementReference())) {
               result = proc;
               found = true;
               break;
            }
         }
         if (!found) {
            inhLogger.warn(fn + "couldn't find a process belonging to contextID '" + contextID + "' and digestAgrementResponse '" + resp + "'");
         }
      } else {
         StringBuffer err = new StringBuffer("CHECK FOR PARAMS FAILED: ");
         if (contextID == null) {
            err.append("contextID was NULL!");
         } else if (contextID.length() == 0) {
            err.append("contextID had ZWERO length!");
         } else if (resp == null) {
            err.append("digestAgrementResponse was NULL!");
         }
         inhLogger.error(fn + err);
      }
      return result;
   }

   /**
    * Gets all communicationProcesses currently running within that context.
    * @param contextID the contextID that houses the processes
    * @return the list of running processes
    */
   private CommunicationProcess[] getCommunicationProcesses(String contextID) {
      return getCommunicationProcesses(getContext(contextID));
   }

   /**
    * Gets all communicationProcesses currently running within that context.
    * @param clientContextInfo the internal representation of the context that houses the processes
    * @return the list of running processes
    */
   private CommunicationProcess[] getCommunicationProcesses(IFContextInfo clientContextInfo) {
      final String fn = "[getCommunicationProcesses] ";
      CommunicationProcess[] result = null;
      if (clientContextInfo != null) {
         Map nonce2CommProcsMapping = (Map) registeredCommunicationProceses.get(clientContextInfo);
         if (nonce2CommProcsMapping != null) {
            Collection values = nonce2CommProcsMapping.values();
            result = (CommunicationProcess[]) values.toArray(new CommunicationProcess[values.size()]);
         } else {
            inhLogger.info(fn + "couldn't locate any currently registered CommunicationProcesses assigned to ClientContextInfo '" + clientContextInfo.getIdentification() + "'");
         }
      } else {
         inhLogger.error(fn + "CHECK FOR PARAMS FAILED: clientContextInfo was NULL!");
      }
      return result;
   }

   /**
    * Searches for the communication-process running within the given context identified by the
    * given nonce (per definition the primary-id of som communication-process)
    * @param contextID the contextID that houses the process
    * @param nonce the identification of the communication-process to look for
    * @return the communication-process if found, NULL else
    */
   private CommunicationProcess getCommunicationProcess(String contextID, String nonce) {
      return getCommunicationProcess(getContext(contextID), nonce);
   }

   /**
    * Searches for the communication-process running within the given context identified by the
    * given nonce (per definition the primary-id of som communication-process)
    * @param clientContextInfo the internal representation of the context that houses the process
    * @param nonce the identification of the communication-process to look for
    * @return the communication-process if found, NULL else
    */
   private CommunicationProcess getCommunicationProcess(IFContextInfo clientContextInfo, String nonce) {
      final String fn = "[getCommunicationProcess] ";
      CommunicationProcess result = null;
      if (clientContextInfo != null && nonce != null && nonce.length() > 0) {
         if (logger.isDebugEnabled()) logger.debug(fn + "looking for communicationProcess contextID '" + clientContextInfo.getIdentification() + "' and nonce '" + nonce + "'");
         Map nonce2CommProcsMapping = (Map) registeredCommunicationProceses.get(clientContextInfo);
         if (nonce2CommProcsMapping != null) {
            result = (CommunicationProcess) nonce2CommProcsMapping.get(nonce);
         } else {
            inhLogger.info(fn + "couldn't locate any currently registered CommunicationProcesses assigned to ClientContextInfo '" + clientContextInfo.getIdentification() + "'");
         }
      } else {
         StringBuffer err = new StringBuffer("CHECK FOR PARAMS FAILED: ");
         if (clientContextInfo == null) {
            err.append("clientContextInfo was NULL!");
         } else if (nonce == null) {
            err.append("nonce was NULL!");
         } else if (nonce.length() == 0) {
            err.append("nonce has ZERO length!");
         }
         inhLogger.error(fn + err);
      }
      return result;
   }

   /**
    * Logs all registered communication-process to the monitor.
    * @param fn name of the method for that should be logged (easier to read in log-file)
    */
   private void logRegisteredCommunicationProcessesToMonitor(String fn) {
      if (communicationStateMonitor.isDebugEnabled()) {
         StringBuffer mon = new StringBuffer("currently registered CommunicationProcesses:\n");
         Set ctxKeys = registeredCommunicationProceses.keySet();
         int ctxCounter = 1;
         for (Iterator iterator = ctxKeys.iterator(); iterator.hasNext();) {
            IFContextInfo ctx = (IFContextInfo) iterator.next();
            mon.append("\tContextInfo_").append(ctxCounter).append(" (ContextID: ").append(ctx.getIdentification()).append(")\n");
            Map commMap = (Map) registeredCommunicationProceses.get(ctx);
            Set commKeys = commMap.keySet();
            int commCounter = 1;
            for (Iterator iterator1 = commKeys.iterator(); iterator1.hasNext();) {
               String nonce = (String) iterator1.next();
               mon.append("\t\tCommunicationProcess_").append(commCounter).append(" (Nonce: ").append(nonce).append(")\n");
               CommunicationProcess commProc = (CommunicationProcess) commMap.get(nonce);
               mon.append("\t\t\tCurrentState:\t").append(commProc.getCurrentStateHumanReadable()).append("\n");
               commCounter++;
            }
            ctxCounter++;
         }
         communicationStateMonitor.debug(fn + mon);
      }
   }

   /**
    * @see IFContextManager#registerDigestAgreementStarted(String, de.tu_dresden.diplom.richter_mirko_mat2628335.common.digestAgreement.IFDigestAgreementRequest, String)
    */
   public synchronized boolean registerDigestAgreementStarted(String contextID, IFDigestAgreementRequest request, String communicationNonce) {
      final String fn = "[registerDigestAgreementStarted] ";
      boolean result = false;
      if (contextID != null && request != null && getContext(contextID) != null) {
         CommunicationProcess commProcess = getCommunicationProcess(contextID, communicationNonce);
         if (commProcess != null) {
            if (request.isRequestPhase()) {
               if (!commProcess.hasRequestPhaseDigestAgreementProcess()) {
                  DigestAgreementProcess requestProc = new DigestAgreementProcess(request, contextID);
                  commProcess.setRequestPhaseDigestAgreementProcess(requestProc);
                  logDigestAgreementStartedToMonitor(contextID, request, fn);
                  result = true;
                  DigestAgreementInitiatedEvent event = new DigestAgreementInitiatedEvent(contextID, request, communicationNonce);
                  event.setPhase(IFDigestAgreementInitiatedEvent.PHASE_REQUEST);
                  fireDigestAgreementInitiatedEvent(event);
               } else {
                  inhLogger.error(fn + "couldn't register start of digestAgreementRequest (request-phase) because the process for the request-phase already exists!");
               }
            } else if (request.isResponsePhase()) {
               if (!commProcess.hasResponsePhaseDigestAgreementProcess()) {
                  if (commProcess.hasRequestPhaseDigestAgreementProcess() && !commProcess.getRequestPhaseDigestAgreementProcess().isWaitingForResponse()) {
                     DigestAgreementProcess requestProc = new DigestAgreementProcess(request, contextID);
                     commProcess.setResponsePhaseDigestAgreementProcess(requestProc);
                     logDigestAgreementStartedToMonitor(contextID, request, fn);
                     result = true;
                     DigestAgreementInitiatedEvent event = new DigestAgreementInitiatedEvent(contextID, request, communicationNonce);
                     event.setPhase(IFDigestAgreementInitiatedEvent.PHASE_RESPONSE);
                     fireDigestAgreementInitiatedEvent(event);
                  } else {
                     inhLogger.error(fn + "couldn't register start of digestAgreementRequest (response-phase) because the process for the request-phase does not exist!");
                  }
               } else {
                  inhLogger.error(fn + "couldn't register start of digestAgreementRequest (response-phase) because the process for the response-phase already exists!");
               }
            } else {
               inhLogger.fatal(fn + "unknown phase of DigestAgreementRequest!");
            }
         } else {
            inhLogger.error(fn + "couldn't locate CommunicationProcess to register DigestAgreementProcess!");
         }
      } else {
         StringBuffer err = new StringBuffer("CHECK FOR PARAMS FAILED: ");
         if (contextID == null) {
            err.append("contextID was NULL!");
         } else if (request == null) {
            err.append("digestAgreementRequest was NULL!");
         } else if (getContext(contextID) == null) {
            err.append("couldn't locate ClientContextInfo with contextID '" + contextID + "'");
         }
         inhLogger.error(fn + err);
      }
      return result;
   }

   /**
    * Logs information about the newly started given digest agreement to the monito
    * @param contextID context in which the digest agreement-process has been started
    * @param request the request being sent to the witness
    * @param fn the name of the method for which the logging-message should be generated
    */
   private void logDigestAgreementStartedToMonitor(String contextID, IFDigestAgreementRequest request, final String fn) {
      if (digestAgreementStateMonitor.isDebugEnabled()) {
         StringBuffer mon = new StringBuffer("registering newly started digestAgreement:\n");
         mon.append("\tContextID:\t\t").append(contextID).append("\n");
         mon.append("\tPhase:\t\t\t");
         if (request.isRequestPhase()) {
            mon.append("REQUEST");
         } else {
            mon.append("RESPONSE");
         }
         mon.append("\n");
         mon.append("\tDigest:\t\t\t").append(request.getDigest()).append("\n");
         mon.append("\tNonce:\t\t\t").append(request.getNonce()).append("\n");
         mon.append("\tDigestAgreement:\t").append(request.getAgreementReference()).append("\n");
         if (request.getAmount() != null) {
            mon.append("\tAmount:\t\t\t").append(request.getAmount().getAmount()).append("\t(Currency:\t").append(request.getAmount().getCurrency().getCurrency()).append(")\n");
         } else {
            mon.append("\tAmount:\t\t\tNULL\n");
         }
         if (request.getAccountIdentification() != null) {
            mon.append("\tAccountIdent:\t\t").append(request.getAccountIdentification().getId()).append("\n");
         } else {
            mon.append("\tAccountIdent:\t\tNULL\n");
         }
         digestAgreementStateMonitor.debug(fn + mon);
      }
   }

   /**
    * Checks the state of the digest agreement in response-phase identified by the given contextID and
    * the communication-nonce (primary-id of a communication-process).<br/>
    * The state may be "successfull done", "still in process with witness" or "failed"
    * @param contextID the id of the context in which the communication runs
    * @param communicationNonce the value to identify the communication-process
    * @return the state-info
    */
   public IFDigestAgreementStateInfo getStateInfo4ResponsePhaseDigestAgreementRequest(String contextID, String communicationNonce) {
      final String fn = "[getStateInfo4ResponsePhaseDigestAgreementRequest] ";
      DigestAgreementStateInfo result = null;
      if (contextID != null && contextID.length() > 0 && communicationNonce != null && communicationNonce.length() > 0) {
         CommunicationProcess commProc = getCommunicationProcess(contextID, communicationNonce);
         if (commProc != null) {
            if (commProc.hasRequestPhaseDigestAgreementProcess()) {
               result = new DigestAgreementStateInfo();
               if (commProc.getRequestPhaseDigestAgreementProcess().isSuccessfull()) {
                  result.setReferenciationNonce(commProc.getRequestPhaseDigestAgreementProcess().getProcessIdentification());
                  result.setState(IFDigestAgreementStateInfo.STATE_SUCCESS);
               } else if (commProc.getRequestPhaseDigestAgreementProcess().isWaitingForResponse()) {
                  result.setState(IFDigestAgreementStateInfo.STATE_WAITING);
               } else if (commProc.getRequestPhaseDigestAgreementProcess().isFailed()) {
                  result.setState(IFDigestAgreementStateInfo.STATE_FAILED);
               } else {
                  inhLogger.fatal(fn + "unknown state of digestAgreementProcess in requestPhase of contextID '" + contextID + "' and communicationNonce '" + communicationNonce + "'");
                  result.setState(IFDigestAgreementStateInfo.STATE_FAILED);
               }
            } else {
               result.setState(IFDigestAgreementStateInfo.STATE_FAILED);
            }
         } else {
            inhLogger.error(fn + "No CommunicationProcess found for contextID '" + contextID + "' and communicationNonce '" + communicationNonce + "'");
         }
      } else {
         StringBuffer err = new StringBuffer("CHECK FOR PARAMS FAILED: ");
         if (contextID == null) {
            err.append("contextID was NULL!");
         } else if (contextID.length() == 0) {
            err.append("contextID had ZERO length!");
         } else if (communicationNonce == null) {
            err.append("communicationNonce was NULL!");
         } else if (communicationNonce.length() == 0) {
            err.append("communicationNonce had ZERO length");
         }
         inhLogger.error(fn + err);
         result.setState(IFDigestAgreementStateInfo.STATE_FAILED);
      }
      return result;
   }

   /**
    * @see IFContextManager#registerSuccessfullDigestAgreement(String, de.tu_dresden.diplom.richter_mirko_mat2628335.common.digestAgreement.IFDigestAgreementResponse, de.tu_dresden.diplom.richter_mirko_mat2628335.common.evidence.IFBodyEvidence)
    */
   public synchronized boolean registerSuccessfullDigestAgreement(String contextID, IFDigestAgreementResponse response, IFBodyEvidence bodyEvidence) {
      final String fn = "[registerSuccessfullDigestAgreement] ";
      boolean result = true;
      if (contextID != null && response != null && response.isSuccess() && bodyEvidence != null && bodyEvidence.isProofed()) {
         ClientEvidenceManagerFactory.getClientEvidenceManager().registerSuccessfullAgreedDigest(contextID, response, bodyEvidence);
         if (response.isRequestPhase()) {
            CommunicationProcess proc = getCommunicationProcessByRequestPhaseDigestAgreementResponse(contextID, response);
            if (proc != null) {
               if (proc.hasRequestPhaseDigestAgreementProcess() && proc.getRequestPhaseDigestAgreementProcess().isWaitingForResponse()) {
                  if (proc.getRequestPhaseDigestAgreementProcess().setDigestAgreementResponse(response)) {
                     result = true;
                     logSuccessfullDigestAgreementToMonitor(fn, contextID, response);
                     DigestAgreementClosedEvent ev = new DigestAgreementClosedEvent(contextID, response);
                     ev.setPhase(IFDigestAgreementClosedEvent.PHASE_REQUEST);
                     fireDigestAgreementClosedEvent(ev);
                  } else {
                     inhLogger.warn(fn + "couldn't set digestAgreementResponse in request-phase digestAgreementProcess");
                  }
               } else {
                  inhLogger.warn(fn + "no digestAgreementProcess in request-phase or it is not in waiting-state anymore!");
               }
            } else {
               inhLogger.warn(fn + "couldn't locate communicationProcess to contextID '" + contextID + "' and digestAgreementResponse '" + response + "'");
            }
         } else if (response.isResponsePhase()) {
            CommunicationProcess proc = getCommunicationProcessByResponsePhaseDigestAgreementResponse(contextID, response);
            if (proc != null) {
               if (proc.hasResponsePhaseDigestAgreementProcess() && proc.getResponsePhaseDigestAgreementProcess().isWaitingForResponse()) {
                  if (proc.getResponsePhaseDigestAgreementProcess().setDigestAgreementResponse(response)) {
                     result = true;
                     DigestAgreementClosedEvent ev = new DigestAgreementClosedEvent(contextID, response);
                     ev.setPhase(IFDigestAgreementClosedEvent.PHASE_RESPONSE);
                     fireDigestAgreementClosedEvent(ev);
                     logSuccessfullDigestAgreementToMonitor(fn, contextID, response);
                  } else {
                     inhLogger.warn(fn + "couldn't set digestAgreementResponse in response-phase digestAgreementProcess");
                  }
               } else {
                  inhLogger.warn(fn + "no digestAgreementProcess in response-phase or it is not in waiting-state anymore!");
               }
            } else {
               inhLogger.warn(fn + "couldn't locate communicationProcess to contectID '" + contextID + "' and digestAgreementResponse '" + response + "'");
            }
         } else {
            inhLogger.fatal(fn + "unknown state of response");
         }
      } else {
         StringBuffer err = new StringBuffer("CHECK FOR PARAMS FAILED: ");
         if (contextID == null) {
            err.append("contextID was NULL!");
         } else if (response == null) {
            err.append("response was NULL!");
         } else if (!response.isSuccess()) {
            err.append("response wasn't successfull!");
         } else if (bodyEvidence == null) {
            err.append("bodyEvidence was NULL!");
         } else if (!bodyEvidence.isProofed()) {
            err.append("bodyEvidence couldn't be proofed!");
         }
         inhLogger.error(fn + err);
      }
      return result;
   }

   /**
    * Logs the informations about the successfull performed digest agreement to the monitor.
    * @param fn the method for that the logging-message shall be genrated
    * @param contextID the ID of the context which runs the communication-process
    * @param response the response that was send from witness
    */
   private void logSuccessfullDigestAgreementToMonitor(final String fn, String contextID, IFDigestAgreementResponse response) {
      if (digestAgreementStateMonitor.isDebugEnabled()) {
         StringBuffer mon = new StringBuffer(fn);
         mon.append("registering successfull digestAgreement\n");
         mon.append("\tContextID:\t\t").append(contextID).append("\n");
         mon.append("\tAgreementReference:\t").append(response.getAgreementReference()).append("\n");
         digestAgreementStateMonitor.debug(mon);
      }
   }

   /**
    * @see IFContextManager#getContext(IFCoordinationContext)
    */
   public IFContextInfo getContext(IFCoordinationContext coordinationContext) {
      IFContextInfo result = null;
      if (coordinationContext != null) {
         result = getContext(coordinationContext.getIdentification());
      }
      return result;
   }

   /**
    * @see IFContextManager#getContext(String)
    */
   public IFContextInfo getContext(String ident) {
      IFContextInfo result = null;
      result = (IFContextInfo) registeredContextInfoObjects.get(ident);
      return result;
   }

   /**
    * Adds the given context to this manager-instance.
    * @param ident identification of the context (may lso be taken from ctxInfo)
    * @param ctxInfo the internl representation of some context
    */
   protected synchronized void addContext(String ident, IFContextInfo ctxInfo) {
      final String fn = "[addContext] ";
      if (ident != null && ident.length() > 0 && ctxInfo != null) {
         if (registeredContextInfoObjects.containsKey(ident)) {
            logger.warn(fn + "overwriting existing Context with identififcation '" + ident + "'");
         }
         registeredContextInfoObjects.put(ident, ctxInfo);
      } else {
         StringBuffer err = new StringBuffer("CHECK FOR PARAMS FAILED: ");
         if (ident == null) {
            err.append("ident was NULL!");
         } else if (ident.length() == 0) {
            err.append("ident had ZERO Length!");
         } else if (ctxInfo == null) {
            err.append("contextInfo was NULL!");
         }
         logger.error(fn + err);
      }
   }

   /**
    * Gets the iterator to iterate through all contextInfo-objects (type: IFContextInfo) (internal representation
    * of some context)
    * @return the iterator
    */
   protected Iterator getContextInfoObjectsIterator() {
      Collection values = registeredContextInfoObjects.values();
      return values.iterator();
   }

   /**
    * Gets the count of managed contextInfo-objects.
    * @return the count
    */
   protected int getContextInfoObjectsCount() {
      return registeredContextInfoObjects.size();
   }

   /**
    * @see IFContextManager#isRunningDigestAgreementRequestPhase(String, String)
    */
   public synchronized boolean isRunningDigestAgreementRequestPhase(String contextID, String nonce) {
      final String fn = "[isRunningDigestAgreementRequestPhase] ";
      boolean result = false;
      if (contextID != null && contextID.length() > 0 && nonce != null && nonce.length() > 0) {
         CommunicationProcess commProc = getCommunicationProcess(contextID, nonce);
         if (commProc.hasRequestPhaseDigestAgreementProcess() && commProc.getRequestPhaseDigestAgreementProcess().isWaitingForResponse()) {
            result = true;
         }
      } else {
         StringBuffer err = new StringBuffer("CHECK FOR PARAMS FAILED: ");
         if (contextID == null) {
            err.append("contextID was NULL!");
         } else if (contextID.length() == 0) {
            err.append("contextID had ZERO length!");
         } else if (nonce == null) {
            err.append("nonce was NULL!");
         } else if (nonce.length() == 0) {
            err.append("nonce had ZERO length!!");
         }
         inhLogger.error(fn + err);
      }
      return result;
   }

   /**
    * @see IFContextManager#isSuccessfullCompletedDigestAgreementRequestPhase(String, String)
    */
   public synchronized boolean isSuccessfullCompletedDigestAgreementRequestPhase(String contextID, String nonce) {
      final String fn = "[isSuccessfullCompletedDigestAgreementRequestPhase] ";
      boolean result = false;
      if (contextID != null && contextID.length() > 0 && nonce != null && nonce.length() > 0) {
         CommunicationProcess commProc = getCommunicationProcess(contextID, nonce);
         if (commProc.hasRequestPhaseDigestAgreementProcess() && commProc.getRequestPhaseDigestAgreementProcess().isSuccessfull()) {
            result = true;
         }
      } else {
         StringBuffer err = new StringBuffer("CHECK FOR PARAMS FAILED: ");
         if (contextID == null) {
            err.append("contextID was NULL!");
         } else if (contextID.length() == 0) {
            err.append("contextID had ZERO length!");
         } else if (nonce == null) {
            err.append("nonce was NULL!");
         } else if (nonce.length() == 0) {
            err.append("nonce had ZERO length!!");
         }
         inhLogger.error(fn + err);
      }
      return result;
   }

   /**
    * @see IFContextManager#isFailedDigestAgreementRequestPhase(String, String)
    */
   public synchronized boolean isFailedDigestAgreementRequestPhase(String contextID, String nonce) {
      final String fn = "[isFailedDigestAgreementRequestPhase] ";
      boolean result = false;
      if (contextID != null && contextID.length() > 0 && nonce != null && nonce.length() > 0) {
         CommunicationProcess commProc = getCommunicationProcess(contextID, nonce);
         if (commProc.hasRequestPhaseDigestAgreementProcess() && commProc.getRequestPhaseDigestAgreementProcess().isFailed()) {
            result = true;
         }
      } else {
         StringBuffer err = new StringBuffer("CHECK FOR PARAMS FAILED: ");
         if (contextID == null) {
            err.append("contextID was NULL!");
         } else if (contextID.length() == 0) {
            err.append("contextID had ZERO length!");
         } else if (nonce == null) {
            err.append("nonce was NULL!");
         } else if (nonce.length() == 0) {
            err.append("nonce had ZERO length!!");
         }
         inhLogger.error(fn + err);
      }
      return result;
   }

   /**
    * @see IFContextManager#isRunningDigestAgreementResponsePhase(String, String)
    */
   public synchronized boolean isRunningDigestAgreementResponsePhase(String contextID, String nonce) {
      final String fn = "[isRunningDigestAgreementResponsePhase] ";
      boolean result = false;
      if (contextID != null && contextID.length() > 0 && nonce != null && nonce.length() > 0) {
         CommunicationProcess commProc = getCommunicationProcess(contextID, nonce);
         if (commProc.hasResponsePhaseDigestAgreementProcess() && commProc.getResponsePhaseDigestAgreementProcess().isWaitingForResponse()) {
            result = true;
         }
      } else {
         StringBuffer err = new StringBuffer("CHECK FOR PARAMS FAILED: ");
         if (contextID == null) {
            err.append("contextID was NULL!");
         } else if (contextID.length() == 0) {
            err.append("contextID had ZERO length!");
         } else if (nonce == null) {
            err.append("nonce was NULL!");
         } else if (nonce.length() == 0) {
            err.append("nonce had ZERO length!!");
         }
         inhLogger.error(fn + err);
      }
      return result;
   }

   /**
    * @see IFContextManager#isSuccessfullCompletedDigestAgreementResponsePhase(String, String)
    */
   public synchronized boolean isSuccessfullCompletedDigestAgreementResponsePhase(String contextID, String nonce) {
      final String fn = "[isSuccessfullCompletedDigestAgreementResponsePhase] ";
      boolean result = false;
      if (contextID != null && contextID.length() > 0 && nonce != null && nonce.length() > 0) {
         CommunicationProcess commProc = getCommunicationProcess(contextID, nonce);
         if (commProc.hasResponsePhaseDigestAgreementProcess() && commProc.getResponsePhaseDigestAgreementProcess().isSuccessfull()) {
            result = true;
         }
      } else {
         StringBuffer err = new StringBuffer("CHECK FOR PARAMS FAILED: ");
         if (contextID == null) {
            err.append("contextID was NULL!");
         } else if (contextID.length() == 0) {
            err.append("contextID had ZERO length!");
         } else if (nonce == null) {
            err.append("nonce was NULL!");
         } else if (nonce.length() == 0) {
            err.append("nonce had ZERO length!!");
         }
         inhLogger.error(fn + err);
      }
      return result;
   }

   /**
    * @see IFContextManager#isFailedDigestAgreementResponsePhase(String, String)
    */
   public synchronized boolean isFailedDigestAgreementResponsePhase(String contextID, String nonce) {
      final String fn = "[isFailedDigestAgreementResponsePhase] ";
      boolean result = false;
      if (contextID != null && contextID.length() > 0 && nonce != null && nonce.length() > 0) {
         CommunicationProcess commProc = getCommunicationProcess(contextID, nonce);
         if (commProc.hasResponsePhaseDigestAgreementProcess() && commProc.getResponsePhaseDigestAgreementProcess().isFailed()) {
            result = true;
         }
      } else {
         StringBuffer err = new StringBuffer("CHECK FOR PARAMS FAILED: ");
         if (contextID == null) {
            err.append("contextID was NULL!");
         } else if (contextID.length() == 0) {
            err.append("contextID had ZERO length!");
         } else if (nonce == null) {
            err.append("nonce was NULL!");
         } else if (nonce.length() == 0) {
            err.append("nonce had ZERO length!!");
         }
         inhLogger.error(fn + err);
      }
      return result;
   }

   /**
    * Fires the event that indicates that a new communication-process has been initiated
    * @param ev the event to be fired
    */
   private void fireCommunicationInitiatedEvent(IFCommunicationInitiatedEvent ev) {
      final String fn = "[fireCommunicationInitiatedEvent] ";
      if (logger.isDebugEnabled()) logger.debug(fn + "firing event '" + ev + "' to '" + communicationInitiatedListener.size() + "' listeners");
      for (int i = 0; i < communicationInitiatedListener.size(); i++) {
         IFCommunicationInitiatedListener initiatedListener = (IFCommunicationInitiatedListener) communicationInitiatedListener.get(i);
         initiatedListener.eventOccurred(ev);
      }
   }

   /**
    * Fires the event that indicates that a communication-process has been closed
    * @param ev the event to be fired
    */
   private void fireCommunicationClosedEvent(IFCommunicationClosedEvent ev) {
      final String fn = "[fireCommunicationClosedEvent] ";
      if (logger.isDebugEnabled()) logger.debug(fn + "firing event '" + ev + "' to '" + communicationClosedListener.size() + "' listeners");
      for (int i = 0; i < communicationClosedListener.size(); i++) {
         IFCommunicationClosedListener closedListener = (IFCommunicationClosedListener) communicationClosedListener.get(i);
         closedListener.eventOccurred(ev);
      }
   }

   /**
    * Fires the event that indicates that a new digest-agreement-process has been initiated
    * @param ev the event to be fired
    */
   private void fireDigestAgreementInitiatedEvent(IFDigestAgreementInitiatedEvent ev) {
      final String fn = "[fireDigestAgreementInitiatedEvent] ";
      if (logger.isDebugEnabled()) logger.debug(fn + "firing event '" + ev + "' to '" + digestAgreementInitiatedListener.size() + "' listeners");
      for (int i = 0; i < digestAgreementInitiatedListener.size(); i++) {
         IFDigestAgreementInitiatedListener initiatedListener = (IFDigestAgreementInitiatedListener) digestAgreementInitiatedListener.get(i);
         initiatedListener.eventOccurred(ev);
      }
   }

   /**
    * Fires the event that indicates that a digest-agreement-process has been closed
    * @param ev the event to be fired
    */
   private void fireDigestAgreementClosedEvent(IFDigestAgreementClosedEvent ev) {
      final String fn = "[fireDigestAgreementClosedEvent] ";
      if (logger.isDebugEnabled()) logger.debug(fn + "firing event '" + ev + "' to '" + digestAgreementClosedListener.size() + "' listeners");
      for (int i = 0; i < digestAgreementClosedListener.size(); i++) {
         IFDigestAgreementClosedListener closedListener = (IFDigestAgreementClosedListener) digestAgreementClosedListener.get(i);
         closedListener.eventOccurred(ev);
      }
   }

   /**
    * @see IFContextManager#addCommunicationInitiatedListener(de.tu_dresden.diplom.richter_mirko_mat2628335.common.listener.IFCommunicationInitiatedListener)
    */
   public void addCommunicationInitiatedListener(IFCommunicationInitiatedListener listener) {
      final String fn = "[addCommunicationInitiatedListener] ";
      if (listener != null) {
         communicationInitiatedListener.add(listener);
      } else {
         logger.warn(fn + "PARAM CHECK FAILED: listener was NULL!");
      }
   }

   /**
    * @see IFContextManager#removeCommunicationInitiatedListener(de.tu_dresden.diplom.richter_mirko_mat2628335.common.listener.IFCommunicationInitiatedListener)
    */
   public void removeCommunicationInitiatedListener(IFCommunicationInitiatedListener listener) {
      final String fn = "[removeCommunicationInitiatedListener] ";
      if (listener != null) {
         communicationInitiatedListener.remove(listener);
      } else {
         logger.warn(fn + "PARAM CHECK FAILED: listener was NULL!");
      }
   }

   /**
    * @see IFContextManager#addCommunicationClosedListener(de.tu_dresden.diplom.richter_mirko_mat2628335.common.listener.IFCommunicationClosedListener)
    */
   public void addCommunicationClosedListener(IFCommunicationClosedListener listener) {
      final String fn = "[addCommunicationClosedListener] ";
      if (listener != null) {
         communicationClosedListener.add(listener);
      } else {
         logger.warn(fn + "PARAM CHECK FAILED: listener was NULL!");
      }
   }

   /**
    * @see IFContextManager#removeCommunicationClosedListener(de.tu_dresden.diplom.richter_mirko_mat2628335.common.listener.IFCommunicationClosedListener)
    */
   public void removeCommunicationClosedListener(IFCommunicationClosedListener listener) {
      final String fn = "[removeCommunicationClosedListener] ";
      if (listener != null) {
         communicationClosedListener.remove(listener);
      } else {
         logger.warn(fn + "PARAM CHECK FAILED: listener was NULL!");
      }
   }

   /**
    * @see IFContextManager#addDigestAgreementInitiatedListener(de.tu_dresden.diplom.richter_mirko_mat2628335.common.listener.IFDigestAgreementInitiatedListener)
    */
   public void addDigestAgreementInitiatedListener(IFDigestAgreementInitiatedListener listener) {
      final String fn = "[addDigestAgreementInitiatedListener] ";
      if (listener != null) {
         digestAgreementInitiatedListener.add(listener);
      } else {
         logger.warn(fn + "PARAM CHECK FAILED: listener was NULL!");
      }
   }

   /**
    * @see IFContextManager#removeDigestAgreementInitiatedListener(de.tu_dresden.diplom.richter_mirko_mat2628335.common.listener.IFDigestAgreementInitiatedListener)
    */
   public void removeDigestAgreementInitiatedListener(IFDigestAgreementInitiatedListener listener) {
      final String fn = "[removeDigestAgreementInitiatedListener] ";
      if (listener != null) {
         digestAgreementInitiatedListener.add(listener);
      } else {
         logger.warn(fn + "PARAM CHECK FAILED: listener was NULL!");
      }
   }

   /**
    * @see IFContextManager#addDigestAgreementClosedListener(de.tu_dresden.diplom.richter_mirko_mat2628335.common.listener.IFDigestAgreementClosedListener)
    */
   public void addDigestAgreementClosedListener(IFDigestAgreementClosedListener listener) {
      final String fn = "[addDigestAgreementClosedListener] ";
      if (listener != null) {
         digestAgreementClosedListener.add(listener);
      } else {
         logger.warn(fn + "PARAM CHECK FAILED: listener was NULL!");
      }
   }

   /**
    * @see IFContextManager#removeDigestAgreementClosedListener(de.tu_dresden.diplom.richter_mirko_mat2628335.common.listener.IFDigestAgreementClosedListener)
    */
   public void removeDigestAgreementClosedListener(IFDigestAgreementClosedListener listener) {
      final String fn = "[removeDigestAgreementClosedListener] ";
      if (listener != null) {
         digestAgreementClosedListener.remove(listener);
      } else {
         logger.warn(fn + "PARAM CHECK FAILED: listener was NULL!");
      }
   }

   /**
    * Internal class that represents a communication-process (running rom step 1 through 6 -&gt; see written part of this thesis)
    */
   private class CommunicationProcess {

      private IFCountingContext countingContext = null;
      private DigestAgreementProcess requestPhaseDigestAgreementProcess = null;
      private DigestAgreementProcess responsePhaseDigestAgreementProcess = null;

      /**
       * Creates a new process from the given counting context.
       * @param countingContext the context
       */
      public CommunicationProcess(IFCountingContext countingContext) {
         this.countingContext = countingContext;
      }

      /**
       * Gets the countingContext on that this process bases.
       * @return the countingContext
       */
      public IFCountingContext getCountingContext() {
         return countingContext;
      }

      /**
       * Returns the current state of this process in a human-readable manner for printing to log
       * or system.
       * @return the human-readable state of this process
       */
      public String getCurrentStateHumanReadable() {
         StringBuffer result = new StringBuffer();
         if (hasRequestPhaseDigestAgreementProcess()) {
            result.append("RequestPhaseDigestAgreementProcess (procId:'").append(getRequestPhaseDigestAgreementProcess().getProcessIdentification()).append("')-> ");
            if (getRequestPhaseDigestAgreementProcess().isSuccessfull()) {
               result.append("SUCCESS");
            } else if (getRequestPhaseDigestAgreementProcess().isFailed()) {
               result.append("FAILED");
            } else if (getRequestPhaseDigestAgreementProcess().isWaitingForResponse()) {
               result.append("WAITING4RESPONSE");
            }
         } else {
            result.append("NO DigestAgreementProcess registered. ");
         }
         if (hasResponsePhaseDigestAgreementProcess()) {
            result.append(" | ResponsePhaseDigestAgreementProcess (procId:'").append(getResponsePhaseDigestAgreementProcess().getProcessIdentification()).append("')-> ");
            if (getResponsePhaseDigestAgreementProcess().isSuccessfull()) {
               result.append("SUCCESS");
            } else if (getResponsePhaseDigestAgreementProcess().isFailed()) {
               result.append("FAILED");
            } else if (getResponsePhaseDigestAgreementProcess().isWaitingForResponse()) {
               result.append("WAITING4RESPONSE");
            }
         }
         return result.toString();
      }

      /**
       * Gets the digestAgreementProcess (request-phase) from this communication-process
       * @return the process if existing, NULL else
       */
      public DigestAgreementProcess getRequestPhaseDigestAgreementProcess() {
         return requestPhaseDigestAgreementProcess;
      }

      /**
       * Sets a new digestAgreementProcess (request-phase) into this communication-process.<br/>
       * This operation is only possible if no other digest-agreement-process already exists!
       * @param requestPhaseDigestAgreementProcess the process to be registered
       */
      public void setRequestPhaseDigestAgreementProcess(DigestAgreementProcess requestPhaseDigestAgreementProcess) {
         final String fn = "[setRequestPhaseDigestAgreementProcess] ";
         if (!hasRequestPhaseDigestAgreementProcess() && !hasResponsePhaseDigestAgreementProcess() && requestPhaseDigestAgreementProcess != null) {
            this.requestPhaseDigestAgreementProcess = requestPhaseDigestAgreementProcess;
         } else {
            inhLogger.error(fn + "couldn't set requestPhaseDigestAgreementProcess because it is NULL or already set!");
         }
      }

      /**
       * Checks wheater a digest-agreement-process (request-phase) exists or not
       * @return true if exists, false else
       */
      public boolean hasRequestPhaseDigestAgreementProcess() {
         return getRequestPhaseDigestAgreementProcess() != null;
      }

      /**
       * Gets the digestAgreementProcess (response-phase) from this communication-process
       * @return the process if existing, NULL else
       */
      public DigestAgreementProcess getResponsePhaseDigestAgreementProcess() {
         return responsePhaseDigestAgreementProcess;
      }

      /**
       * Sets a new digestAgreementProcess (response-phase) into this communication-process.<br/>
       * This operation is only possible if no other digest-agreement-process already exists and
       * a digest-agreement-process (request-phase) has been performed and is not WAITING!
       * @param responsePhaseDigestAgreementProcess the process to be registered
       */
      public void setResponsePhaseDigestAgreementProcess(DigestAgreementProcess responsePhaseDigestAgreementProcess) {
         final String fn = "[setResponsePhaseDigestAgreementProcess] ";
         if (hasRequestPhaseDigestAgreementProcess() && !hasResponsePhaseDigestAgreementProcess() && responsePhaseDigestAgreementProcess != null && !getRequestPhaseDigestAgreementProcess().isWaitingForResponse()) {
            this.responsePhaseDigestAgreementProcess = responsePhaseDigestAgreementProcess;
         } else {
            inhLogger.error(fn + "couldn't set responsePhaseDigestAgreementProcess because it is NULL or already set!");
         }
      }

      /**
       * Checks wheater a digest-agreement-process (response-phase) exists or not
       * @return true if exists, false else
       */
      public boolean hasResponsePhaseDigestAgreementProcess() {
         return getResponsePhaseDigestAgreementProcess() != null;
      }

      /**
       * Adds a digestAgreementResponse-object and tries to determine if it is the response
       * for a request out of request- or response-phase.
       * @param response the response to be added
       */
      public void addDigestAgreementResponse(IFDigestAgreementResponse response) {
         final String fn = "[addDigestAgreementResponse] ";
         if (hasRequestPhaseDigestAgreementProcess() && !hasResponsePhaseDigestAgreementProcess()) {
            //@TODO concatenate the response with the request-phase-process
         } else if (hasRequestPhaseDigestAgreementProcess() && hasResponsePhaseDigestAgreementProcess()) {
            //@TODO concatenate the response with the response-phase-process
         } else {
            inhLogger.error(fn + "couldn't add digestAgreementResponse because of invalid state!");
         }
      }

   }

   /**
    * Internal representation of some digest-agreement-process.
    */
   private class DigestAgreementProcess {

      private IFDigestAgreementRequest digestAgreementRequest = null;
      private IFDigestAgreementResponse digestAgreementResponse = null;
      private String contextID = null;

      /**
       * Creates anew process out of the given request and contextID
       * @param digestAgrementRequest the request from which to create
       * @param contextID the context under which this process runs
       */
      public DigestAgreementProcess(IFDigestAgreementRequest digestAgrementRequest, String contextID) {
         this.digestAgreementRequest = digestAgrementRequest;
         this.contextID = contextID;
      }

      /**
       * Gets the identification of this process (the digest)
       * @return the identification
       */
      public String getProcessIdentification() {
         final String fn = "[getProcessIdentification] ";
         String result = null;
         if (digestAgreementRequest != null) {
            result = digestAgreementRequest.getDigest();
         } else {
            inhLogger.fatal(fn + "couldn't determine process identification because digestAgreementRequest is NULL!");
         }
         return result;
      }

      /**
       * Tries to set the digestAgreementResponse that has been sent by the witness into that process
       * @param response that response that should be set
       * @return true if successfull set, false else
       */
      public boolean setDigestAgreementResponse(IFDigestAgreementResponse response) {
         final String fn = "[DigestAgreementProcess.setDigestAgreementResponse] ";
         boolean result = false;
         if (this.digestAgreementResponse == null) {
            if (response.getAgreementReference().equals(digestAgreementRequest.getDigest())) {
               this.digestAgreementResponse = response;
               result = true;
            } else {
               inhLogger.error(fn + "digestAgreementResponse (agreementReference: '" + response.getAgreementReference() + "') doesn't match to digestAreementRequest (digest: '" + digestAgreementRequest.getDigest() + "')");
            }
         } else {
            inhLogger.error(fn + "couldn't set digestAgreementResponse because it is already set!");
         }
         return result;
      }

      /**
       * Checks wheather this process has been successfull completed or not.
       * @return true if successfull completed, false else
       */
      public boolean isSuccessfull() {
         boolean result = false;
         if (digestAgreementRequest != null && digestAgreementResponse != null && digestAgreementResponse.isSuccess()) {
            result = true;
         }
         return result;
      }

      /**
       * Checks wheather this process is still waiting for response from witness or not.
       * @return true if still waiting, false else
       */
      public boolean isWaitingForResponse() {
         boolean result = false;
         if (digestAgreementRequest != null && digestAgreementResponse == null) {
            result = true;
         }
         return result;
      }

      /**
       * Checks wheather this process has failed (FAILED from witness) or not.
       * @return true if failed, false else
       */
      public boolean isFailed() {
         boolean result = false;
         if (digestAgreementRequest != null && digestAgreementResponse != null && !digestAgreementResponse.isSuccess()) {
            result = true;
         }
         return result;
      }

   }

   /**
    * For better understanding of the Log-Messages the baseManager (abstract) doesn't log
    * standard-information through its own logger but through the logger of ist concrete
    * implementation.
    * @return the logger to use
    */
   public abstract Logger getInheritedLogger();

}
