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}<{@link Boolean}> 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> -> { 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}