/*
* 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 (c) 2011 Pentaho Corporation.. All rights reserved.
*
* @author Ezequiel Cuellar
*/
package org.pentaho.platform.dataaccess.datasource.wizard.sources.multitable;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.pentaho.agilebi.modeler.models.JoinRelationshipModel;
import org.pentaho.agilebi.modeler.models.JoinTableModel;
import org.pentaho.platform.dataaccess.datasource.IConnection;
import org.pentaho.platform.dataaccess.datasource.wizard.AbstractWizardStep;
import org.pentaho.platform.dataaccess.datasource.wizard.controllers.MessageHandler;
import org.pentaho.platform.dataaccess.datasource.wizard.models.IWizardModel;
import org.pentaho.platform.dataaccess.datasource.wizard.service.impl.JoinSelectionServiceGwtImpl;
import org.pentaho.ui.xul.XulComponent;
import org.pentaho.ui.xul.XulException;
import org.pentaho.ui.xul.XulServiceCallback;
import org.pentaho.ui.xul.binding.BindingConvertor;
import org.pentaho.ui.xul.binding.BindingFactory;
import org.pentaho.ui.xul.components.XulMenuList;
import org.pentaho.ui.xul.components.XulRadio;
import org.pentaho.ui.xul.containers.XulListbox;
import org.pentaho.ui.xul.containers.XulVbox;
import org.pentaho.ui.xul.gwt.binding.GwtBindingFactory;
import org.pentaho.ui.xul.stereotype.Bindable;
import org.pentaho.ui.xul.util.AbstractModelList;
@SuppressWarnings("unchecked")
public class TablesSelectionStep extends AbstractWizardStep {
protected static final String JOIN_STEP_PANEL_ID = "joinSelectionWindow";
private XulVbox tablesSelectionDialog;
private XulListbox availableTables;
private XulListbox selectedTables;
private XulMenuList<JoinTableModel> factTables;
private MultitableGuiModel joinGuiModel;
private JoinSelectionServiceGwtImpl joinSelectionServiceGwtImpl;
public TablesSelectionStep(MultitableGuiModel joinGuiModel, JoinSelectionServiceGwtImpl joinSelectionServiceGwtImpl, MultiTableDatasource parentDatasource) {
super(parentDatasource);
this.joinGuiModel = joinGuiModel;
this.joinSelectionServiceGwtImpl = joinSelectionServiceGwtImpl;
}
public String getName() {
return "joinSelectionStepController";
}
public void processAvailableTables(IConnection connection) {
joinSelectionServiceGwtImpl.getDatabaseTables(connection, new XulServiceCallback<List>() {
public void error(String message, Throwable error) {
error.printStackTrace();
}
public void success(List tables) {
joinGuiModel.processAvailableTables(tables);
}
});
}
@Bindable
public void addSelectedTable() {
if (this.availableTables.getSelectedItem() != null) {
List<JoinTableModel> selected = new ArrayList<JoinTableModel>();
for(Object obj : this.availableTables.getSelectedItems()){
selected.add((JoinTableModel) obj);
}
this.joinGuiModel.addSelectedTables(selected);
}
checkValidState();
}
@Bindable
public void removeSelectedTable() {
if (this.selectedTables.getSelectedItem() != null) {
List<JoinTableModel> selected = new ArrayList<JoinTableModel>();
for(Object obj : this.selectedTables.getSelectedItems()){
selected.add((JoinTableModel) obj);
}
this.joinGuiModel.removeSelectedTables(selected);
}
checkValidState();
checkExistingJoinsStillValid();
}
private void checkExistingJoinsStillValid() {
Set<String> allTables = new HashSet<String>();
for (JoinTableModel tbl : joinGuiModel.getSelectedTables()) {
allTables.add(tbl.getName());
}
List<JoinRelationshipModel> toRemove = new ArrayList<JoinRelationshipModel>();
for (JoinRelationshipModel join : joinGuiModel.getJoins()) {
if (!allTables.contains(join.getLeftKeyFieldModel().getParentTable().getName()) || !allTables.contains(join.getRightKeyFieldModel().getParentTable().getName())) {
toRemove.add(join);
}
}
for (JoinRelationshipModel join : toRemove) {
joinGuiModel.getJoins().remove(join);
}
}
@Override
public void init(IWizardModel wizardModel) throws XulException {
this.tablesSelectionDialog = (XulVbox) document.getElementById(JOIN_STEP_PANEL_ID);
this.availableTables = (XulListbox) document.getElementById("availableTables");
this.selectedTables = (XulListbox) document.getElementById("selectedTables");
this.factTables = (XulMenuList<JoinTableModel>) document.getElementById("factTables");
super.init(wizardModel);
}
public void setBindings() {
BindingFactory bf = new GwtBindingFactory(document);
bf.createBinding(this.joinGuiModel.getAvailableTables(), "children", this.availableTables, "elements");
bf.createBinding(this.joinGuiModel.getSelectedTables(), "children", this.selectedTables, "elements");
bf.createBinding(this.joinGuiModel.getSelectedTables(), "children", this.factTables, "elements", new BindingConvertor<AbstractModelList<JoinTableModel>, Collection<JoinTableModel>>() {
@Override
public Collection<JoinTableModel> sourceToTarget(AbstractModelList<JoinTableModel> list) {
List<JoinTableModel> tables = new ArrayList<JoinTableModel>();
tables.addAll(list.asList());
JoinTableModel emptyOption = new JoinTableModel();
emptyOption.setName(MessageHandler.getString("multitable.SELECT_TABLE"));
tables.add(0, emptyOption); //Empty option must be always 0.
return tables;
}
@Override
public AbstractModelList<JoinTableModel> targetToSource(final Collection<JoinTableModel> list) {
return null;
}
});
bf.createBinding(this.factTables, "selectedIndex", this.joinGuiModel, "factTable", new BindingConvertor<Integer, JoinTableModel>() {
@Override
public JoinTableModel sourceToTarget(final Integer index) {
if (index == -1) {
return null;
}
//Index 0 represents [select table] option.
//To be valid index must not be 0.
checkValidState();
int i = (int) index;
i--;
return i < 0 ? null : joinGuiModel.getSelectedTables().get(i);
}
@Override
public Integer targetToSource(final JoinTableModel value) {
return joinGuiModel.getSelectedTables().indexOf(value);
}
});
// use a binding to handle the visibility state of the schema type radio group
try {
bf.createBinding(joinGuiModel, "doOlap", "factTableVbox", "visible").fireSourceChanged();
} catch (Exception e) {
e.printStackTrace();
}
}
public String getStepName() {
return MessageHandler.getString("multitable.SELECT_TABLES");
}
public XulComponent getUIComponent() {
return this.tablesSelectionDialog;
}
public void setFactTable(JoinTableModel factTable) {
List<JoinTableModel> tables = new ArrayList<JoinTableModel>();
tables.addAll(this.factTables.getElements());
this.factTables.setSelectedIndex(tables.indexOf(factTable.getName()));
}
@Override
public void stepActivatingReverse() {
super.stepActivatingReverse();
parentDatasource.setFinishable(false);
checkValidState();
}
private void checkValidState(){
boolean valid = true;
boolean finishable = true;
if(joinGuiModel.isDoOlap()) {
valid &= this.factTables.getSelectedIndex() > 0;
finishable &= this.factTables.getSelectedIndex() > 0;
}
valid &= this.selectedTables.getElements().size() > 1;
finishable &= this.selectedTables.getElements().size() == 1;
super.setValid(valid);
this.parentDatasource.setFinishable(finishable);
}
@Override
public void stepActivatingForward() {
super.stepActivatingForward();
checkValidState();
}
}