/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* 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 Lesser General Public License for more details.
*
* Copyright 2009-2010 Pentaho Corporation. All rights reserved.
*
* Created Sep, 2010
* @author jdixon
*/
package org.pentaho.platform.dataaccess.datasource.wizard.service.impl;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.agilebi.modeler.ModelerWorkspace;
import org.pentaho.agilebi.modeler.gwt.GwtModelerWorkspaceHelper;
import org.pentaho.metadata.model.Domain;
import org.pentaho.metadata.model.LogicalModel;
import org.pentaho.platform.api.engine.IPentahoObjectFactory;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.engine.ObjectFactoryException;
import org.pentaho.platform.dataaccess.datasource.beans.BogoPojo;
import org.pentaho.platform.dataaccess.datasource.wizard.csv.CsvUtils;
import org.pentaho.platform.dataaccess.datasource.wizard.csv.FileUtils;
import org.pentaho.platform.dataaccess.datasource.wizard.models.CsvFileInfo;
import org.pentaho.platform.dataaccess.datasource.wizard.models.CsvTransformGeneratorException;
import org.pentaho.platform.dataaccess.datasource.wizard.models.DatasourceDTO;
import org.pentaho.platform.dataaccess.datasource.wizard.models.FileInfo;
import org.pentaho.platform.dataaccess.datasource.wizard.models.ModelInfo;
import org.pentaho.platform.dataaccess.datasource.wizard.service.agile.AgileHelper;
import org.pentaho.platform.dataaccess.datasource.wizard.service.agile.CsvTransformGenerator;
import org.pentaho.platform.dataaccess.datasource.wizard.service.gwt.ICsvDatasourceService;
import org.pentaho.platform.dataaccess.datasource.wizard.sources.csv.FileTransformStats;
import org.pentaho.platform.engine.core.system.PentahoBase;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.plugin.action.kettle.KettleSystemListener;
import org.pentaho.reporting.libraries.base.util.StringUtils;
import com.thoughtworks.xstream.XStream;
@SuppressWarnings("unchecked")
public class CsvDatasourceServiceImpl extends PentahoBase implements ICsvDatasourceService {
public static final byte[] lock = new byte[0];
private static final long serialVersionUID = 2498165533158485182L;
private Log logger = LogFactory.getLog(CsvDatasourceServiceImpl.class);
private ModelerService modelerService = new ModelerService();
private ModelerWorkspace modelerWorkspace;
public CsvDatasourceServiceImpl(){
super();
modelerWorkspace = new ModelerWorkspace(new GwtModelerWorkspaceHelper());
modelerService = new ModelerService();
}
public Log getLogger() {
return logger;
}
public String getEncoding(String fileName) {
String encoding = null;
try {
CsvUtils csvModelService = new CsvUtils();
encoding = csvModelService.getEncoding(fileName);
} catch (Exception e) {
logger.error(e);
}
return encoding;
}
public ModelInfo stageFile(String fileName, String delimiter, String enclosure, boolean isFirstRowHeader, String encoding)
throws Exception {
ModelInfo modelInfo;
try {
CsvUtils csvModelService = new CsvUtils();
int headerRows = isFirstRowHeader ? 1 : 0;
modelInfo = csvModelService.generateFields("", fileName, AgileHelper.getCsvSampleRowSize(), delimiter, enclosure, headerRows, true, true, encoding); //$NON-NLS-1$
} catch (Exception e) {
logger.error(e);
throw e;
}
return modelInfo;
}
public FileInfo[] getStagedFiles() throws Exception {
FileInfo[] files;
try {
FileUtils fileService = new FileUtils();
files = fileService.listFiles();
} catch (Exception e) {
logger.error(e);
throw e;
}
return files;
}
public FileTransformStats generateDomain(DatasourceDTO datasourceDto) throws Exception {
synchronized (lock) {
ModelInfo modelInfo = datasourceDto.getCsvModelInfo();
IPentahoSession pentahoSession = null;
try {
pentahoSession = getSession();
KettleSystemListener.environmentInit(pentahoSession);
String statsKey = FileTransformStats.class.getSimpleName() + "_" + modelInfo.getFileInfo().getTmpFilename(); //$NON-NLS-1$
FileTransformStats stats = new FileTransformStats();
pentahoSession.setAttribute(statsKey, stats);
CsvTransformGenerator csvTransformGenerator = new CsvTransformGenerator(modelInfo, AgileHelper.getDatabaseMeta());
csvTransformGenerator.setTransformStats(stats);
try {
csvTransformGenerator.dropTable(modelInfo.getStageTableName());
} catch (CsvTransformGeneratorException e) {
// this is ok, the table may not have existed.
logger.info("Could not drop table before staging"); //$NON-NLS-1$
}
csvTransformGenerator.createOrModifyTable(pentahoSession);
// no longer need to truncate the table since we dropped it a few lines up, so just pass false
csvTransformGenerator.loadTable(false, pentahoSession, true);
ArrayList<String> combinedErrors = new ArrayList<String>(modelInfo.getCsvInputErrors());
combinedErrors.addAll(modelInfo.getTableOutputErrors());
stats.setErrors(combinedErrors);
// wait until it it done
while (!stats.isRowsFinished()) {
Thread.sleep(200);
}
modelerWorkspace.setDomain(modelerService.generateCSVDomain(modelInfo.getStageTableName(), modelInfo.getDatasourceName()));
modelerWorkspace.getWorkspaceHelper().autoModelFlat(modelerWorkspace);
modelerWorkspace.getWorkspaceHelper().autoModelRelationalFlat(modelerWorkspace);
modelerWorkspace.setModelName(modelInfo.getDatasourceName());
modelerWorkspace.getWorkspaceHelper().populateDomain(modelerWorkspace);
Domain workspaceDomain = modelerWorkspace.getDomain();
XStream xstream = new XStream();
String serializedDto = xstream.toXML(datasourceDto);
workspaceDomain.getLogicalModels().get(0).setProperty("datasourceModel", serializedDto);
workspaceDomain.getLogicalModels().get(0).setProperty("DatasourceType", "CSV");
prepareForSerialization(workspaceDomain);
modelerService.serializeModels(workspaceDomain, modelerWorkspace.getModelName());
stats.setDomain(modelerWorkspace.getDomain());
return stats;
} catch (Exception e) {
logger.error(e);
throw e;
} finally {
if (pentahoSession != null) {
pentahoSession.destroy();
}
}
}
}
protected void prepareForSerialization(Domain domain) throws IOException {
/*
* This method is responsible for cleaning up legacy information when
* changing datasource types and also manages CSV files for CSV based
* datasources.
*/
String relativePath = PentahoSystem.getSystemSetting("file-upload-defaults/relative-path", String.valueOf(FileUtils.DEFAULT_RELATIVE_UPLOAD_FILE_PATH)); //$NON-NLS-1$
String path = PentahoSystem.getApplicationContext().getSolutionPath(relativePath);
String TMP_FILE_PATH = File.separatorChar + "system" + File.separatorChar + File.separatorChar + "tmp" + File.separatorChar;
String sysTmpDir = PentahoSystem.getApplicationContext().getSolutionPath(TMP_FILE_PATH);
LogicalModel logicalModel = domain.getLogicalModels().get(0);
String modelState = (String) logicalModel.getProperty("datasourceModel"); //$NON-NLS-1$
if (modelState != null) {
XStream xs = new XStream();
DatasourceDTO datasource = (DatasourceDTO) xs.fromXML(modelState);
CsvFileInfo csvFileInfo = datasource.getCsvModelInfo().getFileInfo();
String tmpFileName = csvFileInfo.getTmpFilename();
String csvFileName = csvFileInfo.getFilename();
File tmpFile = new File(sysTmpDir + File.separatorChar + tmpFileName);
// Move CSV temporary file to final destination.
if (tmpFile.exists()) {
File csvFile = new File(path + File.separatorChar + csvFileName);
org.apache.commons.io.FileUtils.copyFile(tmpFile, csvFile);
}
// Cleanup logic when updating from SQL datasource to CSV
// datasource.
datasource.setQuery(null);
// Update datasourceModel with the new modelState
modelState = xs.toXML(datasource);
logicalModel.setProperty("datasourceModel", modelState);
}
}
private IPentahoSession getSession() {
IPentahoSession session = null;
IPentahoObjectFactory pentahoObjectFactory = PentahoSystem.getObjectFactory();
if (pentahoObjectFactory != null) {
try {
session = pentahoObjectFactory.get(IPentahoSession.class, "systemStartupSession", null); //$NON-NLS-1$
} catch (ObjectFactoryException e) {
logger.error(e);
}
}
return session;
}
public List<String> getPreviewRows(String filename, boolean isFirstRowHeader, int rows, String encoding) throws Exception {
List<String> previewRows = null;
if(!StringUtils.isEmpty(filename)) {
CsvUtils service = new CsvUtils();
ModelInfo mi = service.getFileContents("", filename, ",", "\"", rows, isFirstRowHeader, encoding); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
previewRows = mi.getFileInfo().getContents();
}
return previewRows;
}
@Override
public BogoPojo gwtWorkaround(BogoPojo pojo) {
return pojo;
}
}