001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/postem/tags/sakai_2-4-1/postem-app/src/java/org/sakaiproject/tool/postem/CSV.java $
003: * $Id: CSV.java 20863 2007-02-01 14:12:57Z wagnermr@iupui.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.tool.postem;
021:
022: import java.util.ArrayList;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.zip.DataFormatException;
026:
027: import javax.faces.application.FacesMessage;
028:
029: public class CSV {
030:
031: private List contents;
032:
033: private List headers;
034:
035: private List students;
036:
037: private String csv;
038:
039: public static final char COMMA_DELIM = ',';
040: public static final char TAB_DELIM = '\t';
041:
042: public static final int MAX_COL_LENGTH = 2000;
043:
044: // private boolean withHeaders = true;
045:
046: public CSV(String csv, boolean withHeader)
047: throws DataFormatException {
048: contents = retrieveContents(csv, COMMA_DELIM);
049: headers = retrieveHeaders(contents);
050: students = retrieveStudents(contents, withHeader);
051: this .csv = csv;
052: }
053:
054: public CSV(String csv, boolean withHeader, char delimiter)
055: throws DataFormatException {
056: contents = retrieveContents(csv, delimiter);
057: headers = retrieveHeaders(contents);
058: students = retrieveStudents(contents, withHeader);
059: this .csv = csv;
060: }
061:
062: public CSV(List contents, boolean withHeader) {
063: headers = retrieveHeaders(contents);
064: students = retrieveStudents(contents, withHeader);
065: csv = createFromContents(contents);
066: this .contents = contents;
067: }
068:
069: public List getHeaders() {
070: return headers;
071: }
072:
073: public List getStudents() {
074: return students;
075: }
076:
077: public List getStudentUsernames() {
078: List usernames = new ArrayList();
079:
080: Iterator studentIter = students.iterator();
081: while (studentIter.hasNext()) {
082: List s1 = (List) studentIter.next();
083: String usr = ((String) s1.get(0)).trim();
084: usernames.add(usr);
085: }
086:
087: return usernames;
088: }
089:
090: public String getCsv() {
091: return csv;
092: }
093:
094: public static String createFromContents(List rows) {
095: StringBuffer csv = new StringBuffer();
096:
097: Iterator riter = rows.iterator();
098: while (riter.hasNext()) {
099: Iterator citer = ((List) riter.next()).iterator();
100: while (citer.hasNext()) {
101: String current = (String) citer.next();
102: current = current.replaceAll("\"", "\"\"");
103:
104: csv.append("\"");
105: csv.append(current);
106: csv.append("\"");
107:
108: if (citer.hasNext()) {
109: csv.append(",");
110: }
111: }
112: if (riter.hasNext()) {
113: csv.append("\r\n");
114: }
115: }
116: return csv.toString();
117: }
118:
119: public static List retrieveContents(String csv, char delimiter)
120: throws DataFormatException {
121:
122: List all = new ArrayList();
123: List current = new ArrayList();
124: StringBuffer it = new StringBuffer();
125:
126: boolean inQuotes = false;
127:
128: int length = csv.length();
129: for (int ii = 0; ii < length; ii++) {
130:
131: if (inQuotes) {
132: if (ii == length - 1) {
133: current.add((it.length() == 0) ? " " : it
134: .toString());
135: all.add(current);
136: break;
137: }
138: if (csv.charAt(ii) == '"') {
139: if (ii < length - 1 && csv.charAt(ii + 1) == '"') {
140: it.append("\"");
141: ii++;
142: } else {
143: inQuotes = false;
144: }
145: } else {
146: it.append(csv.charAt(ii));
147: }
148: } else {
149: if (ii == length - 1 && csv.charAt(ii) != '\n'
150: && csv.charAt(ii) != '\r') {
151: if (csv.charAt(ii) == delimiter) {
152:
153: it = truncateIt(it);
154: current.add((it.length() == 0) ? " " : it
155: .toString());
156: current.add("");
157: } else {
158: it.append(csv.charAt(ii));
159: it = truncateIt(it);
160: current.add((it.length() == 0) ? " " : it
161: .toString());
162: }
163: all.add(current);
164: break;
165: }
166: if (csv.charAt(ii) == delimiter) {
167: it = truncateIt(it);
168: current.add((it.length() == 0) ? " " : it
169: .toString());
170: it = new StringBuffer();
171: // this line would trim leading spaces per the spec, but not trailing
172: // ones.
173: // we don't care about it so much anyways, since the info
174: // will be output in a web context
175: // csv = csv.trim();
176: } else if (csv.charAt(ii) == '\r'
177: || csv.charAt(ii) == '\n') {
178: if (ii < length - 1 && csv.charAt(ii + 1) == '\n') {
179: ii++;
180: }
181: it = truncateIt(it);
182: current.add((it.length() == 0) ? " " : it
183: .toString());
184: it = new StringBuffer();
185: all.add(current);
186: current = new ArrayList();
187:
188: } else if (csv.charAt(ii) == '"') {
189: inQuotes = true;
190: } else {
191: it.append(csv.charAt(ii));
192: }
193: }
194: }
195:
196: // we want to identify the row with the most columns and then append blank columns until all the rows
197: // are the same length
198: int finalNumCols = 0;
199: for (int i = 0; i < all.size(); i++) {
200: if (((List) all.get(i)).size() > finalNumCols) {
201: finalNumCols = ((List) all.get(i)).size();
202: }
203: }
204:
205: // make sure all of the rows have the same number of cols as the longest row
206: for (int j = 0; j < all.size(); j++) {
207:
208: while (((List) all.get(j)).size() < finalNumCols) {
209: ((List) all.get(j)).add(" ");
210: }
211: }
212:
213: return all;
214: }
215:
216: public static List retrieveHeaders(List rows) {
217: if (rows == null || rows.size() == 0) {
218: return null;
219: }
220:
221: return (List) rows.get(0);
222: }
223:
224: public static List retrieveStudents(List rows, boolean withHeader) {
225: List headers = retrieveHeaders(rows);
226: List results = new ArrayList(rows);
227: if (withHeader == true) {
228: results.remove(0);
229: }
230: return results;
231: }
232:
233: public static int determineColumns(String csv, char delimiter) {
234: int total = 0;
235: boolean inQuotes = false;
236:
237: int length = csv.length();
238: for (int ii = 0; ii < length; ii++) {
239: if (inQuotes) {
240: if (csv.charAt(ii) == '"') {
241: if (ii < length - 1 && csv.charAt(ii + 1) == '"') {
242: ii++;
243: } else {
244: inQuotes = false;
245: }
246: }
247: } else {
248: if (csv.charAt(ii) == delimiter) {
249: total++;
250: } else if (csv.charAt(ii) == '\r'
251: || csv.charAt(ii) == '\n') {
252: break;
253: } else if (csv.charAt(ii) == '"') {
254: inQuotes = true;
255: }
256: }
257: }
258: total++;
259: return total;
260: }
261:
262: /**
263: * we need to truncate any data greater than MAX_COL_LENGTH chars for the db
264: * @param buffer
265: * @return
266: */
267: private static StringBuffer truncateIt(StringBuffer buffer) {
268: if (buffer.length() > MAX_COL_LENGTH) // truncate text longer than MAX_COL_LENGTH
269: {
270: String truncatedString = buffer
271: .substring(0, MAX_COL_LENGTH);
272: buffer = new StringBuffer();
273: buffer.append(truncatedString);
274: }
275:
276: return buffer;
277: }
278: }
|