/**
* ***************************************************************************
* Copyright (c) 2010 Qcadoo Limited
* Project: Qcadoo Framework
* Version: 1.4
*
* This file is part of Qcadoo.
*
* Qcadoo 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***************************************************************************
*/
package com.qcadoo.plugins.qcadooExport.internal;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.qcadoo.model.api.aop.Monitorable;
import com.qcadoo.model.api.file.FileService;
import com.qcadoo.view.api.ViewDefinitionState;
import com.qcadoo.view.api.components.GridComponent;
import com.qcadoo.view.api.crud.CrudService;
@Controller
public class ExportToCsvController {
private static final String L_GRID = "grid";
private static final String L_VIEW_NAME_VARIABLE = "viewName";
private static final String L_PLUGIN_IDENTIFIER_VARIABLE = "pluginIdentifier";
private static final String L_CONTROLLER_PATH = "exportToCsv/{" + L_PLUGIN_IDENTIFIER_VARIABLE + "}/{" + L_VIEW_NAME_VARIABLE
+ "}";
@Value("${exportedCsvSeparator:','}")
private String exportedCsvSeparator;
@Autowired
private FileService fileService;
@Autowired
private CrudService crudService;
@Monitorable(threshold = 500)
@ResponseBody
@RequestMapping(value = { L_CONTROLLER_PATH }, method = RequestMethod.POST)
public Object generateCsv(@PathVariable(L_PLUGIN_IDENTIFIER_VARIABLE) final String pluginIdentifier,
@PathVariable(L_VIEW_NAME_VARIABLE) final String viewName, @RequestBody final JSONObject body, final Locale locale) {
try {
changeMaxResults(body);
ViewDefinitionState state = crudService.invokeEvent(pluginIdentifier, viewName, body, locale);
GridComponent grid = (GridComponent) state.getComponentByReference(L_GRID);
String date = DateFormat.getDateInstance().format(new Date());
File file = fileService.createExportFile("export_" + grid.getName() + "_" + date + ".csv");
BufferedWriter bufferedWriter = null;
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(239);
fileOutputStream.write(187);
fileOutputStream.write(191);
bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileOutputStream, Charset.forName("UTF-8")));
boolean firstName = true;
for (String name : grid.getColumnNames().values()) {
if (firstName) {
firstName = false;
} else {
bufferedWriter.append(exportedCsvSeparator);
}
bufferedWriter.append("\"").append(normalizeString(name)).append("\"");
}
bufferedWriter.append("\n");
List<Map<String, String>> rows;
if (grid.getSelectedEntitiesIds().isEmpty()) {
rows = grid.getColumnValuesOfAllRecords();
} else {
rows = grid.getColumnValuesOfSelectedRecords();
}
for (Map<String, String> row : rows) {
boolean firstValue = true;
for (String value : row.values()) {
if (firstValue) {
firstValue = false;
} else {
bufferedWriter.append(exportedCsvSeparator);
}
bufferedWriter.append("\"").append(normalizeString(value)).append("\"");
}
bufferedWriter.append("\n");
}
bufferedWriter.flush();
} catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
} finally {
IOUtils.closeQuietly(bufferedWriter);
}
state.redirectTo(fileService.getUrl(file.getAbsolutePath()) + "?clean", true, false);
return crudService.renderView(state);
} catch (JSONException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
private String normalizeString(final String string) {
if (StringUtils.hasText(string)) {
return string.replaceAll("\"", "\\\"").replaceAll("\n", " ");
} else {
return "";
}
}
private void changeMaxResults(final JSONObject json) throws JSONException {
JSONObject component = getComponent(json, getComponentName(json));
component.getJSONObject("content").put("firstEntity", 0);
component.getJSONObject("content").put("maxEntities", Integer.MAX_VALUE);
}
private JSONObject getComponent(final JSONObject json, final String componentName) throws JSONException {
String[] path = componentName.split("\\.");
JSONObject component = json;
for (String p : path) {
component = component.getJSONObject("components").getJSONObject(p);
}
return component;
}
private String getComponentName(final JSONObject body) throws JSONException {
return body.getJSONObject("event").getString("component");
}
}