/******************************************************************************
* 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.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.xml.namespace.QName;
import org.eclipse.bpel.common.wsdl.importhelpers.WsdlImportHelper;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.ui.ide.IDE;
import com.ebmwebsourcing.petals.common.internal.provisional.formeditor.ISharedEdition;
import com.ebmwebsourcing.petals.common.internal.provisional.ui.StyledElementListSelectionDialog;
import com.ebmwebsourcing.petals.common.internal.provisional.utils.IoUtils;
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.WsdlUtils;
import com.ebmwebsourcing.petals.common.internal.provisional.utils.WsdlUtils.JbiBasicBean;
import com.ebmwebsourcing.petals.services.cdk.CdkPlugin;
import com.ebmwebsourcing.petals.services.cdk.Messages;
import com.ebmwebsourcing.petals.services.cdk.cdk5.Cdk5Package;
import com.ebmwebsourcing.petals.services.su.editor.su.EMFPCStyledLabelProvider;
import com.ebmwebsourcing.petals.services.su.ui.WsdlParsingJobManager;
import com.sun.java.xml.ns.jbi.JbiPackage;
import com.sun.java.xml.ns.jbi.Provides;
/**
* @author Mickael Istria - EBM WebSourcing
*/
public class WSDLHelperTooltip {
private final AtomicBoolean shown = new AtomicBoolean( false );
private final WsdlParsingJobManager wsdlParsingJob;
private final Shell shell;
private final Control controlToFollow;
private Hyperlink updateLink, importLink, selectServiceLink, openLink;
private final FormToolkit toolkit;
private final Provides service;
private final ISharedEdition ise;
/**
* Constructor.
* @param control
* @param tk
* @param service
* @param ise
* @param wsdlParsingJob
*/
public WSDLHelperTooltip( Control control, FormToolkit tk, Provides service, ISharedEdition ise, WsdlParsingJobManager wsdlParsingJob ) {
this.shell = new Shell( control.getShell(), SWT.TOOL );
this.toolkit = tk;
this.ise = ise;
this.service = service;
this.wsdlParsingJob = wsdlParsingJob;
this.controlToFollow = control;
populateTooltip();
this.shell.pack();
}
/**
* Shows the tool tip (with a small delay).
*/
public void show() {
if( this.shown.get())
return;
this.shown.set( true );
Point point = this.controlToFollow.toDisplay( 10, 10 );
this.shell.setLocation( point );
this.shell.getDisplay().asyncExec( new Runnable() {
@Override
public void run() {
try {
Thread.sleep( 1000 );
} catch( InterruptedException e ) {
// nothing
}
updateEnablement();
if( WSDLHelperTooltip.this.shown.get())
WSDLHelperTooltip.this.shell.setVisible( true );
}
});
}
/**
* Hides the tool tip.
*/
public void hide() {
if( ! this.shown.get())
return;
this.shown.set( false );
this.shell.setVisible( false );
}
/**
* Populates the tool tip.
*/
private void populateTooltip() {
// Deal with the SHELL content
GridLayoutFactory.swtDefaults().applyTo( this.shell );
this.shell.setLayoutData( new GridData( GridData.FILL_BOTH ));
this.shell.setBackground( this.shell.getDisplay().getSystemColor( SWT.COLOR_WHITE ));
Form res = this.toolkit.createForm( this.shell );
res.setText(Messages.wsdlTools);
res.getBody().setLayout( new GridLayout());
// Helper: import the WSDL in the project
this.importLink = this.toolkit.createHyperlink(res.getBody(), "Import this WSDL in the project", SWT.NONE );
final IFolder resFolder = WSDLHelperTooltip.this.ise.getEditedFile().getProject().getFolder( PetalsConstants.LOC_RES_FOLDER );
this.importLink.addHyperlinkListener( new HyperlinkAdapter() {
@Override
public void linkActivated( HyperlinkEvent e ) {
hide();
try {
URI wsdlUri = WSDLHelperTooltip.this.wsdlParsingJob.getWsdlUri();
Map<String,File> map = new WsdlImportHelper().importWsdlOrXsdAndDependencies( resFolder.getLocation().toFile(), wsdlUri.toString());
File importedFile = map.get( wsdlUri.toString());
String value = IoUtils.getRelativeLocationToFile( resFolder.getLocation().toFile(), importedFile );
SetCommand cmd = new SetCommand(
WSDLHelperTooltip.this.ise.getEditingDomain(),
WSDLHelperTooltip.this.service,
Cdk5Package.Literals.CDK5_PROVIDES__WSDL,
value );
WSDLHelperTooltip.this.ise.getEditingDomain().getCommandStack().execute( cmd );
} catch( Exception e1 ) {
CdkPlugin.log( e1, IStatus.ERROR );
}
}
});
// Helper: select a service in the WSDL
this.selectServiceLink = this.toolkit.createHyperlink( res.getBody(), "Select a service in the WSDL to fill-in the properties below", SWT.NONE );
this.selectServiceLink.addHyperlinkListener( new HyperlinkAdapter() {
@Override
public void linkActivated( HyperlinkEvent e ) {
hide();
EMFPCStyledLabelProvider lp = new EMFPCStyledLabelProvider(WSDLHelperTooltip.this.shell);
StyledElementListSelectionDialog dlg = new StyledElementListSelectionDialog(WSDLHelperTooltip.this.shell, lp );
dlg.setFilter( "*" );
dlg.setSize( 120, 20 );
dlg.setMultipleSelection( false );
dlg.setTitle( "Service Selection" );
dlg.setMessage( "Select the service to expose inside Petals." );
dlg.setElements( WSDLHelperTooltip.this.wsdlParsingJob.getBeans().toArray());
if( dlg.open() == Window.OK ) {
CompoundCommand cc = new CompoundCommand();
JbiBasicBean bean = (JbiBasicBean) dlg.getResult()[ 0 ];
cc.append( new SetCommand(
WSDLHelperTooltip.this.ise.getEditingDomain(),
WSDLHelperTooltip.this.service,
JbiPackage.Literals.ABSTRACT_ENDPOINT__SERVICE_NAME,
bean.getServiceName()));
cc.append( new SetCommand(
WSDLHelperTooltip.this.ise.getEditingDomain(), WSDLHelperTooltip.this.service,
JbiPackage.Literals.ABSTRACT_ENDPOINT__INTERFACE_NAME,
bean.getInterfaceName()));
cc.append( new SetCommand(
WSDLHelperTooltip.this.ise.getEditingDomain(), WSDLHelperTooltip.this.service,
JbiPackage.Literals.ABSTRACT_ENDPOINT__ENDPOINT_NAME,
bean.getEndpointName()));
WSDLHelperTooltip.this.ise.getEditingDomain().getCommandStack().execute( cc );
}
lp.dispose();
}
});
// Helper: open in the WSDL editor
this.openLink = this.toolkit.createHyperlink( res.getBody(), "Open in the WSDL editor", SWT.NONE );
this.openLink.setToolTipText( "Open this WSDL in the default WSDL editor" );
this.openLink.addHyperlinkListener( new HyperlinkAdapter() {
@Override
public void linkActivated( HyperlinkEvent e ) {
hide();
URI wsdlUri = WSDLHelperTooltip.this.wsdlParsingJob.getWsdlUri();
File wsdlFile = IoUtils.convertToFile( wsdlUri );
IFile f = ResourceUtils.getIFile( wsdlFile );
if( f == null )
return;
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
try {
IDE.openEditor( page, f, true );
} catch( PartInitException exception ) {
CdkPlugin.log( exception, IStatus.ERROR );
}
}
});
// Helper: update the end-point name in the WSDL
this.updateLink = this.toolkit.createHyperlink(res.getBody(), "Update the service end-point in the WSDL", SWT.NONE );
this.updateLink.setToolTipText( "Update the WSDL so that it declared end-point for this service is the one defined below" );
this.updateLink.addHyperlinkListener( new HyperlinkAdapter() {
@Override
public void linkActivated( HyperlinkEvent e ) {
hide();
QName serviceName = WSDLHelperTooltip.this.service.getServiceName();
String edptName = WSDLHelperTooltip.this.service.getEndpointName();
URI wsdlUri = WSDLHelperTooltip.this.wsdlParsingJob.getWsdlUri();
// Perform an update if, and only if, there is no ambiguity in the WSDL.
// It is too complicated (and there are too many error cases) to keep the old end-point name value.
// So, the user may have to modify the WSDL by hand in some situations.
try {
List<JbiBasicBean> beans = WsdlUtils.INSTANCE.parse( wsdlUri );
int candidates = 0;
for( JbiBasicBean bean : beans ) {
if( serviceName.equals( bean.getServiceName()))
candidates ++;
}
if( candidates > 1 ) {
MessageDialog.openInformation(
WSDLHelperTooltip.this.shell, "Ambiguous Situation",
"The right WSDL port to update could not be determined. Please, update the WSDL manually." );
} else {
File wsdlFile = IoUtils.convertToFile( wsdlUri );
if( ! WsdlUtils.INSTANCE.updateEndpointNameInWsdl( wsdlFile, serviceName, null, edptName )) {
MessageDialog.openError( WSDLHelperTooltip.this.shell, "End-point Update Failure", "The end-point could not be updated in the WSDL." );
} else {
// Force the validation of the file
WSDLHelperTooltip.this.ise.getEditedFile().touch( null );
}
}
} catch( InvocationTargetException e1 ) {
MessageDialog.openError(
WSDLHelperTooltip.this.shell, "Invalid WSDL",
"The WSDL file could not be parsed. Make sure the URL and the file are both valid." );
} catch( CoreException e1 ) {
CdkPlugin.log( e1, IStatus.WARNING );
}
}
});
res.getBody().addListener( SWT.MouseDown, new Listener() {
@Override
public void handleEvent( Event e ) {
hide();
}
});
}
/**
* Updates the enablement state of the links.
*/
private void updateEnablement() {
// Get values
final List<JbiBasicBean> jbiBeans = this.wsdlParsingJob.getBeans();
final URI wsdlUri = this.wsdlParsingJob.getWsdlUri();
final File wsdlFile = IoUtils.convertToFile( wsdlUri );
final IFolder resFolder = WSDLHelperTooltip.this.ise.getEditedFile().getProject().getFolder( PetalsConstants.LOC_RES_FOLDER );
boolean enabled = wsdlFile == null && wsdlUri != null
|| wsdlFile != null && ! resFolder.getLocation().isPrefixOf( new Path( wsdlFile.getAbsolutePath()));
this.importLink.setEnabled( enabled );
this.openLink.setEnabled( wsdlFile != null && wsdlFile.exists());
this.updateLink.setEnabled( wsdlFile != null && wsdlFile.exists());
this.selectServiceLink.setEnabled( ! jbiBeans.isEmpty());
}
}