blob: fba3b7ef673d7c877a0db2231af83466f88c05a9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 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.dialogs;
import java.text.MessageFormat;
import org.eclipse.bpel.model.resource.BPELResourceSetImpl;
import org.eclipse.bpel.model.util.BPELUtils;
import org.eclipse.bpel.ui.BPELUIPlugin;
import org.eclipse.bpel.ui.IBPELUIConstants;
import org.eclipse.bpel.ui.Messages;
import org.eclipse.bpel.ui.details.providers.ModelLabelProvider;
import org.eclipse.bpel.ui.details.providers.ModelTreeLabelProvider;
import org.eclipse.bpel.ui.details.providers.PartnerLinkTypeTreeContentProvider;
import org.eclipse.bpel.ui.details.providers.VariableTypeTreeContentProvider;
import org.eclipse.bpel.ui.details.providers.WSILContentProvider;
import org.eclipse.bpel.ui.util.filedialog.FileSelectionGroup;
import org.eclipse.bpel.wsil.model.inspection.Description;
import org.eclipse.bpel.wsil.model.inspection.Inspection;
import org.eclipse.bpel.wsil.model.inspection.Link;
import org.eclipse.bpel.wsil.model.inspection.Name;
import org.eclipse.bpel.wsil.model.inspection.Service;
import org.eclipse.bpel.wsil.model.inspection.TypeOfAbstract;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.dialogs.SelectionStatusDialog;
import org.eclipse.ui.part.DrillDownComposite;
/**
* Browse for complex/simple types available in the process and choose
* that simple type.
*
*/
public class SchemaImportDialog extends SelectionStatusDialog {
/** Browse local resource */
protected final static int BID_BROWSE_RESOURCE = IDialogConstants.CLIENT_ID + 1;
/* Button id for browsing URLs */
protected final static int BID_BROWSE_URL = IDialogConstants.CLIENT_ID + 2;
/* Button id for browse files */
protected final static int BID_BROWSE_FILE = IDialogConstants.CLIENT_ID + 3;
/* Browse button */
protected static final int BID_BROWSE = IDialogConstants.CLIENT_ID + 4;
/* button id for browsing WSIL */
protected static final int BID_BROWSE_WSIL = IDialogConstants.CLIENT_ID + 5;
/* The import source setting, remembered in the dialog settings */
private static final String IMPORT_KIND = "ImportKind"; //$NON-NLS-1$
private static final String EMPTY = ""; //$NON-NLS-1$
private String[] FILTER_EXTENSIONS = { IBPELUIConstants.EXTENSION_STAR_DOT_XSD,
IBPELUIConstants.EXTENSION_STAR_DOT_WSDL,
IBPELUIConstants.EXTENSION_STAR_DOT_ANY};
private String[] FILTER_NAMES = { IBPELUIConstants.EXTENSION_XSD_NAME,
IBPELUIConstants.EXTENSION_WSDL_NAME,
IBPELUIConstants.EXTENSION_ANY_NAME };
protected EObject modelObject;
protected Tree fTree;
protected TreeViewer fTreeViewer;
Text fLocation;
private Composite fLocationComposite;
FileSelectionGroup fResourceComposite;
// Import from WSIL constructs
private Composite fWSILComposite;
protected TreeViewer fWSILTreeViewer;
protected Tree fWSILTree;
protected Text filterText;
String fFilter = ""; //$NON-NLS-1$
private Button fBrowseButton;
private Group fGroup;
private IDialogSettings fSettings ;
private int KIND = BID_BROWSE_RESOURCE ;
private String fStructureTitle;
private ITreeContentProvider fTreeContentProvider;
protected Object fInput;
protected BPELResourceSetImpl fHackedResourceSet;
protected String fResourceKind = IBPELUIConstants.EXTENSION_XSD;
long fRunnableStart;
URI fRunnableLoadURI;
Job fLoaderJob;
IPreferenceStore fPrefStore = BPELUIPlugin.getPlugin().getPreferenceStore();
String fBasePath = fPrefStore.getString(IBPELUIConstants.PREF_WSIL_URL);
// The WSIL radio box is turned off if the WSIL document is not set in the preferences.
Button fBtnWSIL;
/**
* Create a brand new shiny Schema Import Dialog.
*
* @param parent
*/
public SchemaImportDialog (Shell parent) {
super(parent);
setStatusLineAboveButtons(true);
int shellStyle = getShellStyle();
setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE);
fSettings = BPELUIPlugin.getPlugin().getDialogSettingsFor( this );
try {
KIND = fSettings.getInt(IMPORT_KIND);
} catch (java.lang.NumberFormatException nfe) {
KIND = BID_BROWSE_RESOURCE;
}
setDialogBoundsSettings ( fSettings, getDialogBoundsStrategy() );
configureAsSchemaImport();
}
/**
* Create a brand new shiny Schema Import Dialog
*
* @param parent shell to use
* @param eObject the model object to use as reference
*/
public SchemaImportDialog (Shell parent, EObject eObject) {
this(parent);
this.modelObject = eObject;
setTitle(Messages.SchemaImportDialog_2);
fHackedResourceSet = BPELUtils.slightlyHackedResourceSet(eObject);
}
/**
*
* @see Dialog#createDialogArea(Composite)
*
* @param parent the parent composite to use
* @return the composite it created to be used in the dialog area.
*/
@Override
public Control createDialogArea(Composite parent) {
Composite contents = (Composite) super.createDialogArea(parent);
createImportLocation (contents);
createImportStructure (contents);
buttonPressed(KIND,true);
return contents;
}
@Override
protected void buttonPressed (int buttonId) {
switch (buttonId) {
case BID_BROWSE :
FileDialog fileDialog = new FileDialog(getShell());
fileDialog.setFilterExtensions( FILTER_EXTENSIONS );
fileDialog.setFilterNames( FILTER_NAMES );
String path = fileDialog.open();
if (path == null) {
return;
}
fLocation.setText( path );
attemptLoad ( path );
break;
case IDialogConstants.CANCEL_ID :
if (fLoaderJob != null) {
if (fLoaderJob.getState() == Job.RUNNING) {
fLoaderJob.cancel();
}
}
break;
}
super.buttonPressed(buttonId);
}
protected void buttonPressed (int id, boolean checked) {
if (id == BID_BROWSE_FILE || id == BID_BROWSE_RESOURCE || id == BID_BROWSE_URL || id == BID_BROWSE_WSIL) {
if (checked == false) {
return ;
}
setVisibleControl (fResourceComposite, id == BID_BROWSE_RESOURCE );
setVisibleControl (fLocationComposite ,
id == BID_BROWSE_URL || id == BID_BROWSE_FILE);
setVisibleControl(fWSILComposite, id == BID_BROWSE_WSIL);
fBrowseButton.setEnabled( (id == BID_BROWSE_FILE) || (id == BID_BROWSE_WSIL) );
fLocation.setText(EMPTY);
markEmptySelection();
KIND = id;
fSettings.put(IMPORT_KIND, KIND);
fGroup.getParent().layout(true);
}
}
protected void setVisibleControl (Control c, boolean b) {
Object layoutData = c.getLayoutData();
if (layoutData instanceof GridData) {
GridData data = (GridData) layoutData;
data.exclude = ! b;
}
c.setVisible(b);
}
/**
* Create the dialog.
*
*/
@Override
public void create() {
super.create();
buttonPressed(KIND, true);
}
protected Button createRadioButton (Composite parent, String label, int id, boolean checked) {
Button button = new Button(parent,SWT.RADIO);
button.setText(label);
button.setFont(JFaceResources.getDialogFont());
button.setData(new Integer(id));
button.setSelection( checked );
button.addSelectionListener (new SelectionAdapter() {
@Override
public void widgetSelected (SelectionEvent event) {
Button b = (Button) event.widget;
int bid = ((Integer) b.getData()).intValue();
buttonPressed(bid, b.getSelection());
}
});
return button;
}
protected void createImportLocation (Composite parent) {
fGroup = new Group(parent,SWT.SHADOW_ETCHED_IN);
fGroup.setText(Messages.SchemaImportDialog_4);
GridLayout layout = new GridLayout(1,true);
GridData data = new GridData();
data.grabExcessVerticalSpace = false;
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL;
fGroup.setLayout( layout );
fGroup.setLayoutData( data );
Composite container = new Composite(fGroup, SWT.NONE);
layout = new GridLayout();
layout.makeColumnsEqualWidth = true;
layout.numColumns = 4;
container.setLayout(layout);
data = new GridData();
data.grabExcessVerticalSpace = false;
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.CENTER;
container.setLayoutData(data);
createRadioButton(container,Messages.SchemaImportDialog_5, BID_BROWSE_RESOURCE,
KIND == BID_BROWSE_RESOURCE );
createRadioButton(container,Messages.SchemaImportDialog_6, BID_BROWSE_FILE,
KIND == BID_BROWSE_FILE );
createRadioButton(container,Messages.SchemaImportDialog_7, BID_BROWSE_URL,
KIND == BID_BROWSE_URL );
// Add WSIL option
fBtnWSIL = createRadioButton(container, Messages.SchemaImportDialog_15, BID_BROWSE_WSIL,
KIND == BID_BROWSE_WSIL);
// Create location variant
fLocationComposite = new Composite(fGroup, SWT.NONE);
layout = new GridLayout();
layout.numColumns = 3;
fLocationComposite.setLayout(layout);
data = new GridData();
data.grabExcessVerticalSpace = true;
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL;
fLocationComposite.setLayoutData(data);
Label location = new Label(fLocationComposite,SWT.NONE);
location.setText(Messages.SchemaImportDialog_8);
fLocation = new Text(fLocationComposite,SWT.BORDER);
fLocation.setText(EMPTY);
data = new GridData();
data.grabExcessVerticalSpace = false;
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL;
fLocation.setLayoutData(data);
fLocation.addListener(SWT.FocusOut, new Listener() {
public void handleEvent(Event event) {
String loc = fLocation.getText();
if (loc.length() > 0) {
attemptLoad( loc );
}
}
});
fLocation.addKeyListener( new KeyListener () {
public void keyPressed(KeyEvent event) {
if (event.keyCode == SWT.CR) {
attemptLoad(fLocation.getText());
event.doit = false;
}
}
public void keyReleased(KeyEvent e) {
return ;
}
});
fBrowseButton = createButton(fLocationComposite, BID_BROWSE, Messages.SchemaImportDialog_9, false);
// End of location variant
// Start Resource Variant
fResourceComposite = new FileSelectionGroup(fGroup,
new Listener() {
public void handleEvent(Event event) {
IResource resource = fResourceComposite.getSelectedResource();
if (resource != null && resource.getType() == IResource.FILE) {
// only attempt to load a resource which is not a container
attemptLoad ( (IFile) resource );
return ;
}
markEmptySelection();
}
},
Messages.SchemaImportDialog_10,
IBPELUIConstants.EXTENSION_DOT_XSD + "," + IBPELUIConstants.EXTENSION_DOT_WSDL ); //$NON-NLS-1$
TreeViewer viewer = fResourceComposite.getTreeViewer();
viewer.setAutoExpandLevel(2);
// End resource variant
// create WSIL UI widgets
createWSILStructure(fGroup);
}
protected Object createWSILStructure(Composite parent) {
fWSILComposite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginWidth = 0;
fWSILComposite.setLayout(layout);
GridData data = new GridData();
data.grabExcessVerticalSpace = true;
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL;
data.minimumHeight = 220;
fWSILComposite.setLayoutData(data);
Label location = new Label(fWSILComposite, SWT.NONE);
location.setText( Messages.SchemaImportDialog_16 );
data = new GridData();
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = SWT.LEFT;
location.setLayoutData(data);
filterText = new Text(fWSILComposite, SWT.BORDER);
data = new GridData(GridData.FILL_HORIZONTAL);
filterText.setLayoutData(data);
filterText.addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
// set the value of the filter.
fFilter = filterText.getText().trim().toLowerCase();
if (fFilter.length() > 0) {
/* for the time being, only filter 3 levels deep
* since link references within WSIL are rare at
* this time. when adoption of WSIL directories
* take off, this needs to be rehashed */
fWSILTreeViewer.expandToLevel(3);
}
fWSILTreeViewer.refresh();
e.doit = false;
}
});
DrillDownComposite wsilTreeComposite = new DrillDownComposite(fWSILComposite, SWT.BORDER);
layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 0;
layout.verticalSpacing = 0;
wsilTreeComposite.setLayout(layout);
data = new GridData();
data.grabExcessVerticalSpace = true;
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL;
wsilTreeComposite.setLayoutData(data);
// Tree viewer for variable structure ...
fWSILTree = new Tree(wsilTreeComposite, SWT.NONE );
data = new GridData();
data.grabExcessVerticalSpace = true;
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL;
data.minimumHeight = 200;
fWSILTree.setLayoutData(data);
fWSILTreeViewer = new TreeViewer( fWSILTree );
fWSILTreeViewer.setContentProvider( new WSILContentProvider() );
fWSILTreeViewer.setLabelProvider( new ModelLabelProvider() );
Object wsilDoc = attemptLoad(URI.createURI(fBasePath),IBPELUIConstants.EXTENSION_WSIL);
fWSILTreeViewer.setInput ( wsilDoc ) ;
if (wsilDoc == null || wsilDoc instanceof Throwable ) {
fBtnWSIL.setEnabled(false);
// that's always available.
KIND = BID_BROWSE_RESOURCE;
}
// set default tree expansion to the 2nd level
fWSILTreeViewer.expandToLevel(2);
fWSILTreeViewer.addFilter(new TreeFilter());
fWSILTreeViewer.setComparator(new WSILViewerComparator());
wsilTreeComposite.setChildTree(fWSILTreeViewer);
fWSILTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
// TODO Auto-generated method stub
IStructuredSelection sel = (IStructuredSelection)event.getSelection();
if (sel.getFirstElement() instanceof Service) {
Service serv = (Service)sel.getFirstElement();
Description descr = (Description)serv.getDescription().get(0);
attemptLoad(descr.getLocation() );
} else {
markEmptySelection();
}
}
});
// end tree viewer for variable structure
return fWSILComposite;
}
protected Object createImportStructure (Composite parent) {
Label location = new Label(parent,SWT.NONE);
location.setText( fStructureTitle );
// Tree viewer for variable structure ...
fTree = new Tree(parent, SWT.BORDER );
VariableTypeTreeContentProvider variableContentProvider = new VariableTypeTreeContentProvider(true, true);
fTreeViewer = new TreeViewer(fTree);
fTreeViewer.setContentProvider( fTreeContentProvider != null ? fTreeContentProvider : variableContentProvider );
fTreeViewer.setLabelProvider(new ModelTreeLabelProvider());
fTreeViewer.setInput ( null );
fTreeViewer.setAutoExpandLevel(3);
// end tree viewer for variable structure
GridData data = new GridData();
data.grabExcessVerticalSpace = true;
data.grabExcessHorizontalSpace = true;
data.horizontalAlignment = GridData.FILL;
data.verticalAlignment = GridData.FILL;
data.minimumHeight = 200;
fTree.setLayoutData(data);
return fTree;
}
Object attemptLoad ( URI uri, String kind) {
Resource resource = null;
try {
resource = fHackedResourceSet.getResource(uri, true, kind);
} catch (Throwable t) {
// BPELUIPlugin.log(t);
return t;
}
if (resource.getErrors().isEmpty() && resource.isLoaded() ) {
return resource.getContents().get(0);
}
return null;
}
Object attemptLoad ( URI uri ) {
return attemptLoad (uri, fResourceKind );
}
void attemptLoad ( IFile file ) {
attemptLoad ( file.getFullPath().toString() );
}
void attemptLoad ( String path ) {
if (fLoaderJob != null) {
if (fLoaderJob.getState() == Job.RUNNING) {
fLoaderJob.cancel();
}
}
updateStatus ( Status.OK_STATUS );
// empty paths are ignored
if (path.length() == 0) {
return ;
}
URI uri = convertToURI ( path );
if (uri == null) {
return ;
}
if (uri.isRelative()) {
// construct absolute path
String absolutepath = fBasePath.substring(0, fBasePath.lastIndexOf('/')+1) + path;
uri = URI.createURI(absolutepath);
}
fRunnableLoadURI = uri;
final String msg = MessageFormat.format(Messages.SchemaImportDialog_17,fRunnableLoadURI);
fLoaderJob = new Job(msg) {
@Override
protected IStatus run(IProgressMonitor monitor) {
monitor.beginTask(msg, 1);
fInput = attemptLoad(fRunnableLoadURI);
monitor.worked(1);
fTree.getDisplay().asyncExec(new Runnable() {
public void run() {
loadDone();
}
});
return Status.OK_STATUS;
}
};
fLoaderJob.schedule();
fRunnableStart = System.currentTimeMillis();
updateStatus ( new Status(IStatus.INFO, BPELUIPlugin.getPlugin().getID(),0,msg,null));
}
@SuppressWarnings("boxing")
void loadDone () {
if (fBrowseButton.isDisposed()) {
// we were closed before this is being called. Quit.
return ;
}
long elapsed = System.currentTimeMillis() - fRunnableStart;
if (fInput == null || fInput instanceof Throwable) {
markEmptySelection();
updateStatus( new Status(IStatus.ERROR,BPELUIPlugin.getPlugin().getID(),0,
MessageFormat.format(Messages.SchemaImportDialog_19,fRunnableLoadURI,elapsed),(Throwable) fInput) );
fInput = null;
} else {
updateStatus ( new Status(IStatus.INFO, BPELUIPlugin.getPlugin().getID(),0,
MessageFormat.format(Messages.SchemaImportDialog_18,fRunnableLoadURI,elapsed),null)) ;
fTreeViewer.setInput(fInput);
fTree.getVerticalBar().setSelection(0);
}
}
void markEmptySelection () {
updateStatus ( Status.OK_STATUS );
updateOK(false);
fTreeViewer.setInput(null);
}
private URI convertToURI (String path ) {
try {
switch (KIND) {
case BID_BROWSE_FILE :
return URI.createFileURI( path );
case BID_BROWSE_RESOURCE :
return URI.createPlatformResourceURI(path);
case BID_BROWSE_WSIL :
//return URI.createFileURI( path );
case BID_BROWSE_URL :
return URI.createURI(path);
default :
return null;
}
} catch (Exception ex) {
updateStatus ( new Status(IStatus.ERROR,BPELUIPlugin.getPlugin().getID(),0,Messages.SchemaImportDialog_13,ex) );
return null;
}
}
/**
* Update the state of the OK button to the state indicated.
*
* @param state false to disable, true to enable.
*/
public void updateOK ( boolean state ) {
Button okButton = getOkButton();
if (okButton != null && !okButton.isDisposed()) {
okButton.setEnabled(state);
}
}
/**
* @see org.eclipse.ui.dialogs.SelectionStatusDialog#computeResult()
*/
@Override
protected void computeResult() {
Object object = fTreeViewer.getInput();
if (object == null) {
return ;
}
setSelectionResult(new Object[]{ object });
}
/**
* Configure the dialog as a schema import dialog. Set the title and
* the structure pane message.
*
*/
public void configureAsSchemaImport ( ) {
setTitle(Messages.SchemaImportDialog_2);
fStructureTitle = Messages.SchemaImportDialog_11;
fResourceKind = IBPELUIConstants.EXTENSION_XSD;
}
/**
* Configure the dialog as a WSDL import dialog. Set the title and
* the structure pane message.
*
*/
public void configureAsWSDLImport ( ) {
setTitle(Messages.SchemaImportDialog_0);
fStructureTitle = Messages.SchemaImportDialog_14;
fTreeContentProvider = new PartnerLinkTypeTreeContentProvider(true);
fResourceKind = IBPELUIConstants.EXTENSION_WSDL;
}
/**
*
* @author Michal Chmielewski (michal.chmielewski@oracle.com)
* @date May 4, 2007
*
*/
public class TreeFilter extends ViewerFilter {
/** (non-Javadoc)
* @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
*/
@Override
public boolean select (Viewer viewer, Object parentElement, Object element) {
if (fFilter == null || fFilter.length() == 0) {
return true;
}
if (element instanceof Service) {
String text = ""; //$NON-NLS-1$
Service service = (Service)element;
if (service.getName().size() > 0) {
Name name = (Name)service.getName().get(0);
text += name.getValue();
}
if (service.getAbstract().size() > 0) {
TypeOfAbstract abst = (TypeOfAbstract)service.getAbstract().get(0);
text += abst.getValue();
}
return (text.toLowerCase().indexOf(fFilter) > -1);
}
return true;
}
}
/**
*
* @author Michal Chmielewski (michal.chmielewski@oracle.com)
* @date May 10, 2007
*
*/
public class WSILViewerComparator extends ViewerComparator {
/**
* @see org.eclipse.jface.viewers.ViewerComparator#category(java.lang.Object)
*/
@Override
public int category(Object element) {
if (element instanceof Inspection)
return 1;
if (element instanceof Link)
return 2;
if (element instanceof Service)
return 3;
return 0;
}
}
}