1/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved. 2 * 3 * This program and the accompanying materials are made available under 4 * the terms of the Common Public License v1.0 which accompanies this distribution, 5 * and is available at http://www.eclipse.org/legal/cpl-v10.html 6 * 7 * $Id: Strings.java,v 1.1.1.1 2004/05/09 16:57:55 vlad_r Exp $ 8 */ 9package com.vladium.util; 10 11import java.io.File; 12import java.io.IOException; 13import java.util.ArrayList; 14import java.util.HashSet; 15import java.util.List; 16import java.util.Set; 17import java.util.StringTokenizer; 18 19// ---------------------------------------------------------------------------- 20/** 21 * @author Vlad Roubtsov, (C) 2003 22 */ 23public 24abstract class Strings 25{ 26 // public: ................................................................ 27 28 29 public static final String WHITE_SPACE = " \t\r\n"; 30 31 32 //TODO: add duplicate removal 33 public static String toListForm (final String [] strings, final char delimiter) 34 { 35 if (strings == null) return null; 36 if (strings.length == 0) return ""; 37 38 final StringBuffer s = new StringBuffer (); 39 for (int i = 0, iLimit = strings.length; i < iLimit; ++ i) 40 { 41 if (i != 0) s.append (delimiter); 42 s.append (strings [i]); 43 } 44 45 return s.toString (); 46 } 47 48 public static String [] removeDuplicates (final String [] strings, final boolean removeNull) 49 { 50 if (strings == null) return strings; 51 52 final int length = strings.length; 53 if (length == 0) return strings; 54 55 final Set /* String */ _strings = new HashSet (length); 56 final List /* String */ _result = new ArrayList (length); 57 58 for (int i = 0; i < length; ++ i) 59 { 60 final String s = strings [i]; 61 if (removeNull && (s == null)) continue; 62 63 if (_strings.add (s)) _result.add (s); 64 } 65 66 final int resultLength = _result.size (); 67 if (resultLength == length) 68 return strings; 69 else 70 { 71 final String [] result = new String [resultLength]; 72 _result.toArray (result); 73 74 return result; 75 } 76 } 77 78 /** 79 * Also removes duplicates. 80 * 81 * @param strings 82 * @param delimiters 83 * @param removeNull 84 * @return 85 */ 86 public static String [] merge (final String [] strings, final String delimiters, final boolean removeNull) 87 { 88 if (strings == null) return strings; 89 90 final int length = strings.length; 91 if (length == 0) return strings; 92 93 if ((delimiters == null) || (delimiters.length () == 0)) 94 throw new IllegalArgumentException ("null/empty input: delimiters"); 95 96 final Set /* String */ _strings = new HashSet (length); 97 final List /* String */ _result = new ArrayList (length); 98 99 for (int i = 0; i < length; ++ i) 100 { 101 final String s = strings [i]; 102 if (removeNull && (s == null)) continue; 103 104 final StringTokenizer tokenizer = new StringTokenizer (s, delimiters); 105 while (tokenizer.hasMoreTokens ()) 106 { 107 final String ss = tokenizer.nextToken (); 108 if (_strings.add (ss)) _result.add (ss); 109 } 110 } 111 112 final String [] result = new String [_result.size ()]; 113 _result.toArray (result); 114 115 return result; 116 } 117 118 /** 119 * Removes duplicates. 120 * 121 * @param delimiters 122 * @param processAtFiles 123 * @return 124 * @throws IOException 125 */ 126 public static String [] mergeAT (final String [] strings, final String delimiters, final boolean processAtFiles) 127 throws IOException 128 { 129 if (! processAtFiles) 130 return merge (strings, delimiters, true); 131 else 132 { 133 if (strings == null) return strings; 134 135 final int length = strings.length; 136 if (length == 0) return strings; 137 138 if ((delimiters == null) || (delimiters.length () == 0)) 139 throw new IllegalArgumentException ("null/empty input: delimiters"); 140 141 final Set /* String */ _strings = new HashSet (length); 142 final List /* String */ _result = new ArrayList (length); 143 144 for (int i = 0; i < length; ++ i) 145 { 146 final String s = strings [i]; 147 if (s == null) continue; 148 149 final StringTokenizer tokenizer = new StringTokenizer (s, delimiters); 150 while (tokenizer.hasMoreTokens ()) 151 { 152 final String ss = tokenizer.nextToken (); 153 154 if (ss.startsWith ("@")) 155 { 156 final String [] fileList = Files.readFileList (new File (ss.substring (1))); 157 for (int j = 0; j < fileList.length; ++ j) 158 { 159 final String sss = fileList [j]; 160 if (_strings.add (sss)) _result.add (sss); 161 } 162 } 163 else if (_strings.add (ss)) _result.add (ss); 164 } 165 } 166 167 final String [] result = new String [_result.size ()]; 168 _result.toArray (result); 169 170 return result; 171 } 172 } 173 174 /** 175 * HTML attribute values can be quoted using either double or single quotes. 176 * Depending on the type of quote used, the other kind can be used unescaped 177 * within the attribute value. This method assumes that only double quotes 178 * are used for delimiting, hence this is the only kind that is escaped. 179 */ 180 public static void HTMLEscape (final String s, final StringBuffer append) 181 { 182 if (s == null) throw new IllegalArgumentException ("null input: s"); 183 if (append == null) throw new IllegalArgumentException ("null input: append"); 184 185 final char [] chars; 186 if (USE_GET_CHARS) chars = s.toCharArray (); 187 188 for (int i = 0, iLimit = s.length (); i < iLimit; ++ i) 189 { 190 final char c = USE_GET_CHARS ? chars [i] : s.charAt (i); 191 192 switch (c) 193 { 194 case '<': 195 append.append ("<"); 196 break; 197 198 case '>': 199 append.append (">"); 200 break; 201 202 case '"': 203 append.append ("""); 204 break; 205 206 case '&': 207 append.append ("&"); 208 break; 209 210 default: 211 append.append (c); 212 213 } // end of switch 214 } 215 } 216 217 /** 218 * Same as {@link #HTMLEscape(String, StringBuffer)} but also replaces spaces 219 * with " "'s, which is handy for escaping code. 220 */ 221 public static void HTMLEscapeNB (final String s, final StringBuffer append) 222 { 223 if (s == null) throw new IllegalArgumentException ("null input: s"); 224 if (append == null) throw new IllegalArgumentException ("null input: append"); 225 226 final char [] chars; 227 if (USE_GET_CHARS) chars = s.toCharArray (); 228 229 for (int i = 0, iLimit = s.length (); i < iLimit; ++ i) 230 { 231 final char c = USE_GET_CHARS ? chars [i] : s.charAt (i); 232 233 switch (c) 234 { 235 case ' ': 236 append.append ('\u00A0'); // don't use " ": a waste of space 237 break; 238 239 case '\t': 240 append.append ("\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0"); // TODO: define a prop for this 241 break; 242 243// case '-': 244// append.append ((char) 0x8209); 245// break; 246 247 case '<': 248 append.append ("<"); 249 break; 250 251 case '>': 252 append.append (">"); 253 break; 254 255 case '"': 256 append.append ("""); 257 break; 258 259 case '&': 260 append.append ("&"); 261 break; 262 263 default: 264 append.append (c); 265 266 } // end of switch 267 } 268 } 269 270 public static String HTMLEscape (final String s) 271 { 272 final StringBuffer buf = new StringBuffer (); 273 HTMLEscape (s, buf); 274 275 return buf.toString (); 276 } 277 278 public static String HTMLEscapeSP (final String s) 279 { 280 final StringBuffer buf = new StringBuffer (); 281 HTMLEscapeNB (s, buf); 282 283 return buf.toString (); 284 } 285 286 // protected: ............................................................. 287 288 // package: ............................................................... 289 290 // private: ............................................................... 291 292 293 private Strings () {} // prevent subclassing 294 295 296 private static final boolean USE_GET_CHARS = true; 297 298} // end of class 299// ----------------------------------------------------------------------------