001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 * 027 * This file is based on: 028 * org.json.CDL 029 * from the JSON in Java implementation. 030 * 031 * Copyright (c) 2002 JSON.org 032 * 033 * Permission is hereby granted, free of charge, to any person obtaining a copy 034 * of this software and associated documentation files (the "Software"), to deal 035 * in the Software without restriction, including without limitation the rights 036 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 037 * copies of the Software, and to permit persons to whom the Software is 038 * furnished to do so, subject to the following conditions: 039 * 040 * The above copyright notice and this permission notice shall be included in all 041 * copies or substantial portions of the Software. 042 * 043 * The Software shall be used for Good, not Evil. 044 * 045 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 046 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 047 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 048 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 049 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 050 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 051 * SOFTWARE. 052 */ 053 054package org.opencms.json; 055 056/** 057 * This provides static methods to convert comma delimited text into a 058 * JSONArray, and to covert a JSONArray into comma delimited text. Comma 059 * delimited text is a very popular format for data interchange. It is 060 * understood by most database, spreadsheet, and organizer programs. 061 * <p> 062 * Each row of text represents a row in a table or a data record. Each row 063 * ends with a NEWLINE character. Each row contains one or more values. 064 * Values are separated by commas. A value can contain any character except 065 * for comma, unless is is wrapped in single quotes or double quotes. 066 * <p> 067 * The first row usually contains the names of the columns. 068 * <p> 069 * A comma delimited list can be converted into a JSONArray of JSONObjects. 070 * The names for the elements in the JSONObjects can be taken from the names 071 * in the first row.<p> 072 * 073 */ 074public final class CDL { 075 076 /** 077 * Hidden constructor.<p> 078 */ 079 private CDL() { 080 081 // hidden constructor 082 } 083 084 /** 085 * Produce a JSONArray of strings from a row of comma delimited values.<p> 086 * 087 * @param x A JSONTokener of the source text 088 * @return A JSONArray of strings 089 * @throws JSONException if something goes wrong 090 */ 091 public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException { 092 093 JSONArray ja = new JSONArray(); 094 for (;;) { 095 String value = getValue(x); 096 if ((value == null) || ((ja.length() == 0) && (value.length() == 0))) { 097 return null; 098 } 099 ja.put(value); 100 for (;;) { 101 char c = x.next(); 102 if (c == ',') { 103 break; 104 } 105 if (c != ' ') { 106 if ((c == '\n') || (c == '\r') || (c == 0)) { 107 return ja; 108 } 109 throw x.syntaxError("Bad character '" + c + "' (" + (int)c + ")."); 110 } 111 } 112 } 113 } 114 115 /** 116 * Produce a JSONObject from a row of comma delimited text, using a 117 * parallel JSONArray of strings to provides the names of the elements.<p> 118 * 119 * @param names A JSONArray of names. This is commonly obtained from the 120 * first row of a comma delimited text file using the rowToJSONArray 121 * method 122 * @param x A JSONTokener of the source text 123 * @return A JSONObject combining the names and values 124 * @throws JSONException if something goes wrong 125 */ 126 public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x) throws JSONException { 127 128 JSONArray ja = rowToJSONArray(x); 129 return ja != null ? ja.toJSONObject(names) : null; 130 } 131 132 /** 133 * Produce a comma delimited text row from a JSONArray. Values containing 134 * the comma character will be quoted.<p> 135 * 136 * @param ja A JSONArray of strings 137 * @return A string ending in NEWLINE 138 */ 139 public static String rowToString(JSONArray ja) { 140 141 StringBuffer sb = new StringBuffer(); 142 for (int i = 0; i < ja.length(); i += 1) { 143 if (i > 0) { 144 sb.append(','); 145 } 146 Object o = ja.opt(i); 147 if (o != null) { 148 String s = o.toString(); 149 if (s.indexOf(',') >= 0) { 150 if (s.indexOf('"') >= 0) { 151 sb.append('\''); 152 sb.append(s); 153 sb.append('\''); 154 } else { 155 sb.append('"'); 156 sb.append(s); 157 sb.append('"'); 158 } 159 } else { 160 sb.append(s); 161 } 162 } 163 } 164 sb.append('\n'); 165 return sb.toString(); 166 167 } 168 169 /** 170 * Produce a JSONArray of JSONObjects from a comma delimited text string 171 * using a supplied JSONArray as the source of element names.<p> 172 * 173 * @param names A JSONArray of strings 174 * @param x A JSONTokener of the source text 175 * @return A JSONArray of JSONObjects 176 * @throws JSONException if something goes wrong 177 */ 178 public static JSONArray toJSONArray(JSONArray names, JSONTokener x) throws JSONException { 179 180 if ((names == null) || (names.length() == 0)) { 181 return null; 182 } 183 JSONArray ja = new JSONArray(); 184 for (;;) { 185 JSONObject jo = rowToJSONObject(names, x); 186 if (jo == null) { 187 break; 188 } 189 ja.put(jo); 190 } 191 if (ja.length() == 0) { 192 return null; 193 } 194 return ja; 195 } 196 197 /** 198 * Produce a JSONArray of JSONObjects from a comma delimited text string 199 * using a supplied JSONArray as the source of element names.<p> 200 * 201 * @param names A JSONArray of strings. 202 * @param string The comma delimited text 203 * @return A JSONArray of JSONObjects 204 * @throws JSONException if something goes wrong 205 */ 206 public static JSONArray toJSONArray(JSONArray names, String string) throws JSONException { 207 208 return toJSONArray(names, new JSONTokener(string)); 209 } 210 211 /** 212 * Produce a JSONArray of JSONObjects from a comma delimited text string, 213 * using the first row as a source of names.<p> 214 * 215 * @param x The JSONTokener containing the comma delimited text 216 * @return A JSONArray of JSONObjects 217 * @throws JSONException if something goes wrong 218 */ 219 public static JSONArray toJSONArray(JSONTokener x) throws JSONException { 220 221 return toJSONArray(rowToJSONArray(x), x); 222 } 223 224 /** 225 * Produce a JSONArray of JSONObjects from a comma delimited text string, 226 * using the first row as a source of names.<p> 227 * 228 * @param string The comma delimited text 229 * @return A JSONArray of JSONObjects 230 * @throws JSONException if something goes wrong 231 */ 232 public static JSONArray toJSONArray(String string) throws JSONException { 233 234 return toJSONArray(new JSONTokener(string)); 235 } 236 237 /** 238 * Produce a comma delimited text from a JSONArray of JSONObjects. The 239 * first row will be a list of names obtained by inspecting the first 240 * JSONObject.<p> 241 * 242 * @param ja A JSONArray of JSONObjects 243 * @return A comma delimited text 244 * @throws JSONException if something goes wrong 245 */ 246 public static String toString(JSONArray ja) throws JSONException { 247 248 JSONObject jo = ja.optJSONObject(0); 249 if (jo != null) { 250 JSONArray names = jo.names(); 251 if (names != null) { 252 return rowToString(names) + toString(names, ja); 253 } 254 } 255 return null; 256 } 257 258 /** 259 * Produce a comma delimited text from a JSONArray of JSONObjects using 260 * a provided list of names. The list of names is not included in the 261 * output.<p> 262 * 263 * @param names A JSONArray of strings 264 * @param ja A JSONArray of JSONObjects 265 * @return A comma delimited text 266 * @throws JSONException if something goes wrong 267 */ 268 public static String toString(JSONArray names, JSONArray ja) throws JSONException { 269 270 if ((names == null) || (names.length() == 0)) { 271 return null; 272 } 273 StringBuffer sb = new StringBuffer(); 274 for (int i = 0; i < ja.length(); i += 1) { 275 JSONObject jo = ja.optJSONObject(i); 276 if (jo != null) { 277 sb.append(rowToString(jo.toJSONArray(names))); 278 } 279 } 280 return sb.toString(); 281 } 282 283 /** 284 * Get the next value. The value can be wrapped in quotes. The value can 285 * be empty.<p> 286 * 287 * @param x A JSONTokener of the source text 288 * @return The value string, or null if empty 289 * @throws JSONException if the quoted string is badly formed 290 */ 291 private static String getValue(JSONTokener x) throws JSONException { 292 293 char c; 294 do { 295 c = x.next(); 296 } while ((c == ' ') || (c == '\t')); 297 switch (c) { 298 case 0: 299 return null; 300 case '"': 301 case '\'': 302 return x.nextString(c); 303 case ',': 304 x.back(); 305 return ""; 306 default: 307 x.back(); 308 return x.nextTo(','); 309 } 310 } 311}