From 0e47fcf59332b96c43f4737143025e07f8202638 Mon Sep 17 00:00:00 2001
From: jdemendi <jdemendi@localhost>
Date: Fri, 31 Oct 2008 11:12:52 +0000
Subject: [PATCH] fix 35353, Workflows are not notified when their root workflow elements are disabled

---
 opends/src/server/org/opends/server/workflowelement/WorkflowElement.java |  184 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 182 insertions(+), 2 deletions(-)

diff --git a/opends/src/server/org/opends/server/workflowelement/WorkflowElement.java b/opends/src/server/org/opends/server/workflowelement/WorkflowElement.java
index 7b8a29b..80eaff5 100644
--- a/opends/src/server/org/opends/server/workflowelement/WorkflowElement.java
+++ b/opends/src/server/org/opends/server/workflowelement/WorkflowElement.java
@@ -27,7 +27,13 @@
 package org.opends.server.workflowelement;
 
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Observable;
+import java.util.Observer;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
 import org.opends.server.admin.std.server.WorkflowElementCfg;
 import org.opends.server.types.Operation;
 import org.opends.server.types.CanceledOperationException;
@@ -44,8 +50,8 @@
  *
  * @param  <T>  The type of configuration handled by this workflow element.
  */
-public abstract class WorkflowElement
-       <T extends WorkflowElementCfg>
+public abstract class WorkflowElement <T extends WorkflowElementCfg>
+    implements Observer
 {
   // Indicates whether the workflow element encapsulates a private local
   // backend.
@@ -61,6 +67,170 @@
   private String workflowElementID = null;
 
 
+  // The observable state of the workflow element.
+  private ObservableWorkflowElementState observableState =
+    new ObservableWorkflowElementState(this);
+
+
+  // The list of observers who want to be notified when a workflow element
+  // required by the observer is created. The key of the map is a string
+  // that identifies the newly created workflow element.
+  private static ConcurrentMap<String, List<Observer>>
+    newWorkflowElementNotificationList =
+      new ConcurrentHashMap<String, List<Observer>>();
+
+
+  /**
+   * Provides the observable state of the workflow element.
+   * This method is intended to be called by the WorkflowElementConfigManager
+   * that wants to notify observers that the workflow element state has
+   * changed (in particular when a workflow element has been disabled).
+   *
+   * @return the observable state of the workflow element
+   */
+  protected ObservableWorkflowElementState getObservableState()
+  {
+    return observableState;
+  }
+
+
+  /**
+   * Registers with a specific workflow element to be notified when the
+   * workflow element state has changed. This notification system is
+   * mainly used to be warned when a workflow element is enabled or
+   * disabled.
+   * <p>
+   * If the workflow element <code>we</code> is not <code>null</code>
+   * then the <code>observer</code> is registered with the list of objects
+   * to notify when <code>we</code> has changed.
+   * <p>
+   * If the workflow element <code>we</code> is <code>null</code> then
+   * the <code>observer</code> is registered with a static list of objects
+   * to notify when a workflow element named <code>weid</code> is created.
+   *
+   * @param we        the workflow element. If <code>null</code> then observer
+   *                  is registered with a list of workflow element
+   *                  identifiers.
+   * @param weid      the identifier of the workflow element. This parameter
+   *                  is useless when <code>we</code> is not <code>null</code>
+   * @param observer  the observer to notify when the workflow element state
+   *                  has been modified
+   */
+  public static void registereForStateUpdate(
+      WorkflowElement<?> we,
+      String weid,
+      Observer observer
+      )
+  {
+    // If the workflow element "we" exists then register the observer with "we"
+    // else register the observer with a static list of workflow element
+    // identifiers
+    if (we != null)
+    {
+      ObservableWorkflowElementState westate = we.getObservableState();
+      westate.addObserver(observer);
+    }
+    else
+    {
+      if (weid == null)
+      {
+        return;
+      }
+
+      List<Observer> observers = newWorkflowElementNotificationList.get(weid);
+      if (observers == null)
+      {
+        // create the list of observers
+        observers = new ArrayList<Observer>();
+        observers.add(observer);
+        newWorkflowElementNotificationList.put(weid, observers);
+      }
+      else
+      {
+        // update the observer list
+        observers.add(observer);
+      }
+    }
+  }
+
+
+  /**
+   * Deregisters an observer that was registered with a specific workflow
+   * element.
+   * <p>
+   * If the workflow element <code>we</code> is not <code>null</code>
+   * then the <code>observer</code> is deregistered with the list of objects
+   * to notify when <code>we</code> has changed.
+   * <p>
+   * If the workflow element <code>we</code> is <code>null</code> then
+   * the <code>observer</code> is deregistered with a static list of objects
+   * to notify when a workflow element named <code>weid</code> is created.
+   *
+   * @param we        the workflow element. If <code>null</code> then observer
+   *                  is deregistered with a list of workflow element
+   *                  identifiers.
+   * @param weid      the identifier of the workflow element. This parameter
+   *                  is useless when <code>we</code> is not <code>null</code>
+   * @param observer  the observer to deregister
+   */
+  public static void deregistereForStateUpdate(
+      WorkflowElement<?> we,
+      String weid,
+      Observer observer
+      )
+  {
+    // If the workflow element "we" exists then deregister the observer
+    // with "we" else deregister the observer with a static list of
+    // workflow element identifiers
+    if (we != null)
+    {
+      ObservableWorkflowElementState westate = we.getObservableState();
+      westate.deleteObserver(observer);
+    }
+    else
+    {
+      List<Observer> observers = newWorkflowElementNotificationList.get(weid);
+      if (observers != null)
+      {
+        observers.remove(observer);
+      }
+    }
+  }
+
+
+  /**
+   * Notifies all the observers who want to be warn when a workflow element
+   * is created.
+   *
+   * @param workflowElement  the newly created workflow element
+   */
+  public static void notifyStateUpdate(
+      WorkflowElement<?> workflowElement)
+  {
+    // Go through the list of observers and notify them all
+    String weID = workflowElement.getWorkflowElementID();
+
+    List<Observer> observers = newWorkflowElementNotificationList.get(weID);
+    if (observers != null)
+    {
+      for (Observer observer: observers)
+      {
+        // The update might fail because an observer could have been
+        // terminated. In this case, just ignore the failure and remove
+        // the observer from the list of objects to notify.
+        try
+        {
+          observer.update(workflowElement.getObservableState(), null);
+        }
+        catch(Exception e)
+        {
+          observers.remove(observer);
+        }
+      }
+    }
+  }
+
+
   /**
    * Creates a new instance of the workflow element.
    */
@@ -69,6 +239,7 @@
     // There is nothing to do in the constructor.
   }
 
+
   /**
    * Initializes the instance of the workflow element.
    *
@@ -89,6 +260,15 @@
 
 
   /**
+   * {@inheritDoc}
+   */
+  public void update(Observable o, Object arg)
+  {
+    // By default, do nothing when notification hits the workflow element.
+  }
+
+
+  /**
    * Get the type of the workflow element. The type is a string information
    * indicating which type is the current workflow element. This information
    * is intended to be used by tools for trace and debug purpose.

--
Gitblit v1.10.0