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