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.core;
028    import org.opends.messages.Message;
029    import org.opends.messages.MessageBuilder;
030    
031    
032    import org.opends.server.types.ResultCode;
033    
034    
035    /**
036     * This class implements the workflow result code. The workflow result code
037     * contains an LDAP result code along with an LDAP error message.
038     */
039    public class WorkflowResultCode
040    {
041      // The global result code.
042      private ResultCode resultCode = ResultCode.UNDEFINED;
043    
044      // The global error message.
045      private MessageBuilder errorMessage = new MessageBuilder(Message.EMPTY);
046    
047    
048      /**
049       * Creates a new instance of a workflow result. By default the result code
050       * is set to UNDEFINED and there is no error message.
051       */
052      public WorkflowResultCode()
053      {
054        // Nothing to implement.
055      }
056    
057    
058      /**
059       * Creates a new instance of a workflow result code and initializes it
060       * with a result code and an error message.
061       *
062       * @param resultCode    the initial value for the result code
063       * @param errorMessage  the initial value for the error message
064       */
065      public WorkflowResultCode(
066          ResultCode     resultCode,
067          MessageBuilder errorMessage
068          )
069      {
070        this.resultCode   = resultCode;
071        this.errorMessage = errorMessage;
072      }
073    
074    
075      /**
076       * Elaborates a global result code. A workflow may execute an operation
077       * on several subordinate workflows. In such case, the parent workflow
078       * has to take into account all the subordinate result codes to elaborate
079       * a global result code.
080       *
081       * Sometimes, a referral result code has to be turned into a reference
082       * entry. When such case is occurring the elaborateGlobalResultCode method
083       * will return true.
084       *
085       * The global result code is elaborated as follows:
086       *
087       * <PRE>
088       *  -----------+------------+------------+-------------------------------
089       *  new        | current    | resulting  |
090       *  resultCode | resultCode | resultCode | action
091       *  -----------+------------+------------+-------------------------------
092       *  SUCCESS      NO_SUCH_OBJ  SUCCESS      -
093       *               REFERRAL     SUCCESS      send reference entry to client
094       *               other        [unchanged]  -
095       *  ---------------------------------------------------------------------
096       *  NO_SUCH_OBJ  SUCCESS      [unchanged]  -
097       *               REFERRAL     [unchanged]  -
098       *               other        [unchanged]  -
099       *  ---------------------------------------------------------------------
100       *  REFERRAL     SUCCESS      [unchanged]  send reference entry to client
101       *               REFERRAL     SUCCESS      send reference entry to client
102       *               NO_SUCH_OBJ  REFERRAL     -
103       *               other        [unchanged]  send reference entry to client
104       *  ---------------------------------------------------------------------
105       *  others       SUCCESS      other        -
106       *               REFERRAL     other        send reference entry to client
107       *               NO_SUCH_OBJ  other        -
108       *               other2       [unchanged]  -
109       *  ---------------------------------------------------------------------
110       * </PRE>
111       *
112       * @param newResultCode    the new result code to take into account
113       * @param newErrorMessage  the new error message associated to the new
114       *                         error code
115       * @return <code>true</code> if a referral result code must be turned
116       *         into a reference entry
117       */
118      public boolean elaborateGlobalResultCode(
119          ResultCode     newResultCode,
120          MessageBuilder newErrorMessage
121          )
122      {
123        // Returned value
124        boolean sendReferenceEntry = false;
125    
126        // if global result code has not been set yet then just take the new
127        // result code as is
128        if (resultCode == ResultCode.UNDEFINED)
129        {
130          resultCode   = newResultCode;
131          errorMessage = new MessageBuilder (newErrorMessage);
132        }
133        else
134        {
135          // Elaborate the new result code (see table in the description header).
136    
137          switch (newResultCode)
138          {
139          case SUCCESS:
140            //
141            // Received SUCCESS
142            // ----------------
143            //
144            switch (resultCode)
145            {
146              case NO_SUCH_OBJECT:
147                resultCode = ResultCode.SUCCESS;
148                errorMessage = new MessageBuilder(Message.EMPTY);
149                break;
150              case REFERRAL:
151                resultCode = ResultCode.SUCCESS;
152                errorMessage = new MessageBuilder(Message.EMPTY);
153                sendReferenceEntry = true;
154                break;
155              default:
156                // global resultCode remains the same
157                break;
158            }
159            break;
160          case NO_SUCH_OBJECT:
161            //
162            // Received NO SUCH OBJECT
163            // -----------------------
164            //
165            // global resultCode remains the same
166            break;
167          case REFERRAL:
168            //
169            // Received REFERRAL
170            // -----------------
171            //
172            switch (resultCode)
173            {
174              case REFERRAL:
175                resultCode = ResultCode.SUCCESS;
176                errorMessage = new MessageBuilder(Message.EMPTY);
177                sendReferenceEntry = true;
178                break;
179              case NO_SUCH_OBJECT:
180                resultCode = ResultCode.REFERRAL;
181                errorMessage = new MessageBuilder (Message.EMPTY);
182                break;
183              default:
184                // global resultCode remains the same
185                sendReferenceEntry = true;
186                break;
187            }
188            break;
189          default:
190            //
191            // Received other result codes
192            // ---------------------------
193            //
194            switch (resultCode)
195            {
196              case REFERRAL:
197                resultCode = newResultCode;
198                errorMessage = new MessageBuilder (newErrorMessage);
199                sendReferenceEntry = true;
200                break;
201              case SUCCESS:
202                resultCode = newResultCode;
203                errorMessage = new MessageBuilder (newErrorMessage);
204                break;
205              case NO_SUCH_OBJECT:
206                resultCode = newResultCode;
207                errorMessage = new MessageBuilder (newErrorMessage);
208                break;
209              default:
210                // global resultCode remains the same but append the new
211                // error message into the current error message
212                if (errorMessage == null)
213                {
214                  errorMessage =  new MessageBuilder (newErrorMessage);
215                }
216                else
217                {
218                  errorMessage.append(newErrorMessage);
219                }
220                break;
221            }
222            break;
223          }
224        }
225    
226        return sendReferenceEntry;
227      }
228    
229    
230      /**
231       * Returns the global result code.
232       *
233       * @return the global result code.
234       */
235      public ResultCode resultCode()
236      {
237        return resultCode;
238      }
239    
240    
241      /**
242       * Returns the global error message.
243       *
244       * @return the global error message.
245       */
246      public MessageBuilder errorMessage()
247      {
248        return errorMessage;
249      }
250    
251    }