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.util.cli;
028    
029    
030    
031    import java.util.ArrayList;
032    import java.util.Collection;
033    import java.util.Collections;
034    
035    
036    
037    /**
038     * The result of running a {@link Menu}. The result indicates to the
039     * application how it should proceed:
040     * <ul>
041     * <li>{@link #again()} - the menu should be displayed again. A good
042     * example of this is when a user chooses to view some help. Normally,
043     * after the help is displayed, the user is allowed to select another
044     * option
045     * <li>{@link #cancel()} - the user chose to cancel any task
046     * currently in progress and go back to the previous main menu if
047     * applicable
048     * <li>{@link #success()} - the user chose to apply any task
049     * currently in progress and go back to the previous menu if
050     * applicable. Any result values applicable to the chosen option can
051     * be retrieved using {@link #getValue()} or {@link #getValues()}
052     * <li>{@link #quit()} - the user chose to quit the application and
053     * cancel all outstanding tasks.
054     * </ul>
055     *
056     * @param <T>
057     *          The type of result value(s) contained in success results.
058     *          Use <code>Void</code> if success results should not
059     *          contain values.
060     */
061    public final class MenuResult<T> {
062    
063      /**
064       * The type of result returned from the menu.
065       */
066      private static enum Type {
067        /**
068         * The user selected an option which did not return a result, so
069         * the menu should be displayed again.
070         */
071        AGAIN,
072    
073        /**
074         * The user did not select an option and instead chose to cancel
075         * the current task.
076         */
077        CANCEL,
078    
079        /**
080         * The user did not select an option and instead chose to quit the
081         * entire application.
082         */
083        QUIT,
084    
085        /**
086         * The user selected an option which succeeded and returned one or
087         * more result values.
088         */
089        SUCCESS
090      }
091    
092    
093    
094      /**
095       * Creates a new menu result indicating that the menu should be
096       * displayed again. A good example of this is when a user chooses to
097       * view some help. Normally, after the help is displayed, the user
098       * is allowed to select another option.
099       *
100       * @param <T>
101       *          The type of result value(s) contained in success
102       *          results. Use <code>Void</code> if success results
103       *          should not contain values.
104       * @return Returns a new menu result indicating that the menu should
105       *         be displayed again.
106       */
107      public static <T> MenuResult<T> again() {
108        return new MenuResult<T>(Type.AGAIN, Collections.<T> emptyList());
109      }
110    
111    
112    
113      /**
114       * Creates a new menu result indicating that the user chose to
115       * cancel any task currently in progress and go back to the previous
116       * main menu if applicable.
117       *
118       * @param <T>
119       *          The type of result value(s) contained in success
120       *          results. Use <code>Void</code> if success results
121       *          should not contain values.
122       * @return Returns a new menu result indicating that the user chose
123       *         to cancel any task currently in progress and go back to
124       *         the previous main menu if applicable.
125       */
126      public static <T> MenuResult<T> cancel() {
127        return new MenuResult<T>(Type.CANCEL, Collections.<T> emptyList());
128      }
129    
130    
131    
132      /**
133       * Creates a new menu result indicating that the user chose to quit
134       * the application and cancel all outstanding tasks.
135       *
136       * @param <T>
137       *          The type of result value(s) contained in success
138       *          results. Use <code>Void</code> if success results
139       *          should not contain values.
140       * @return Returns a new menu result indicating that the user chose
141       *         to quit the application and cancel all outstanding tasks.
142       */
143      public static <T> MenuResult<T> quit() {
144        return new MenuResult<T>(Type.QUIT, Collections.<T> emptyList());
145      }
146    
147    
148    
149      /**
150       * Creates a new menu result indicating that the user chose to apply
151       * any task currently in progress and go back to the previous menu
152       * if applicable. The menu result will not contain any result
153       * values.
154       *
155       * @param <T>
156       *          The type of result value(s) contained in success
157       *          results. Use <code>Void</code> if success results
158       *          should not contain values.
159       * @return Returns a new menu result indicating that the user chose
160       *         to apply any task currently in progress and go back to
161       *         the previous menu if applicable.The menu result will not
162       *         contain any result values.
163       */
164      public static <T> MenuResult<T> success() {
165        return success(Collections.<T> emptySet());
166      }
167    
168    
169    
170      /**
171       * Creates a new menu result indicating that the user chose to apply
172       * any task currently in progress and go back to the previous menu
173       * if applicable. The menu result will contain the provided values,
174       * which can be retrieved using {@link #getValue()} or
175       * {@link #getValues()}.
176       *
177       * @param <T>
178       *          The type of the result values.
179       * @param values
180       *          The result values.
181       * @return Returns a new menu result indicating that the user chose
182       *         to apply any task currently in progress and go back to
183       *         the previous menu if applicable. The menu result will
184       *         contain the provided values, which can be retrieved using
185       *         {@link #getValue()} or {@link #getValues()}.
186       */
187      public static <T> MenuResult<T> success(Collection<T> values) {
188        return new MenuResult<T>(Type.SUCCESS, new ArrayList<T>(values));
189      }
190    
191    
192    
193      /**
194       * Creates a new menu result indicating that the user chose to apply
195       * any task currently in progress and go back to the previous menu
196       * if applicable. The menu result will contain the provided value,
197       * which can be retrieved using {@link #getValue()} or
198       * {@link #getValues()}.
199       *
200       * @param <T>
201       *          The type of the result value.
202       * @param value
203       *          The result value.
204       * @return Returns a new menu result indicating that the user chose
205       *         to apply any task currently in progress and go back to
206       *         the previous menu if applicable. The menu result will
207       *         contain the provided value, which can be retrieved using
208       *         {@link #getValue()} or {@link #getValues()}.
209       */
210      public static <T> MenuResult<T> success(T value) {
211        return success(Collections.singleton(value));
212      }
213    
214      // The type of result returned from the menu.
215      private final Type type;
216    
217      // The menu result value(s).
218      private final Collection<T> values;
219    
220    
221    
222      // Private constructor.
223      private MenuResult(Type type, Collection<T> values) {
224        this.type = type;
225        this.values = values;
226      }
227    
228    
229    
230      /**
231       * Gets the menu result value if this is a menu result indicating
232       * success.
233       *
234       * @return Returns the menu result value, or <code>null</code> if
235       *         there was no result value or if this is not a success
236       *         menu result.
237       * @see #isSuccess()
238       */
239      public T getValue() {
240        if (values.isEmpty()) {
241          return null;
242        } else {
243          return values.iterator().next();
244        }
245      }
246    
247    
248    
249      /**
250       * Gets the menu result values if this is a menu result indicating
251       * success.
252       *
253       * @return Returns the menu result values, which may be empty if
254       *         there were no result values or if this is not a success
255       *         menu result.
256       * @see #isSuccess()
257       */
258      public Collection<T> getValues() {
259        return new ArrayList<T>(values);
260      }
261    
262    
263    
264      /**
265       * Determines if this menu result indicates that the menu should be
266       * displayed again. A good example of this is when a user chooses to
267       * view some help. Normally, after the help is displayed, the user
268       * is allowed to select another option.
269       *
270       * @return Returns <code>true</code> if this menu result indicates
271       *         that the menu should be displayed again.
272       */
273      public boolean isAgain() {
274        return type == Type.AGAIN;
275      }
276    
277    
278    
279      /**
280       * Determines if this menu result indicates that the user chose to
281       * cancel any task currently in progress and go back to the previous
282       * main menu if applicable.
283       *
284       * @return Returns <code>true</code> if this menu result indicates
285       *         that the user chose to cancel any task currently in
286       *         progress and go back to the previous main menu if
287       *         applicable.
288       */
289      public boolean isCancel() {
290        return type == Type.CANCEL;
291      }
292    
293    
294    
295      /**
296       * Determines if this menu result indicates that the user chose to
297       * quit the application and cancel all outstanding tasks.
298       *
299       * @return Returns <code>true</code> if this menu result indicates
300       *         that the user chose to quit the application and cancel
301       *         all outstanding tasks.
302       */
303      public boolean isQuit() {
304        return type == Type.QUIT;
305      }
306    
307    
308    
309      /**
310       * Determines if this menu result indicates that the user chose to
311       * apply any task currently in progress and go back to the previous
312       * menu if applicable. Any result values can be retrieved using the
313       * {@link #getValue()} or {@link #getValues()} methods.
314       *
315       * @return Returns <code>true</code> if this menu result indicates
316       *         that the user chose to apply any task currently in
317       *         progress and go back to the previous menu if applicable.
318       * @see #getValue()
319       * @see #getValues()
320       */
321      public boolean isSuccess() {
322        return type == Type.SUCCESS;
323      }
324    }