package org.pentaho.platform.dataaccess.datasource.wizard.sources.csv;
import org.pentaho.metadata.model.concept.types.DataType;
import org.pentaho.platform.dataaccess.datasource.wizard.controllers.MessageHandler;
import org.pentaho.platform.dataaccess.datasource.wizard.models.*;
import org.pentaho.platform.dataaccess.datasource.wizard.service.gwt.ICsvDatasourceServiceAsync;
import org.pentaho.platform.dataaccess.datasource.wizard.AbstractWizardStep;
import org.pentaho.ui.xul.XulComponent;
import org.pentaho.ui.xul.XulEventSource;
import org.pentaho.ui.xul.XulException;
import com.google.gwt.user.client.rpc.AsyncCallback;
import org.pentaho.ui.xul.binding.Binding;
import org.pentaho.ui.xul.binding.BindingConvertor;
import org.pentaho.ui.xul.binding.FactoryBasedBindingProvider;
import org.pentaho.ui.xul.components.XulLabel;
import org.pentaho.ui.xul.components.XulTreeCell;
import org.pentaho.ui.xul.containers.XulDialog;
import org.pentaho.ui.xul.containers.XulTree;
import org.pentaho.ui.xul.containers.XulTreeItem;
import org.pentaho.ui.xul.containers.XulTreeRow;
import org.pentaho.ui.xul.stereotype.Bindable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
public class StageDataStep extends AbstractWizardStep implements IModelInfoValidationListener {
private DatasourceModel datasourceModel;
private ICsvDatasourceServiceAsync csvDatasourceService;
private static final String MSG_STAGING_DATA = "physicalDatasourceDialog.STAGING_DATA"; //$NON-NLS-1$
private static final String MSG_ROWS_STAGED = "physicalDatasourceDialog.ROWS_STAGED"; //$NON-NLS-1$
private static final String MSG_STAGING_FILE = "physicalDatasourceDialog.STAGING_FILE"; //$NON-NLS-1$
private static final String MSG_STAGING_ERRORS = "physicalDatasourceDialog.STAGING_ERRORS"; //$NON-NLS-1$
private XulDialog errorDialog = null;
private XulLabel errorLabel = null;
private XulDialog waitingDialog = null;
private XulLabel waitingLabel = null;
private XulDialog successDialog = null;
private XulLabel successLabel = null;
private XulDialog previewDialog = null;
private XulLabel previewLabel = null;
public StageDataStep(DatasourceModel datasourceModel, CsvDatasource parentDatasource, ICsvDatasourceServiceAsync csvDatasourceService ) {
super(parentDatasource);
this.datasourceModel = datasourceModel;
this.csvDatasourceService = csvDatasourceService;
}
public String getStepName() {
return MessageHandler.getString("wizardStepName.STAGE"); //$NON-NLS-1$
}
public void setBindings() {
}
@Override
public XulComponent getUIComponent() {
return document.getElementById("stagedatastep");
}
@Override
public void init(IWizardModel wizardModel) throws XulException {
super.init(wizardModel);
waitingDialog = (XulDialog) document.getElementById("waitingDialog"); //$NON-NLS-1$
waitingLabel = (XulLabel) document.getElementById("waitingDialogLabel"); //$NON-NLS-1$
errorDialog = (XulDialog) document.getElementById("errorDialog"); //$NON-NLS-1$
errorLabel = (XulLabel) document.getElementById("errorLabel"); //$NON-NLS-1$
successDialog = (XulDialog) document.getElementById("successDialog"); //$NON-NLS-1$
successLabel = (XulLabel) document.getElementById("successLabel"); //$NON-NLS-1$
previewDialog = (XulDialog) document.getElementById("csvPreviewDialog"); //$NON-NLS-1$
previewLabel = (XulLabel) document.getElementById("csvTextPreviewLabel"); //$NON-NLS-1$
datasourceModel.getModelInfo().addModelInfoValidationListener(this);
}
@Override
public void stepActivatingForward() {
setStepImageVisible(true);
showWaitingFileStageDialog();
loadColumnData(datasourceModel.getModelInfo().getFileInfo().getTmpFilename());
}
@Override
public void stepActivatingReverse() {
setStepImageVisible(true);
}
private void loadColumnData(String selectedFile){
String encoding = datasourceModel.getModelInfo().getFileInfo().getEncoding();
try {
clearColumnGrid();
} catch (XulException e) {
// couldn't clear the tree out
e.printStackTrace();
}
if (datasourceModel.getGuiStateModel().isDirty()) {
csvDatasourceService.stageFile(selectedFile,
datasourceModel.getModelInfo().getFileInfo().getDelimiter(),
datasourceModel.getModelInfo().getFileInfo().getEnclosure(),
datasourceModel.getModelInfo().getFileInfo().getHeaderRows() > 0,
encoding,
new StageFileCallback());
} else {
refreshColumnGrid();
closeWaitingDialog();
}
}
public void onCsvValid() {
//don't care about csv on this step
}
public void onCsvInValid() {
//don't care about csv on this step
}
public void onModelInfoValid() {
parentDatasource.setFinishable(true);
}
public void onModelInfoInvalid() {
parentDatasource.setFinishable(false);
}
public class StageFileCallback implements AsyncCallback<ModelInfo> {
public void onSuccess(ModelInfo aModelInfo) {
datasourceModel.getModelInfo().setColumns(aModelInfo.getColumns());
datasourceModel.getModelInfo().setData(aModelInfo.getData());
datasourceModel.getModelInfo().getFileInfo().setEncoding(aModelInfo.getFileInfo().getEncoding());
refreshColumnGrid();
closeWaitingDialog();
parentDatasource.setFinishable(true);
}
public void onFailure(Throwable caught) {
closeWaitingDialog();
parentDatasource.setFinishable(false);
if (caught instanceof CsvParseException) {
CsvParseException e = (CsvParseException) caught;
showErrorDialog(MessageHandler.getString(caught.getMessage(), String.valueOf(e.getLineNumber()), e.getOffendingLine()));
} else {
showErrorDialog(caught.getMessage());
}
}
}
@Override
public boolean stepDeactivatingForward() {
super.stepDeactivatingForward();
return true;
}
@Override
public boolean stepDeactivatingReverse() {
setStepImageVisible(false);
return true;
}
@Bindable
public void closePreviewDialog() {
previewDialog.hide();
}
@Bindable
public void showPreviewDialog() throws Exception {
previewLabel.setValue(datasourceModel.getModelInfo().getFileInfo().formatSampleContents());
previewDialog.show();
}
public void clearColumnGrid() throws XulException {
XulTree tree = (XulTree) document.getElementById("csvModelDataTable"); //$NON-NLS-1$
tree.setElements(null);
tree.update();
}
@Bindable
public void refreshColumnGrid() {
generateDataTypeDisplay_horizontal();
}
private void generateDataTypeDisplay_horizontal() {
XulTree tree = (XulTree) document.getElementById("csvModelDataTable"); //$NON-NLS-1$
tree.setRows(datasourceModel.getModelInfo().getColumns().length);
bf.setBindingType(Binding.Type.ONE_WAY);
tree.setBindingProvider(new FactoryBasedBindingProvider(bf) {
@Override
public BindingConvertor getConvertor(XulEventSource source, String prop1, XulEventSource target, String prop2) {
if (source instanceof ColumnInfo) {
if (prop1.equals("length") || prop1.equals("precision")) { //$NON-NLS-1$ //$NON-NLS-2$
return BindingConvertor.integer2String();
}
else if (prop1.equals("include") && prop2.equals("value")) { //$NON-NLS-1$//$NON-NLS-2$
// this is the binding from the cell to the value of the checkbox
return null;
} else if (prop1.equals("include")) { //$NON-NLS-1$
// this binding is from the model to the checkbox
return BindingConvertor.boolean2String();
} else if (prop1.equals("availableDataTypes")) { //$NON-NLS-1$
return new BindingConvertor<List, Vector>() {
@SuppressWarnings("unchecked")
public Vector sourceToTarget(List value) {
return new Vector(value);
}
@SuppressWarnings("unchecked")
public List targetToSource(Vector value) {
return new ArrayList(value);
}
};
} else if (prop1.equals("formatStrings")) { //$NON-NLS-1$
return new BindingConvertor<List, Vector>() {
@SuppressWarnings("unchecked")
public Vector sourceToTarget(List value) {
return new Vector(value);
}
@SuppressWarnings("unchecked")
public List targetToSource(Vector value) {
return new ArrayList(value);
}
};
} else if (prop1.equals("dataType") && prop2.equals("selectedIndex")) { //$NON-NLS-1$ //$NON-NLS-2$
return new BindingConvertor<DataType, Integer>() {
@Override
public Integer sourceToTarget(DataType value) {
List<DataType> types = ColumnInfo.getAvailableDataTypes();
for(int i = 0; i < types.size(); i++) {
if (types.get(i).equals(value)) {
return i;
}
}
return 0;
}
@Override
public DataType targetToSource(Integer value) {
return ColumnInfo.getAvailableDataTypes().get(value);
}
};
} else if(prop1.equals("formatStringsDisabled")){
return null;
} else {
return BindingConvertor.string2String();
}
} else {
return null;
}
}
});
tree.setElements(Arrays.asList(datasourceModel.getModelInfo().getColumns()));
if(datasourceModel.getModelInfo().getColumns().length > 0){
tree.setSelectedRows(new int[]{0});
}
tree.update();
}
@Bindable
public void selectAll() {
XulTree tree = (XulTree) document.getElementById("csvModelDataTable"); //$NON-NLS-1$
for (XulComponent component : tree.getRootChildren().getChildNodes()) {
XulTreeItem item = (XulTreeItem)component;
for (XulComponent childComp : item.getChildNodes()) {
XulTreeRow row = (XulTreeRow)childComp;
XulTreeCell cell = row.getCell(0);
cell.setValue(true);
}
}
datasourceModel.getModelInfo().validate();
}
@Bindable
public void deselectAll() {
XulTree tree = (XulTree) document.getElementById("csvModelDataTable"); //$NON-NLS-1$
for (XulComponent component : tree.getRootChildren().getChildNodes()) {
XulTreeItem item = (XulTreeItem)component;
for (XulComponent childComp : item.getChildNodes()) {
XulTreeRow row = (XulTreeRow)childComp;
XulTreeCell cell = row.getCell(0);
cell.setValue(false);
}
}
datasourceModel.getModelInfo().validate();
}
public String getName() {
return "stageDataController";
}
@Bindable
public void closeErrorDialog() {
errorDialog.hide();
}
public void showErrorDialog(String message) {
errorLabel.setValue(message);
errorDialog.show();
}
public void closeWaitingDialog() {
MessageHandler.getInstance().closeWaitingDialog();
}
public void showWaitingDataStageDialog() {
MessageHandler.getInstance().showWaitingDialog(MessageHandler.getString(MSG_STAGING_DATA));
}
public void showWaitingFileStageDialog() {
MessageHandler.getInstance().showWaitingDialog(MessageHandler.getString(MSG_STAGING_FILE));
}
@Bindable
public void closeSuccessDialog() {
successDialog.hide();
}
public void showSuccessDialog(String message) {
successLabel.setValue(message);
successDialog.show();
}
}