/****************************************************************************** * Copyright (c) 2011-2013, Linagora * * 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: * Linagora - initial API and implementation *******************************************************************************/ package com.ebmwebsourcing.petals.services.eip.designer.tabbedproperties; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.net.URI; import java.util.HashMap; import java.util.Map; import javax.xml.namespace.QName; import org.eclipse.bpel.common.wsdl.helpers.UriAndUrlHelper; import org.eclipse.gef.commands.Command; import org.eclipse.gef.commands.CommandStack; import org.eclipse.gef.commands.CompoundCommand; 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.SelectionChangedEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.views.properties.tabbed.AbstractPropertySection; import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; import com.ebmwebsourcing.petals.common.generation.Mep; import com.ebmwebsourcing.petals.common.internal.provisional.swt.DefaultSelectionListener; import com.ebmwebsourcing.petals.common.internal.provisional.utils.NamespaceUtils; import com.ebmwebsourcing.petals.common.internal.provisional.utils.StringUtils; import com.ebmwebsourcing.petals.common.internal.provisional.utils.WsdlUtils; import com.ebmwebsourcing.petals.services.eip.designer.edit.commands.EipConnectionSetAttributeCommand; import com.ebmwebsourcing.petals.services.eip.designer.edit.parts.EipConnectionEditPart; import com.ebmwebsourcing.petals.services.eip.designer.model.EipConnection; import com.ebmwebsourcing.petals.services.eip.designer.model.EipNode; import com.ebmwebsourcing.petals.services.eip.designer.model.Endpoint; import com.ebmwebsourcing.petals.services.su.ui.OperationLabelProvider; import com.ebmwebsourcing.petals.services.utils.ConsumeUtils; /** * The section to define the condition associated with an EIP connection. * @author Vincent Zurczak - EBM WebSourcing */ public class ConnectionConsumeSection extends AbstractPropertySection implements PropertyChangeListener { private EipConnection connection; private boolean enableListener; private Button itfButton, srvButton, edptButton; private CCombo mepCCombo; private Text opNameText, opNsText; private final Map<QName,Mep> opNameToMep = new HashMap<QName,Mep> (); private ComboViewer operationViewer; /** * Constructor. */ public ConnectionConsumeSection() { // nothing } /* * (non-Jsdoc) * @see java.beans.PropertyChangeListener * #propertyChange(java.beans.PropertyChangeEvent) */ @Override public void propertyChange( PropertyChangeEvent evt ) { if( EipConnection.PROPERTY_CONSUME_BY_ITF.equals( evt.getPropertyName()) || EipConnection.PROPERTY_CONSUME_BY_SRV.equals( evt.getPropertyName()) || EipConnection.PROPERTY_CONSUME_BY_EDPT.equals( evt.getPropertyName()) || EipConnection.PROPERTY_CONSUMED_MEP.equals( evt.getPropertyName()) || EipConnection.PROPERTY_CONSUMED_OPERATION.equals( evt.getPropertyName())) refresh(); } /* * (non-Javadoc) * @see org.eclipse.ui.views.properties.tabbed.AbstractPropertySection * #createControls(org.eclipse.swt.widgets.Composite, org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage) */ @Override public void createControls( Composite parent, TabbedPropertySheetPage aTabbedPropertySheetPage ) { // Create the container super.createControls( parent, aTabbedPropertySheetPage ); Composite container = getWidgetFactory().createPlainComposite( parent, SWT.NONE ); container.setLayout( new GridLayout( 2, false )); // Add the buttons CLabel label = getWidgetFactory().createCLabel( container, "Resolve the target service by:" ); label.setToolTipText( "Specify the way the target service will be resolved (implicit or explicit addressing)" ); GridData layoutData = new GridData( SWT.DEFAULT, SWT.BEGINNING, false, false ); layoutData.verticalIndent = 2; label.setLayoutData( layoutData ); Composite buttonsContainer = getWidgetFactory().createComposite( container ); GridLayout layout = new GridLayout(); layout.marginHeight = 5; buttonsContainer.setLayout( layout ); SelectionListener buttonListener = new DefaultSelectionListener() { @Override public void widgetSelected( SelectionEvent e ) { if( ConnectionConsumeSection.this.enableListener ) { EipConnectionSetAttributeCommand cmd = new EipConnectionSetAttributeCommand((String) e.widget.getData()); cmd.setEipConnection( ConnectionConsumeSection.this.connection ); cmd.setNewValue(((Button) e.widget).getSelection()); executeCommand( cmd ); } } }; this.itfButton = getWidgetFactory().createButton( buttonsContainer, "Interface name", SWT.CHECK ); this.itfButton.setToolTipText( "Find the service by interface name" ); this.itfButton.setData( EipConnection.PROPERTY_CONSUME_BY_ITF ); this.itfButton.addSelectionListener( buttonListener ); this.itfButton.setEnabled( false ); this.srvButton = getWidgetFactory().createButton( buttonsContainer, "Service name", SWT.CHECK ); this.srvButton.setToolTipText( "Find the service by service name" ); this.srvButton.setData( EipConnection.PROPERTY_CONSUME_BY_SRV ); this.srvButton.addSelectionListener( buttonListener ); this.edptButton = getWidgetFactory().createButton( buttonsContainer, "End-point name", SWT.CHECK ); this.edptButton.setToolTipText( "Find the service by end-point name" ); this.edptButton.setData( EipConnection.PROPERTY_CONSUME_BY_EDPT ); this.edptButton.addSelectionListener( buttonListener ); // Add the text sections label = getWidgetFactory().createCLabel( container, "Operation helper:" ); label.setToolTipText( "A helper to select the operation to invoke" ); CCombo opCombo = getWidgetFactory().createCCombo( container, SWT.READ_ONLY | SWT.DROP_DOWN ); this.operationViewer = new ComboViewer( opCombo ); this.operationViewer.getCCombo().setLayoutData( new GridData( GridData.FILL_HORIZONTAL )); this.operationViewer.setContentProvider( new ArrayContentProvider()); this.operationViewer.setLabelProvider( new OperationLabelProvider()); this.operationViewer.setInput( this.opNameToMep.keySet()); label = getWidgetFactory().createCLabel( container, "Operation Name:" ); label.setToolTipText( "Define the local part of the operation to invoke" ); this.opNameText = getWidgetFactory().createText( container, "", SWT.BORDER ); this.opNameText.setLayoutData( new GridData( GridData.FILL_HORIZONTAL )); label = getWidgetFactory().createCLabel( container, "Operation Namespace:" ); label.setToolTipText( "Define the name space URI of the operation to invoke" ); this.opNsText = getWidgetFactory().createText( container, "", SWT.BORDER ); this.opNsText.setLayoutData( new GridData( GridData.FILL_HORIZONTAL )); label = getWidgetFactory().createCLabel( container, "Invocation MEP:" ); label.setToolTipText( "Define the way the service provider and consumer will interact together" ); this.mepCCombo = getWidgetFactory().createCCombo( container, SWT.READ_ONLY | SWT.DROP_DOWN ); layoutData = new GridData(); layoutData.widthHint = 300; this.mepCCombo.setLayoutData( layoutData ); for( Mep mep : Mep.values()) this.mepCCombo.add( mep.toString()); // The listeners this.operationViewer.addSelectionChangedListener( new ISelectionChangedListener() { @Override public void selectionChanged( SelectionChangedEvent event ) { // This listener will directly update the model ISelection selection = ConnectionConsumeSection.this.operationViewer.getSelection(); if( ConnectionConsumeSection.this.enableListener && ! selection.isEmpty()) { Object o = ((IStructuredSelection) selection).getFirstElement(); CompoundCommand cmd = new CompoundCommand(); EipConnectionSetAttributeCommand cmd1 = new EipConnectionSetAttributeCommand( EipConnection.PROPERTY_CONSUMED_OPERATION ); cmd1.setEipConnection( ConnectionConsumeSection.this.connection ); cmd1.setNewValue(((QName) o).toString()); cmd.add( cmd1 ); EipConnectionSetAttributeCommand cmd2 = new EipConnectionSetAttributeCommand( EipConnection.PROPERTY_CONSUMED_MEP ); cmd2.setEipConnection( ConnectionConsumeSection.this.connection ); Mep invocationMep = ConnectionConsumeSection.this.opNameToMep.get( o ); cmd2.setNewValue( invocationMep.toString()); cmd.add( cmd2 ); executeCommand( cmd ); } } }); ModifyListener opModifyListener = new ModifyListener() { @Override public void modifyText( ModifyEvent e ) { if( ConnectionConsumeSection.this.enableListener ) { EipConnectionSetAttributeCommand cmd = new EipConnectionSetAttributeCommand( EipConnection.PROPERTY_CONSUMED_OPERATION ); cmd.setEipConnection( ConnectionConsumeSection.this.connection ); String uri = ConnectionConsumeSection.this.opNsText.getText().trim(); String local = ConnectionConsumeSection.this.opNameText.getText().trim(); String value = uri.length() > 0 || local.length() > 0 ? "{" + uri + "}" + local : null; cmd.setNewValue( value ); executeCommand( cmd ); } } }; this.opNameText.addModifyListener( opModifyListener ); this.opNsText.addModifyListener( opModifyListener ); this.mepCCombo.addModifyListener( new ModifyListener() { @Override public void modifyText( ModifyEvent e ) { if( ConnectionConsumeSection.this.enableListener ) { EipConnectionSetAttributeCommand cmd = new EipConnectionSetAttributeCommand( EipConnection.PROPERTY_CONSUMED_MEP ); cmd.setEipConnection( ConnectionConsumeSection.this.connection ); cmd.setNewValue( ConnectionConsumeSection.this.mepCCombo.getText()); executeCommand( cmd ); } } }); } /** * Executes a command on top of the EIP editor's command stack. * @param command */ private void executeCommand( Command command ) { IEditorPart part = getPart().getSite().getPage().getActiveEditor(); CommandStack commandStack = (CommandStack) part.getAdapter( CommandStack.class ); if( commandStack != null ) commandStack.execute( command ); } /* * (non-Javadoc) * @see org.eclipse.ui.views.properties.tabbed.AbstractPropertySection * #setInput(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) */ @Override public void setInput( IWorkbenchPart part, ISelection selection ) { super.setInput( part, selection ); // Do not listen to model changes from the previous input if( this.connection != null ) this.connection.removePropertyChangeListener( this ); if( selection instanceof IStructuredSelection ) { Object input = ((IStructuredSelection) selection).getFirstElement(); if( input instanceof EipConnectionEditPart ) this.connection = (EipConnection) ((EipConnectionEditPart) input).getModel(); } // Listen to changes in the new model if( this.connection != null ) this.connection.addPropertyChangeListener( this ); } /* * (non-Javadoc) * @see org.eclipse.ui.views.properties.tabbed.AbstractPropertySection * #refresh() */ @Override public void refresh() { this.enableListener = false; if( this.opNsText != null && ! this.opNsText.isDisposed() && this.connection != null ) { // Save the caret position Text focusText = null; if( this.opNameText.isFocusControl()) focusText = this.opNameText; else if( this.opNsText.isFocusControl()) focusText = this.opNsText; int caret = focusText != null ? focusText.getCaretPosition() : -1; // Update values String local = NamespaceUtils.removeNamespaceElements( this.connection.getConsumeOperation()); String uri = NamespaceUtils.extractNamespaceUri( this.connection.getConsumeOperation()); this.opNameText.setText( local != null ? local : "" ); this.opNsText.setText( uri != null ? uri : "" ); this.itfButton.setSelection( this.connection.isConsumeItf()); this.srvButton.setSelection( this.connection.isConsumeSrv()); this.edptButton.setSelection( this.connection.isConsumeEdpt()); this.srvButton.setEnabled( this.connection.isConsumeSrvPossible()); this.edptButton.setEnabled( this.connection.isConsumeEdptPossible()); int index = -1; if( this.connection.getConsumeMep() != null ) index = this.mepCCombo.indexOf( this.connection.getConsumeMep()); if( index != -1 ) this.mepCCombo.select( index ); else this.mepCCombo.select( 0 ); // Restore the caret if( focusText != null ) focusText.setSelection( caret ); // Update the content of the operation helper this.opNameToMep.clear(); // End-point: search in the local repository if( this.connection.getTarget() instanceof Endpoint ) { Endpoint edpt = (Endpoint) this.connection.getTarget(); QName itf = null; if( ! StringUtils.isEmpty( edpt.getInterfaceNamespace()) && ! StringUtils.isEmpty( edpt.getInterfaceName())) itf = new QName( edpt.getInterfaceNamespace(), edpt.getInterfaceName()); QName srv = null; if( ! StringUtils.isEmpty( edpt.getServiceNamespace()) && ! StringUtils.isEmpty( edpt.getServiceName())) srv = new QName( edpt.getServiceNamespace(), edpt.getServiceName()); String en = edpt.getEndpointName(); if( StringUtils.isEmpty( en )) en = null; this.opNameToMep.putAll( ConsumeUtils.getValidOperationsForConsume( itf, srv, en )); } // EIP: check the associated WSDL, if it exists else if( this.connection.getTarget() != null ) { EipNode eip = ((EipNode) this.connection.getTarget()); URI javaNetUri = null; if( eip.getWsdlUri() != null ) javaNetUri = UriAndUrlHelper.urlToUri( eip.getWsdlUri()); if( javaNetUri != null ) { this.opNameToMep.putAll( WsdlUtils.INSTANCE.getOperations( javaNetUri, eip.getInterfaceName(), eip.getInterfaceNamespace(), eip.getServiceName(), eip.getServiceNamespace(), eip.getEndpointName())); } } // Hack for EIP nodes without a WSDL - not handled before because the EIP is not (yet) a Petals end-point if( this.opNameToMep.isEmpty() && this.connection.getTarget() instanceof EipNode ) { QName op = new QName( EipNode.DEFAULT_EIP_NS, "anyOperation" ); this.opNameToMep.put( op, Mep.UNKNOWN ); } // Update the viewer this.operationViewer.setInput( this.opNameToMep.keySet()); this.operationViewer.refresh(); this.operationViewer.getCCombo().setEnabled( ! this.opNameToMep.isEmpty()); } this.enableListener = true; } }