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