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