001    package ezvcard.util;
002    
003    import java.util.Collection;
004    import java.util.Map;
005    
006    /*
007     Copyright (c) 2013, Michael Angstadt
008     All rights reserved.
009    
010     Redistribution and use in source and binary forms, with or without
011     modification, are permitted provided that the following conditions are met: 
012    
013     1. Redistributions of source code must retain the above copyright notice, this
014     list of conditions and the following disclaimer. 
015     2. Redistributions in binary form must reproduce the above copyright notice,
016     this list of conditions and the following disclaimer in the documentation
017     and/or other materials provided with the distribution. 
018    
019     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023     ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
026     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029    
030     The views and conclusions contained in the software and documentation are those
031     of the authors and should not be interpreted as representing official policies, 
032     either expressed or implied, of the FreeBSD Project.
033     */
034    
035    /**
036     * Helper class for dealing with vCard strings.
037     * @author Michael Angstadt
038     */
039    public class StringUtils {
040            /**
041             * The local computer's newline character sequence.
042             */
043            public static final String NEWLINE = System.getProperty("line.separator");
044    
045            /**
046             * Trims the whitespace off the left side of a string.
047             * @param string the string to trim
048             * @return the trimmed string
049             */
050            public static String ltrim(String string) {
051                    if (string == null) {
052                            return null;
053                    }
054    
055                    int i;
056                    for (i = 0; i < string.length() && Character.isWhitespace(string.charAt(i)); i++) {
057                            //do nothing
058                    }
059                    return (i == string.length()) ? "" : string.substring(i);
060            }
061    
062            /**
063             * Trims the whitespace off the right side of a string.
064             * @param string the string to trim
065             * @return the trimmed string
066             */
067            public static String rtrim(String string) {
068                    if (string == null) {
069                            return null;
070                    }
071    
072                    int i;
073                    for (i = string.length() - 1; i >= 0 && Character.isWhitespace(string.charAt(i)); i--) {
074                            //do nothing
075                    }
076                    return (i == 0) ? "" : string.substring(0, i + 1);
077            }
078    
079            /**
080             * Joins a collection of values into a delimited list.
081             * @param collection the collection of values
082             * @param delimiter the delimiter (e.g. ",")
083             * @return the final string
084             */
085            public static <T> String join(Collection<T> collection, String delimiter) {
086                    StringBuilder sb = new StringBuilder();
087                    join(collection, delimiter, sb);
088                    return sb.toString();
089            }
090    
091            /**
092             * Joins a collection of values into a delimited list.
093             * @param collection the collection of values
094             * @param delimiter the delimiter (e.g. ",")
095             * @param sb the string builder to append onto
096             */
097            public static <T> void join(Collection<T> collection, String delimiter, StringBuilder sb) {
098                    join(collection, delimiter, sb, new JoinCallback<T>() {
099                            public void handle(StringBuilder sb, T value) {
100                                    sb.append(value);
101                            }
102                    });
103            }
104    
105            /**
106             * Joins a collection of values into a delimited list.
107             * @param collection the collection of values
108             * @param delimiter the delimiter (e.g. ",")
109             * @param join callback function to call on every element in the collection
110             * @return the final string
111             */
112            public static <T> String join(Collection<T> collection, String delimiter, JoinCallback<T> join) {
113                    StringBuilder sb = new StringBuilder();
114                    join(collection, delimiter, sb, join);
115                    return sb.toString();
116            }
117    
118            /**
119             * Joins a collection of values into a delimited list.
120             * @param collection the collection of values
121             * @param delimiter the delimiter (e.g. ",")
122             * @param sb the string builder to append onto
123             * @param join callback function to call on every element in the collection
124             */
125            public static <T> void join(Collection<T> collection, String delimiter, StringBuilder sb, JoinCallback<T> join) {
126                    boolean first = true;
127                    for (T element : collection) {
128                            if (first) {
129                                    first = false;
130                            } else {
131                                    sb.append(delimiter);
132                            }
133                            join.handle(sb, element);
134                    }
135            }
136    
137            /**
138             * Joins a map into a delimited list.
139             * @param map the map
140             * @param delimiter the delimiter (e.g. ",")
141             * @param join callback function to call on every element in the collection
142             * @return the final string
143             */
144            public static <K, V> String join(Map<K, V> map, String delimiter, final JoinMapCallback<K, V> join) {
145                    return join(map.entrySet(), delimiter, new JoinCallback<Map.Entry<K, V>>() {
146                            public void handle(StringBuilder sb, Map.Entry<K, V> entry) {
147                                    join.handle(sb, entry.getKey(), entry.getValue());
148                            }
149                    });
150            }
151    
152            /**
153             * Callback interface used with various {@code VCardStringUtils.join()}
154             * methods.
155             * @author Michael Angstadt
156             * @param <T> the value type
157             */
158            public static interface JoinCallback<T> {
159                    void handle(StringBuilder sb, T value);
160            }
161    
162            /**
163             * Callback interface used with the
164             * {@link #join(Map, String, JoinMapCallback)} method.
165             * @author Michael Angstadt
166             * @param <K> the key class
167             * @param <V> the value class
168             */
169            public static interface JoinMapCallback<K, V> {
170                    void handle(StringBuilder sb, K key, V value);
171            }
172    
173            private StringUtils() {
174                    //hide constructor
175            }
176    }