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 integer value.
024 *
025 * <p>
026 * This class extends {@link Value}&lt;{@link Integer}&gt; and adds a convenience method for incrementing
027 * the value, which is useful for counting operations in lambdas and loops.
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 {@link java.util.concurrent.atomic.AtomicInteger} instead.
032 * </ul>
033 *
034 * <h5 class='section'>Example:</h5>
035 * <p class='bjava'>
036 *    <jc>// Create a counter</jc>
037 *    IntegerValue <jv>counter</jv> = IntegerValue.<jsm>create</jsm>();
038 *
039 *    <jc>// Use in a lambda to count valid items</jc>
040 *    list.forEach(<jv>x</jv> -&gt; {
041 *       <jk>if</jk> (<jv>x</jv>.isValid()) {
042 *          <jv>counter</jv>.getAndIncrement();
043 *       }
044 *    });
045 *
046 *    <jsm>log</jsm>(<js>"Valid items: "</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 IntegerValue extends Value<Integer> {
054
055   /**
056    * Creates a new integer value initialized to <c>0</c>.
057    *
058    * <h5 class='section'>Example:</h5>
059    * <p class='bjava'>
060    *    IntegerValue <jv>counter</jv> = IntegerValue.<jsm>create</jsm>();
061    *    <jsm>assertEquals</jsm>(0, <jv>counter</jv>.get());
062    * </p>
063    *
064    * @return A new integer value.
065    */
066   public static IntegerValue create() {
067      return of(0);
068   }
069
070   /**
071    * Creates a new integer value with the specified initial value.
072    *
073    * <h5 class='section'>Example:</h5>
074    * <p class='bjava'>
075    *    IntegerValue <jv>counter</jv> = IntegerValue.<jsm>of</jsm>(42);
076    *    <jsm>assertEquals</jsm>(42, <jv>counter</jv>.get());
077    * </p>
078    *
079    * @param value The initial value.
080    * @return A new integer value.
081    */
082   public static IntegerValue of(Integer value) {
083      return new IntegerValue(value);
084   }
085
086   /**
087    * Constructor.
088    */
089   public IntegerValue() {
090      super(0);
091   }
092
093   /**
094    * Constructor.
095    *
096    * @param value The initial value.
097    */
098   public IntegerValue(Integer 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    *    IntegerValue <jv>value</jv> = IntegerValue.<jsm>of</jsm>(10);
108    *    <jv>value</jv>.add(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 IntegerValue add(Integer x) {
116      set(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    *    IntegerValue <jv>value</jv> = IntegerValue.<jsm>of</jsm>(10);
126    *    <jk>int</jk> <jv>result</jv> = <jv>value</jv>.addAndGet(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 Integer addAndGet(Integer x) {
134      set(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    *    IntegerValue <jv>counter</jv> = IntegerValue.<jsm>of</jsm>(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 IntegerValue decrement() {
151      set(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    *    IntegerValue <jv>counter</jv> = IntegerValue.<jsm>of</jsm>(5);
161    *    <jk>int</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 Integer decrementAndGet() {
168      set(get() - 1);
169      return get();
170   }
171
172   /**
173    * Returns the current value and then increments it.
174    *
175    * <p>
176    * This is a convenience method commonly used for counting operations in lambdas and loops.
177    *
178    * <h5 class='section'>Example:</h5>
179    * <p class='bjava'>
180    *    IntegerValue <jv>counter</jv> = IntegerValue.<jsm>of</jsm>(5);
181    *    <jk>int</jk> <jv>current</jv> = <jv>counter</jv>.getAndIncrement();  <jc>// Returns 5</jc>
182    *    <jk>int</jk> <jv>next</jv> = <jv>counter</jv>.get();                <jc>// Returns 6</jc>
183    * </p>
184    *
185    * @return The value before it was incremented.
186    */
187   public Integer getAndIncrement() {
188      var v = get();
189      var result = v == null ? 0 : v;
190      set(result + 1);
191      return result;
192   }
193
194   /**
195    * Increments the value by 1.
196    *
197    * <h5 class='section'>Example:</h5>
198    * <p class='bjava'>
199    *    IntegerValue <jv>counter</jv> = IntegerValue.<jsm>of</jsm>(5);
200    *    <jv>counter</jv>.increment();
201    *    <jsm>assertEquals</jsm>(6, <jv>counter</jv>.get());
202    * </p>
203    *
204    * @return This object.
205    */
206   public IntegerValue increment() {
207      set(get() + 1);
208      return this;
209   }
210
211   /**
212    * Increments the value by 1 and returns the new value.
213    *
214    * <h5 class='section'>Example:</h5>
215    * <p class='bjava'>
216    *    IntegerValue <jv>counter</jv> = IntegerValue.<jsm>of</jsm>(5);
217    *    <jk>int</jk> <jv>result</jv> = <jv>counter</jv>.incrementAndGet();  <jc>// Returns 6</jc>
218    *    <jsm>assertEquals</jsm>(6, <jv>counter</jv>.get());
219    * </p>
220    *
221    * @return The incremented value.
222    */
223   public Integer incrementAndGet() {
224      set(get() + 1);
225      return get();
226   }
227
228   /**
229    * Checks if the current value is equal to the specified value.
230    *
231    * <p>
232    * Uses {@link org.apache.juneau.commons.utils.Utils#eq(Object, Object)} for deep equality comparison, which handles nulls safely.
233    *
234    * <h5 class='section'>Example:</h5>
235    * <p class='bjava'>
236    *    IntegerValue <jv>value</jv> = IntegerValue.<jsm>of</jsm>(42);
237    *    <jsm>assertTrue</jsm>(<jv>value</jv>.is(42));
238    *    <jsm>assertFalse</jsm>(<jv>value</jv>.is(43));
239    * </p>
240    *
241    * @param value The value to compare to.
242    * @return <jk>true</jk> if the current value is equal to the specified value.
243    */
244   public boolean is(Integer value) {
245      return eq(get(), value);
246   }
247
248   /**
249    * Checks if the current value matches any of the specified values.
250    *
251    * <p>
252    * Uses {@link org.apache.juneau.commons.utils.Utils#eq(Object, Object)} for deep equality comparison of each value.
253    *
254    * <h5 class='section'>Example:</h5>
255    * <p class='bjava'>
256    *    IntegerValue <jv>value</jv> = IntegerValue.<jsm>of</jsm>(5);
257    *    <jsm>assertTrue</jsm>(<jv>value</jv>.isAny(3, 5, 7));
258    *    <jsm>assertFalse</jsm>(<jv>value</jv>.isAny(1, 2));
259    * </p>
260    *
261    * @param values The values to compare to.
262    * @return <jk>true</jk> if the current value matches any of the specified values.
263    */
264   public boolean isAny(Integer...values) {
265      assertArgNotNull("values", values);
266      var current = get();
267      for (var value : values)
268         if (eq(current, value))
269            return true;
270      return false;
271   }
272}