blob: 3536708580c701cc89c163bbbf1e844dc1b22e50 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.bpel.ui.expressions;
import org.eclipse.bpel.common.ui.details.IDetailsAreaConstants;
import org.eclipse.bpel.fnmeta.model.Function;
import org.eclipse.bpel.model.util.BPELConstants;
import org.eclipse.bpel.model.util.BPELUtils;
import org.eclipse.bpel.ui.BPELUIPlugin;
import org.eclipse.bpel.ui.IBPELUIConstants;
import org.eclipse.bpel.ui.IHelpContextIds;
import org.eclipse.bpel.ui.Messages;
import org.eclipse.bpel.ui.commands.CompoundCommand;
import org.eclipse.bpel.ui.commands.SetNamespaceMappingCommand;
import org.eclipse.bpel.ui.editors.TextEditorInput;
import org.eclipse.bpel.ui.editors.xpath.XPathTextEditor;
import org.eclipse.bpel.ui.properties.BPELPropertySection;
import org.eclipse.bpel.ui.properties.DateTimeSelector;
import org.eclipse.bpel.ui.properties.DurationSelector;
import org.eclipse.bpel.ui.util.BPELDateTimeHelpers;
import org.eclipse.bpel.ui.util.BPELUtil;
import org.eclipse.core.resources.IMarker;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.FormToolkit;
/**
* Expression language editor for XPath.
*/
@SuppressWarnings("nls")
public class XPathExpressionEditor extends AbstractExpressionEditor {
static final String BOOLEAN_EXPR_DEFAULT = "true()"; //$NON-NLS-1$
static final String UNSIGNED_INT_EXPR_DEFAULT = "1"; //$NON-NLS-1$
static final String TEXT_STRING = Messages.XPathExpressionEditor_Text_0,
LITERAL_STRING = Messages.XPathExpressionEditor_Literal_1;
static final int TEXT = 0, LITERAL = 1;
protected static final String DEFAULT_DURATION_VALUE = "\'P0D\'"; //$NON-NLS-1$
protected Combo combo; // Expression type values
protected Label comboLabel; // Expression type
protected Composite mainComposite; // high level composite control
protected XPathTextEditor textEditor; // expression text
/** The date/time selector, alternative to just plain text */
protected DateTimeSelector dateTimeSelector;
/** The duration selector, alternative to just plain text */
protected DurationSelector durationSelector;
protected IPropertyListener propertyListener;
/** This composite holds a stack of editors, only the top one is shown */
protected Composite editorComposite;
/** The text editor composite, a child control of the editorComposite */
protected Composite textEditorComposite;
/** The duration editor composite, a child control of the editorComposiste */
protected Composite durationEditorComposite;
/** The date time editor composite, a child control of the editorComposiste */
protected Composite dateTimeEditorComposite;
// private int comboValue = -1;
/** The input to the text editor. */
protected TextEditorInput textEditorInput;
private FocusListener focusListener;
/**
* Create a brand new shiny XPathExpressionEditor ...
*/
public XPathExpressionEditor() {
super();
}
/**
* Create controls ..
*/
@Override
public void createControls(Composite parent, FormToolkit toolkit) {
super.createControls(parent, toolkit);
createEditor(parent);
}
protected void createEditor(Composite parent) {
this.mainComposite = wf.createComposite( parent );
FormLayout layout = new FormLayout();
layout.marginWidth = layout.marginHeight = 0;
mainComposite.setLayout(layout);
mainComposite.setBackground(BPELUIPlugin.INSTANCE.getColorRegistry()
.get(IBPELUIConstants.COLOR_WHITE));
comboLabel = wf.createLabel(mainComposite,
Messages.XPathExpressionEditor_Expression_Type_2);
combo = new Combo(mainComposite, SWT.BORDER | SWT.READ_ONLY | SWT.FLAT);
combo.add(TEXT_STRING);
combo.add(LITERAL_STRING);
combo.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
updateEditorToType(combo.getSelectionIndex());
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
FormData data = new FormData();
data.top = new FormAttachment(combo, 0, SWT.CENTER);
data.left = new FormAttachment(0, 0);
data.right = new FormAttachment(combo, -IDetailsAreaConstants.HSPACE);
comboLabel.setLayoutData(data);
data = new FormData();
data.top = new FormAttachment(0, IDetailsAreaConstants.VSPACE );
data.left = new FormAttachment(0, BPELUtil.calculateLabelWidth(
comboLabel, BPELPropertySection.STANDARD_LABEL_WIDTH_LRG));
data.right = new FormAttachment(100, 0);
combo.setLayoutData(data);
// Create the editor composite
// The editor composite will contain one of N editors.
// We use stack layout, because only one editor is visible at a time.
editorComposite = wf.createComposite(mainComposite);
editorComposite.setLayout(new StackLayout());
data = new FormData();
data.top = new FormAttachment(combo,2 * IDetailsAreaConstants.VSPACE);
data.left = new FormAttachment(0, 5);
data.right = new FormAttachment(100, 0);
data.bottom = new FormAttachment(100, 0);
editorComposite.setLayoutData(data);
}
protected void rearrangeComboAndEditorComposite() {
boolean comboVisible = isLiteralType();
combo.setVisible(comboVisible);
comboLabel.setVisible(comboVisible);
if (editorComposite != null) {
FormData data = (FormData) editorComposite.getLayoutData();
if (comboVisible) {
data.top = new FormAttachment(combo,
2 * IDetailsAreaConstants.VSPACE);
} else {
data.top = new FormAttachment(0,
2 * IDetailsAreaConstants.VSPACE);
}
}
}
/**
* Gets the text editor composite, creates it if necessary and makes it
* visible by default.
*
* @return the composite for the text editor ...
*/
Composite getTextEditorComposite() {
if (textEditorComposite != null) {
return textEditorComposite;
}
textEditorComposite = wf.createComposite(editorComposite,SWT.BORDER);
textEditorComposite.setLayout(new FillLayout());
textEditor = (XPathTextEditor) createEditor(
XPathTextEditor.XPATH_EDITOR_ID,
this.textEditorInput,
textEditorComposite);
textEditor.addPropertyListener(getPropertyListener());
textEditor.addFocusListener(getFocusListener());
textEditor.setDecoration(true);
return textEditorComposite;
}
protected FocusListener getFocusListener() {
if (focusListener == null){
focusListener = new FocusAdapter(){
public void focusLost(FocusEvent e) {
notifyFocusOut();
}
};}
return focusListener;
}
Composite getDateTimeEditor() {
if (dateTimeEditorComposite != null) {
return dateTimeEditorComposite;
}
dateTimeEditorComposite = wf.createComposite(editorComposite, SWT.NONE);
FormLayout layout = new FormLayout();
layout.marginWidth = layout.marginHeight = 0;
dateTimeEditorComposite.setLayout(layout);
Label label = wf.createLabel(dateTimeEditorComposite,
Messages.XPathExpressionEditor_Date_Time_UTC_3);
dateTimeSelector = new DateTimeSelector(wf, dateTimeEditorComposite,
SWT.NONE, BPELDateTimeHelpers.yearMin,
BPELDateTimeHelpers.yearMax);
String body = (String) textEditorInput.getAdapter(String.class);
int[] dateTime = BPELDateTimeHelpers.parseXPathDateTime(body, false);
dateTimeSelector.setValues(dateTime);
FormData data = new FormData();
data.top = new FormAttachment(0, 10);
data.left = new FormAttachment(0, 0);
data.right = new FormAttachment(dateTimeSelector,
-IDetailsAreaConstants.HSPACE);
label.setLayoutData(data);
data = new FormData();
data.top = new FormAttachment(0, 10);
data.left = new FormAttachment(0, BPELUtil.calculateLabelWidth(
label, BPELPropertySection.STANDARD_LABEL_WIDTH_LRG));
// data.right = new FormAttachment(100, 0);
dateTimeSelector.setLayoutData(data);
dateTimeSelector.addSelectionListener( new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
// Push new values to the text editor document so that
// it is reflected next time we shift
// to the text editor.
if (textEditorInput != null) {
int[] values = dateTimeSelector.getValues();
textEditorInput.setEditorContent ( BPELDateTimeHelpers.createXPathDateTime(values, false) , getModelObject() );
}
notifyChanged();
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
PlatformUI.getWorkbench().getHelpSystem().setHelp(
dateTimeEditorComposite,
IHelpContextIds.XPATH_DATE);
return dateTimeEditorComposite;
}
/**
* Get or create the duration editor.
*
* @return
*/
Composite getDurationEditor() {
if (durationEditorComposite != null) {
return durationEditorComposite;
}
durationEditorComposite = wf.createComposite(editorComposite, SWT.NONE);
FormLayout layout = new FormLayout();
layout.marginWidth = layout.marginHeight = 0;
durationEditorComposite.setLayout(layout);
Label label = wf.createLabel(durationEditorComposite, Messages.XPathExpressionEditor_Duration_4);
durationSelector = new DurationSelector(wf, durationEditorComposite, SWT.NONE);
FormData data = new FormData();
data.top = new FormAttachment(0, 10);
data.left = new FormAttachment(0, 0);
data.right = new FormAttachment(durationSelector, -IDetailsAreaConstants.HSPACE);
label.setLayoutData(data);
data = new FormData();
data.top = new FormAttachment(0, 10);
data.left = new FormAttachment(0, BPELUtil.calculateLabelWidth(label, BPELPropertySection.STANDARD_LABEL_WIDTH_LRG));
// data.right = new FormAttachment(100, 0);
durationSelector.setLayoutData(data);
durationSelector.addSelectionListener( new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
// Push new values to the text editor document so that
// it is reflected next time we shift
// to the text editor.
if (textEditorInput != null) {
int[] duration = durationSelector.getValues();
textEditorInput.setEditorContent( BPELDateTimeHelpers.createXPathDuration(duration) , getModelObject() );
}
}
public void widgetDefaultSelected(SelectionEvent e) { }
});
PlatformUI.getWorkbench().getHelpSystem().setHelp(
durationEditorComposite, IHelpContextIds.XPATH_DURATION);
return durationEditorComposite;
}
/**
* (non-Javadoc)
*
* @see org.eclipse.bpel.ui.expressions.IExpressionEditor#dispose()
*/
public void dispose() {
if (textEditor != null) {
getEditorManager().disposeEditor(textEditor);
textEditor = null;
}
// This is the main composite of all the editors.
if (editorComposite != null && !editorComposite.isDisposed()) {
editorComposite.dispose();
editorComposite = null;
}
}
/**
* This is called from a number of places and we have to be smart to not
* create and re-create the editors every time refresh is called.
*
*/
@Override
public void refresh() {
int editorType = combo.getSelectionIndex();
if (editorType < 0) {
String body = (String) textEditorInput.getAdapter(String.class);
// TODO: try literal widgets!
editorType = TEXT;
if (BPELDateTimeHelpers.parseXPathDuration(body) != null) {
editorType = LITERAL;
} else if (BPELDateTimeHelpers.parseXPathDateTime(body, false) != null) {
editorType = LITERAL;
}
// update the editor type
combo.select(editorType);
}
updateEditorToType(editorType);
}
/**
* Update the editor to the right type.
*
* @param editorType
*/
void updateEditorToType(int editorType) {
String body = (String) textEditorInput.getAdapter(String.class);
switch (editorType) {
case TEXT:
restackEditorComposite(getTextEditorComposite());
break;
case LITERAL:
if (IEditorConstants.ET_DURATION.equals(getExprType())) {
restackEditorComposite(getDurationEditor());
int[] duration = BPELDateTimeHelpers.parseXPathDuration(body);
if (duration != null) {
durationSelector.setValues(duration);
}
} else {
restackEditorComposite(getDateTimeEditor());
int[] dateTime = BPELDateTimeHelpers.parseXPathDateTime(body,
false);
if (dateTime != null) {
dateTimeSelector.setValues(dateTime);
}
}
break;
}
}
/**
* We re-stack the editors and have stack layout only show the top child
* control.
*
* @param c
* the editor composite for one of our editors.
*/
void restackEditorComposite(Composite c) {
Layout layout = c.getParent().getLayout();
if (layout instanceof StackLayout) {
StackLayout stackLayout = (StackLayout) layout;
if (c != stackLayout.topControl) {
stackLayout.topControl = c;
rearrangeComboAndEditorComposite();
c.getParent().layout(true);
}
}
}
/**
* About to be hidden.
*/
public void aboutToBeHidden() {
}
/**
* The editor is about to be shown.
*
* @see org.eclipse.bpel.ui.expressions.IExpressionEditor#aboutToBeShown()
*/
public void aboutToBeShown() {
refresh();
}
/**
* If the editor is dirty it registers an ongoing change.
*/
protected IPropertyListener getPropertyListener() {
if (propertyListener == null) {
propertyListener = new IPropertyListener() {
public void propertyChanged(Object source, int propId) {
if (propId == IEditorPart.PROP_DIRTY) {
boolean isEditorDirty = false;
if (textEditor != null) {
isEditorDirty = textEditor.isDirty();
}
if (isEditorDirty) {
notifyChanged();
}
}
}
};
}
return propertyListener;
}
/**
* @see org.eclipse.bpel.ui.expressions.IExpressionEditor#getUserContext()
*/
public Object getUserContext() {
return null;
}
/**
* @see org.eclipse.bpel.ui.expressions.IExpressionEditor#restoreUserContext(java.lang.Object)
*/
public void restoreUserContext(Object userContext) {
// TODO! this is bogus
if (textEditor != null) {
textEditor.setFocus();
}
}
/**
* Return the body of the editor.
*
* @see org.eclipse.bpel.ui.expressions.AbstractExpressionEditor#getEditorContent()
*/
@Override
public String getEditorContent() {
int editorType = combo.getSelectionIndex();
if (editorType == LITERAL) {
if (IEditorConstants.ET_DURATION.equals(getExprType())) {
int[] duration = durationSelector.getValues();
return BPELDateTimeHelpers.createXPathDuration(duration);
}
int[] dateTime = dateTimeSelector.getValues();
return BPELDateTimeHelpers.createXPathDateTime(dateTime, false);
}
return textEditor.getContents();
}
/**
* @see org.eclipse.bpel.ui.expressions.AbstractExpressionEditor#setEditorContent(java.lang.String)
*/
@Override
public void setEditorContent (String body) {
this.textEditorInput = new TextEditorInput(body, getModelObject(), getExprType() );
// Refresh the text editor input, if not set
if (textEditor != null) {
textEditor.setInput(this.textEditorInput);
}
}
/**
* Answer if the editor edits literal type expressions. These have their own
* editor UI to deal with that.
*
* @return
*/
boolean isLiteralType() {
return IEditorConstants.ET_DURATION.equals(getExprType())
|| IEditorConstants.ET_DATETIME.equals(getExprType());
}
/**
* Return the default body for the given edit UI type.
*
* @return the default body to throw into the editor.
*/
public String getDefaultContent() {
if (isLiteralType()) {
return getDefaultBody(LITERAL);
}
return getDefaultBody(TEXT);
}
protected String getDefaultBody(int comboValue) {
String exprType = getExprType();
switch (comboValue) {
case TEXT: {
if (exprType.indexOf(IEditorConstants.ET_BOOLEAN) >= 0) {
return BOOLEAN_EXPR_DEFAULT;
} else if (exprType.indexOf(IEditorConstants.ET_UNSIGNED_INT) >= 0) {
return UNSIGNED_INT_EXPR_DEFAULT;
}
return ""; //$NON-NLS-1$
}
case LITERAL: {
if (exprType.indexOf(IEditorConstants.ET_DURATION) >= 0) {
return DEFAULT_DURATION_VALUE;
}
int[] dateTime = BPELDateTimeHelpers.getCurrentLocalDateTime();
BPELDateTimeHelpers.convertLocalToGMT(dateTime);
return BPELDateTimeHelpers.createXPathDateTime(dateTime, false);
}
}
return ""; //$NON-NLS-1$
}
/**
* @see org.eclipse.bpel.ui.expressions.IExpressionEditor#gotoTextMarker(org.eclipse.core.resources.IMarker, java.lang.String, java.lang.Object)
*/
public void gotoTextMarker(IMarker marker, String codeType,
Object modelObject) {
// TODO
}
/**
* @see org.eclipse.bpel.ui.expressions.IExpressionEditor#supportsExpressionType(java.lang.String)
*/
public boolean supportsExpressionType ( String exprType ) {
return true;
}
/**
*
* @see org.eclipse.bpel.ui.expressions.IExpressionEditor#markAsClean()
*/
public void markAsClean() {
if (textEditor != null) {
textEditor.markAsClean();
}
}
/**
* This is probably not the best place to do this, but we do need to do this someplace ...
*
* @see org.eclipse.bpel.ui.expressions.AbstractExpressionEditor#addExtraStoreCommands(org.eclipse.gef.commands.CompoundCommand)
*/
@Override
public void addExtraStoreCommands (CompoundCommand compoundCommand) {
EObject eObj = (EObject) getModelObject();
for(Function fn : Functions.getInstance(BPELConstants.XMLNS_XPATH_EXPRESSION_LANGUAGE_2007).getFunctions().values()) {
if (BPELUtils.isEmptyOrWhitespace(fn.getNamespace()) || BPELConstants.XMLNS_XPATH_EXPRESSION_LANGUAGE.equals(fn.getNamespace())) {
continue;
}
String pfx = BPELUtils.getNamespacePrefix( eObj, fn.getNamespace());
if (pfx == null) {
compoundCommand.add(new SetNamespaceMappingCommand(eObj, fn.getNamespace(), fn.getPrefix() )) ;
}
}
}
}