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.logging.log4j.util;
018
019import java.util.Iterator;
020import java.util.Locale;
021import java.util.Objects;
022
023/**
024 * <em>Consider this class private.</em>
025 * 
026 * @see <a href="http://commons.apache.org/proper/commons-lang/">Apache Commons Lang</a>
027 */
028public final class Strings {
029
030    /**
031     * The empty string.
032     */
033    public static final String EMPTY = "";
034    
035    /**
036     * OS-dependent line separator, defaults to {@code "\n"} if the system property {@code ""line.separator"} cannot be
037     * read.
038     */
039    public static final String LINE_SEPARATOR = PropertiesUtil.getProperties().getStringProperty("line.separator",
040            "\n");
041
042    private Strings() {
043        // empty
044    }
045
046    /**
047     * Returns a double quoted string.
048     * 
049     * @param str a String
050     * @return {@code "str"}
051     */
052    public static String dquote(final String str) {
053        return Chars.DQUOTE + str + Chars.DQUOTE;
054    }
055
056    /**
057     * Checks if a String is blank. A blank string is one that is {@code null}, empty, or when trimmed using
058     * {@link String#trim()} is empty.
059     *
060     * @param s the String to check, may be {@code null}
061     * @return {@code true} if the String is {@code null}, empty, or trims to empty.
062     */
063    public static boolean isBlank(final String s) {
064        return s == null || s.trim().isEmpty();
065    }
066
067    /**
068     * <p>
069     * Checks if a CharSequence is empty ("") or null.
070     * </p>
071     *
072     * <pre>
073     * Strings.isEmpty(null)      = true
074     * Strings.isEmpty("")        = true
075     * Strings.isEmpty(" ")       = false
076     * Strings.isEmpty("bob")     = false
077     * Strings.isEmpty("  bob  ") = false
078     * </pre>
079     *
080     * <p>
081     * NOTE: This method changed in Lang version 2.0. It no longer trims the CharSequence. That functionality is
082     * available in isBlank().
083     * </p>
084     *
085     * <p>
086     * Copied from Apache Commons Lang org.apache.commons.lang3.StringUtils.isEmpty(CharSequence)
087     * </p>
088     *
089     * @param cs the CharSequence to check, may be null
090     * @return {@code true} if the CharSequence is empty or null
091     */
092    public static boolean isEmpty(final CharSequence cs) {
093        return cs == null || cs.length() == 0;
094    }
095
096    /**
097     * Checks if a String is not blank. The opposite of {@link #isBlank(String)}.
098     *
099     * @param s the String to check, may be {@code null}
100     * @return {@code true} if the String is non-{@code null} and has content after being trimmed.
101     */
102    public static boolean isNotBlank(final String s) {
103        return !isBlank(s);
104    }
105
106    /**
107     * <p>
108     * Checks if a CharSequence is not empty ("") and not null.
109     * </p>
110     *
111     * <pre>
112     * Strings.isNotEmpty(null)      = false
113     * Strings.isNotEmpty("")        = false
114     * Strings.isNotEmpty(" ")       = true
115     * Strings.isNotEmpty("bob")     = true
116     * Strings.isNotEmpty("  bob  ") = true
117     * </pre>
118     *
119     * <p>
120     * Copied from Apache Commons Lang org.apache.commons.lang3.StringUtils.isNotEmpty(CharSequence)
121     * </p>
122     *
123     * @param cs the CharSequence to check, may be null
124     * @return {@code true} if the CharSequence is not empty and not null
125     */
126    public static boolean isNotEmpty(final CharSequence cs) {
127        return !isEmpty(cs);
128    }
129
130    /**
131     * Returns a quoted string.
132     * 
133     * @param str a String
134     * @return {@code 'str'}
135     */
136    public static String quote(final String str) {
137        return Chars.QUOTE + str + Chars.QUOTE;
138    }
139
140    /**
141     * Shorthand for {@code str.toUpperCase(Locale.ROOT);}
142     * @param str The string to upper case.
143     * @return a new string
144     * @see String#toLowerCase(Locale)
145     */
146    public String toRootUpperCase(final String str) {
147        return str.toUpperCase(Locale.ROOT);
148    }
149    
150    /**
151     * <p>
152     * Removes control characters (char &lt;= 32) from both ends of this String returning {@code null} if the String is
153     * empty ("") after the trim or if it is {@code null}.
154     *
155     * <p>
156     * The String is trimmed using {@link String#trim()}. Trim removes start and end characters &lt;= 32.
157     * </p>
158     *
159     * <pre>
160     * Strings.trimToNull(null)          = null
161     * Strings.trimToNull("")            = null
162     * Strings.trimToNull("     ")       = null
163     * Strings.trimToNull("abc")         = "abc"
164     * Strings.trimToNull("    abc    ") = "abc"
165     * </pre>
166     *
167     * <p>
168     * Copied from Apache Commons Lang org.apache.commons.lang3.StringUtils.trimToNull(String)
169     * </p>
170     *
171     * @param str the String to be trimmed, may be null
172     * @return the trimmed String, {@code null} if only chars &lt;= 32, empty or null String input
173     */
174    public static String trimToNull(final String str) {
175        final String ts = str == null ? null : str.trim();
176        return isEmpty(ts) ? null : ts;
177    }
178
179    /**
180     * <p>Joins the elements of the provided {@code Iterable} into
181     * a single String containing the provided elements.</p>
182     *
183     * <p>No delimiter is added before or after the list. Null objects or empty
184     * strings within the iteration are represented by empty strings.</p>
185     *
186     * @param iterable  the {@code Iterable} providing the values to join together, may be null
187     * @param separator  the separator character to use
188     * @return the joined String, {@code null} if null iterator input
189     */
190    public static String join(final Iterable<?> iterable, final char separator) {
191        if (iterable == null) {
192            return null;
193        }
194        return join(iterable.iterator(), separator);
195    }
196
197    /**
198     * <p>Joins the elements of the provided {@code Iterator} into
199     * a single String containing the provided elements.</p>
200     *
201     * <p>No delimiter is added before or after the list. Null objects or empty
202     * strings within the iteration are represented by empty strings.</p>
203     *
204     * @param iterator  the {@code Iterator} of values to join together, may be null
205     * @param separator  the separator character to use
206     * @return the joined String, {@code null} if null iterator input
207     */
208    public static String join(final Iterator<?> iterator, final char separator) {
209
210        // handle null, zero and one elements before building a buffer
211        if (iterator == null) {
212            return null;
213        }
214        if (!iterator.hasNext()) {
215            return EMPTY;
216        }
217        final Object first = iterator.next();
218        if (!iterator.hasNext()) {
219            return Objects.toString(first);
220        }
221
222        // two or more elements
223        final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small
224        if (first != null) {
225            buf.append(first);
226        }
227
228        while (iterator.hasNext()) {
229            buf.append(separator);
230            final Object obj = iterator.next();
231            if (obj != null) {
232                buf.append(obj);
233            }
234        }
235
236        return buf.toString();
237    }
238
239}