/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.util.model; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import javax.swing.table.AbstractTableModel; import com.servoy.j2db.util.Debug; /** * Ascii import model * @author jblok */ public class SeparatedASCIIImportTableModel extends AbstractTableModel { public static final String NONE_QUALIFIER = "<none>"; //$NON-NLS-1$ public static final String SINGLE_QUOTE_QUALIFIER = "'"; //$NON-NLS-1$ public static final String DUBBLE_QUOTE_QUALIFIER = "\""; //$NON-NLS-1$ private String separator = ""; //$NON-NLS-1$ private String qualifier = ""; //$NON-NLS-1$ private boolean headerRow = false; private List items; private String[] lineCache0; private String[] lineCacheN; private int cacheForLine = -1; private static boolean lastLineNotComplete; public SeparatedASCIIImportTableModel() { super(); } public String setList(List items, boolean headerRowIncluded) { fireTableRowsDeleted(0, getRowCount() - 1); this.items = items; lineCacheN = null; cacheForLine = -1; headerRow = headerRowIncluded; lastLineNotComplete = false; String str = parseLines(); fireTableRowsInserted(0, getRowCount() - 1); return str; } public String parseLines() { for (int i = 0; i < getRowCount(); i++) { getValueAt(i, 0); if (lineCacheN == null) { if (lastLineNotComplete) { return (String)items.remove(items.size() - 1); } return null; } if (headerRow) items.set(i + 1, lineCacheN); else items.set(i, lineCacheN); } return null; } @Override public String getColumnName(int col) { if (separator.equals("")) //$NON-NLS-1$ { String line = (String)items.get(0); lineCache0 = new String[] { line }; return line; } if (lineCache0 == null) { lineCache0 = parseLine(0, items, separator, qualifier); for (int i = 0; i < lineCache0.length; i++) { if (lineCache0[i] == null || lineCache0[i].trim().length() == 0) { lineCache0[i] = "(" + (i + 1) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } } } if (col < lineCache0.length) { String str = lineCache0[col]; return str; } return ""; //$NON-NLS-1$ } public Object getValueAt(int row, int col) { if (headerRow) row++; if (row >= items.size()) return null; Object o = items.get(row); if (o instanceof String) { String line = (String)o; if (separator.equals("")) return line; //$NON-NLS-1$ } if (cacheForLine != row) { cacheForLine = row; lineCacheN = parseLine(row, items, separator, qualifier); if (lineCacheN == null) return null; } if (col < lineCacheN.length) { return lineCacheN[col]; } else { return null; } } public int getRowCount() { if (items == null) return 0; if (headerRow) { return items.size() - 1; } else { return items.size(); } } public int getColumnCount() { if (lineCache0 == null) { getColumnName(0); } return lineCache0.length; } public void setSeparator(String separator) { this.separator = separator; lineCache0 = null; cacheForLine = -1; fireTableStructureChanged(); } public void setUseHeaderRow(boolean headerRow) { this.headerRow = headerRow; lineCache0 = null; cacheForLine = -1; fireTableStructureChanged(); } public void setTextQualifier(String q) { if (q == null) return; if (!q.equals(NONE_QUALIFIER)) { if (q.length() > 1) { q = q.substring(0, 1); } this.qualifier = q; } else { this.qualifier = ""; //$NON-NLS-1$ } fireTableStructureChanged(); } @Override public boolean isCellEditable(int row, int col) { return false; } @Override public void setValueAt(Object value, int row, int col) { } private static List tokenizeLine(int start_row, List lines, String separator, String qualifier) { if (start_row >= lines.size()) return null; String line = (String)lines.get(start_row); if (line == null) return null; if (line.equals("")) //$NON-NLS-1$ { ArrayList al = new ArrayList(); al.add(""); //$NON-NLS-1$ return al; } ArrayList list = new ArrayList(); StringTokenizer tk = new StringTokenizer(line, qualifier + separator, true); while (tk.hasMoreTokens()) { list.add(tk.nextToken()); } return list; } public static String[] parseLine(int start_row, List lines, String separator, String qualifier) { Object line = lines.get(start_row); if (line instanceof String[]) { return (String[])line; } List list = tokenizeLine(start_row, lines, separator, qualifier); if (list == null) return new String[0]; List retval = new ArrayList(); for (int i = 0; i < list.size(); i++) { String element = (String)list.get(i); if (element.equals(qualifier)) { i = handleQualifiedString(start_row, lines, i, list, retval, separator, qualifier); if (i == -1) return null; } else if (element.equals(separator)) { if (i == 0) { retval.add(null); } else if (i + 1 < list.size()) { String nextElement = (String)list.get(i + 1); if (separator.equals(nextElement)) { retval.add(null); } } else { retval.add(null); } } else { retval.add(element); } } String[] array = new String[retval.size()]; retval.toArray(array); return array; } private static int handleQualifiedString(int start_row, List lines, int start_pos, List list, List retval, String separator, String qualifier) { StringBuffer sb = new StringBuffer(); int i = start_pos + 1; boolean inString = true; // it is a start string but the next line starts with an /r or /n if (i == list.size()) { list.add(""); //$NON-NLS-1$ } for (; i < list.size(); i++) { String element = (String)list.get(i); if (qualifier.equals(element)) { if (i + 1 < list.size()) { String nextElement = (String)list.get(i + 1); if (nextElement.equals(qualifier)) { sb.append(qualifier);//add single qualifier i++;//skip nextElement in element if (i + 1 >= list.size() && inString) { //concat next line List newlist = tokenizeLine(start_row + 1, lines, separator, qualifier); if (newlist == null) { // there should be a next line! lastLineNotComplete = true; return -1; } list.addAll(newlist); String line1 = (String)lines.get(start_row); String line2 = (String)lines.get(start_row + 1); lines.set(start_row, line1 + "\n" + line2); //$NON-NLS-1$ lines.remove(start_row + 1); } } else //end of string found { inString = !inString; break; } } else //end of line found { //do nothing } } else { sb.append(element); if (i + 1 == list.size() && inString) { //concat next line List newlist = tokenizeLine(start_row + 1, lines, separator, qualifier); if (newlist == null) { // there should be a next line! lastLineNotComplete = true; return -1; } list.addAll(newlist); String line1 = (String)lines.get(start_row); String line2 = (String)lines.get(start_row + 1); lines.set(start_row, line1 + "\n" + line2); //$NON-NLS-1$ lines.remove(start_row + 1); } } } String retString = sb.toString(); if (retString.length() == 0) retString = null; retval.add(retString); return i; } @Override public String toString() { StringBuffer sb = new StringBuffer(); for (int i = 0; i < getColumnCount(); i++) { sb.append(getColumnName(i)); sb.append(";"); //$NON-NLS-1$ } sb.append("\n"); //$NON-NLS-1$ for (int i = 0; i < getRowCount(); i++) { for (int j = 0; j < getColumnCount(); j++) { sb.append(getValueAt(i, j)); sb.append(";"); //$NON-NLS-1$ } sb.append("\n"); //$NON-NLS-1$ } return sb.toString(); } public static void main(String[] args)//for testing { List v = new ArrayList(); v.add("\"jan,piet\"\t13\t\t\"345\"\t"); //$NON-NLS-1$ v.add("\"tr\tude\"\t40\t\"\"\t200\t3"); //$NON-NLS-1$ v.add("\"tr\"\"ude\"\t50\t\t20\t4"); //$NON-NLS-1$ SeparatedASCIIImportTableModel m = new SeparatedASCIIImportTableModel(); m.setList(v, false); m.setSeparator("\t"); //$NON-NLS-1$ m.setTextQualifier(SeparatedASCIIImportTableModel.DUBBLE_QUOTE_QUALIFIER); System.out.println(m); } public SeparatedASCIIImportTableModel(List items) { super(); String lastLine = setList(items, false); if (lastLine != null) { Debug.error("WARNING the last line of the file is not terminated correctly: " + lastLine); //$NON-NLS-1$ } } }