/*!
* 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) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.pms.ui.dialog;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.pentaho.di.core.logging.LogChannelInterface;
import org.pentaho.di.ui.core.PropsUI;
import org.pentaho.di.ui.core.gui.WindowProperty;
import org.pentaho.di.ui.trans.step.BaseStepDialog;
import org.pentaho.pms.core.exception.PentahoMetadataException;
import org.pentaho.pms.mql.PMSFormula;
import org.pentaho.pms.mql.Selection;
import org.pentaho.pms.messages.Messages;
import org.pentaho.pms.schema.BusinessColumn;
import org.pentaho.pms.schema.BusinessModel;
import org.pentaho.pms.schema.BusinessTable;
import org.pentaho.pms.schema.RelationshipMeta;
import org.pentaho.pms.ui.util.Const;
import org.pentaho.pms.ui.util.GUIResource;
import org.pentaho.reporting.libraries.formula.Formula;
import org.pentaho.reporting.libraries.formula.function.logical.AndFunction;
import org.pentaho.reporting.libraries.formula.lvalues.ContextLookup;
import org.pentaho.reporting.libraries.formula.lvalues.FormulaFunction;
import org.pentaho.reporting.libraries.formula.parser.ParseException;
public class RelationshipDialog extends Dialog {
private Label wlFrom;
private CCombo wFrom;
private FormData fdlFrom, fdFrom;
private Label wlTo;
private CCombo wTo;
private FormData fdlTo, fdTo;
private CCombo wFromField;
private FormData fdFromField;
private CCombo wToField;
private FormData fdToField;
private Button wGuess;
private FormData fdGuess;
private Listener lsGuess;
private Label wlRelation;
private CCombo wRelation;
private FormData fdlRelation, fdRelation;
private Button wGuessRel;
private FormData fdGuessRel;
private Listener lsGuessRel;
private Label wlComplex;
private Button wComplex;
private FormData fdlComplex, fdComplex;
private Label wlComplexJoin;
private Text wComplexJoin;
private FormData fdlComplexJoin, fdComplexJoin;
private Label wlDescription;
private Text wDescription;
private FormData fdlDescription, fdDescription;
private Label wlJoinType;
private CCombo wJoinType;
private Label wlJoinOrderKey;
private Text wJoinOrderKey;
private Button wOK, wCancel;
private Listener lsOK, lsCancel;
private RelationshipMeta relationshipMeta;
private Shell shell;
private BusinessModel businessModel;
private BusinessTable fromTable, toTable;
private ModifyListener lsMod;
private boolean changed, backupComplex;
private ToolBar toolBar;
private FormData fdlJoinType;
public RelationshipDialog(Shell parent, int style, LogChannelInterface l, RelationshipMeta relationshipMeta,
BusinessModel businessModel) {
super(parent, style);
this.relationshipMeta = relationshipMeta;
this.businessModel = businessModel;
fromTable = relationshipMeta.getTableFrom();
toTable = relationshipMeta.getTableTo();
}
public Object open() {
PropsUI props = PropsUI.getInstance();
Shell parent = getParent();
Display display = parent.getDisplay();
shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE);
shell.setBackground(GUIResource.getInstance().getColorBackground());
lsMod = new ModifyListener() {
public void modifyText(ModifyEvent e) {
relationshipMeta.setChanged();
}
};
changed = relationshipMeta.hasChanged();
backupComplex = relationshipMeta.isComplex();
FormLayout formLayout = new FormLayout();
formLayout.marginWidth = Const.FORM_MARGIN;
formLayout.marginHeight = Const.FORM_MARGIN;
shell.setLayout(formLayout);
shell.setText(Messages.getString("RelationshipDialog.USER_HOP_FROM_TO")); //$NON-NLS-1$
int middle = props.getMiddlePct();
int margin = Const.MARGIN;
//////////////////////////////////////////////////////////////////////
// From table
//
wFrom = new CCombo(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
wFrom.setText(Messages.getString("RelationshipDialog.USER_SELECT_SOURCE_TABLE")); //$NON-NLS-1$
props.setLook(wFrom);
for (int i = 0; i < businessModel.nrBusinessTables(); i++) {
BusinessTable ti = businessModel.getBusinessTable(i);
wFrom.add(ti.getId());
}
wFrom.addModifyListener(lsMod);
wFrom.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
// grab the new fromtable:
fromTable = businessModel.findBusinessTable(wFrom.getText());
refreshFromFields();
}
});
fdFrom = new FormData();
fdFrom.left = new FormAttachment(middle, margin);
fdFrom.top = new FormAttachment(0, margin);
fdFrom.right = new FormAttachment(60, 0);
wFrom.setLayoutData(fdFrom);
wlFrom = new Label(shell, SWT.RIGHT);
wlFrom.setText(Messages.getString("RelationshipDialog.USER_FROM_TABLE_FIELD")); //$NON-NLS-1$
props.setLook(wlFrom);
fdlFrom = new FormData();
fdlFrom.left = new FormAttachment(0, 0);
fdlFrom.right = new FormAttachment(middle, -margin);
fdlFrom.top = new FormAttachment(wFrom, 0, SWT.CENTER);
wlFrom.setLayoutData(fdlFrom);
//////////////////////////////////////////////////////////////////////
// From field...
//
wFromField = new CCombo(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
wFromField.setText(""); //$NON-NLS-1$
props.setLook(wFromField);
refreshFromFields();
wFromField.addModifyListener(lsMod);
fdFromField = new FormData();
fdFromField.left = new FormAttachment(wFrom, margin * 2);
fdFromField.top = new FormAttachment(0, margin);
fdFromField.right = new FormAttachment(100, 0);
wFromField.setLayoutData(fdFromField);
//////////////////////////////////////////////////////////////////////
// To Table
//
wTo = new CCombo(shell, SWT.BORDER | SWT.READ_ONLY);
wTo.setText(Messages.getString("RelationshipDialog.USER_SELECT_DESTINATION_TABLE")); //$NON-NLS-1$
props.setLook(wTo);
for (int i = 0; i < businessModel.nrBusinessTables(); i++) {
BusinessTable ti = businessModel.getBusinessTable(i);
wTo.add(ti.getId());
}
wTo.addModifyListener(lsMod);
wTo.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
// grab the new fromtable:
toTable = businessModel.findBusinessTable(wTo.getText());
refreshToFields();
}
});
fdTo = new FormData();
fdTo.left = new FormAttachment(middle, margin);
fdTo.top = new FormAttachment(wFrom, margin);
fdTo.right = new FormAttachment(60, 0);
wTo.setLayoutData(fdTo);
wlTo = new Label(shell, SWT.RIGHT);
wlTo.setText(Messages.getString("RelationshipDialog.USER_TO_TABLE_FIELD")); //$NON-NLS-1$
props.setLook(wlTo);
fdlTo = new FormData();
fdlTo.left = new FormAttachment(0, 0);
fdlTo.right = new FormAttachment(middle, -margin);
fdlTo.top = new FormAttachment(wTo, 0, SWT.CENTER);
wlTo.setLayoutData(fdlTo);
//////////////////////////////////////////////////////////////////////
// ToField step line
//
wToField = new CCombo(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
wToField.setText(Messages.getString("RelationshipDialog.USER_SELECT_THE_FIELD")); //$NON-NLS-1$
props.setLook(wToField);
refreshToFields();
wToField.addModifyListener(lsMod);
fdToField = new FormData();
fdToField.left = new FormAttachment(wTo, margin * 2);
fdToField.top = new FormAttachment(wFromField, margin);
fdToField.right = new FormAttachment(100, 0);
wToField.setLayoutData(fdToField);
//////////////////////////////////////////////////////////////////////
// The "Guess matching fields" button
//
wGuess = new Button(shell, SWT.PUSH);
wGuess.setText(Messages.getString("RelationshipDialog.USER_GUESS_MATCHING_FIELDS")); //$NON-NLS-1$
lsGuess = new Listener() {
public void handleEvent(Event e) {
guess();
}
};
wGuess.addListener(SWT.Selection, lsGuess);
fdGuess = new FormData();
fdGuess.left = new FormAttachment(wTo, margin * 2);
fdGuess.top = new FormAttachment(wToField, margin);
wGuess.setLayoutData(fdGuess);
//////////////////////////////////////////////////////////////////////
// Relation line
//
wRelation = new CCombo(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
props.setLook(wRelation);
wRelation.setItems(RelationshipMeta.typeRelationshipDesc);
fdRelation = new FormData();
fdRelation.left = new FormAttachment(middle, margin);
fdRelation.top = new FormAttachment(wGuess, margin * 6);
fdRelation.right = new FormAttachment(60, 0);
wRelation.setLayoutData(fdRelation);
wGuessRel = new Button(shell, SWT.PUSH);
wGuessRel.setText(Messages.getString("RelationshipDialog.USER_GUESS_RELATIONSHIP")); //$NON-NLS-1$
lsGuessRel = new Listener() {
public void handleEvent(Event e) {
guessRelationship();
}
};
wGuessRel.addListener(SWT.Selection, lsGuessRel);
fdGuessRel = new FormData();
fdGuessRel.left = new FormAttachment(wRelation, margin * 2);
fdGuessRel.top = new FormAttachment(wRelation, 0, SWT.CENTER);
wGuessRel.setLayoutData(fdGuessRel);
wlRelation = new Label(shell, SWT.RIGHT);
wlRelation.setText(Messages.getString("RelationshipDialog.USER_RELATIONSHIP")); //$NON-NLS-1$
props.setLook(wlRelation);
fdlRelation = new FormData();
fdlRelation.left = new FormAttachment(0, 0);
fdlRelation.right = new FormAttachment(middle, -margin);
fdlRelation.top = new FormAttachment(wRelation, 0, SWT.CENTER);
wlRelation.setLayoutData(fdlRelation);
//////////////////////////////////////////////////////////////////////
// JoinType line
//
wJoinType = new CCombo(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER | SWT.READ_ONLY);
props.setLook(wJoinType);
wJoinType.setItems(RelationshipMeta.typeJoinDesc);
wJoinType.addModifyListener(lsMod);
FormData fdJoinType = new FormData();
fdJoinType.left = new FormAttachment(middle, 0);
fdJoinType.top = new FormAttachment(wGuessRel, margin * 2);
fdJoinType.right = new FormAttachment(60, 0);
wJoinType.setLayoutData(fdJoinType);
wlJoinType = new Label(shell, SWT.RIGHT);
wlJoinType.setText(Messages.getString("RelationshipDialog.USER_JOINTYPE")); //$NON-NLS-1$
props.setLook(wlJoinType);
fdlJoinType = new FormData();
fdlJoinType.left = new FormAttachment(0, 0);
fdlJoinType.right = new FormAttachment(middle, -margin);
fdlJoinType.top = new FormAttachment(wJoinType, 0, SWT.CENTER);
wlJoinType.setLayoutData(fdlJoinType);
//////////////////////////////////////////////////////////////////////
// Add the join sort order next to the join type...
//
wlJoinOrderKey = new Label(shell, SWT.LEFT);
wlJoinOrderKey.setText(Messages.getString("RelationshipDialog.USER_JOIN_SORT_KEY")); //$NON-NLS-1$
props.setLook(wlJoinOrderKey);
FormData fdlJoinOrderKey = new FormData();
fdlJoinOrderKey.left = new FormAttachment(wJoinType, margin*2);
fdlJoinOrderKey.top = new FormAttachment(wJoinType, 0, SWT.CENTER);
wlJoinOrderKey.setLayoutData(fdlJoinOrderKey);
wJoinOrderKey = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
props.setLook(wJoinOrderKey);
wJoinOrderKey.addModifyListener(lsMod);
FormData fdJoinOrderKey = new FormData();
fdJoinOrderKey.left = new FormAttachment(wlJoinOrderKey, margin);
fdJoinOrderKey.top = new FormAttachment(wJoinType, 0, SWT.CENTER);
fdJoinOrderKey.right = new FormAttachment(100, 0);
wJoinOrderKey.setLayoutData(fdJoinOrderKey);
//////////////////////////////////////////////////////////////////////
// Complex check box
//
wComplex = new Button(shell, SWT.CHECK);
props.setLook(wComplex);
fdComplex = new FormData();
fdComplex.left = new FormAttachment(middle, 0);
fdComplex.top = new FormAttachment(wJoinType, margin*6);
wComplex.setLayoutData(fdComplex);
wComplex.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
relationshipMeta.flipComplex();
relationshipMeta.setChanged();
setComplex();
}
});
wlComplex = new Label(shell, SWT.RIGHT);
wlComplex.setText(Messages.getString("RelationshipDialog.USER_COMPLEX_JOIN")); //$NON-NLS-1$
props.setLook(wlComplex);
fdlComplex = new FormData();
fdlComplex.left = new FormAttachment(0, 0);
fdlComplex.right = new FormAttachment(middle, -margin);
fdlComplex.top = new FormAttachment(wComplex, 0, SWT.CENTER);
wlComplex.setLayoutData(fdlComplex);
// ComplexJoin line
wlComplexJoin = new Label(shell, SWT.RIGHT);
wlComplexJoin.setText(Messages.getString("RelationshipDialog.USER_COMPLEX_JOIN_EXPRESSION")); //$NON-NLS-1$
props.setLook(wlComplexJoin);
fdlComplexJoin = new FormData();
fdlComplexJoin.left = new FormAttachment(0, 0);
fdlComplexJoin.right = new FormAttachment(middle, -margin);
fdlComplexJoin.top = new FormAttachment(wlComplex, margin*2);
wlComplexJoin.setLayoutData(fdlComplexJoin);
// complex join toolbar
toolBar = new ToolBar(shell, SWT.HORIZONTAL | SWT.RIGHT_TO_LEFT);
FormData fdTb = new FormData();
fdTb.left = new FormAttachment(middle, margin);
fdTb.right = new FormAttachment(100, 0);
fdTb.top = new FormAttachment(wComplex, 0);
props.setLook(toolBar);
toolBar.setLayoutData(fdTb);
// add column
ToolItem addColumnCJ = new ToolItem(toolBar, SWT.NULL);
addColumnCJ.setImage(GUIResource.getInstance().getImageGenericAdd());
addColumnCJ.setToolTipText(Messages.getString("RelationshipDialog.COMPLEX_JOIN_ADD_CONDITION"));//TODO:i18n
addColumnCJ.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) { /**/ }
public void widgetSelected(SelectionEvent e) {
AddComplexJoinColumnsDialog dialog = new AddComplexJoinColumnsDialog();
dialog.open();
}
});
// validate
ToolItem validateCJ = new ToolItem(toolBar, SWT.NULL);
validateCJ.setImage(GUIResource.getInstance().getImageCheck());
validateCJ.setToolTipText(Messages.getString("RelationshipDialog.COMPLEX_JOIN_VALIDATE"));//$NON-NLS-1$
validateCJ.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) { /**/ }
public void widgetSelected(SelectionEvent e) {
validateComplexJoinFormula(wComplexJoin.getText());
}
});
// ComplexJoin formula text
wComplexJoin = new Text(shell, SWT.MULTI | SWT.LEFT | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
wComplexJoin.setText(""); //$NON-NLS-1$
props.setLook(wComplexJoin);
wComplexJoin.addModifyListener(lsMod);
fdComplexJoin = new FormData();
fdComplexJoin.left = new FormAttachment(middle, margin);
fdComplexJoin.right = new FormAttachment(100, 0);
fdComplexJoin.top = new FormAttachment(toolBar, margin);
fdComplexJoin.bottom = new FormAttachment(wlComplexJoin, 150);
wComplexJoin.setLayoutData(fdComplexJoin);
// Description
wlDescription = new Label(shell, SWT.RIGHT);
wlDescription.setText(Messages.getString("RelationshipDialog.USER_DESCRIPTION")); //$NON-NLS-1$
props.setLook(wlDescription);
fdlDescription = new FormData();
fdlDescription.left = new FormAttachment(0, 0);
fdlDescription.right = new FormAttachment(middle, -margin);
fdlDescription.top = new FormAttachment(wComplexJoin, margin);
wlDescription.setLayoutData(fdlDescription);
wDescription = new Text(shell, SWT.MULTI | SWT.LEFT | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
wDescription.setText(""); //$NON-NLS-1$
props.setLook(wDescription);
wDescription.addModifyListener(lsMod);
fdDescription = new FormData();
fdDescription.left = new FormAttachment(middle, margin);
fdDescription.right = new FormAttachment(100, 0);
fdDescription.top = new FormAttachment(wComplexJoin, margin);
fdDescription.bottom = new FormAttachment(100, -50);
wDescription.setLayoutData(fdDescription);
// Some buttons
wOK = new Button(shell, SWT.PUSH);
wOK.setText(Messages.getString("General.USER_OK")); //$NON-NLS-1$
wCancel = new Button(shell, SWT.PUSH);
wCancel.setText(Messages.getString("General.USER_CANCEL")); //$NON-NLS-1$
BaseStepDialog.positionBottomButtons(shell, new Button[] { wOK, wCancel }, margin, null);
// Add listeners
lsCancel = new Listener() {
public void handleEvent(Event e) {
cancel();
}
};
lsOK = new Listener() {
public void handleEvent(Event e) {
ok();
}
};
wOK.addListener(SWT.Selection, lsOK);
wCancel.addListener(SWT.Selection, lsCancel);
// If someone changes the relationship, we automatically modify the join type.
//
wRelation.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent arg0) {
wJoinType.select(RelationshipMeta.getJoinType(wRelation.getSelectionIndex()));
}
});
// If someone changes the join type (informational only) we change the relationship.
// This is a lossy process, but it's better than nothing.
//
wJoinType.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
wRelation.select(RelationshipMeta.getRelationType(wJoinType.getSelectionIndex()));
}
});
// Detect [X] or ALT-F4 or something that kills this window...
shell.addShellListener(new ShellAdapter() {
public void shellClosed(ShellEvent e) {
cancel();
}
});
getData();
relationshipMeta.setChanged(changed);
shell.layout();
WindowProperty winprop = props.getScreen(shell.getText());
if (winprop != null)
winprop.setShell(shell);
else
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
return relationshipMeta;
}
public void setComplex() {
wFromField.setEnabled(!relationshipMeta.isComplex());
wToField.setEnabled(!relationshipMeta.isComplex());
wComplexJoin.setEnabled(relationshipMeta.isComplex());
wlComplexJoin.setEnabled(relationshipMeta.isComplex());
toolBar.setEnabled(relationshipMeta.isComplex());
wGuess.setEnabled(relationshipMeta.isComplex());
}
public void refreshFromFields() {
refreshFields(fromTable, wFromField);
}
public void refreshToFields() {
refreshFields(toTable, wToField);
}
protected static void refreshFields(BusinessTable table, CCombo combo) {
combo.removeAll();
if (table != null) {
for(BusinessColumn column : table.getBusinessColumns()) {
combo.add(column.getId());
}
}
}
public void dispose() {
PropsUI.getInstance().setScreen(new WindowProperty(shell));
shell.dispose();
}
/**
* Copy information from the meta-data relationshipMeta to the dialog fields.
*/
public void getData() {
if (relationshipMeta.getTableFrom() != null)
wFrom.setText(relationshipMeta.getTableFrom().getId());
if (relationshipMeta.getTableTo() != null)
wTo.setText(relationshipMeta.getTableTo().getId());
if (relationshipMeta.getFieldFrom() != null) {
int idx = wFromField.indexOf(relationshipMeta.getFieldFrom().getId());
if (idx >= 0)
wFromField.select(idx);
}
if (relationshipMeta.getFieldTo() != null) {
int idx = wToField.indexOf(relationshipMeta.getFieldTo().getId());
if (idx >= 0)
wToField.select(idx);
}
wRelation.select(relationshipMeta.getType());
wJoinType.select(relationshipMeta.getJoinType());
wComplex.setSelection(relationshipMeta.isComplex());
if (relationshipMeta.getComplexJoin() != null) {
wComplexJoin.setText(relationshipMeta.getComplexJoin());
}
setComplex();
wDescription.setText(Const.NVL(relationshipMeta.getDescription(), ""));
wJoinOrderKey.setText(Const.NVL(relationshipMeta.getJoinOrderKey(), ""));
}
private void cancel() {
relationshipMeta.setChanged(changed);
relationshipMeta.setComplex(backupComplex);
relationshipMeta = null;
dispose();
}
private void ok() {
BusinessTable tableFrom = businessModel.findBusinessTable(wFrom.getText());
relationshipMeta.setTableFrom(tableFrom);
BusinessTable tableTo = businessModel.findBusinessTable(wTo.getText());
relationshipMeta.setTableTo(tableTo);
if (tableFrom != null) {
BusinessColumn fieldFrom = tableFrom.findBusinessColumn(wFromField.getText());
relationshipMeta.setFieldFrom(fieldFrom);
}
if (tableTo != null) {
BusinessColumn fieldTo = tableTo.findBusinessColumn(wToField.getText());
relationshipMeta.setFieldTo(fieldTo);
}
relationshipMeta.setType(wRelation.getSelectionIndex());
relationshipMeta.setComplexJoin(wComplexJoin.getText());
relationshipMeta.setDescription(wDescription.getText());
relationshipMeta.setJoinOrderKey(wJoinOrderKey.getText());
if (relationshipMeta.getTableFrom() == null) {
MessageBox mb = new MessageBox(shell, SWT.YES | SWT.ICON_WARNING);
// Is there a problem with the chosen table name, or did the user not choose a table at all?
if (wFrom.getText().equals(Messages.getString("RelationshipDialog.USER_SELECT_SOURCE_TABLE")))
mb.setMessage(Messages.getString("RelationshipDialog.USER_SELECT_SOURCE_TABLE")); //$NON-NLS-1$
else
mb.setMessage(Messages.getString("RelationshipDialog.USER_WARNING_TABLE_DOESNT_EXIST", wFrom.getText())); //$NON-NLS-1$
mb.setText(Messages.getString("General.USER_TITLE_WARNING")); //$NON-NLS-1$
mb.open();
return;
}
if (relationshipMeta.getTableTo() == null) {
MessageBox mb = new MessageBox(shell, SWT.YES | SWT.ICON_WARNING);
// Is there a problem with the chosen table name, or did the user not choose a table at all?
if (wTo.getText().equals(Messages.getString("RelationshipDialog.USER_SELECT_DESTINATION_TABLE")))
mb.setMessage(Messages.getString("RelationshipDialog.USER_SELECT_DESTINATION_TABLE")); //$NON-NLS-1$
else
mb.setMessage(Messages.getString("RelationshipDialog.USER_WARNING_TABLE_DOESNT_EXIST", wTo.getText())); //$NON-NLS-1$
mb.setText(Messages.getString("General.USER_TITLE_WARNING")); //$NON-NLS-1$
mb.open();
return;
}
if (relationshipMeta.getTableFrom().getId().equalsIgnoreCase(relationshipMeta.getTableTo().getId())) {
MessageBox mb = new MessageBox(shell, SWT.YES | SWT.ICON_WARNING);
mb.setMessage(Messages.getString("RelationshipDialog.USER_WARNING_RELATIONSHIP_SAME_TABLE_NOT_ALLOWED")); //$NON-NLS-1$
mb.setText(Messages.getString("General.USER_TITLE_WARNING")); //$NON-NLS-1$
mb.open();
return;
}
if(!relationshipMeta.isComplex() && relationshipMeta.getFieldFrom()==null){
MessageBox mb = new MessageBox(shell, SWT.YES | SWT.ICON_WARNING);
mb.setMessage(Messages.getString("RelationshipDialog.USER_WARNING_FROM_FIELD_NOT_DEFINED")); //$NON-NLS-1$
mb.setText(Messages.getString("General.USER_TITLE_WARNING")); //$NON-NLS-1$
mb.open();
return;
}
if(!relationshipMeta.isComplex() && relationshipMeta.getFieldTo()==null){
MessageBox mb = new MessageBox(shell, SWT.YES | SWT.ICON_WARNING);
mb.setMessage(Messages.getString("RelationshipDialog.USER_WARNING_TO_FIELD_NOT_DEFINED")); //$NON-NLS-1$
mb.setText(Messages.getString("General.USER_TITLE_WARNING")); //$NON-NLS-1$
mb.open();
return;
}
if(relationshipMeta.getType()<=0){
MessageBox mb = new MessageBox(shell, SWT.YES | SWT.ICON_WARNING);
mb.setMessage(Messages.getString("RelationshipDialog.USER_WARNING_TYPE_NOT_DEFINED")); //$NON-NLS-1$
mb.setText(Messages.getString("General.USER_TITLE_WARNING")); //$NON-NLS-1$
mb.open();
return;
}
if (relationshipMeta.isComplex()) {
if (!checkComplexJoin()) {
return;
}
}
dispose();
}
private boolean checkComplexJoin() {
if (relationshipMeta.isComplex()) {
String complexJoin = relationshipMeta.getComplexJoin();
// if there is something wrong with the formula,
// we must make the user aware of the implications
try {
PMSFormula joinFormula = new PMSFormula(businessModel, complexJoin, null);
joinFormula.parseAndValidate();
List<BusinessColumn> referencedColumns = new ArrayList<BusinessColumn>();
for (Selection selection : joinFormula.getBusinessColumns()) {
referencedColumns.add(selection.getBusinessColumn());
}
relationshipMeta.setCJReferencedColumns(referencedColumns);
return true;
} catch (PentahoMetadataException e) {
return MessageDialog.openConfirm(shell,
Messages.getString("RelationshipDialog.COMPLEX_JOIN_BAD_FORMULA_TITLE"),
Messages.getString("RelationshipDialog.COMPLEX_JOIN_BAD_FORMULA_DESC"));
}
}
else return true;
}
private void validateComplexJoinFormula(String formula) {
if (StringUtils.isEmpty(formula)) return;
PMSFormula joinFormula;
try {
joinFormula = new PMSFormula(businessModel, formula, null);
joinFormula.parseAndValidate();
// all clear
MessageDialog.openInformation(shell, "Formula OK", "Validations passed."); //TODO:i18n
} catch (PentahoMetadataException e) {
// if it's a parse error we might get friendlier message
String message = e.getLocalizedMessage();
if (e.getCause() != null && e.getCause() instanceof ParseException) {
message += System.getProperty("line.separator");
message += System.getProperty("line.separator");
message += e.getCause().getLocalizedMessage();
}
MessageDialog.openError(shell, Messages.getString("RelationshipDialog.COMPLEX_JOIN_BAD_FORMULA_TITLE"), message);
}
}
// Try to find fields with the same name in both tables...
public void guess() {
String from[] = wFromField.getItems();
String to[] = wToField.getItems();
// What is the longest string?
int longest = -1;
for (int i = 0; i < from.length; i++)
if (from[i].length() > longest)
longest = from[i].length();
for (int i = 0; i < to.length; i++)
if (to[i].length() > longest)
longest = to[i].length();
for (int length = longest; length > 3; length--) {
for (int i = 0; i < from.length; i++) {
for (int j = 0; j < to.length; j++) {
String one = wFromField.getItem(i);
String two = wToField.getItem(j);
int endOne = length;
if (endOne > one.length())
endOne = one.length();
int endTwo = length;
if (endTwo > two.length())
endTwo = two.length();
String leftOne = one.substring(0, endOne);
String leftTwo = two.substring(0, endTwo);
if (leftOne.equalsIgnoreCase(leftTwo)) {
wFromField.select(i);
wToField.select(j);
return;
}
int startOne = one.length() - length;
if (startOne < 0)
startOne = 0;
int startTwo = two.length() - length;
if (startTwo < 0)
startTwo = 0;
String rightOne = one.substring(startOne, one.length());
String rightTwo = two.substring(startTwo, two.length());
if (rightOne.equalsIgnoreCase(rightTwo)) {
wFromField.select(i);
wToField.select(j);
return;
}
}
}
}
}
// Try to find fields with the same name in both tables...
public void guessRelationship() {
if (fromTable != null && toTable != null) {
if (fromTable.isFactTable() && toTable.isDimensionTable())
wRelation.select(RelationshipMeta.TYPE_RELATIONSHIP_N_1);
if (fromTable.isDimensionTable() && toTable.isFactTable())
wRelation.select(RelationshipMeta.TYPE_RELATIONSHIP_1_N);
if (fromTable.isFactTable() && toTable.isFactTable())
wRelation.select(RelationshipMeta.TYPE_RELATIONSHIP_N_N);
}
}
/**
* Simple interface to cover simplest join cases
*/
class AddComplexJoinColumnsDialog extends TitleAreaDialog {
private Shell shell;
public AddComplexJoinColumnsDialog() {
super(RelationshipDialog.this.shell);
}
CCombo wColumnTo;
CCombo wColumnFrom;
protected Control createDialogArea(Composite parent) {
Composite c0 = (Composite) super.createDialogArea(parent);
setTitle(Messages.getString("RelationshipDialog.COMPLEX_JOIN_ADD_CONDITION"));
setMessage(Messages.getString("RelationshipDialog.COMPLEX_JOIN_ADD_CONDITION_DETAIL"));
FormLayout formLayout = new FormLayout();
formLayout.marginWidth = Const.FORM_MARGIN;
formLayout.marginHeight = Const.FORM_MARGIN;
Composite c1 = new Composite(c0, SWT.BORDER);
c1.setBackground(GUIResource.getInstance().getColorWhite());
c1.setLayout(formLayout);
PropsUI props = PropsUI.getInstance();
int middle = 50;
CCombo wFrom = new CCombo(c1, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
props.setLook(wFrom);
// free will is overrated
wFrom.add(fromTable.getId());
wFrom.select(0);
wFrom.setEditable(false);
wFrom.setEnabled(false);
FormData fdFrom = new FormData();
fdFrom.left = new FormAttachment(0, Const.MARGIN);
fdFrom.top = new FormAttachment(0, Const.MARGIN);
fdFrom.right = new FormAttachment(middle, -Const.MARGIN);
wFrom.setLayoutData(fdFrom);
wColumnFrom = new CCombo(c1, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
props.setLook(wColumnFrom);
refreshFields(fromTable, wColumnFrom);
wColumnFrom.select(0);
wColumnFrom.setEditable(false);
FormData fdFromField = new FormData();
fdFromField.left = new FormAttachment(wFrom, Const.MARGIN );//*2
fdFromField.top = new FormAttachment(0, Const.MARGIN);
fdFromField.right = new FormAttachment(100, 0);
wColumnFrom.setLayoutData(fdFromField);
CCombo wTo = new CCombo(c1, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
props.setLook(wTo);
wTo.add(toTable.getId());
wTo.select(0);
wTo.setEditable(false);
wTo.setEnabled(false);
FormData fdTo = new FormData();
fdTo.left = new FormAttachment(0, Const.MARGIN);
fdTo.top = new FormAttachment(wFrom, Const.MARGIN);
fdTo.right = new FormAttachment(middle, -Const.MARGIN);
wTo.setLayoutData(fdTo);
wColumnTo = new CCombo(c1, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
props.setLook(wColumnTo);
refreshFields(toTable, wColumnTo);
wColumnTo.select(0);
wColumnTo.setEditable(false);
FormData fdToField = new FormData();
fdToField.left = new FormAttachment(wTo, Const.MARGIN );
fdToField.top = new FormAttachment(wColumnFrom, Const.MARGIN);
fdToField.right = new FormAttachment(100, 0);
wColumnTo.setLayoutData(fdToField);
return c0;
}
protected void okPressed() {
// nothing fancy just assume simplest use cases
// or just add to the formula otherwise
String complexJoin = wComplexJoin.getText();
BusinessColumn fieldTo = toTable.findBusinessColumn(wColumnTo.getText());
BusinessColumn fieldFrom = fromTable.findBusinessColumn(wColumnFrom.getText());
ContextLookup to = new ContextLookup(fieldTo.toString());
ContextLookup from = new ContextLookup(fieldFrom.toString());
final String newLine = System.getProperty("line.separator");
String toAdd = from.toString() + " = " + to.toString();
if (StringUtils.isEmpty(complexJoin)) {
complexJoin = toAdd;
}
else {
toAdd = newLine + toAdd;
Formula formula = null;
boolean done = false;
try {
PMSFormula joinFormula = new PMSFormula(businessModel, complexJoin, null);
joinFormula.parseAndValidate();
formula = joinFormula.getFormula();
} catch (PentahoMetadataException e) {
formula = null;
}
if (formula != null) {
if (formula.getRootReference() instanceof FormulaFunction
&& ((FormulaFunction)formula.getRootReference()).getFunction() instanceof AndFunction) {
// there's an and add to the end of it
int insertPoint = complexJoin.lastIndexOf(')');
if (insertPoint > 0) {
toAdd = " ;" + toAdd;
complexJoin =
complexJoin.substring(0, insertPoint) +
toAdd + " " +
complexJoin.substring(insertPoint);
done = true;
}
}
else {
// otherwise assume it's a condition and wrap it in an AND
complexJoin =
"AND(" +
newLine +
complexJoin + " ;" +
toAdd +" " +
")";
}
}
else {
// no valid formula, just stick it in there
complexJoin += toAdd;
}
}
wComplexJoin.setText(complexJoin);
setReturnCode(OK);
close();
}
}
}