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 legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2009 Sun Microsystems, Inc.
025 */
026
027package org.forgerock.opendj.ldap;
028
029/**
030 * The result of a tri-state logical expression. Condition results are used to
031 * represent the result of a conditional evaluation that can yield three
032 * possible values: {@code FALSE} (i.e. "no"), {@code TRUE} (i.e. "yes"), or
033 * {@code UNDEFINED} (i.e. "maybe"). A result of {@code UNDEFINED} indicates
034 * that further investigation may be required.
035 */
036public enum ConditionResult {
037    /**
038     * Indicates that the condition evaluated to {@code false}.
039     */
040    FALSE("false"),
041
042    /**
043     * Indicates that the condition could not be evaluated and its result is
044     * undefined.
045     */
046    UNDEFINED("undefined"),
047
048    /**
049     * Indicates that the condition evaluated to {@code true}.
050     */
051    TRUE("true");
052
053    /** Boolean -> ConditionResult map. */
054    private static final boolean[] BOOLEAN_MAP = { false, false, true };
055
056    /** AND truth table. */
057    private static final ConditionResult[][] LOGICAL_AND = { { FALSE, FALSE, FALSE },
058        { FALSE, UNDEFINED, UNDEFINED }, { FALSE, UNDEFINED, TRUE }, };
059
060    /** NOT truth table. */
061    private static final ConditionResult[] LOGICAL_NOT = { TRUE, UNDEFINED, FALSE };
062
063    /** OR truth table. */
064    private static final ConditionResult[][] LOGICAL_OR = { { FALSE, UNDEFINED, TRUE },
065        { UNDEFINED, UNDEFINED, TRUE }, { TRUE, TRUE, TRUE }, };
066
067    /**
068     * Returns the logical AND of zero condition results, which is always
069     * {@code TRUE}.
070     *
071     * @return The logical OR of zero condition results, which is always
072     *         {@code TRUE}.
073     */
074    public static ConditionResult and() {
075        return TRUE;
076    }
077
078    /**
079     * Returns the logical AND of the provided condition result, which is always
080     * {@code r}.
081     *
082     * @param r
083     *            The condition result.
084     * @return The logical AND of the provided condition result, which is always
085     *         {@code r}.
086     */
087    public static ConditionResult and(final ConditionResult r) {
088        return r;
089    }
090
091    /**
092     * Returns the logical AND of the provided condition results, which is
093     * {@code TRUE} if all of the provided condition results are {@code TRUE},
094     * {@code FALSE} if at least one of them is {@code FALSE}, and
095     * {@code UNDEFINED} otherwise. Note that {@code TRUE} is returned if the
096     * provided list of results is empty.
097     *
098     * @param results
099     *            The condition results to be compared.
100     * @return The logical AND of the provided condition results.
101     */
102    public static ConditionResult and(final ConditionResult... results) {
103        ConditionResult finalResult = TRUE;
104        for (final ConditionResult result : results) {
105            finalResult = and(finalResult, result);
106            if (finalResult == FALSE) {
107                break;
108            }
109        }
110        return finalResult;
111    }
112
113    /**
114     * Returns the logical AND of the provided condition results, which is
115     * {@code TRUE} if both of the provided condition results are {@code TRUE},
116     * {@code FALSE} if at least one of them is {@code FALSE} , and
117     * {@code UNDEFINED} otherwise.
118     *
119     * @param r1
120     *            The first condition result to be compared.
121     * @param r2
122     *            The second condition result to be compared.
123     * @return The logical AND of the provided condition results.
124     */
125    public static ConditionResult and(final ConditionResult r1, final ConditionResult r2) {
126        return LOGICAL_AND[r1.ordinal()][r2.ordinal()];
127    }
128
129    /**
130     * Returns the logical NOT of the provided condition result, which is
131     * {@code TRUE} if the provided condition result is {@code FALSE},
132     * {@code TRUE} if it is {@code FALSE}, and {@code UNDEFINED} otherwise.
133     *
134     * @param r
135     *            The condition result to invert.
136     * @return The logical NOT of the provided condition result.
137     */
138    public static ConditionResult not(final ConditionResult r) {
139        return LOGICAL_NOT[r.ordinal()];
140    }
141
142    /**
143     * Returns the logical OR of zero condition results, which is always
144     * {@code FALSE}.
145     *
146     * @return The logical OR of zero condition results, which is always
147     *         {@code FALSE}.
148     */
149    public static ConditionResult or() {
150        return FALSE;
151    }
152
153    /**
154     * Returns the logical OR of the provided condition result, which is always
155     * {@code r}.
156     *
157     * @param r
158     *            The condition result.
159     * @return The logical OR of the provided condition result, which is always
160     *         {@code r}.
161     */
162    public static ConditionResult or(final ConditionResult r) {
163        return r;
164    }
165
166    /**
167     * Returns the logical OR of the provided condition results, which is
168     * {@code FALSE} if all of the provided condition results are {@code FALSE},
169     * {@code TRUE} if at least one of them is {@code TRUE}, and
170     * {@code UNDEFINED} otherwise. Note that {@code FALSE} is returned if the
171     * provided list of results is empty.
172     *
173     * @param results
174     *            The condition results to be compared.
175     * @return The logical OR of the provided condition results.
176     */
177    public static ConditionResult or(final ConditionResult... results) {
178        ConditionResult finalResult = FALSE;
179        for (final ConditionResult result : results) {
180            finalResult = or(finalResult, result);
181            if (finalResult == TRUE) {
182                break;
183            }
184        }
185        return finalResult;
186    }
187
188    /**
189     * Returns the logical OR of the provided condition results, which is
190     * {@code FALSE} if both of the provided condition results are {@code FALSE}
191     * , {@code TRUE} if at least one of them is {@code TRUE} , and
192     * {@code UNDEFINED} otherwise.
193     *
194     * @param r1
195     *            The first condition result to be compared.
196     * @param r2
197     *            The second condition result to be compared.
198     * @return The logical OR of the provided condition results.
199     */
200    public static ConditionResult or(final ConditionResult r1, final ConditionResult r2) {
201        return LOGICAL_OR[r1.ordinal()][r2.ordinal()];
202    }
203
204    /**
205     * Returns the condition result which is equivalent to the provided boolean
206     * value.
207     *
208     * @param b
209     *            The boolean value.
210     * @return {@code TRUE} if {@code b} was {@code true}, otherwise
211     *         {@code FALSE} .
212     */
213    public static ConditionResult valueOf(final boolean b) {
214        return b ? TRUE : FALSE;
215    }
216
217    /** The human-readable name for this result. */
218    private final String resultName;
219
220    /** Prevent instantiation. */
221    private ConditionResult(final String resultName) {
222        this.resultName = resultName;
223    }
224
225    /**
226     * Converts this condition result to a boolean value. {@code FALSE} and
227     * {@code UNDEFINED} are both converted to {@code false}, and {@code TRUE}
228     * is converted to {@code true}.
229     *
230     * @return The boolean equivalent of this condition result.
231     */
232    public boolean toBoolean() {
233        return BOOLEAN_MAP[ordinal()];
234    }
235
236    /**
237     * Returns the string representation of this condition result.
238     *
239     * @return The string representation of his condition result.
240     */
241    @Override
242    public String toString() {
243        return resultName;
244    }
245}