001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.util.table; 028 029 030 031 import java.io.BufferedWriter; 032 import java.io.OutputStream; 033 import java.io.OutputStreamWriter; 034 import java.io.PrintWriter; 035 import java.io.Writer; 036 037 038 039 /** 040 * An interface for creating a CSV formatted table. 041 */ 042 public final class CSVTablePrinter extends TablePrinter { 043 044 /** 045 * Table serializer implementation. 046 */ 047 private final class Serializer extends TableSerializer { 048 049 // The current column being output. 050 private int column = 0; 051 052 // Counts the number of separators that should be output the next 053 // time a non-empty cell is displayed. The comma separators are 054 // not displayed immediately so that we can avoid displaying 055 // unnecessary trailing separators. 056 private int requiredSeparators = 0; 057 058 059 060 // Private constructor. 061 private Serializer() { 062 // No implementation required. 063 } 064 065 066 067 /** 068 * {@inheritDoc} 069 */ 070 @Override 071 public void addCell(String s) { 072 // Avoid printing comma separators for trailing empty cells. 073 if (s.length() == 0) { 074 requiredSeparators++; 075 } else { 076 for (int i = 0; i < requiredSeparators; i++) { 077 writer.print(','); 078 } 079 requiredSeparators = 1; 080 } 081 082 boolean needsQuoting = false; 083 084 if (s.contains(",")) { 085 needsQuoting = true; 086 } 087 088 if (s.contains("\n")) { 089 needsQuoting = true; 090 } 091 092 if (s.contains("\r")) { 093 needsQuoting = true; 094 } 095 096 if (s.contains("\"")) { 097 needsQuoting = true; 098 s = s.replace("\"", "\"\""); 099 } 100 101 if (s.startsWith(" ")) { 102 needsQuoting = true; 103 } 104 105 if (s.endsWith(" ")) { 106 needsQuoting = true; 107 } 108 109 StringBuilder builder = new StringBuilder(); 110 if (needsQuoting) { 111 builder.append("\""); 112 } 113 114 builder.append(s); 115 116 if (needsQuoting) { 117 builder.append("\""); 118 } 119 120 writer.print(builder.toString()); 121 column++; 122 } 123 124 125 126 /** 127 * {@inheritDoc} 128 */ 129 @Override 130 public void addHeading(String s) { 131 if (displayHeadings) { 132 addCell(s); 133 } 134 } 135 136 137 138 /** 139 * {@inheritDoc} 140 */ 141 @Override 142 public void endHeader() { 143 if (displayHeadings) { 144 writer.println(); 145 } 146 } 147 148 149 150 /** 151 * {@inheritDoc} 152 */ 153 @Override 154 public void endRow() { 155 writer.println(); 156 } 157 158 159 160 /** 161 * {@inheritDoc} 162 */ 163 @Override 164 public void endTable() { 165 writer.flush(); 166 } 167 168 169 170 /** 171 * {@inheritDoc} 172 */ 173 @Override 174 public void startHeader() { 175 column = 0; 176 requiredSeparators = 0; 177 } 178 179 180 181 /** 182 * {@inheritDoc} 183 */ 184 @Override 185 public void startRow() { 186 column = 0; 187 requiredSeparators = 0; 188 } 189 } 190 191 // Indicates whether or not the headings should be output. 192 private boolean displayHeadings = false; 193 194 // The output destination. 195 private PrintWriter writer = null; 196 197 198 199 /** 200 * Creates a new CSV table printer for the specified output stream. 201 * Headings will not be displayed by default. 202 * 203 * @param stream 204 * The stream to output tables to. 205 */ 206 public CSVTablePrinter(OutputStream stream) { 207 this(new BufferedWriter(new OutputStreamWriter(stream))); 208 } 209 210 211 212 /** 213 * Creates a new CSV table printer for the specified writer. 214 * Headings will not be displayed by default. 215 * 216 * @param writer 217 * The writer to output tables to. 218 */ 219 public CSVTablePrinter(Writer writer) { 220 this.writer = new PrintWriter(writer); 221 } 222 223 224 225 /** 226 * Specify whether or not table headings should be displayed. 227 * 228 * @param displayHeadings 229 * <code>true</code> if table headings should be 230 * displayed. 231 */ 232 public void setDisplayHeadings(boolean displayHeadings) { 233 this.displayHeadings = displayHeadings; 234 } 235 236 237 238 /** 239 * {@inheritDoc} 240 */ 241 @Override 242 protected TableSerializer getSerializer() { 243 return new Serializer(); 244 } 245 246 }