001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.commons.lang;
018
019import static org.apache.juneau.commons.utils.AssertionUtils.*;
020import static org.apache.juneau.commons.utils.Utils.*;
021
022import java.util.concurrent.atomic.*;
023
024/**
025 * A simple mutable boolean value.
026 *
027 * <p>
028 * This class extends {@link Value}&lt;{@link Boolean}&gt; and provides a convenient way to pass mutable
029 * boolean references to lambdas, inner classes, or methods. Unlike {@link Flag}, this class supports three
030 * states: <c>true</c>, <c>false</c>, and <c>null</c>.
031 *
032 * <h5 class='section'>Notes:</h5><ul>
033 *    <li class='note'>
034 *       This class is <b>not thread-safe</b>. For concurrent access, use {@link AtomicBoolean} instead.
035 *    <li class='note'>
036 *       This class supports three states (<c>true</c>, <c>false</c>, <c>null</c>). If you only need
037 *       two states (<c>true</c>/<c>false</c>), consider using {@link Flag} instead.
038 * </ul>
039 *
040 * <h5 class='section'>Example:</h5>
041 * <p class='bjava'>
042 *    <jc>// Create a boolean value to track if a condition was met</jc>
043 *    BooleanValue <jv>found</jv> = BooleanValue.<jsm>create</jsm>();
044 *
045 *    <jc>// Use in a lambda</jc>
046 *    list.forEach(<jv>x</jv> -&gt; {
047 *       <jk>if</jk> (<jv>x</jv>.matches(criteria)) {
048 *          <jv>found</jv>.set(<jk>true</jk>);
049 *       }
050 *    });
051 *
052 *    <jk>if</jk> (<jv>found</jv>.isTrue()) {
053 *       <jsm>log</jsm>(<js>"Match found!"</js>);
054 *    }
055 * </p>
056 *
057 * <h5 class='section'>See Also:</h5><ul>
058 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauCommonsLang">Lang Package</a>
059 *    <li class='jc'>{@link Flag}
060 * </ul>
061 */
062public class BooleanValue extends Value<Boolean> {
063
064   /**
065    * Creates a new boolean value initialized to <c>false</c>.
066    *
067    * <h5 class='section'>Example:</h5>
068    * <p class='bjava'>
069    *    BooleanValue <jv>value</jv> = BooleanValue.<jsm>create</jsm>();
070    *    <jsm>assertEquals</jsm>(<jk>false</jk>, <jv>value</jv>.get());
071    * </p>
072    *
073    * @return A new boolean value.
074    */
075   public static BooleanValue create() {
076      return of(false);
077   }
078
079   /**
080    * Creates a new boolean value with the specified initial value.
081    *
082    * <h5 class='section'>Example:</h5>
083    * <p class='bjava'>
084    *    BooleanValue <jv>value</jv> = BooleanValue.<jsm>of</jsm>(<jk>true</jk>);
085    *    <jsm>assertEquals</jsm>(<jk>true</jk>, <jv>value</jv>.get());
086    * </p>
087    *
088    * @param value The initial value.
089    * @return A new boolean value.
090    */
091   public static BooleanValue of(Boolean value) {
092      return new BooleanValue(value);
093   }
094
095   /**
096    * Constructor.
097    *
098    * @param value The initial value.
099    */
100   public BooleanValue(Boolean value) {
101      super(value);
102   }
103
104   /**
105    * Checks if the current value is equal to the specified value.
106    *
107    * <p>
108    * Uses {@link org.apache.juneau.commons.utils.Utils#eq(Object, Object)} for deep equality comparison, which handles nulls safely.
109    *
110    * <h5 class='section'>Example:</h5>
111    * <p class='bjava'>
112    *    BooleanValue <jv>value</jv> = BooleanValue.<jsm>of</jsm>(<jk>true</jk>);
113    *    <jsm>assertTrue</jsm>(<jv>value</jv>.is(<jk>true</jk>));
114    *    <jsm>assertFalse</jsm>(<jv>value</jv>.is(<jk>false</jk>));
115    *
116    *    <jc>// Handles null safely</jc>
117    *    BooleanValue <jv>empty</jv> = BooleanValue.<jsm>of</jsm>(<jk>null</jk>);
118    *    <jsm>assertTrue</jsm>(<jv>empty</jv>.is(<jk>null</jk>));
119    * </p>
120    *
121    * @param value The value to compare to.
122    * @return <jk>true</jk> if the current value is equal to the specified value.
123    */
124   public boolean is(Boolean value) {
125      return eq(get(), value);
126   }
127
128   /**
129    * Checks if the current value matches any of the specified values.
130    *
131    * <p>
132    * Uses {@link org.apache.juneau.commons.utils.Utils#eq(Object, Object)} for deep equality comparison of each value.
133    *
134    * <h5 class='section'>Example:</h5>
135    * <p class='bjava'>
136    *    BooleanValue <jv>value</jv> = BooleanValue.<jsm>of</jsm>(<jk>true</jk>);
137    *    <jsm>assertTrue</jsm>(<jv>value</jv>.isAny(<jk>true</jk>, <jk>null</jk>));
138    *    <jsm>assertFalse</jsm>(<jv>value</jv>.isAny(<jk>false</jk>));
139    * </p>
140    *
141    * @param values The values to compare to.
142    * @return <jk>true</jk> if the current value matches any of the specified values.
143    */
144   public boolean isAny(Boolean...values) {
145      assertArgNotNull("values", values);
146      var current = get();
147      for (var value : values)
148         if (eq(current, value))
149            return true;
150      return false;
151   }
152
153   /**
154    * Returns <c>true</c> if the value is not set to <c>true</c> (i.e., it's <c>false</c> or <c>null</c>).
155    *
156    * <h5 class='section'>Example:</h5>
157    * <p class='bjava'>
158    *    BooleanValue <jv>value</jv> = BooleanValue.<jsm>of</jsm>(<jk>false</jk>);
159    *    <jk>if</jk> (<jv>value</jv>.isNotTrue()) {
160    *       <jsm>log</jsm>(<js>"Value is not true"</js>);
161    *    }
162    * </p>
163    *
164    * @return <c>true</c> if the value is not set to <c>true</c>, <c>false</c> otherwise.
165    */
166   public boolean isNotTrue() { return ! isTrue(); }
167
168   /**
169    * Returns <c>true</c> if the value is set to <c>true</c>.
170    *
171    * <h5 class='section'>Example:</h5>
172    * <p class='bjava'>
173    *    BooleanValue <jv>value</jv> = BooleanValue.<jsm>of</jsm>(<jk>true</jk>);
174    *    <jk>if</jk> (<jv>value</jv>.isTrue()) {
175    *       <jsm>log</jsm>(<js>"Value is true"</js>);
176    *    }
177    * </p>
178    *
179    * @return <c>true</c> if the value is set to <c>true</c>, <c>false</c> otherwise (including when <c>null</c>).
180    */
181   public boolean isTrue() { return Boolean.TRUE.equals(get()); }
182}