/****************************************************************************** * 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.cdk.editor; import java.io.File; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import javax.xml.namespace.QName; import org.eclipse.bpel.common.wsdl.helpers.UriAndUrlHelper; import org.eclipse.core.databinding.UpdateValueStrategy; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.command.CompoundCommand; import org.eclipse.emf.edit.command.SetCommand; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.jface.databinding.swt.SWTObservables; import org.eclipse.jface.databinding.viewers.ViewersObservables; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseTrackAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; import org.eclipse.ui.forms.events.HyperlinkEvent; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Hyperlink; import com.ebmwebsourcing.petals.common.generation.Mep; import com.ebmwebsourcing.petals.common.internal.provisional.databinding.LocalQNameToStringConverter; import com.ebmwebsourcing.petals.common.internal.provisional.databinding.NamespaceQNameToStringConverter; import com.ebmwebsourcing.petals.common.internal.provisional.emf.EObjectUIHelper; import com.ebmwebsourcing.petals.common.internal.provisional.formeditor.ISharedEdition; import com.ebmwebsourcing.petals.common.internal.provisional.swt.DefaultSelectionListener; import com.ebmwebsourcing.petals.common.internal.provisional.swt.PetalsHyperlinkListener; import com.ebmwebsourcing.petals.common.internal.provisional.utils.JbiXmlUtils; import com.ebmwebsourcing.petals.common.internal.provisional.utils.PetalsConstants; import com.ebmwebsourcing.petals.common.internal.provisional.utils.ResourceUtils; import com.ebmwebsourcing.petals.common.internal.provisional.utils.StringUtils; import com.ebmwebsourcing.petals.common.internal.provisional.utils.SwtFactory; import com.ebmwebsourcing.petals.services.cdk.Messages; import com.ebmwebsourcing.petals.services.cdk.cdk5.Cdk5Package; import com.ebmwebsourcing.petals.services.cdk.editor.databinding.MepToStringConverter; import com.ebmwebsourcing.petals.services.cdk.editor.databinding.StringToMepConverter; import com.ebmwebsourcing.petals.services.su.editor.su.ActivableListener; import com.ebmwebsourcing.petals.services.su.editor.su.JBIEndpointUIHelpers; import com.ebmwebsourcing.petals.services.su.editor.su.JBIEndpointUIHelpers.CommonUIBean; import com.ebmwebsourcing.petals.services.su.ui.EnhancedConsumeDialog; import com.ebmwebsourcing.petals.services.su.ui.WsdlParsingJobManager; import com.sun.java.xml.ns.jbi.AbstractEndpoint; import com.sun.java.xml.ns.jbi.JbiPackage; import com.sun.java.xml.ns.jbi.Provides; /** * @author Mickael Istria - EBM WebSourcing */ public final class CDK5JBIEndpointUIHelper { public static final String CONSUME_TITLE = "Invocation Properties"; public static final String CONSUME_DESC = "Edit the invoked operation and the message exchange pattern."; /** * Private constructor for utility class. */ private CDK5JBIEndpointUIHelper() { // nothing } /** * Creates the specific UI for "consume" blocks in the JBI editor (with CDK 5 fields). * @param endpoint * @param toolkit * @param cdkComposite * @param ise * @param parent * @param commonUiBean */ public static void createConsumesUI( final AbstractEndpoint endpoint, final FormToolkit toolkit, final Composite parent, final ISharedEdition ise, final CommonUIBean commonUiBean ) { Color blueFont = parent.getDisplay().getSystemColor( SWT.COLOR_DARK_BLUE ); // The controls SwtFactory.createLabel( parent, "Operation Namespace:", "The QName of the operation (should match an operation declared in a WSDL)" ).setForeground( blueFont ); final Text opNamespaceText = SwtFactory.createSimpleTextField( parent, true ); SwtFactory.createLabel( parent, "Operation Name:", "The QName of the operation (should match an operation declared in a WSDL)" ).setForeground( blueFont ); final Text opNameText = SwtFactory.createSimpleTextField( parent, true ); SwtFactory.createLabel( parent, "Invocation MEP *:", "The Message Exchange Pattern to use for the invocation" ).setForeground( blueFont ); ComboViewer mepViewer = SwtFactory.createDefaultComboViewer( parent, false, true, Mep.values()); toolkit.adapt( mepViewer.getCombo()); // Add the helpers toolkit.createLabel( parent, "" ); Hyperlink selectLink = toolkit.createHyperlink( parent, "Select a Petals service and an operation to invoke", SWT.NONE ); selectLink.setToolTipText( "Select the service and the operation to invoke from the known Petals services" ); // The data-binding ise.getDataBindingContext().bindValue( SWTObservables.observeText( opNameText ), EObjectUIHelper.createCustomEmfEditObservable( ise.getEditingDomain(), endpoint, Cdk5Package.Literals.CDK5_CONSUMES__OPERATION ), null, new UpdateValueStrategy().setConverter( new LocalQNameToStringConverter())); ise.getDataBindingContext().bindValue( SWTObservables.observeText( opNamespaceText ), EObjectUIHelper.createCustomEmfEditObservable( ise.getEditingDomain(), endpoint, Cdk5Package.Literals.CDK5_CONSUMES__OPERATION ), null, new UpdateValueStrategy().setConverter( new NamespaceQNameToStringConverter())); ise.getDataBindingContext().bindValue( ViewersObservables.observeSingleSelection( mepViewer ), EObjectUIHelper.createCustomEmfEditObservable( ise.getEditingDomain(), endpoint, Cdk5Package.Literals.CDK5_CONSUMES__MEP ), new UpdateValueStrategy().setConverter( new MepToStringConverter()), new UpdateValueStrategy().setConverter( new StringToMepConverter())); // The data-binding handles the "model to target (widget)" parts. But not ALL the "widget to model" parts. // For QNames, in fact, the data-binding cannot be applied in this sense. We have to use a modify listener for this. final ActivableListener activableListener = JBIEndpointUIHelpers.createModifyListenerForQname( ise.getEditingDomain(), endpoint, opNamespaceText, opNameText, Cdk5Package.Literals.CDK5_CONSUMES__OPERATION, true ); // Deal with the helper listener selectLink.addHyperlinkListener( new PetalsHyperlinkListener() { @Override public void linkActivated( HyperlinkEvent e ) { final EnhancedConsumeDialog dlg = new EnhancedConsumeDialog( parent.getShell(), toolkit ); if( dlg.open() == Window.OK ) { // Prepare the model update CompoundCommand compositeCommand = new CompoundCommand(); EditingDomain editDomain = ise.getEditingDomain(); QName q = dlg.getItfToInvoke(); Command command = new SetCommand(editDomain, endpoint, JbiPackage.Literals.ABSTRACT_ENDPOINT__INTERFACE_NAME, q); compositeCommand.append(command); q = dlg.getSrvToInvoke(); command = new SetCommand(editDomain, endpoint, JbiPackage.Literals.ABSTRACT_ENDPOINT__SERVICE_NAME, q); compositeCommand.append(command); String edpt = dlg.getEdptToInvoke(); command = new SetCommand(editDomain, endpoint, JbiPackage.Literals.ABSTRACT_ENDPOINT__ENDPOINT_NAME, edpt); compositeCommand.append(command); command = EObjectUIHelper.createCustomSetCommand( editDomain, endpoint, Cdk5Package.Literals.CDK5_CONSUMES__OPERATION, dlg.getOperationToInvoke()); compositeCommand.append(command); String mep = dlg.getInvocationMep() == Mep.UNKNOWN ? null : dlg.getInvocationMep().toString(); command = EObjectUIHelper.createCustomSetCommand( editDomain, endpoint, Cdk5Package.Literals.CDK5_CONSUMES__MEP, mep ); compositeCommand.append(command); // Identify the listeners to disable, so that all the fields are correctly set List<ActivableListener> theListeners = new ArrayList<ActivableListener> (); theListeners.add( activableListener ); for( Text t : new Text[] { commonUiBean.itfNameText, commonUiBean.srvNameText }) { for( Listener ml : t.getListeners( SWT.Modify )) { if( ml instanceof ActivableListener ) theListeners.add((ActivableListener) ml); } } // Perform the update carefully for( ActivableListener ml : theListeners ) ml.setEnabled( false ); editDomain.getCommandStack().execute(compositeCommand); for( ActivableListener ml : theListeners ) ml.setEnabled( true ); } } }); } /** * Creates the UI for "provide" blocks in the JBI editor (with CDK 5 fields). * @param endpoint * @param toolkit * @param generalDetails * @param ise */ public static void createProvidesUI( final AbstractEndpoint endpoint, final FormToolkit toolkit, final Composite parent, final ISharedEdition ise) { // First: the WSDL part Color blueFont = parent.getDisplay().getSystemColor( SWT.COLOR_DARK_BLUE ); // The label browser Label wsdlLabel = toolkit.createLabel( parent, "WSDL location:" ); wsdlLabel.setToolTipText( "The relative path of the WSDL in the service unit or an URL" ); wsdlLabel.setForeground( blueFont ); GridDataFactory.swtDefaults().align( SWT.LEFT, SWT.TOP ).indent( 0, 4 ).applyTo( wsdlLabel ); Composite subContainer = new Composite( parent, SWT.NONE ); GridLayoutFactory.swtDefaults().margins( 0, 0 ).numColumns( 2 ).extendedMargins( 0, 0, 0, 20 ).applyTo( subContainer ); subContainer.setLayoutData( new GridData( GridData.FILL_HORIZONTAL )); final Text wsdlText = toolkit.createText( subContainer, "", SWT.SINGLE | SWT.BORDER ); wsdlText.setLayoutData( new GridData( GridData.FILL_HORIZONTAL )); Button browseButton = toolkit.createButton( subContainer, "Browse...", SWT.PUSH ); browseButton.setToolTipText( "Select a WSDL located in the project resources" ); browseButton.addSelectionListener( new DefaultSelectionListener() { @Override public void widgetSelected( SelectionEvent e ) { IProject project = ise.getEditedFile().getProject(); IFolder resourceFolder = project.getFolder( PetalsConstants.LOC_RES_FOLDER ); // FIXME: replace this dialog by one that only shows WSDLs? ElementTreeSelectionDialog dlg = SwtFactory.createWorkspaceFileSelectionDialog( wsdlText.getShell(), resourceFolder, "WSDL Selection", "Select a WSDL file located in the project's resource directory.", "wsdl" ); File file = JbiXmlUtils.getWsdlFile( ise.getEditedFile(), wsdlText.getText()); if( file != null ) { IFile wsdlFile = ResourceUtils.getIFile( file ); if( wsdlFile != null ) dlg.setInitialElementSelections( Arrays.asList( wsdlFile )); } if( dlg.open() == Window.OK ) { IFile selectedFile = (IFile) dlg.getResult()[ 0 ]; int rfsc = resourceFolder.getFullPath().segmentCount(); String wsdlValue = selectedFile.getFullPath().removeFirstSegments( rfsc ).toString(); wsdlText.setText( wsdlValue ); } } }); // The helpers final WsdlParsingJobManager wsdlParsingJob = new WsdlParsingJobManager(); wsdlText.addModifyListener( new ModifyListener() { @Override public void modifyText( ModifyEvent e ) { String wsdlValue = ((Text) e.widget).getText().trim(); File f = JbiXmlUtils.getWsdlFile( ise.getEditedFile(), wsdlValue ); final URI wsdlUri; if( f != null ) wsdlUri = f.toURI(); else if( ! StringUtils.isEmpty( wsdlValue )) wsdlUri = UriAndUrlHelper.urlToUri( wsdlValue ); else wsdlUri = null; wsdlParsingJob.setWsdlUri( wsdlUri ); } }); Link link = new Link( subContainer, SWT.NONE ); link.setText("<A>" + Messages.wsdlTools + "</A>"); final AtomicBoolean tooltipVisible = new AtomicBoolean( false ); final WSDLHelperTooltip tooltip = new WSDLHelperTooltip( link, toolkit, (Provides) endpoint, ise, wsdlParsingJob ); link.addSelectionListener( new DefaultSelectionListener() { @Override public void widgetSelected( SelectionEvent e ) { boolean visible = tooltipVisible.get(); if( visible ) tooltip.hide(); else tooltip.show(); tooltipVisible.set( ! visible ); } }); link.addMouseTrackListener( new MouseTrackAdapter() { @Override public void mouseEnter( MouseEvent e ) { tooltip.show(); } @Override public void mouseExit( MouseEvent e ) { if( ! tooltipVisible.get()) tooltip.hide(); } }); // The data-binding ise.getDataBindingContext().bindValue( SWTObservables.observeDelayedValue(200, SWTObservables.observeText( wsdlText, SWT.Modify )), EObjectUIHelper.createCustomEmfEditObservable( ise.getEditingDomain(), endpoint, Cdk5Package.Literals.CDK5_PROVIDES__WSDL )); // Then, the common widgets final CommonUIBean commonBean = JBIEndpointUIHelpers.createCommonEndpointUI( endpoint, toolkit, parent, ise ); // Then, add the auto-generation button toolkit.createLabel( parent, "" ); // Add the button and its label final Button generateEdptButton = toolkit.createButton( parent, "", SWT.CHECK ); generateEdptButton.setText( "Generate the end-point at deployment time" ); generateEdptButton.setToolTipText( "The end-point name will be generated by Petals on deployment" ); generateEdptButton.addSelectionListener( new DefaultSelectionListener() { private String oldValue; @Override public void widgetSelected( SelectionEvent e ) { boolean selected = generateEdptButton.getSelection(); commonBean.edptText.setEnabled( ! selected ); commonBean.edptLabel.setEnabled( ! selected ); if( selected ) this.oldValue = commonBean.edptText.getText().trim(); else if( StringUtils.isEmpty( this.oldValue )) this.oldValue = commonBean.srvNameText.getText() + "Endpoint"; String edptValue = selected ? PetalsConstants.AUTO_GENERATE : this.oldValue; Command cmd = SetCommand.create( ise.getEditingDomain(), endpoint, JbiPackage.Literals.ABSTRACT_ENDPOINT__ENDPOINT_NAME, edptValue ); ise.getEditingDomain().getCommandStack().execute( cmd ); } }); } /** * Generates the default contributions for the CDK section. * @param ae the abstract end-point * @param toolkit the form toolkit * @param parent the parent * @param domain the editing domain * @param dbc the data-binding context */ public static void generateDefaultCdkWidgetsForProvidesEditor( AbstractEndpoint ae, FormToolkit toolkit, Composite parent, ISharedEdition ise ) { EObjectUIHelper.generateEditorWidgets( ae, toolkit, parent, ise.getEditingDomain(), ise.getDataBindingContext(), true, Cdk5Package.Literals.CDK5_PROVIDES__TIMEOUT, Cdk5Package.Literals.CDK5_PROVIDES__VALIDATE_WSDL, Cdk5Package.Literals.CDK5_PROVIDES__FORWARD_SECURITY_SUBJECT, Cdk5Package.Literals.CDK5_PROVIDES__FORWARD_MESSAGE_PROPERTIES, Cdk5Package.Literals.CDK5_PROVIDES__FORWARD_ATTACHMENTS ); } /** * Generates the default contributions for the CDK section. * @param ae the abstract end-point * @param toolkit the form toolkit * @param parent the parent * @param domain the editing domain * @param dbc the data-binding context */ public static void generateDefaultCdkWidgetsForConsumesEditor( AbstractEndpoint ae, FormToolkit toolkit, Composite parent, ISharedEdition ise ) { EObjectUIHelper.generateEditorWidgets( ae, toolkit, parent, ise.getEditingDomain(), ise.getDataBindingContext(), true, Cdk5Package.Literals.CDK5_CONSUMES__TIMEOUT ); } }