package au.com.vaadinutils.crud;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.examples.HtmlToPlainText;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.server.FileDownloader;
import com.vaadin.server.StreamResource;
import com.vaadin.server.StreamResource.StreamSource;
import com.vaadin.ui.AbstractLayout;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Table;
import com.vaadin.ui.Table.ColumnGenerator;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
import au.com.bytecode.opencsv.CSVWriter;
import au.com.vaadinutils.fields.ClickableLabel;
import au.com.vaadinutils.jasper.AttachmentType;
import au.com.vaadinutils.util.PipedOutputStreamWrapper;
public class ContainerCSVExport<E>
{
// Logger logger = LogManager.getLogger();
PipedOutputStreamWrapper stream = new PipedOutputStreamWrapper();
Logger logger = LogManager.getLogger();
private HeadingPropertySet headingsSet;
private Table table;
private LinkedHashMap<String, Object> extraColumnHeadersAndPropertyIds;
public ContainerCSVExport(final String fileName, final Table table, final HeadingPropertySet headingsSet)
{
this.table = table;
this.headingsSet = headingsSet;
final Window window = new Window();
window.setCaption("Download " + fileName + " CSV data");
window.center();
window.setHeight("100");
window.setWidth("300");
window.setModal(true);
HorizontalLayout layout = new HorizontalLayout();
layout.setMargin(true);
window.setContent(layout);
UI.getCurrent().addWindow(window);
window.setVisible(true);
final Button downloadButton = createDownloadButton(fileName, window);
layout.addComponent(downloadButton);
layout.setComponentAlignment(downloadButton, Alignment.MIDDLE_CENTER);
layout.addComponent(downloadButton);
}
private Button createDownloadButton(final String fileName, final Window window)
{
final Button downloadButton = new Button("Download CSV Data");
downloadButton.setDisableOnClick(true);
@SuppressWarnings("serial")
StreamSource source = new StreamSource()
{
@Override
public InputStream getStream()
{
try
{
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(arrayOutputStream));
export(table, bufferedWriter, headingsSet);
return new ByteArrayInputStream(arrayOutputStream.toByteArray());
}
catch (Throwable e)
{
logger.error(e, e);
Notification.show(e.getMessage());
}
finally
{
Runnable runner = new Runnable()
{
@Override
public void run()
{
try
{
Thread.sleep(500);
UI.getCurrent().access(new Runnable()
{
@Override
public void run()
{
window.close();
}
});
}
catch (InterruptedException e)
{
logger.error(e, e);
}
}
};
new Thread(runner, "Dialog closer").start();
}
return null;
}
};
StreamResource resource = new StreamResource(source, fileName + AttachmentType.CSV.getFileExtension());
resource.setMIMEType(AttachmentType.CSV.getMIMETypeString());
FileDownloader fileDownloader = new FileDownloader(resource);
fileDownloader.setOverrideContentType(false);
fileDownloader.extend(downloadButton);
return downloadButton;
}
public void export(Table table, Writer stream, HeadingPropertySet headingsSet) throws IOException
{
CSVWriter writer = new CSVWriter(stream);
Map<String, Object> headerPropertyMap = new LinkedHashMap<>();
List<HeadingToPropertyId> cols = headingsSet.getColumns();
for (HeadingToPropertyId col : cols)
{
headerPropertyMap.put(col.getHeader(), col.getPropertyId());
}
List<String> headerList = new LinkedList<>();
headerList.addAll(headerPropertyMap.keySet());
extraColumnHeadersAndPropertyIds = getExtraColumnHeadersAndPropertyIds();
headerList.addAll(extraColumnHeadersAndPropertyIds.keySet());
writeHeaders(writer, headerList);
Set<Object> properties = new LinkedHashSet<>();
properties.addAll(headerPropertyMap.values());
for (Object id : table.getContainerDataSource().getItemIds())
{
writeRow(writer, table, id, properties);
}
writer.flush();
}
private void writeRow(CSVWriter writer, Table table, Object id, Set<Object> properties)
{
Item item = table.getItem(id);
String[] values = new String[properties.size() + extraColumnHeadersAndPropertyIds.size()];
int i = 0;
for (Object propertyId : properties)
{
@SuppressWarnings("rawtypes")
final Property itemProperty = item.getItemProperty(propertyId);
if (itemProperty != null && itemProperty.getValue() != null)
{
ColumnGenerator generator = table.getColumnGenerator(propertyId);
if (generator != null)
{
Object value = generator.generateCell(table, id, propertyId);
if (value instanceof Label)
{
value = new HtmlToPlainText().getPlainText(Jsoup.parse(((Label) value).getValue()));
}
if (value instanceof AbstractLayout)
{
value = new HtmlToPlainText().getPlainText(Jsoup.parse(itemProperty.getValue().toString()));
}
if (value != null)
{
values[i++] = value.toString();
}
}
else
{
values[i++] = itemProperty.getValue().toString();
}
}
else
{
ColumnGenerator generator = table.getColumnGenerator(propertyId);
if (generator != null)
{
Object value = generator.generateCell(table, id, propertyId);
if (value != null)
{
if (value instanceof ClickableLabel)
{
value = new HtmlToPlainText()
.getPlainText(Jsoup.parse(((ClickableLabel) value).getValue()));
}
if (value instanceof Label)
{
value = new HtmlToPlainText().getPlainText(Jsoup.parse(((Label) value).getValue()));
// value = ((Label) value).getValue();
}
if (value instanceof AbstractLayout)
{
value = new HtmlToPlainText().getPlainText(Jsoup.parse(value.toString()));
}
}
if (value == null)
{
value = "";
}
values[i++] = value.toString();
}
else
{
values[i++] = "";
}
}
}
for (Object columnId : extraColumnHeadersAndPropertyIds.values())
{
String value = getValueForExtraColumn(item, columnId);
if (value == null)
{
value = "";
}
values[i++] = value;
}
writer.writeNext(values);
}
private void writeHeaders(CSVWriter writer, List<String> headers)
{
writer.writeNext(headers.toArray(new String[] {}));
}
/**
* propertyId's will later be passed to getValueForExtraColumn so it can
* generate the data for a column
*
* @return - an ordered map where key=heading string and value = a unique
* propertyId
*/
protected LinkedHashMap<String, Object> getExtraColumnHeadersAndPropertyIds()
{
return new LinkedHashMap<>();
}
/**
*
* @param item
* @param columnId
* - as specified in the map returned from
* getExtraColumnHeadersAndPropertyIds()
* @return
*/
protected String getValueForExtraColumn(Item item, Object columnId)
{
return null;
}
}