001    /*
002     * Created on Jun 2, 2006
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005     * the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
010     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011     * specific language governing permissions and limitations under the License.
012     *
013     * Copyright @2006-2011 the original author or authors.
014     */
015    package org.fest.util;
016    
017    /**
018     * Utility methods related to {@code String}s.
019     *
020     * @author Alex Ruiz
021     */
022    public final class Strings {
023    
024      /**
025       * Returns {@code true} if the given {@code String} is {@code null} or empty.
026       * @param s the {@code String} to check.
027       * @return {@code true} if the given {@code String} is {@code null} or empty, otherwise {@code false}.
028       */
029      public static boolean isEmpty(String s) {
030        return s == null || s.length() == 0;
031      }
032    
033      /**
034       * Returns the given {@code String} surrounded by single quotes, or {@code null} if the given {@code String} is
035       * {@code null}.
036       * @param s the given {@code String}.
037       * @return the given {@code String} surrounded by single quotes, or {@code null} if the given {@code String} is
038       * {@code null}.
039       */
040      public static String quote(String s) {
041        return s != null ? concat("'", s, "'") : null;
042      }
043    
044      /**
045       * Returns the given object surrounded by single quotes, only if the object is a {@code String}.
046       * @param o the given object.
047       * @return the given object surrounded by single quotes, only if the object is a {@code String}.
048       * @see #quote(String)
049       */
050      public static Object quote(Object o) {
051        return o instanceof String ? quote(o.toString()) : o;
052      }
053    
054      /**
055       * Concatenates the given objects into a single {@code String}. This method is more efficient than concatenating using
056       * "+", since only one <code>{@link StringBuilder}</code> is created.
057       * @param objects the objects to concatenate.
058       * @return a {@code String} containing the given objects.
059       */
060      public static String concat(Object... objects) {
061        if (Arrays.isEmpty(objects)) return null;
062        StringBuilder b = new StringBuilder();
063        for (Object o : objects)
064          b.append(o);
065        return b.toString();
066      }
067    
068      /**
069       * Joins the given {@code String}s using a given delimiter. The following example illustrates proper usage of this
070       * method:
071       *
072       * <pre>
073       * Strings.join("a", "b", "c").with("|")
074       * </pre>
075       *
076       * which will result in the {@code String} <code>"a|b|c"</code>.
077       * @param strings the {@code String}s to join.
078       * @return an intermediate object that takes a given delimiter and knows how to join the given {@code String}s.
079       * @see StringsToJoin#with(String)
080       */
081      public static StringsToJoin join(String... strings) {
082        return new StringsToJoin(strings);
083      }
084    
085      /**
086       * Knows how to join {@code String}s using a given delimiter.
087       * @see Strings#join(String[])
088       */
089      public static class StringsToJoin {
090    
091        /** The {@code String}s to join. */
092        private final String[] strings;
093    
094        /**
095         * Creates a new <code>{@link StringsToJoin}</code>.
096         * @param strings the {@code String}s to join.
097         */
098        StringsToJoin(String... strings) {
099          this.strings = strings;
100        }
101    
102        /**
103         * Specifies the delimeter to use to join {@code String}s.
104         * @param delimeter the delimeter to use.
105         * @return the {@code String}s joined using the given delimeter.
106         */
107        public String with(String delimeter) {
108          if (delimeter == null) throw new IllegalArgumentException("Delimiter should not be null");
109          if (Arrays.isEmpty(strings)) return "";
110          StringBuilder b = new StringBuilder();
111          int stringCount = strings.length;
112          for (int i = 0; i < stringCount; i++) {
113            String s = strings[i];
114            b.append(s != null ? s : "");
115            if (i < stringCount - 1) b.append(delimeter);
116          }
117          return b.toString();
118        }
119      }
120    
121      /**
122       * Appends a given {@code String} to the given target, only if the target does not end with the given {@code String}
123       * to append. The following example illustrates proper usage of this method:
124       * <pre>
125       * Strings.append("c").to("ab");
126       * Strings.append("c").to("abc");
127       * </pre>
128       * resulting in the {@code String} <code>"abc"</code> for both cases.
129       * @param toAppend the {@code String} to append.
130       * @return an intermediate object that takes the target {@code String} and knows to append the given {@code String}.
131       * @see StringToAppend#to(String)
132       */
133      public static StringToAppend append(String toAppend) {
134        return new StringToAppend(toAppend);
135      }
136    
137      /**
138       * Knows how to append a given {@code String} to the given target, only if the target does not end with the
139       * given {@code String} to append.
140       */
141      public static class StringToAppend {
142    
143        /** The {@code String} to append. */
144        private final String toAppend;
145    
146        /**
147         * Creates a new <code>{@link StringToAppend}</code>.
148         * @param toAppend the {@code String} to append.
149         */
150        StringToAppend(String toAppend) {
151          this.toAppend = toAppend;
152        }
153    
154        /**
155         * Appends the {@code String} specified in the constructor to the {@code String} passed as argument.
156         * @param s the target {@code String}.
157         * @return a {@code String} containing the target {@code String} with the given {@code String} to append added to
158         * the end.
159         */
160        public String to(String s) {
161          if (!s.endsWith(toAppend)) return concat(s, toAppend);
162          return s;
163        }
164      }
165    
166      private Strings() {}
167    }