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.Shorts.*;
020import static org.apache.juneau.commons.utils.ThrowableUtils.*;
021
022import org.apache.juneau.commons.function.*;
023
024/**
025 * A simple mutable boolean flag.
026 *
027 * <p>
028 * This class provides a thread-unsafe alternative to {@link java.util.concurrent.atomic.AtomicBoolean} for cases
029 * where atomic operations are not required. It is useful in situations where you need to pass a mutable boolean
030 * reference to lambdas, inner classes, or methods.
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 java.util.concurrent.atomic.AtomicBoolean} instead.
035 *    <li class='note'>
036 *       This class supports only two states (<c>true</c>/<c>false</c>). If you need to represent three states
037 *       (<c>true</c>/<c>false</c>/<c>null</c>), use {@link BooleanHolder} instead.
038 * </ul>
039 *
040 * <h5 class='section'>Example:</h5>
041 * <p class='bjava'>
042 *    <jc>// Create a flag to track if an operation was performed</jc>
043 *    Flag <jv>processed</jv> = Flag.<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>.needsProcessing()) {
048 *          <jv>processed</jv>.set();
049 *          process(<jv>x</jv>);
050 *       }
051 *    });
052 *
053 *    <jk>if</jk> (<jv>processed</jv>.isSet()) {
054 *       <jsm>log</jsm>(<js>"Processing completed"</js>);
055 *    }
056 * </p>
057 *
058 * <h5 class='section'>See Also:</h5><ul>
059 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauCommonsLang">Lang Package</a>
060 *    <li class='jc'>{@link BooleanHolder}
061 * </ul>
062 */
063public class Flag {
064
065   /**
066    * Creates a new flag initialized to <jk>false</jk>.
067    *
068    * <h5 class='section'>Example:</h5>
069    * <p class='bjava'>
070    *    Flag <jv>flag</jv> = Flag.<jsm>create</jsm>();
071    *    <jsm>assertTrue</jsm>(<jv>flag</jv>.isUnset());
072    * </p>
073    *
074    * @return A new flag.
075    */
076   public static Flag create() {
077      return of(false);
078   }
079
080   /**
081    * Creates a new flag with the specified initial state.
082    *
083    * <h5 class='section'>Example:</h5>
084    * <p class='bjava'>
085    *    Flag <jv>flag</jv> = Flag.<jsm>of</jsm>(<jk>true</jk>);
086    *    <jsm>assertTrue</jsm>(<jv>flag</jv>.isSet());
087    * </p>
088    *
089    * @param value The initial state of the flag.
090    * @return A new flag.
091    */
092   public static Flag of(boolean value) {
093      return new Flag(value);
094   }
095
096   private boolean value;
097
098   private Flag(boolean value) {
099      this.value = value;
100   }
101
102   /**
103    * Sets the flag to <jk>true</jk> and returns the previous value.
104    *
105    * <h5 class='section'>Example:</h5>
106    * <p class='bjava'>
107    *    Flag <jv>flag</jv> = Flag.<jsm>create</jsm>();
108    *    <jk>boolean</jk> <jv>wasSet</jv> = <jv>flag</jv>.getAndSet();  <jc>// Returns false, flag is now true</jc>
109    *    <jk>boolean</jk> <jv>wasSet2</jv> = <jv>flag</jv>.getAndSet(); <jc>// Returns true, flag remains true</jc>
110    * </p>
111    *
112    * @return The value before it was set to <jk>true</jk>.
113    */
114   public boolean getAndSet() {
115      var b = value;
116      value = true;
117      return b;
118   }
119
120   /**
121    * Sets the flag to <jk>false</jk> and returns the previous value.
122    *
123    * <h5 class='section'>Example:</h5>
124    * <p class='bjava'>
125    *    Flag <jv>flag</jv> = Flag.<jsm>of</jsm>(<jk>true</jk>);
126    *    <jk>boolean</jk> <jv>wasSet</jv> = <jv>flag</jv>.getAndUnset();  <jc>// Returns true, flag is now false</jc>
127    *    <jk>boolean</jk> <jv>wasSet2</jv> = <jv>flag</jv>.getAndUnset(); <jc>// Returns false, flag remains false</jc>
128    * </p>
129    *
130    * @return The value before it was set to <jk>false</jk>.
131    */
132   public boolean getAndUnset() {
133      var v = value;
134      value = false;
135      return v;
136   }
137
138   /**
139    * Executes a code snippet if the flag is <jk>false</jk>.
140    *
141    * <p>
142    * This method is useful for conditional execution based on the flag state, particularly in lambda expressions
143    * or method chains.
144    *
145    * <h5 class='section'>Example:</h5>
146    * <p class='bjava'>
147    *    Flag <jv>initialized</jv> = Flag.<jsm>create</jsm>();
148    *
149    *    <jc>// Initialize only once</jc>
150    *    <jv>initialized</jv>.ifNotSet(() -&gt; {
151    *       <jsm>initialize</jsm>();
152    *       <jv>initialized</jv>.set();
153    *    });
154    * </p>
155    *
156    * @param snippet The code snippet to execute if the flag is <jk>false</jk>.
157    * @return This object.
158    */
159   public Flag ifNotSet(Snippet snippet) {
160      if (! value)
161         safe(snippet);
162      return this;
163   }
164
165   /**
166    * Executes a code snippet if the flag is <jk>true</jk>.
167    *
168    * <p>
169    * This method is useful for conditional execution based on the flag state, particularly in lambda expressions
170    * or method chains.
171    *
172    * <h5 class='section'>Example:</h5>
173    * <p class='bjava'>
174    *    Flag <jv>hasErrors</jv> = Flag.<jsm>create</jsm>();
175    *
176    *    <jc>// Log only if errors occurred</jc>
177    *    <jv>hasErrors</jv>.ifSet(() -&gt; <jsm>logErrors</jsm>());
178    * </p>
179    *
180    * @param snippet The code snippet to execute if the flag is <jk>true</jk>.
181    * @return This object.
182    */
183   public Flag ifSet(Snippet snippet) {
184      if (value)
185         safe(snippet);
186      return this;
187   }
188
189   /**
190    * Returns <jk>true</jk> if the flag is set.
191    *
192    * <h5 class='section'>Example:</h5>
193    * <p class='bjava'>
194    *    Flag <jv>flag</jv> = Flag.<jsm>of</jsm>(<jk>true</jk>);
195    *    <jsm>assertTrue</jsm>(<jv>flag</jv>.isSet());
196    * </p>
197    *
198    * @return <jk>true</jk> if the flag is set, <jk>false</jk> otherwise.
199    */
200   public boolean isSet() { return value; }
201
202   /**
203    * Returns <jk>true</jk> if the flag is not set.
204    *
205    * <h5 class='section'>Example:</h5>
206    * <p class='bjava'>
207    *    Flag <jv>flag</jv> = Flag.<jsm>create</jsm>();
208    *    <jsm>assertTrue</jsm>(<jv>flag</jv>.isUnset());
209    * </p>
210    *
211    * @return <jk>true</jk> if the flag is not set, <jk>false</jk> otherwise.
212    */
213   public boolean isUnset() { return ! value; }
214
215   /**
216    * Sets the flag to <jk>true</jk>.
217    *
218    * <h5 class='section'>Example:</h5>
219    * <p class='bjava'>
220    *    Flag <jv>flag</jv> = Flag.<jsm>create</jsm>();
221    *    <jv>flag</jv>.set();
222    *    <jsm>assertTrue</jsm>(<jv>flag</jv>.isSet());
223    * </p>
224    *
225    * @return This object.
226    */
227   public Flag set() {
228      value = true;
229      return this;
230   }
231
232   /**
233    * Sets the flag to <jk>true</jk> if the specified value is <jk>true</jk>.
234    *
235    * <p>
236    * This method uses a logical OR operation, so once the flag is set, it remains set regardless of subsequent
237    * calls with <jk>false</jk>.
238    *
239    * <h5 class='section'>Example:</h5>
240    * <p class='bjava'>
241    *    Flag <jv>flag</jv> = Flag.<jsm>create</jsm>();
242    *    <jv>flag</jv>.setIf(<jk>false</jk>);  <jc>// Flag remains false</jc>
243    *    <jv>flag</jv>.setIf(<jk>true</jk>);   <jc>// Flag becomes true</jc>
244    *    <jv>flag</jv>.setIf(<jk>false</jk>);  <jc>// Flag remains true</jc>
245    * </p>
246    *
247    * @param value If <jk>true</jk>, the flag will be set to <jk>true</jk>.
248    * @return This object.
249    */
250   public Flag setIf(boolean value) {
251      this.value |= value;
252      return this;
253   }
254
255   /**
256    * Sets the flag to <jk>false</jk>.
257    *
258    * <h5 class='section'>Example:</h5>
259    * <p class='bjava'>
260    *    Flag <jv>flag</jv> = Flag.<jsm>of</jsm>(<jk>true</jk>);
261    *    <jv>flag</jv>.unset();
262    *    <jsm>assertTrue</jsm>(<jv>flag</jv>.isUnset());
263    * </p>
264    *
265    * @return This object.
266    */
267   public Flag unset() {
268      value = false;
269      return this;
270   }
271
272   /**
273    * Returns a string representation of this flag.
274    *
275    * <p>
276    * The format is simply the string representation of the boolean value.
277    *
278    * @return A string representation of this flag.
279    */
280   @Override
281   public String toString() {
282      return String.valueOf(value);
283   }
284
285   /**
286    * Compares the specified object with this flag for equality.
287    *
288    * <p>
289    * Returns <jk>true</jk> if and only if the specified object is also a <c>Flag</c> and both flags
290    * have the same boolean value.
291    *
292    * @param o The object to be compared for equality with this flag.
293    * @return <jk>true</jk> if the specified object is equal to this flag.
294    */
295   @Override
296   public boolean equals(Object o) {
297      return (o instanceof Flag o2) && eq(this, o2, (x, y) -> x.value == y.value);
298   }
299
300   /**
301    * Returns the hash code value for this flag.
302    *
303    * <p>
304    * The hash code is computed from the boolean value using the standard <c>Boolean.hashCode(boolean)</c>
305    * method, which returns <c>1231</c> for <c>true</c> and <c>1237</c> for <c>false</c>.
306    *
307    * <p>
308    * This ensures that <c>flag1.equals(flag2)</c> implies that <c>flag1.hashCode()==flag2.hashCode()</c>
309    * for any two flags <c>flag1</c> and <c>flag2</c>, as required by the general contract of
310    * {@link Object#hashCode()}.
311    *
312    * @return The hash code value for this flag.
313    */
314   @Override
315   public int hashCode() {
316      return Boolean.hashCode(value);
317   }
318}