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
022/**
023 * A simple mutable byte value.
024 *
025 * <p>
026 * This class extends {@link Value}&lt;{@link Byte}&gt; and adds convenience methods for incrementing,
027 * decrementing, and testing byte values, which are useful in lambdas and byte manipulation operations.
028 *
029 * <h5 class='section'>Notes:</h5><ul>
030 *    <li class='note'>
031 *       This class is <b>not thread-safe</b>. For concurrent access, use synchronization or atomic classes.
032 * </ul>
033 *
034 * <h5 class='section'>Example:</h5>
035 * <p class='bjava'>
036 *    <jc>// Create a counter</jc>
037 *    ByteValue <jv>counter</jv> = ByteValue.<jsm>create</jsm>();
038 *
039 *    <jc>// Use in a lambda to count items</jc>
040 *    list.forEach(<jv>x</jv> -&gt; {
041 *       <jk>if</jk> (<jv>x</jv>.isValid()) {
042 *          <jv>counter</jv>.increment();
043 *       }
044 *    });
045 *
046 *    <jsm>log</jsm>(<js>"Count: "</js> + <jv>counter</jv>.get());
047 * </p>
048 *
049 * <h5 class='section'>See Also:</h5><ul>
050 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauCommonsLang">Lang Package</a>
051 * </ul>
052 */
053public class ByteValue extends Value<Byte> {
054
055   /**
056    * Creates a new byte value initialized to <c>0</c>.
057    *
058    * <h5 class='section'>Example:</h5>
059    * <p class='bjava'>
060    *    ByteValue <jv>counter</jv> = ByteValue.<jsm>create</jsm>();
061    *    <jsm>assertEquals</jsm>(0, <jv>counter</jv>.get());
062    * </p>
063    *
064    * @return A new byte value.
065    */
066   public static ByteValue create() {
067      return of((byte)0);
068   }
069
070   /**
071    * Creates a new byte value with the specified initial value.
072    *
073    * <h5 class='section'>Example:</h5>
074    * <p class='bjava'>
075    *    ByteValue <jv>value</jv> = ByteValue.<jsm>of</jsm>((<jk>byte</jk>)42);
076    *    <jsm>assertEquals</jsm>(42, <jv>value</jv>.get());
077    * </p>
078    *
079    * @param value The initial value.
080    * @return A new byte value.
081    */
082   public static ByteValue of(Byte value) {
083      return new ByteValue(value);
084   }
085
086   /**
087    * Constructor.
088    */
089   public ByteValue() {
090      super((byte)0);
091   }
092
093   /**
094    * Constructor.
095    *
096    * @param value The initial value.
097    */
098   public ByteValue(Byte value) {
099      super(value == null ? 0 : value);
100   }
101
102   /**
103    * Adds the specified value to the current value.
104    *
105    * <h5 class='section'>Example:</h5>
106    * <p class='bjava'>
107    *    ByteValue <jv>value</jv> = ByteValue.<jsm>of</jsm>((<jk>byte</jk>)10);
108    *    <jv>value</jv>.add((<jk>byte</jk>)5);
109    *    <jsm>assertEquals</jsm>(15, <jv>value</jv>.get());
110    * </p>
111    *
112    * @param x The value to add.
113    * @return This object.
114    */
115   public ByteValue add(Byte x) {
116      set((byte)(get() + (x == null ? 0 : x)));
117      return this;
118   }
119
120   /**
121    * Adds the specified value to the current value and returns the new value.
122    *
123    * <h5 class='section'>Example:</h5>
124    * <p class='bjava'>
125    *    ByteValue <jv>value</jv> = ByteValue.<jsm>of</jsm>((<jk>byte</jk>)10);
126    *    <jk>byte</jk> <jv>result</jv> = <jv>value</jv>.addAndGet((<jk>byte</jk>)5);  <jc>// Returns 15</jc>
127    *    <jsm>assertEquals</jsm>(15, <jv>value</jv>.get());
128    * </p>
129    *
130    * @param x The value to add.
131    * @return The new value after addition.
132    */
133   public Byte addAndGet(Byte x) {
134      set((byte)(get() + (x == null ? 0 : x)));
135      return get();
136   }
137
138   /**
139    * Decrements the value by 1.
140    *
141    * <h5 class='section'>Example:</h5>
142    * <p class='bjava'>
143    *    ByteValue <jv>counter</jv> = ByteValue.<jsm>of</jsm>((<jk>byte</jk>)5);
144    *    <jv>counter</jv>.decrement();
145    *    <jsm>assertEquals</jsm>(4, <jv>counter</jv>.get());
146    * </p>
147    *
148    * @return This object.
149    */
150   public ByteValue decrement() {
151      set((byte)(get() - 1));
152      return this;
153   }
154
155   /**
156    * Decrements the value by 1 and returns the new value.
157    *
158    * <h5 class='section'>Example:</h5>
159    * <p class='bjava'>
160    *    ByteValue <jv>counter</jv> = ByteValue.<jsm>of</jsm>((<jk>byte</jk>)5);
161    *    <jk>byte</jk> <jv>result</jv> = <jv>counter</jv>.decrementAndGet();  <jc>// Returns 4</jc>
162    *    <jsm>assertEquals</jsm>(4, <jv>counter</jv>.get());
163    * </p>
164    *
165    * @return The decremented value.
166    */
167   public Byte decrementAndGet() {
168      set((byte)(get() - 1));
169      return get();
170   }
171
172   /**
173    * Increments the value by 1.
174    *
175    * <h5 class='section'>Example:</h5>
176    * <p class='bjava'>
177    *    ByteValue <jv>counter</jv> = ByteValue.<jsm>of</jsm>((<jk>byte</jk>)5);
178    *    <jv>counter</jv>.increment();
179    *    <jsm>assertEquals</jsm>(6, <jv>counter</jv>.get());
180    * </p>
181    *
182    * @return This object.
183    */
184   public ByteValue increment() {
185      set((byte)(get() + 1));
186      return this;
187   }
188
189   /**
190    * Increments the value by 1 and returns the new value.
191    *
192    * <h5 class='section'>Example:</h5>
193    * <p class='bjava'>
194    *    ByteValue <jv>counter</jv> = ByteValue.<jsm>of</jsm>((<jk>byte</jk>)5);
195    *    <jk>byte</jk> <jv>result</jv> = <jv>counter</jv>.incrementAndGet();  <jc>// Returns 6</jc>
196    *    <jsm>assertEquals</jsm>(6, <jv>counter</jv>.get());
197    * </p>
198    *
199    * @return The incremented value.
200    */
201   public Byte incrementAndGet() {
202      set((byte)(get() + 1));
203      return get();
204   }
205
206   /**
207    * Checks if the current value is equal to the specified value.
208    *
209    * <p>
210    * Uses {@link org.apache.juneau.commons.utils.Utils#eq(Object, Object)} for deep equality comparison, which handles nulls safely.
211    *
212    * <h5 class='section'>Example:</h5>
213    * <p class='bjava'>
214    *    ByteValue <jv>value</jv> = ByteValue.<jsm>of</jsm>((<jk>byte</jk>)42);
215    *    <jsm>assertTrue</jsm>(<jv>value</jv>.is((<jk>byte</jk>)42));
216    *    <jsm>assertFalse</jsm>(<jv>value</jv>.is((<jk>byte</jk>)43));
217    * </p>
218    *
219    * @param value The value to compare to.
220    * @return <jk>true</jk> if the current value is equal to the specified value.
221    */
222   public boolean is(Byte value) {
223      return eq(get(), value);
224   }
225
226   /**
227    * Checks if the current value matches any of the specified values.
228    *
229    * <p>
230    * Uses {@link org.apache.juneau.commons.utils.Utils#eq(Object, Object)} for deep equality comparison of each value.
231    *
232    * <h5 class='section'>Example:</h5>
233    * <p class='bjava'>
234    *    ByteValue <jv>value</jv> = ByteValue.<jsm>of</jsm>((<jk>byte</jk>)5);
235    *    <jsm>assertTrue</jsm>(<jv>value</jv>.isAny((<jk>byte</jk>)3, (<jk>byte</jk>)5, (<jk>byte</jk>)7));
236    *    <jsm>assertFalse</jsm>(<jv>value</jv>.isAny((<jk>byte</jk>)1, (<jk>byte</jk>)2));
237    * </p>
238    *
239    * @param values The values to compare to.
240    * @return <jk>true</jk> if the current value matches any of the specified values.
241    */
242   public boolean isAny(Byte...values) {
243      assertArgNotNull("values", values);
244      var current = get();
245      for (var value : values)
246         if (eq(current, value))
247            return true;
248      return false;
249   }
250}