Java tutorial
/******************************************************************************* * Copyright (c) 2012-2014 Red Hat, Inc. * All rights reserved. * This program is 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: * Red Hat, Inc. - initial API and implementation * * @author bfitzpat ******************************************************************************/ package org.switchyard.tools.ui.editor.diagram.binding; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.eclipse.core.databinding.DataBindingContext; import org.eclipse.core.databinding.UpdateValueStrategy; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.value.ComputedValue; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.core.databinding.observable.value.IValueChangeListener; import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.core.databinding.observable.value.WritableValue; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.ListenerList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.search.IJavaSearchScope; import org.eclipse.jdt.core.search.SearchEngine; import org.eclipse.jdt.ui.IJavaElementSearchConstants; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jface.databinding.fieldassist.ControlDecorationSupport; import org.eclipse.jface.databinding.swt.SWTObservables; import org.eclipse.jface.databinding.viewers.ViewersObservables; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.soa.sca.sca1_1.model.sca.Binding; import org.eclipse.soa.sca.sca1_1.model.sca.Contract; import org.eclipse.soa.sca.sca1_1.model.sca.OperationSelectorType; import org.eclipse.soa.sca.sca1_1.model.sca.ScaPackage; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.SelectionDialog; import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory; import org.switchyard.tools.models.switchyard1_0.switchyard.JavaOperationSelectorType; import org.switchyard.tools.models.switchyard1_0.switchyard.RegexOperationSelectorType; import org.switchyard.tools.models.switchyard1_0.switchyard.StaticOperationSelectorType; import org.switchyard.tools.models.switchyard1_0.switchyard.SwitchyardFactory; import org.switchyard.tools.models.switchyard1_0.switchyard.XPathOperationSelectorType; import org.switchyard.tools.ui.editor.Messages; import org.switchyard.tools.ui.editor.databinding.ObservablesUtil; import org.switchyard.tools.ui.editor.databinding.RegexValidator; import org.switchyard.tools.ui.editor.databinding.SWTValueUpdater; import org.switchyard.tools.ui.editor.impl.SwitchyardSCAEditor; import org.switchyard.tools.ui.editor.util.InterfaceOpsUtil; /** * @author bfitzpat * */ public class OperationSelectorComposite extends Composite { private boolean _isReadOnly = false; private EObject _targetObj = null; private Binding _binding = null; private ListenerList _changeListeners; private Combo _operationSelectionCombo; private Text _xpathText; private Text _regexText; private Text _javaText; private Composite _operationSelectionComposite; private Composite _xpathComposite; private Composite _regexComposite; private Composite _javaComposite; private Composite _panel; private ComboViewer _typeCombo; private Composite _contentPanel = null; private StackLayout _stackLayout = null; private Button _browseClassBtn = null; private WritableValue _bindingValue; private IObservableValue _selectorValue; /** * Constructor. * * @param parent composite * @param style style bits * @param container the containing binding composite */ public OperationSelectorComposite(Composite parent, int style, AbstractSYBindingComposite container) { this(parent, style, container, false); } /** * Constructor. * * @param parent composite * @param style style bits * @param container the containing binding composite * @param isReadOnly true/false */ public OperationSelectorComposite(Composite parent, int style, AbstractSYBindingComposite container, boolean isReadOnly) { super(parent, style); _panel = parent; _isReadOnly = isReadOnly; _changeListeners = new ListenerList(); int additionalStyles = SWT.NONE; if (isReadOnly) { additionalStyles = SWT.READ_ONLY; } final GridLayout gridLayout = new GridLayout(); gridLayout.marginWidth = 0; gridLayout.marginHeight = 0; gridLayout.numColumns = 2; setLayout(gridLayout); Group opGroup = new Group(this, additionalStyles); opGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); GridLayout layout = new GridLayout(2, false); opGroup.setLayout(layout); opGroup.setText(Messages.OperationSelectorComposite_OperationSelectorGroup_label); _typeCombo = new ComboViewer(createCombo(opGroup, null, true)); _typeCombo.getControl().setLayoutData(new GridData()); _typeCombo.setContentProvider(ArrayContentProvider.getInstance()); _typeCombo.setLabelProvider(new LabelProvider() { @Override public String getText(Object element) { if (element instanceof SelectorType) { return ((SelectorType) element).getLabel(); } return super.getText(element); } }); _typeCombo.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { if (event.getSelection().isEmpty()) { return; } handleSelectorTypeChanged( (SelectorType) ((IStructuredSelection) event.getSelection()).getFirstElement()); } }); _typeCombo.setInput(SelectorType.values()); _contentPanel = new Composite(opGroup, SWT.NONE); _stackLayout = new StackLayout(); _contentPanel.setLayout(_stackLayout); _contentPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); _operationSelectionComposite = new Composite(_contentPanel, SWT.NONE); _operationSelectionCombo = createCombo(_operationSelectionComposite, Messages.label_operationName, false); _operationSelectionComposite.setLayout(new GridLayout()); _operationSelectionCombo.setLayoutData(new GridData(SWT.FILL, SWT.NULL, true, false)); _xpathComposite = new Composite(_contentPanel, SWT.NONE); _xpathText = createText(_xpathComposite); _xpathComposite.setLayout(new GridLayout()); _xpathText.setLayoutData(new GridData(SWT.FILL, SWT.NULL, true, false)); _regexComposite = new Composite(_contentPanel, SWT.NONE); _regexText = createText(_regexComposite); _regexComposite.setLayout(new GridLayout()); _regexText.setLayoutData(new GridData(SWT.FILL, SWT.NULL, true, false)); _javaComposite = new Composite(_contentPanel, SWT.NONE); _javaText = createText(_javaComposite); _javaComposite.setLayout(new GridLayout(2, false)); _browseClassBtn = new Button(_javaComposite, SWT.PUSH); _browseClassBtn.setText("..."); _browseClassBtn.setEnabled(this._isReadOnly); _javaText.setLayoutData(new GridData(SWT.FILL, SWT.NULL, true, false)); _browseClassBtn.setLayoutData(new GridData(SWT.FILL, SWT.NULL, false, false)); _browseClassBtn.addSelectionListener(new SelectionAdapter() { public void widgetSelected(final SelectionEvent e) { try { IType selected = selectType(_panel.getShell(), "org.switchyard.selector.OperationSelector", //$NON-NLS-1$ null); if (selected != null) { _javaText.setText(selected.getFullyQualifiedName()); } } catch (JavaModelException e1) { e1.printStackTrace(); } } }); _typeCombo.setSelection(new StructuredSelection(SelectorType.STATIC_TYPE)); } /** * If we changed, fire a changed event. * * @param source */ protected void fireChangedEvent(Object source) { ChangeEvent e = new ChangeEvent(source); // inform any listeners of the resize event Object[] listeners = this._changeListeners.getListeners(); for (int i = 0; i < listeners.length; ++i) { ((ChangeListener) listeners[i]).stateChanged(e); } } /** * Add a change listener. * * @param listener new listener */ public void addChangeListener(ChangeListener listener) { this._changeListeners.add(listener); } /** * Remove a change listener. * * @param listener old listener */ public void removeChangeListener(ChangeListener listener) { this._changeListeners.remove(listener); } /** * @param target Passed in what we're dropping on */ public void setTargetObject(EObject target) { this._targetObj = target; populateOperationCombo(); } protected EObject getTargetObject() { return this._targetObj; } protected Binding getBinding() { return this._binding; } /** * @param binding incoming */ public void setBinding(Binding binding) { _binding = binding; populateOperationCombo(); _bindingValue.setValue(binding); } /** * Bind the controls. * * @param domain the editing domain, may be null * @param context the data binding context */ public void bindControls(EditingDomain domain, DataBindingContext context) { final Realm realm = SWTObservables.getRealm(getDisplay()); _bindingValue = new WritableValue(realm, null, Binding.class); /* * intermediate values, used to separate control changes from value * changes (i.e. the bindings for these are wrapped with * SWTValueUpdater). */ final IObservableValue selectorTypeValue = new WritableValue(realm, null, SelectorType.class); final IObservableValue staticValue = new WritableValue(realm, null, String.class); final IObservableValue regexValue = new WritableValue(realm, null, String.class); final IObservableValue xpathValue = new WritableValue(realm, null, String.class); final IObservableValue javaValue = new WritableValue(realm, null, String.class); // bind intermediate values to controls org.eclipse.core.databinding.Binding binding = context.bindValue( ViewersObservables.observeSingleSelection(_typeCombo), selectorTypeValue, new UpdateValueStrategy(), null); ControlDecorationSupport.create(binding, SWT.TOP | SWT.LEFT); binding = context.bindValue(SWTObservables.observeSelection(_operationSelectionCombo), staticValue, new UpdateValueStrategy(UpdateValueStrategy.POLICY_CONVERT), null); ControlDecorationSupport.create(SWTValueUpdater.attach(binding), SWT.TOP | SWT.LEFT); binding = context.bindValue(SWTObservables.observeText(_regexText, SWT.Modify), regexValue, new UpdateValueStrategy(UpdateValueStrategy.POLICY_CONVERT) .setAfterConvertValidator(new RegexValidator()), null); ControlDecorationSupport.create(SWTValueUpdater.attach(binding), SWT.TOP | SWT.LEFT); binding = context.bindValue(SWTObservables.observeText(_xpathText, SWT.Modify), xpathValue, new UpdateValueStrategy(UpdateValueStrategy.POLICY_CONVERT), null); ControlDecorationSupport.create(SWTValueUpdater.attach(binding), SWT.TOP | SWT.LEFT); binding = context.bindValue(SWTObservables.observeText(_javaText, SWT.Modify), javaValue, new UpdateValueStrategy(UpdateValueStrategy.POLICY_CONVERT), null); ControlDecorationSupport.create(SWTValueUpdater.attach(binding), SWT.TOP | SWT.LEFT); /* * computed value. creates an operation selector based on the current * state of the controls. */ _selectorValue = new ComputedValue(realm, OperationSelectorType.class) { @Override protected Object calculate() { // we need to interrogate all values, or we'll miss events final SelectorType selectedType = (SelectorType) selectorTypeValue.getValue(); final String operationText = (String) staticValue.getValue(); final String xpathText = (String) xpathValue.getValue(); final String regexText = (String) regexValue.getValue(); final String javaText = (String) javaValue.getValue(); if (selectedType == null) { return null; } switch (selectedType) { case STATIC_TYPE: return selectedType.createOperationSelector(operationText); case XPATH_TYPE: return selectedType.createOperationSelector(xpathText); case REGEX_TYPE: return selectedType.createOperationSelector(regexText); case JAVA_TYPE: return selectedType.createOperationSelector(javaText); } return null; } @Override protected void doSetValue(Object value) { if (value == null) { selectorTypeValue.setValue(SelectorType.STATIC_TYPE); staticValue.setValue(""); } else if (value instanceof OperationSelectorType) { final SelectorType selectorType = SelectorType.valueOf((OperationSelectorType) value); selectorTypeValue.setValue(selectorType); switch (selectorType) { case STATIC_TYPE: staticValue.setValue(((StaticOperationSelectorType) value).getOperationName()); break; case XPATH_TYPE: xpathValue.setValue(((XPathOperationSelectorType) value).getExpression()); break; case REGEX_TYPE: regexValue.setValue(((RegexOperationSelectorType) value).getExpression()); break; case JAVA_TYPE: javaValue.setValue(((JavaOperationSelectorType) value).getClass_()); break; } } else { throw new IllegalArgumentException( "Unknown selector type: " + value.getClass().getCanonicalName()); } // update our cached value getValue(); } }; // now bind the selector into the binding context.bindValue(_selectorValue, ObservablesUtil.observeDetailValue(domain, _bindingValue, ScaPackage.eINSTANCE.getBinding_OperationSelector())); // propagate changes to the old binding composites _selectorValue.addValueChangeListener(new IValueChangeListener() { @Override public void handleValueChange(ValueChangeEvent event) { fireChangedEvent(OperationSelectorComposite.this); } }); } /** * @param parent parent composite * @param label string to put in label * @return reference to created Text control */ protected Combo createLabelAndCombo(Composite parent, String label) { return createLabelAndCombo(parent, label, false); } protected Combo createLabelAndCombo(Composite parent, String label, boolean readOnly) { if (label != null && !label.trim().isEmpty()) { Label labelControl = new Label(parent, SWT.NONE); labelControl.setText(label); TabbedPropertySheetWidgetFactory factory = new TabbedPropertySheetWidgetFactory(); factory.adapt(labelControl, false, false); } int styles = SWT.BORDER | SWT.DROP_DOWN; if (readOnly) { styles = SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY; } Combo combo = new Combo(parent, styles); combo.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false)); if (!readOnly) { addEnterNextListener(combo); } // _observableControls.add(combo); return combo; } protected Combo createCombo(Composite parent, String label, boolean readOnly) { int styles = SWT.BORDER | SWT.DROP_DOWN; if (readOnly) { styles = SWT.BORDER | SWT.DROP_DOWN | SWT.READ_ONLY; } Combo combo = new Combo(parent, styles); combo.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false)); addEnterNextListener(combo); return combo; } protected Text createText(Composite parent) { int styles = SWT.BORDER; Text textfield = new Text(parent, styles); textfield.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false)); addEnterNextListener(textfield); return textfield; } private void addEnterNextListener(final Control control) { control.addTraverseListener(new TraverseListener() { @Override public void keyTraversed(TraverseEvent e) { if (e.character == SWT.CR) { control.traverse(SWT.TRAVERSE_TAB_NEXT); } } }); } /** * Populate the drop-down with available operations from the contract * interface. */ public void populateOperationCombo() { if (_operationSelectionCombo != null && !_operationSelectionCombo.isDisposed()) { EObject target = null; if (getBinding() != null && getTargetObject() == null) { EObject parent = getBinding().eContainer(); if (parent != null && !(parent instanceof Contract)) { parent = parent.eContainer(); } if (parent instanceof Contract) { target = (EObject) parent; setTargetObject(target); } } final String selection = _operationSelectionCombo.getText(); if (getTargetObject() != null && getTargetObject() instanceof Contract) { String[] operations = InterfaceOpsUtil.gatherOperations((Contract) getTargetObject()); _operationSelectionCombo.setItems(operations); } if (selection != null && selection.length() > 0) { final int index = _operationSelectionCombo.indexOf(selection); if (index < 0) { _operationSelectionCombo.setText(selection); } else { _operationSelectionCombo.select(index); } } } } private void handleSelectorTypeChanged(final SelectorType typeToSelect) { _xpathText.setEnabled(false); _regexText.setEnabled(false); _javaText.setEnabled(false); _browseClassBtn.setEnabled(false); switch (typeToSelect) { case STATIC_TYPE: _operationSelectionCombo.setEnabled(true); _stackLayout.topControl = _operationSelectionComposite; break; case XPATH_TYPE: _xpathText.setEnabled(true); _stackLayout.topControl = _xpathComposite; break; case REGEX_TYPE: _regexText.setEnabled(true); _stackLayout.topControl = _regexComposite; break; case JAVA_TYPE: _javaText.setEnabled(true); _browseClassBtn.setEnabled(true); _stackLayout.topControl = _javaComposite; break; } _contentPanel.layout(); } /** * @param shell Shell for the window * @param superTypeName supertype to search for * @param project project to look in * @return IType the type created * @throws JavaModelException exception thrown */ public IType selectType(Shell shell, String superTypeName, IProject project) throws JavaModelException { IJavaSearchScope searchScope = null; if (project == null) { ISelection selection = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService() .getSelection(); IStructuredSelection selectionToPass = StructuredSelection.EMPTY; if (selection instanceof IStructuredSelection) { selectionToPass = (IStructuredSelection) selection; if (selectionToPass.getFirstElement() instanceof IFile) { project = ((IFile) selectionToPass.getFirstElement()).getProject(); } } } if (superTypeName != null) { if (project == null) { project = SwitchyardSCAEditor.getActiveEditor().getModelFile().getProject(); } IJavaProject javaProject = JavaCore.create(project); IType superType = javaProject.findType(superTypeName); if (superType != null) { searchScope = SearchEngine.createStrictHierarchyScope(javaProject, superType, true, false, null); } } else { searchScope = SearchEngine.createWorkspaceScope(); } SelectionDialog dialog = JavaUI.createTypeDialog(shell, new ProgressMonitorDialog(shell), searchScope, IJavaElementSearchConstants.CONSIDER_CLASSES_AND_INTERFACES, false); dialog.setTitle(Messages.label_selectEntries); dialog.setMessage(Messages.label_matchingItems); if (dialog.open() == IDialogConstants.CANCEL_ID) { return null; } Object[] types = dialog.getResult(); if (types == null || types.length == 0) { return null; } return (IType) types[0]; } private enum SelectorType { STATIC_TYPE(Messages.label_operationName) { @Override public OperationSelectorType createOperationSelector(String selectorText) { if (selectorText == null || selectorText.trim().length() == 0) { return null; } final StaticOperationSelectorType selector = SwitchyardFactory.eINSTANCE .createStaticOperationSelectorType(); selector.setOperationName(selectorText); return selector; } }, XPATH_TYPE(Messages.label_xpath) { @Override public OperationSelectorType createOperationSelector(String selectorText) { if (selectorText == null || selectorText.trim().length() == 0) { return null; } final XPathOperationSelectorType selector = SwitchyardFactory.eINSTANCE .createXPathOperationSelectorType(); selector.setExpression(selectorText); return selector; } }, REGEX_TYPE(Messages.label_regex) { @Override public OperationSelectorType createOperationSelector(String selectorText) { if (selectorText == null || selectorText.trim().length() == 0) { return null; } final RegexOperationSelectorType selector = SwitchyardFactory.eINSTANCE .createRegexOperationSelectorType(); selector.setExpression(selectorText); return selector; } }, JAVA_TYPE(Messages.label_javaClass) { @Override public OperationSelectorType createOperationSelector(String selectorText) { if (selectorText == null || selectorText.trim().length() == 0) { return null; } final JavaOperationSelectorType selector = SwitchyardFactory.eINSTANCE .createJavaOperationSelectorType(); selector.setClass(selectorText); return selector; } }; private final String _label; private SelectorType(String label) { _label = label; } /** * @return the display label for this selector type. */ public String getLabel() { return _label; } /** * Create a new operation selector. * * @param selectorText the selector text * @return a new operation selector */ public abstract OperationSelectorType createOperationSelector(String selectorText); /** * @param value an operation selector * @return the matching enum value */ public static SelectorType valueOf(final OperationSelectorType value) { if (value == null) { return null; } else if (value instanceof StaticOperationSelectorType) { return STATIC_TYPE; } else if (value instanceof XPathOperationSelectorType) { return XPATH_TYPE; } else if (value instanceof RegexOperationSelectorType) { return REGEX_TYPE; } else if (value instanceof JavaOperationSelectorType) { return JAVA_TYPE; } else { throw new IllegalArgumentException("Unknown selector type: " + value.getClass().getCanonicalName()); } } } }