001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.workflowelement;
028    
029    import static org.opends.server.util.Validator.ensureNotNull;
030    import static org.opends.messages.ConfigMessages.*;
031    
032    import java.util.List;
033    import java.util.TreeMap;
034    
035    import org.opends.messages.Message;
036    import org.opends.server.admin.std.server.WorkflowElementCfg;
037    import org.opends.server.config.ConfigException;
038    import org.opends.server.types.Operation;
039    import org.opends.server.types.CanceledOperationException;
040    
041    
042    /**
043     * This class defines the super class for all the workflow elements. A workflow
044     * element is a task in a workflow. A workflow element can wrap a physical
045     * repository such as a local backend, a remote LDAP server or a local ldif
046     * file. A workflow element can also be used to route operations. This is the
047     * case for load balancing and distribution. And workflow element can be used
048     * in a virtual environment to transform data (DN and attribute renaming,
049     * attribute value renaming...).
050     *
051     * @param  <T>  The type of configuration handled by this workflow elelemnt.
052     */
053    public abstract class WorkflowElement
054           <T extends WorkflowElementCfg>
055    {
056      // Indicates whether the workflow element encapsulates a private local
057      // backend.
058      private boolean isPrivate = false;
059    
060    
061      // The workflow element identifier.
062      private String workflowElementID = null;
063    
064    
065      // The set of workflow elements registered with the server.
066      // The workflow element identifier is used as a key in the map.
067      private static TreeMap<String, WorkflowElement> registeredWorkflowElements =
068        new TreeMap<String, WorkflowElement>();
069    
070    
071      // A lock to protect access to the registered workflow elements.
072      private static Object registeredWorkflowElementsLock = new Object();
073    
074    
075      // The parent of the workflow element (null if the workflow element is
076      // the root of the processing tree).
077      private WorkflowElement<?> parent = null;
078    
079    
080      /**
081       * Creates a new instance of the workflow element.
082       */
083      public WorkflowElement()
084      {
085        // There is nothing to do in the constructor.
086      }
087    
088    
089      /**
090       * Initializes the instance of the workflow element.
091       *
092       * @param workflowElementID  the workflow element identifier as defined
093       *                           in the configuration.
094       */
095      public void initialize(String workflowElementID)
096      {
097        this.workflowElementID = workflowElementID;
098      }
099    
100    
101      /**
102       * Set the parent of the current workflow element.
103       *
104       * @param parent  the parent of the workflow element
105       */
106      protected void setParent(WorkflowElement<?> parent)
107      {
108        this.parent = parent;
109      }
110    
111    
112      /**
113       * Indicates whether the provided configuration is acceptable for
114       * this workflow elelement.
115       *
116       * @param  configuration        The workflow element configuration for
117       *                              which to make the determination.
118       * @param  unacceptableReasons  A list that may be used to hold the
119       *                              reasons that the provided
120       *                              configuration is not acceptable.
121       *
122       * @return  {@code true} if the provided configuration is acceptable
123       *          for this workflow element, or {@code false} if not.
124       */
125      public boolean isConfigurationAcceptable(
126          WorkflowElementCfg configuration,
127          List<String> unacceptableReasons)
128      {
129        // This default implementation does not perform any special
130        // validation.  It should be overridden by workflow element
131        // implementations that wish to perform more detailed validation.
132        return true;
133      }
134    
135    
136      /**
137       * Performs any finalization that might be required when this
138       * workflow element is unloaded.  No action is taken in the default
139       * implementation.
140       */
141      public void finalizeWorkflowElement()
142      {
143        // No action is required by default.
144      }
145    
146    
147      /**
148       * Executes the workflow element for an operation.
149       *
150       * @param operation the operation to execute
151       *
152       * @throws CanceledOperationException if this operation should be
153       * cancelled
154       */
155      public abstract void execute(Operation operation)
156          throws CanceledOperationException;
157    
158    
159      /**
160       * Indicates whether the workflow element encapsulates a private
161       * local backend.
162       *
163       * @return <code>true</code> if the workflow element encapsulates a private
164       *         local backend, <code>false</code> otherwise
165       */
166      public boolean isPrivate()
167      {
168        return isPrivate;
169      }
170    
171    
172      /**
173       * Specifies whether the workflow element encapsulates a private local
174       * backend.
175       *
176       * @param  isPrivate  Indicates whether the workflow element encapsulates a
177       *                    private local backend.
178       */
179      protected void setPrivate(boolean isPrivate)
180      {
181        this.isPrivate = isPrivate;
182      }
183    
184    
185      /**
186       * Provides the workflow element identifier.
187       *
188       * @return the worflow element identifier
189       */
190      public String getWorkflowElementID()
191      {
192        return workflowElementID;
193      }
194    
195    
196      /**
197       * Registers the workflow element (this) with the server.
198       *
199       * @throws  ConfigException  If the workflow element ID for the provided
200       *                           workflow element conflicts with the workflow
201       *                           element ID of an existing workflow element.
202       */
203      public void register()
204          throws ConfigException
205      {
206        ensureNotNull(workflowElementID);
207    
208        synchronized (registeredWorkflowElementsLock)
209        {
210          // the workflow element must not be already registered
211          if (registeredWorkflowElements.containsKey(workflowElementID))
212          {
213            Message message = ERR_CONFIG_WORKFLOW_ELEMENT_ALREADY_REGISTERED.get(
214                workflowElementID);
215            throw new ConfigException(message);
216          }
217    
218          TreeMap<String, WorkflowElement> newWorkflowElements =
219            new TreeMap<String, WorkflowElement>(registeredWorkflowElements);
220          newWorkflowElements.put(workflowElementID, this);
221          registeredWorkflowElements = newWorkflowElements;
222        }
223      }
224    
225    
226      /**
227       * Deregisters the workflow element (this) with the server.
228       */
229      public void deregister()
230      {
231        ensureNotNull(workflowElementID);
232    
233        synchronized (registeredWorkflowElementsLock)
234        {
235          TreeMap<String, WorkflowElement> newWorkflowElements =
236            new TreeMap<String, WorkflowElement>(registeredWorkflowElements);
237          newWorkflowElements.remove(workflowElementID);
238          registeredWorkflowElements = newWorkflowElements;
239        }
240      }
241    
242    
243      /**
244       * Gets a workflow element that was registered with the server.
245       *
246       * @param workflowElementID  the ID of the workflow element to get
247       * @return the requested workflow element
248       */
249      public static WorkflowElement getWorkflowElement(
250          String workflowElementID)
251      {
252        return registeredWorkflowElements.get(workflowElementID);
253      }
254    
255    
256      /**
257       * Resets all the registered workflows.
258       */
259      public static void resetConfig()
260      {
261        synchronized (registeredWorkflowElementsLock)
262        {
263          registeredWorkflowElements = new TreeMap<String, WorkflowElement>();
264        }
265      }
266    
267    }
268