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 string value.
024 *
025 * <p>
026 * This class extends {@link Value}&lt;{@link String}&gt; and adds convenience methods for string
027 * equality testing, which are useful in lambdas and conditional logic.
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 mutable string</jc>
037 *    StringValue <jv>name</jv> = StringValue.<jsm>of</jsm>(<js>"John"</js>);
038 *
039 *    <jc>// Check equality</jc>
040 *    <jk>if</jk> (<jv>name</jv>.is(<js>"John"</js>)) {
041 *       <jsm>System</jsm>.<jsf>out</jsf>.println(<js>"Name is John"</js>);
042 *    }
043 *
044 *    <jc>// Check multiple values</jc>
045 *    <jk>if</jk> (<jv>name</jv>.isAny(<js>"John"</js>, <js>"Jane"</js>, <js>"Bob"</js>)) {
046 *       <jsm>System</jsm>.<jsf>out</jsf>.println(<js>"Name found"</js>);
047 *    }
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 */
054public class StringValue extends Value<String> {
055
056   /**
057    * Creates a new empty string value.
058    *
059    * <h5 class='section'>Example:</h5>
060    * <p class='bjava'>
061    *    StringValue <jv>name</jv> = StringValue.<jsm>create</jsm>();
062    *    <jsm>assertNull</jsm>(<jv>name</jv>.get());
063    * </p>
064    *
065    * @return A new string value.
066    */
067   public static StringValue create() {
068      return of(null);
069   }
070
071   /**
072    * Creates a new string value with the specified initial value.
073    *
074    * <h5 class='section'>Example:</h5>
075    * <p class='bjava'>
076    *    StringValue <jv>name</jv> = StringValue.<jsm>of</jsm>(<js>"Hello"</js>);
077    *    <jsm>assertEquals</jsm>(<js>"Hello"</js>, <jv>name</jv>.get());
078    * </p>
079    *
080    * @param value The initial value.
081    * @return A new string value.
082    */
083   public static StringValue of(String value) {
084      return new StringValue(value);
085   }
086
087   /**
088    * Constructor.
089    */
090   public StringValue() {
091      super(null);
092   }
093
094   /**
095    * Constructor.
096    *
097    * @param value The initial value.
098    */
099   public StringValue(String value) {
100      super(value);
101   }
102
103   /**
104    * Checks if the current value is equal to the specified value.
105    *
106    * <p>
107    * Uses {@link org.apache.juneau.commons.utils.Utils#eq(Object, Object)} for deep equality comparison, which handles nulls safely.
108    *
109    * <h5 class='section'>Example:</h5>
110    * <p class='bjava'>
111    *    StringValue <jv>name</jv> = StringValue.<jsm>of</jsm>(<js>"John"</js>);
112    *    <jsm>assertTrue</jsm>(<jv>name</jv>.is(<js>"John"</js>));
113    *    <jsm>assertFalse</jsm>(<jv>name</jv>.is(<js>"Jane"</js>));
114    *
115    *    <jc>// Handles null safely</jc>
116    *    StringValue <jv>empty</jv> = StringValue.<jsm>create</jsm>();
117    *    <jsm>assertTrue</jsm>(<jv>empty</jv>.is(<jk>null</jk>));
118    * </p>
119    *
120    * @param value The value to compare to.
121    * @return <jk>true</jk> if the current value is equal to the specified value.
122    */
123   public boolean is(String value) {
124      return eq(get(), value);
125   }
126
127   /**
128    * Checks if the current value matches any of the specified values.
129    *
130    * <p>
131    * Uses {@link org.apache.juneau.commons.utils.Utils#eq(Object, Object)} for deep equality comparison of each value.
132    *
133    * <h5 class='section'>Example:</h5>
134    * <p class='bjava'>
135    *    StringValue <jv>name</jv> = StringValue.<jsm>of</jsm>(<js>"John"</js>);
136    *    <jsm>assertTrue</jsm>(<jv>name</jv>.isAny(<js>"John"</js>, <js>"Jane"</js>, <js>"Bob"</js>));
137    *    <jsm>assertFalse</jsm>(<jv>name</jv>.isAny(<js>"Alice"</js>, <js>"Charlie"</js>));
138    *
139    *    <jc>// Empty array returns false</jc>
140    *    <jsm>assertFalse</jsm>(<jv>name</jv>.isAny());
141    * </p>
142    *
143    * @param values The values to compare to.
144    * @return <jk>true</jk> if the current value matches any of the specified values.
145    */
146   public boolean isAny(String...values) {
147      assertArgNotNull("values", values);
148      var current = get();
149      for (var value : values)
150         if (eq(current, value))
151            return true;
152      return false;
153   }
154}