package com.im.imjutil.report.csv;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import com.im.imjutil.exception.ValidationException;
import com.im.imjutil.validation.Format;
import com.im.imjutil.validation.Validator;
/**
* Classe que define um arquivo CSV.<br>
* Um arquivo e composto de varios elementos CSV do tipo {@link CSVElement}<br>
* Para a construcao do arquivo use o metodo {@link #write()}
* e para a leitura de um arquivo use o metodo {@link #read(String)}
*
* @author Felipe Zappala
*/
public class CSVFile implements Iterable<CSVElement>, Comparable<CSVFile> {
/** Lista dos elementos CSV do arquivo */
private List<CSVElement> elements;
/** Padrao do formato de escrita do arquivo */
private CSVPattern pattern;
/**
* Construtor padrao
*/
public CSVFile() {
init();
}
/**
* Construtor padrao
*/
public CSVFile(List<CSVElement> elements) {
if (Validator.isEmpty(elements)) {
throw new ValidationException("Lista de elementos nula ou vazia.");
}
init();
this.addAll(elements);
}
/**
* Inicializa o elemento.
*/
private void init() {
this.elements = new ArrayList<CSVElement>();
this.pattern = CSVPattern.DEFAULT;
}
/**
* Escreve os elementos do arquivo CSV em uma string.
*
* @return A string do arquivo CSV
*/
public String write() {
StringBuilder sb = new StringBuilder(1024);
if (!elements.isEmpty()) {
for (CSVElement element : elements) {
for(String data : element) {
sb.append(pattern.apply(data));
}
sb.setLength(sb.length() - pattern.COMMA.length());
sb.append(pattern.LINE);
}
}
return sb.toString();
}
/**
* Escreve os elementos do arquivo CSV em um arquivo no disco.
*
* @param file O ponteiro do arquivo CSV
* @throws IOException caso ocorra um erro de entrada ou saida
*/
public void write(File file) throws IOException {
if (Validator.isValid(file)) {
write(new FileOutputStream(file));
}
}
/**
* Escreve os elementos do arquivo CSV em um fluxo de bytes de saida.
*
* @param stream O fluxo de saida para o arquivo CSV
* @param close Determina se o metodo deve fechar o fluxo de bytes.
* @throws IOException caso ocorra um erro de entrada ou saida
*/
public void write(OutputStream stream) throws IOException {
write(stream, "UTF-8", true);
}
/**
* Escreve os elementos do arquivo CSV em um fluxo de bytes de saida.
*
* @param file O fluxo de saida para o arquivo CSV
* @param close Determina se o metodo deve fechar o fluxo de bytes.
* @throws IOException caso ocorra um erro de entrada ou saida
*/
public void write(OutputStream file, String charset, boolean close)
throws IOException {
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(file, charset));
write(writer, true);
}
/**
* Escreve os elementos do arquivo CSV em um fluxo de bytes de saida
* e fechar o fluxo de bytes.
*
* @param file O fluxo de saida para o arquivo CSV
* @throws IOException caso ocorra um erro de entrada ou saida
*/
public void write(Writer writer) throws IOException {
write(writer, true);
}
/**
* Escreve os elementos do arquivo CSV em um fluxo de bytes de saida.
*
* @param file O fluxo de saida para o arquivo CSV
* @param close Determina se o metodo deve fechar o fluxo de bytes.
* @throws IOException caso ocorra um erro de entrada ou saida
*/
public void write(Writer writer, boolean close) throws IOException {
if (Validator.isValid(writer)) {
StringBuilder sb = new StringBuilder(1024);
if (!elements.isEmpty()) {
for (CSVElement element : elements) {
for(String data : element) {
sb.append(pattern.apply(data));
}
sb.setLength(sb.length() - pattern.COMMA.length());
sb.append(pattern.LINE);
writer.write(sb.toString());
writer.flush();
sb.setLength(0);
}
}
if (close) {
writer.close();
}
}
}
/**
* Le uma string para os elementos do arquivo CSV.
*
* @param string A string do arquivo CSV.
* @throws ValidationException caso ocorra um erro de entrada ou saida
*/
public void read(String string) {
if (Validator.isValid(string)) {
try {
read(new BufferedReader(new StringReader(string)));
} catch (IOException e) {
throw new ValidationException("Erro na leitura do arquivo.", e);
}
}
}
/**
* Le um ponteiro de arquivo para os elementos do arquivo CSV.
*
* @param file O ponteiro do arquivo CSV
* @throws IOException caso ocorra um erro de entrada ou saida
*/
public void read(File file) throws IOException {
if (Validator.isValid(file)) {
read(new FileInputStream(file));
}
}
/**
* Le um fluxo de bytes de entrada para os elementos do arquivo CSV.
*
* @param stream O fluxo de entrada para o arquivo CSV
* @throws IOException caso ocorra um erro de entrada ou saida
*/
public void read(InputStream stream)
throws IOException {
read(stream, "UTF-8", true);
}
/**
* Le um fluxo de bytes de entrada para os elementos do arquivo CSV.
*
* @param stream O fluxo de entrada para o arquivo CSV
* @throws IOException caso ocorra um erro de entrada ou saida
*/
public void read(InputStream stream, String charset, boolean close)
throws IOException {
BufferedReader reader = new BufferedReader(
new InputStreamReader(stream, charset));
read(reader, close);
}
/**
* Le um fluxo de bytes de entrada para os elementos do arquivo CSV.
*
* @param file O fluxo de entrada para o arquivo CSV
* @throws IOException caso ocorra um erro de entrada ou saida
*/
public void read(BufferedReader reader) throws IOException {
read(reader, true);
}
/**
* Le um fluxo de bytes de entrada para os elementos do arquivo CSV.
*
* @param file O fluxo de entrada para o arquivo CSV
* @throws IOException caso ocorra um erro de entrada ou saida
*/
public void read(BufferedReader reader, boolean close) throws IOException {
if (reader == null) {
throw new ValidationException("Reader nulo");
}
CSVElement element;
String line;
while (reader.ready()) {
line = reader.readLine();
if (line == null)
break;
element = new CSVElement();
for (String celule : line.split(pattern.COMMA)) {
element.add(celule.replaceAll(pattern.QUOTE, ""));
}
if (!element.isEmpty()) {
elements.add(element);
}
}
if (close) {
reader.close();
}
}
/**
* Obtem o {@link CSVElement} do indice indicado
*
* @param index Indice do elemento
* @return O elemento do indice indicado
*/
public CSVElement get(int index) {
return this.elements.get(index);
}
/**
* Adiciona um {@link CSVElement} ao arquivo CSV.
*
* @param element O elemento a ser adicionado.
* @return A referencia para o mesmo objeto.
*/
public CSVFile add(CSVElement element) {
set(element);
return this;
}
/**
* Adiciona uma lista de {@link CSVElement} ao arquivo CSV.
*
* @param elements O elementos a serem adicionados.
* @return A referencia para o mesmo objeto.
*/
public CSVFile addAll(List<CSVElement> elements) {
if (!Validator.isEmpty(elements)) {
this.elements.addAll(elements);
}
return this;
}
/**
* Obtem uma lista de {@link CSVElement} ao arquivo CSV.
*
* @return A lista de elementos do arquivo CSV.
*/
public List<CSVElement> getAll() {
return Collections.unmodifiableList(this.elements);
}
/**
* Configura um {@link CSVElement} no arquivo CSV.
*
* @param index Indice do elemento CSV
* @param element O elemento a ser adicionado
*/
public void set(int index, CSVElement element) {
if (index >= 0) {
if (Validator.isValid(element) && index >= 0) {
this.elements.set(index, element);
} else {
this.elements.set(index, new CSVElement());
}
}
}
/**
* Adiciona um elemento ao arquivo CSV
*
* @param element O elemento a ser adicionado
*/
public void set(CSVElement element) {
if (Validator.isValid(element)) {
this.elements.add(element);
} else {
this.elements.add(new CSVElement());
}
}
/**
* Adiciona um elemento ao arquivo CSV no indice indicado
*
* @param index O indice a ser adicionado
* @param element O elemento a ser adicionado
*/
public void setLine(int index, CSVElement element) {
set(index, element);
}
/**
* Adiciona um elemento ao arquivo CSV
*
* @param element O elemento a ser adicionado
*/
public void setLine(CSVElement element) {
set(element);
}
/**
* Adiciona um elemento ao arquivo CSV no indice indicado
*
* @param index O indice a ser adicionado
* @param element O elemento a ser adicionado
*/
public void setElement(int index, CSVElement element) {
set(index, element);
}
/**
* Adiciona um elemento ao arquivo CSV
*
* @param element O elemento a ser adicionado
*/
public void setElement(CSVElement element) {
set(element);
}
/**
* Obtem um {@link CSVElement} do arquivo CSV no indice indicado.
*
* @param index O indice a ser obtido
* @return O elemento do CSV
*/
public CSVElement getElement(int index) {
return get(index);
}
/**
* Obtem um {@link CSVElement} do arquivo CSV no indice indicado.
*
* @param index O indice a ser obtido
* @return O elemento do CSV
*/
public CSVElement getLine(int index) {
return get(index);
}
/**
* Obtem o padrao de formatacao {@link CSVPattern} do arquivo CSV
*
* @return O padrao de formatacao
*/
public CSVPattern getPattern() {
return pattern;
}
/**
* Configura o padrao de formatacao {@link CSVPattern} do arquivo CSV
*
* @param pattern O padrao de formatacao
*/
public void setPattern(CSVPattern pattern) {
if (pattern != null) {
this.pattern = pattern;
}
}
@Override
public int compareTo(CSVFile o) {
if (o != null) {
return this.elements.toString().compareTo(o.elements.toString());
}
return 1;
}
/**
* Obtem um iterador para as linhas do relatorio.
*/
@Override
public Iterator<CSVElement> iterator() {
return this.elements.iterator();
}
/**
* Numero de linha do csv.
*
* @return Retorna o tamanho da lista de itens.
*/
public int size() {
return elements.size();
}
/**
* Verifica se o elemento e vazio, ou seja, nao possui colunas.
*
* @return Verdadeiro quando for vazio.
*/
public boolean isEmpty() {
boolean isEmpty = true;
for (CSVElement row : this.elements) {
isEmpty &= row.isEmpty();
}
return isEmpty;
}
@Override
public int hashCode() {
return this.elements.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof CSVFile) {
CSVFile another = (CSVFile) obj;
return this.elements.equals(another.elements);
}
return false;
}
@Override
public String toString() {
return Format.toString(this);
}
// public static void main(String[] args) throws IOException {
// System.out.println("Escrevendo...");
// CSVFile f = new CSVFile();
// f.setPattern(CSVPattern.EXCEL);
//
// f.add(new CSVElement().add("c1����").add("c2").add("c3").add("c4"));
// f.add(new CSVElement().add("d1").add("d2").add("d3").add("d4"));
// f.add(new CSVElement().add("d11").add("d22").add("d33").add("d44"));
//
// File e = new File("/Users/fzappala/Desktop/arq.csv");
//
// f.write(new FileOutputStream(e), "ISO-8859-1", true);
// System.out.println("Foi");
//
//
//
// f = new CSVFile();
// f.setPattern(CSVPattern.EXCEL);
// f.read(new FileInputStream(e), "ISO-8859-1", true);
//
// System.out.println("Lendo...");
// for (CSVElement ee : f) {
// for (String s : ee) {
// System.out.print(s);
// System.out.print(" | ");
// }
// System.out.println("");
// }
//
// }
}