/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.metamodels.xsd.ui.editor; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.EventObject; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import java.util.Timer; import java.util.TimerTask; import org.apache.xerces.util.EncodingMap; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.emf.common.command.BasicCommandStack; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.common.command.CommandStack; import org.eclipse.emf.common.command.CommandStackListener; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.ui.ViewerPane; import org.eclipse.emf.common.ui.celleditor.ExtendedComboBoxCellEditor; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EDataType; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.xmi.XMIException; import org.eclipse.emf.ecore.xmi.XMLHelper; import org.eclipse.emf.ecore.xmi.XMLLoad; import org.eclipse.emf.ecore.xmi.XMLResource; import org.eclipse.emf.ecore.xmi.impl.SAXXMLHandler; import org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl; import org.eclipse.emf.ecore.xmi.impl.XMLLoadImpl; import org.eclipse.emf.ecore.xmi.impl.XMLMapImpl; import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl; import org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl; import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.emf.edit.domain.IEditingDomainProvider; import org.eclipse.emf.edit.provider.AdapterFactoryItemDelegator; import org.eclipse.emf.edit.provider.IDisposable; import org.eclipse.emf.edit.provider.IItemPropertyDescriptor; import org.eclipse.emf.edit.provider.IItemPropertySource; import org.eclipse.emf.edit.provider.ItemProvider; import org.eclipse.emf.edit.ui.action.CommandAction; import org.eclipse.emf.edit.ui.action.CreateChildAction; import org.eclipse.emf.edit.ui.action.CreateSiblingAction; import org.eclipse.emf.edit.ui.action.EditingDomainActionBarContributor; import org.eclipse.emf.edit.ui.celleditor.AdapterFactoryTreeEditor; import org.eclipse.emf.edit.ui.dnd.EditingDomainViewerDropAdapter; import org.eclipse.emf.edit.ui.dnd.LocalTransfer; import org.eclipse.emf.edit.ui.dnd.ViewerDragAdapter; import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider; import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry; import org.eclipse.emf.edit.ui.provider.PropertyDescriptor; import org.eclipse.emf.edit.ui.provider.PropertySource; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.IContributionManager; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IStatusLineManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.action.SubContributionItem; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentListener; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.IVerticalRuler; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Tree; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IPartListener; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.eclipse.ui.dialogs.SaveAsDialog; import org.eclipse.ui.editors.text.IEncodingSupport; import org.eclipse.ui.editors.text.TextEditor; import org.eclipse.ui.ide.IGotoMarker; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.part.MultiPageEditorPart; import org.eclipse.ui.part.MultiPageSelectionProvider; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.IElementStateListener; import org.eclipse.ui.views.contentoutline.ContentOutline; import org.eclipse.ui.views.contentoutline.ContentOutlinePage; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import org.eclipse.ui.views.properties.IPropertyDescriptor; import org.eclipse.ui.views.properties.IPropertySheetPage; import org.eclipse.ui.views.properties.IPropertySource; import org.eclipse.ui.views.properties.PropertySheet; import org.eclipse.ui.views.properties.PropertySheetPage; import org.eclipse.xsd.XSDAttributeDeclaration; import org.eclipse.xsd.XSDAttributeGroupDefinition; import org.eclipse.xsd.XSDAttributeUse; import org.eclipse.xsd.XSDComplexTypeDefinition; import org.eclipse.xsd.XSDConcreteComponent; import org.eclipse.xsd.XSDDiagnostic; import org.eclipse.xsd.XSDDiagnosticSeverity; import org.eclipse.xsd.XSDElementDeclaration; import org.eclipse.xsd.XSDModelGroup; import org.eclipse.xsd.XSDModelGroupDefinition; import org.eclipse.xsd.XSDParticle; import org.eclipse.xsd.XSDSchema; import org.eclipse.xsd.XSDSimpleTypeDefinition; import org.eclipse.xsd.XSDTerm; import org.eclipse.xsd.XSDTypeDefinition; import org.eclipse.xsd.ecore.XSDEcoreBuilder; import org.eclipse.xsd.provider.XSDItemProviderAdapterFactory; import org.eclipse.xsd.provider.XSDSemanticItemProviderAdapterFactory; import org.eclipse.xsd.util.XSDConstants; import org.eclipse.xsd.util.XSDParser; import org.eclipse.xsd.util.XSDResourceImpl; import org.eclipse.xsd.util.XSDSwitch; import org.teiid.core.designer.util.StringConstants; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.workspace.ModelWorkspaceException; import org.teiid.designer.metamodels.xsd.XsdResourceFactory; import org.teiid.designer.metamodels.xsd.ui.XsdUiPlugin; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.helpers.DefaultHandler; /** * This is a an example of a xsd model editor. * * @since 8.0 */ public class XsdEditor extends MultiPageEditorPart implements IEditingDomainProvider, ISelectionProvider, IMenuListener, IGotoMarker { /** * ResourceSet to be used when constructing the editor. */ protected static ResourceSet resourceSet; /** * This keeps track of the root object of the model. */ protected XSDSchema xsdSchema; /** * This keeps track of the editing domain that is used to track all changes to the model. */ protected AdapterFactoryEditingDomain editingDomain; /** * This is the adapter factory used for providing the syntactive views of the model. */ protected XSDItemProviderAdapterFactory syntacticAdapterFactory; /** * This is the adapter factory used for providing the semantic views of the model. */ protected XSDItemProviderAdapterFactory semanticAdapterFactory; /** * This is the content outline page. */ protected IContentOutlinePage contentOutlinePage; /** * This is a kludge... */ protected IStatusLineManager contentOutlineStatusLineManager; /** * This is the content outline page's viewer. */ protected TreeViewer contentOutlineViewer; /** * This is the property sheet page. */ protected PropertySheetPage propertySheetPage; /** * This source part of the editor. */ protected TextEditor textEditor; protected ISourceViewer sourceViewer; /** * This is the syntactic viewer that shadows the selection in the content outline. The parent relation must be correctly * defined for this to work. */ protected TreeViewer syntacticSelectionViewer; /** * This is the semantic viewer that shadows the selection in the content outline. */ protected TreeViewer semanticSelectionViewer; /** * This keeps track of the active viewer pane, in the book. */ protected ViewerPane currentViewerPane; /** * This keeps track of the active content viewer, which may be either one of the viewers in the pages or the content outline * viewer. */ protected Viewer currentViewer; /** * This listens to which ever viewer is active. */ protected ISelectionChangedListener selectionChangedListener; /** * This keeps track of all the {@link org.eclipse.jface.viewers.ISelectionChangedListener}s that are listening to this editor. */ protected Collection selectionChangedListeners = new ArrayList(); /** * This keeps track of the selection of the editor as a whole. */ protected ISelection editorSelection; /** * This is the outline action to select the next unresolved component. */ protected SelectDiagnosticAction selectNextDiagnosticsAction; /** * This is the outline action to select the previous unresolved component. */ protected SelectDiagnosticAction selectPreviousDiagnosticsAction; /** * This is the outline action to select the next use of a component. */ protected SelectUseAction selectNextUseAction; /** * This is the outline action to select the previous use of a component. */ protected SelectUseAction selectPreviousUseAction; /** * This is the model resource for the current xsd file being displayed in the editor */ private Resource xsdResource; /** * This listens for when things becomes active. */ protected IPartListener partListener = new IPartListener() { @Override public void partActivated( IWorkbenchPart p ) { handlePartActivated(p); } @Override public void partBroughtToTop( IWorkbenchPart p ) { } @Override public void partClosed( IWorkbenchPart p ) { } @Override public void partDeactivated( IWorkbenchPart p ) { } @Override public void partOpened( IWorkbenchPart p ) { } }; /** * This creates a model editor. */ public XsdEditor() { super(); // Create an adapter factory that yields item providers. // syntacticAdapterFactory = new XSDItemProviderAdapterFactory(); semanticAdapterFactory = new XSDSemanticItemProviderAdapterFactory(); // Create the command stack that will notify this editor as commands are executed. // BasicCommandStack commandStack = new BasicCommandStack(); // Add a listener to set the most recent command's affected objects to be the selection of the viewer with focus. // commandStack.addCommandStackListener(new CommandStackListener() { @Override public void commandStackChanged( final EventObject event ) { getParentComposite().getDisplay().asyncExec(new Runnable() { @Override public void run() { firePropertyChange(IEditorPart.PROP_DIRTY); // Try to select the affected objects. // Command mostRecentCommand = ((CommandStack)event.getSource()).getMostRecentCommand(); if (mostRecentCommand != null) { setSelectionToViewer(mostRecentCommand.getAffectedObjects()); } handleStructuredModelChange(); updateActions(); if (propertySheetPage != null) { propertySheetPage.refresh(); } } }); } }); if (resourceSet != null) { editingDomain = new AdapterFactoryEditingDomain(syntacticAdapterFactory, commandStack, resourceSet); } else { editingDomain = new AdapterFactoryEditingDomain(syntacticAdapterFactory, commandStack); } // Register our xsd resource factory for this context. // Map map = editingDomain.getResourceSet().getResourceFactoryRegistry().getExtensionToFactoryMap(); if (!map.containsKey(StringConstants.XSD)) { map.put(StringConstants.XSD, new XsdResourceFactory()); } } Composite getParentComposite() { return getContainer(); } protected void updateActions() { if (selectNextDiagnosticsAction != null) { selectNextDiagnosticsAction.updateAction(); selectPreviousDiagnosticsAction.updateAction(); selectNextUseAction.updateAction(); selectPreviousUseAction.updateAction(); } } protected String determineEncoding() { String encoding = (String)((XSDResourceImpl)getXsdSchema().eResource()).getDefaultSaveOptions().get(XSDResourceImpl.XSD_ENCODING); if (encoding != null && EncodingMap.getIANA2JavaMapping(encoding) != null) { encoding = EncodingMap.getIANA2JavaMapping(encoding); } return encoding; } protected boolean handledStructuredModelChange = false; protected void handleStructuredModelChange() { IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput()); if (getXsdSchema().getElement() == null) { getXsdSchema().updateElement(); } ByteArrayOutputStream out = new ByteArrayOutputStream(); try { getXsdSchema().eResource().save(out, null); String encoding = determineEncoding(); String newContent = encoding == null ? out.toString() : out.toString(encoding); String oldContent = document.get(); int startIndex = 0; while (startIndex < newContent.length() && startIndex < oldContent.length() && newContent.charAt(startIndex) == oldContent.charAt(startIndex)) { ++startIndex; } int newEndIndex = newContent.length() - 1; int oldEndIndex = oldContent.length() - 1; while (newEndIndex >= startIndex && oldEndIndex >= startIndex && newContent.charAt(newEndIndex) == oldContent.charAt(oldEndIndex)) { --newEndIndex; --oldEndIndex; } String replacement = newContent.substring(startIndex, newEndIndex + 1); int length = oldEndIndex - startIndex + 1; handledStructuredModelChange = true; document.replace(startIndex, length, replacement); getXsdSchema().eResource().setModified(true); } catch (Exception exception) { XsdUiPlugin.Util.log(exception); } } /** * This handles part activation. */ protected void handlePartActivated( IWorkbenchPart workbenchPart ) { if (workbenchPart == this) { if (getActivePage() == 0) { setCurrentViewer((Viewer)sourceViewer); } } else if (workbenchPart instanceof ContentOutline) { if (((ContentOutline)workbenchPart).getCurrentPage() == contentOutlinePage) { getEditorSite().getActionBarContributor().setActiveEditor(XsdEditor.this); setCurrentViewer(contentOutlineViewer); } } else if (workbenchPart instanceof PropertySheet) { if (((PropertySheet)workbenchPart).getCurrentPage() == propertySheetPage) { getActionBarContributor().setActiveEditor(XsdEditor.this); } } } /** * This is here for the listener to be able to call it. */ @Override protected void firePropertyChange( int action ) { super.firePropertyChange(action); } /** * This sets the selection into whichever viewer is active. */ public void setSelectionToViewer( final Collection collection ) { // Make sure it's okay. // if (collection != null && !collection.isEmpty()) { // I don't know if this should be run this deferred // because we might have to give the editor a chance to process the viewer update events // and hence to update the views first. // // Runnable runnable = new Runnable() { @Override public void run() { // Try to select the items in the current content viewer of the editor. // if (currentViewer != null) { currentViewer.setSelection(new StructuredSelection(collection.toArray()), true); } } }; runnable.run(); } } /** * This returns the editing domain as required by the {@link IEditingDomainProvider} interface. This is important for * implementing the static methods of {@link AdapterFactoryEditingDomain} and for supporting {@link CommandAction}. */ @Override public EditingDomain getEditingDomain() { return editingDomain; } public void setCurrentViewerPane( ViewerPane viewerPane ) { if (currentViewerPane != viewerPane) { if (currentViewerPane != null) { currentViewerPane.showFocus(false); } currentViewerPane = viewerPane; } if (currentViewerPane != null) { setCurrentViewer(currentViewerPane.getViewer()); } } /** * This makes sure that one content viewer, either for the current page or the outline view, if it has focus, is the current * one. */ public void setCurrentViewer( Viewer viewer ) { // If it is changing... // if (currentViewer != viewer) { if (selectionChangedListener == null) { // Create the listener on demand. // selectionChangedListener = new ISelectionChangedListener() { // This just notifies those things that are affected by the section. // @Override public void selectionChanged( SelectionChangedEvent selectionChangedEvent ) { setSelection(selectionChangedEvent.getSelection()); } }; } // Stop listening to the old one. // if (currentViewer != null) { currentViewer.removeSelectionChangedListener(selectionChangedListener); } // Start listening to the new one. // if (viewer != null) { viewer.addSelectionChangedListener(selectionChangedListener); } // Remember it. // currentViewer = viewer; // Set the editors selection based on the current viewer's selection. // setSelection(currentViewer == null ? StructuredSelection.EMPTY : currentViewer.getSelection()); } } /** * This is the contributor for the XSD model editor. */ static public class ActionBarContributor extends EditingDomainActionBarContributor implements ISelectionChangedListener { protected IEditorPart activeEditorPart; protected ISelectionProvider selectionProvider; /** * This will contain one CreateChildAction corresponding to each descriptor generated for the current selection. */ protected Collection createChildActions = Collections.EMPTY_LIST; /** * This is the menu manager into which menu contribution items should be added for the child creation actions. */ protected IMenuManager createChildMenuManager; /** * This will contain one CreateSiblingAction corresponding to each descriptor generated for the current selection's * parent. */ protected Collection createSiblingActions = Collections.EMPTY_LIST; /** * This is the menu manager into which menu contribution items should be added for sibling creation actions. */ protected IMenuManager createSiblingMenuManager; /** * This creates an instance of the contributor. */ public ActionBarContributor() { } /** * This adds to the menu bar a menu for editor actions, duplicating the menu contribution made in the plugin.xml, so that * the new menu is accessible for modification in code. Also, sub-menus are created for the addition and removal of child * and sibling creation items. */ @Override public void contributeToMenu( IMenuManager menuManager ) { super.contributeToMenu(menuManager); // duplicate the menu contribution in the plugin.xml IMenuManager submenuManager = new MenuManager( XsdUiPlugin.Util.getString("_UI_XSDEditor_menu"), "org.eclipse.xsdMenuID"); //$NON-NLS-1$ //$NON-NLS-2$ menuManager.insertAfter(XsdUiPlugin.Util.getString("XsdEditor.additions_4"), submenuManager); //$NON-NLS-1$ submenuManager.add(new Separator(XsdUiPlugin.Util.getString("XsdEditor.settings_5"))); //$NON-NLS-1$ submenuManager.add(new Separator(XsdUiPlugin.Util.getString("XsdEditor.additions_6"))); //$NON-NLS-1$ // prepare for child and sibling creation item addition/removal createChildMenuManager = new MenuManager(XsdUiPlugin.Util.getString("_UI_CreateChild_menu_item")); //$NON-NLS-1$ createSiblingMenuManager = new MenuManager(XsdUiPlugin.Util.getString("_UI_CreateSibling_menu_item")); //$NON-NLS-1$ submenuManager.insertBefore(XsdUiPlugin.Util.getString("XsdEditor.additions_9"), new Separator(XsdUiPlugin.Util.getString("XsdEditor.actions_10"))); //$NON-NLS-1$ //$NON-NLS-2$ submenuManager.insertBefore(XsdUiPlugin.Util.getString("XsdEditor.additions_11"), createChildMenuManager); //$NON-NLS-1$ submenuManager.insertBefore(XsdUiPlugin.Util.getString("XsdEditor.additions_12"), createSiblingMenuManager); //$NON-NLS-1$ } /** * This adds Separators to the tool bar. */ @Override public void contributeToToolBar( IToolBarManager toolBarManager ) { toolBarManager.add(new Separator(XsdUiPlugin.Util.getString("XsdEditor.xsd-settings_13"))); //$NON-NLS-1$ toolBarManager.add(new Separator(XsdUiPlugin.Util.getString("XsdEditor.xsd-additions_14"))); //$NON-NLS-1$ } /** * When the active editor changes, this remembers the change, and registers with it as a selection provider. */ @Override public void setActiveEditor( IEditorPart part ) { super.setActiveEditor(part); activeEditorPart = part; // switch to the new selection provider if (selectionProvider != null) { selectionProvider.removeSelectionChangedListener(this); } selectionProvider = part.getSite().getSelectionProvider(); selectionProvider.addSelectionChangedListener(this); // fake a selection changed event to update the menus if (selectionProvider.getSelection() != null) selectionChanged(new SelectionChangedEvent( selectionProvider, selectionProvider.getSelection())); } /** * This implements {@link ISelectionChangedListener}, handling SelectionChangedEvents by querying for the children and * siblings that can be added to the selected object and updating the menus accordingly. */ @Override public void selectionChanged( SelectionChangedEvent event ) { // remove any menu items for old selection if (createChildMenuManager != null) { depopulateManager(createChildMenuManager, createChildActions); } if (createSiblingMenuManager != null) { depopulateManager(createSiblingMenuManager, createSiblingActions); } // query new selection for appropriate new child/sibling descriptors... Collection newChildDescriptors = Collections.EMPTY_LIST; Collection newSiblingDescriptors = Collections.EMPTY_LIST; ISelection sel = event.getSelection(); if (sel instanceof IStructuredSelection && ((IStructuredSelection)sel).size() == 1) { Object object = ((IStructuredSelection)sel).getFirstElement(); EditingDomain domain = ((IEditingDomainProvider)activeEditorPart).getEditingDomain(); newChildDescriptors = domain.getNewChildDescriptors(object, null); newSiblingDescriptors = domain.getNewChildDescriptors(domain.getParent(object), object); } // generate actions for selection, populate and redraw menu createChildActions = generateCreateChildActions(newChildDescriptors, sel); createSiblingActions = generateCreateSiblingActions(newSiblingDescriptors, sel); if (createChildMenuManager != null) { populateManager(createChildMenuManager, createChildActions, null); createChildMenuManager.update(true); } if (createSiblingMenuManager != null) { populateManager(createSiblingMenuManager, createSiblingActions, null); createSiblingMenuManager.update(true); } } /** * This generates a {@link CreateChildAction} for each object in <code>descriptors</code>, and returns the collection of * these actions. */ protected Collection generateCreateChildActions( Collection descriptors, ISelection sel ) { Collection actions = new LinkedList(); for (Iterator i = descriptors.iterator(); i.hasNext();) { actions.add(new CreateChildAction(activeEditorPart, sel, i.next())); } return actions; } /** * This generates a {@link CreateSiblingAction} for each object in <code>descriptors</code>, and returns the collection of * these actions. */ protected Collection generateCreateSiblingActions( Collection descriptors, ISelection sel ) { Collection actions = new LinkedList(); for (Iterator i = descriptors.iterator(); i.hasNext();) { actions.add(new CreateSiblingAction(activeEditorPart, sel, i.next())); } return actions; } /** * This populates the specified IContributionManager with ActionContributionItems based on the IActions contained in the * actions collection, by inserting them before the specified contribution item ID. If ID is null, they are simply added. */ protected void populateManager( IContributionManager manager, Collection actions, String ID ) { for (Iterator i = actions.iterator(); i.hasNext();) { IAction action = (IAction)i.next(); if (ID != null) { manager.insertBefore(ID, action); } else { manager.add(action); } } } /** * This removes from the specified IContributionManager all ActionContributionItems based on the IActions contained in the * actions collection. */ protected void depopulateManager( IContributionManager manager, Collection actions ) { IContributionItem[] item = manager.getItems(); for (int i = 0; i < item.length; i++) { // look into SubContributionItems IContributionItem curItem = item[i]; while (curItem instanceof SubContributionItem) { curItem = ((SubContributionItem)curItem).getInnerItem(); } // delete ActionContributionItems with matching action if (curItem instanceof ActionContributionItem) { IAction action = ((ActionContributionItem)curItem).getAction(); if (actions.contains(action)) { manager.remove(curItem); } } } } /** * This populates the pop-up menu before it appears. */ @Override public void menuAboutToShow( IMenuManager menuManager ) { super.menuAboutToShow(menuManager); menuManager.insertAfter(XsdUiPlugin.Util.getString("XsdEditor.additions_15"), new Separator()); //$NON-NLS-1$ MenuManager submenuManager = new MenuManager(XsdUiPlugin.Util.getString("_UI_CreateSibling_menu_item")); //$NON-NLS-1$ populateManager(submenuManager, createSiblingActions, null); menuManager.insertAfter(XsdUiPlugin.Util.getString("XsdEditor.additions_17"), submenuManager); //$NON-NLS-1$ submenuManager = new MenuManager(XsdUiPlugin.Util.getString("_UI_CreateChild_menu_item")); //$NON-NLS-1$ populateManager(submenuManager, createChildActions, null); menuManager.insertAfter(XsdUiPlugin.Util.getString("XsdEditor.additions_19"), submenuManager); //$NON-NLS-1$ } } /** * This creates a context menu for the viewer and adds a listener as well registering the menu for extension. */ protected void createContextMenuFor( StructuredViewer viewer ) { MenuManager contextMenu = new MenuManager("#PopUp"); //$NON-NLS-1$ contextMenu.add(new Separator(XsdUiPlugin.Util.getString("XsdEditor.additions_21"))); //$NON-NLS-1$ contextMenu.setRemoveAllWhenShown(true); contextMenu.addMenuListener(this); Menu menu = contextMenu.createContextMenu(viewer.getControl()); viewer.getControl().setMenu(menu); getSite().registerContextMenu(contextMenu, viewer); int dndOperations = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK; Transfer[] transfers = new Transfer[] {LocalTransfer.getInstance()}; viewer.addDragSupport(dndOperations, transfers, new ViewerDragAdapter(viewer)); viewer.addDropSupport(dndOperations, transfers, new EditingDomainViewerDropAdapter(editingDomain, viewer)); } /** * This is the method used by the framework to install your own controls. */ @Override public void createPages() { createSourcePage(); createSemanticsPage(); createSyntaxPage(); setActivePage(0); setCurrentViewer((Viewer)sourceViewer); } protected void createResource( String uri ) { extendedCreateResource(uri); } protected void standardCreateResource( String uri ) { // Load the resource through the editing domain. // This will creat a context and associate it with the resource set. // XSDResourceImpl xsdResource = (XSDResourceImpl)editingDomain.loadResource(uri); xsdSchema = xsdResource.getSchema(); } protected void extendedCreateResource( String uri ) { editingDomain.getResourceSet().getLoadOptions().put(XSDResourceImpl.XSD_TRACK_LOCATION, Boolean.TRUE); try { XSDResourceImpl xsdResource = (XSDResourceImpl)editingDomain.getResourceSet().getResource(URI.createFileURI(uri), true); xsdSchema = xsdResource.getSchema(); // code to close the editor when the resource is deleted textEditor.getDocumentProvider().addElementStateListener(new IElementStateListener() { @Override public void elementDirtyStateChanged( Object element, boolean isDirty ) { } @Override public void elementContentAboutToBeReplaced( Object element ) { } @Override public void elementContentReplaced( Object element ) { } @Override public void elementDeleted( Object element ) { Display display = getSite().getShell().getDisplay(); display.asyncExec(new Runnable() { @Override public void run() { if (sourceViewer != null) { getSite().getPage().closeEditor(XsdEditor.this, false); } } }); } @Override public void elementMoved( Object originalElement, Object movedElement ) { } }); } catch (Exception exception) { XsdUiPlugin.Util.log(exception); } } protected void createModel() { // Do the work within an operation because this is a long running activity that modifies the workbench. // WorkspaceModifyOperation operation = new WorkspaceModifyOperation() { // This is the method that gets invoked when the operation runs. // @Override protected void execute( IProgressMonitor progressMonitor ) { try { progressMonitor.beginTask(XsdUiPlugin.Util.getString("XsdEditor._22"), 10); //$NON-NLS-1$ IFileEditorInput modelFile = (IFileEditorInput)getEditorInput(); IFile file = modelFile.getFile(); editingDomain.getResourceSet().getLoadOptions().put(XSDResourceImpl.XSD_PROGRESS_MONITOR, progressMonitor); createResource(file.getLocation().toString()); editingDomain.getResourceSet().getLoadOptions().remove(XSDResourceImpl.XSD_PROGRESS_MONITOR); progressMonitor.worked(1); final String msg = XsdUiPlugin.Util.getString("_UI_Validating_message");//$NON-NLS-1$ progressMonitor.subTask(msg); if (getXsdSchema().getDiagnostics().isEmpty()) { getXsdSchema().validate(); getXsdSchema().eResource().setModified(false); } progressMonitor.worked(1); progressMonitor.subTask(XsdUiPlugin.Util.getString("_UI_ReportingErrors_message")); //$NON-NLS-1$ handleDiagnostics(progressMonitor); } catch (Throwable t) { XsdUiPlugin.Util.log(t); } finally { progressMonitor.done(); } } }; try { // This runs the operation, and shows progress. // (It appears to be a bad thing to fork this onto another thread.) // new ProgressMonitorDialog(getSite().getShell()).run(false, false, operation); } catch (Exception exception) { XsdUiPlugin.Util.log(exception); } } protected void handleSourceCaretPosition() { int offset = sourceViewer.getTextWidget().getCaretOffset(); Element element = getXsdSchema().getElement(); if (element != null) { IDocument document = sourceViewer.getDocument(); int line = 0; int lineOffset = 0; try { line = document.getLineOfOffset(offset); lineOffset = document.getLineOffset(line); } catch (BadLocationException exception) { } int column = offset - lineOffset; // System.out.println("[" + line + "," + column + "]"); Element bestElement = findBestElement(element, line + 1, column + 1); if (bestElement != null) { handleSelectedNodes(Collections.singleton(bestElement)); } } } public Element findBestElement( Element element, int line, int column ) { int startLine = XSDParser.getStartLine(element); int startColumn = XSDParser.getStartColumn(element); int endLine = XSDParser.getEndLine(element); int endColumn = XSDParser.getEndColumn(element); Element candidate = null; if ((line == startLine ? column >= startColumn : line > startLine) && (line == endLine ? column <= endColumn : line < endLine)) { candidate = element; for (Node child = element.getFirstChild(); child != null; child = child.getNextSibling()) { if (child.getNodeType() == Node.ELEMENT_NODE) { Element childElement = (Element)child; Element betterCandidate = findBestElement(childElement, line, column); if (betterCandidate != null) { candidate = betterCandidate; break; } } } } return candidate; } public void handleSelectedNodes( Collection nodes ) { Collection selection = new ArrayList(); for (Iterator i = nodes.iterator(); i.hasNext();) { Node node = (Node)i.next(); XSDConcreteComponent bestXSDConcreteComponent = getXsdSchema().getCorrespondingComponent(node); if (bestXSDConcreteComponent != null) { boolean add = true; for (XSDConcreteComponent parent = bestXSDConcreteComponent; parent != null; parent = parent.getContainer()) { if (selection.contains(parent)) { add = false; break; } } if (add) { XSDConcreteComponent container = bestXSDConcreteComponent.getContainer(); if (container instanceof XSDParticle || container instanceof XSDAttributeUse) { bestXSDConcreteComponent = container; } selection.add(bestXSDConcreteComponent); } } } if (!selection.isEmpty()) { ISelection newSelection = new StructuredSelection(selection.toArray()); if (contentOutlineViewer != null) { contentOutlineViewer.setSelection(newSelection, true); } setSelection(newSelection); handleContentOutlineSelectionForTextEditor(newSelection, false); } } protected void handleDocumentChange() { try { XSDParser xsdParser = new XSDParser(null); String documentContent = sourceViewer.getDocument().get(); byte[] bytes = // domDocument.getEncoding() == null ? documentContent.getBytes() : // documentContent.getBytes(domDocument.getEncoding()); documentContent.getBytes(); xsdParser.parse(new ByteArrayInputStream(bytes)); xsdParser.setSchema(getXsdSchema()); getXsdSchema().validate(); getXsdSchema().eResource().setModified(true); handleDiagnostics(null); } catch (Exception exception) { XsdUiPlugin.Util.log(exception); } } protected void createSourcePage() { try { // Create the SED Editor. // textEditor = new TextEditor() { @Override public ISourceViewer createSourceViewer( Composite parent, IVerticalRuler ruler, int styles ) { final ISourceViewer result = super.createSourceViewer(parent, ruler, styles); result.getTextWidget().addMouseListener(new MouseAdapter() { @Override public void mouseDown( MouseEvent event ) { handleSourceCaretPosition(); } }); result.getTextWidget().addKeyListener(new KeyAdapter() { @Override public void keyPressed( KeyEvent event ) { switch (event.keyCode) { case SWT.ARROW_UP: case SWT.ARROW_DOWN: case SWT.ARROW_LEFT: case SWT.ARROW_RIGHT: case SWT.PAGE_UP: case SWT.PAGE_DOWN: { handleSourceCaretPosition(); break; } } } }); sourceViewer = result; return result; } }; IFileEditorInput modelFile = (IFileEditorInput)getEditorInput(); int pageIndex = addPage(textEditor, modelFile); createModel(); String encoding = determineEncoding(); IEncodingSupport encodingSupport = (IEncodingSupport)textEditor.getAdapter(IEncodingSupport.class); if (encodingSupport != null && encoding != null) { encodingSupport.setEncoding(encoding); } setPageText(pageIndex, XsdUiPlugin.Util.getString("XsdEditor.Source_26")); //$NON-NLS-1$ IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput()); document.addDocumentListener(new IDocumentListener() { protected Timer timer = new Timer(); protected TimerTask timerTask; @Override public void documentAboutToBeChanged( DocumentEvent documentEvent ) { } @Override public void documentChanged( final DocumentEvent documentEvent ) { try { // This is need for the Properties view. // // setSelection(StructuredSelection.EMPTY); if (timerTask != null) { timerTask.cancel(); } if (handledStructuredModelChange) { handledStructuredModelChange = false; handleDocumentChange(); } else { timerTask = new TimerTask() { @Override public void run() { getSite().getShell().getDisplay().asyncExec(new Runnable() { @Override public void run() { handleDocumentChange(); } }); } }; timer.schedule(timerTask, 1000); } } catch (Exception exception) { XsdUiPlugin.Util.log(exception); } } }); } catch (Exception exception) { XsdUiPlugin.Util.log(exception); } } protected void createSemanticsPage() { // Create a page for the selection tree view. // { ViewerPane viewerPane = new ViewerPane(getSite().getPage(), XsdEditor.this) { @Override public Viewer createViewer( Composite composite ) { Tree tree = new Tree(composite, SWT.MULTI); TreeViewer newTreeViewer = new TreeViewer(tree); return newTreeViewer; } @Override public void requestActivation() { super.requestActivation(); setCurrentViewerPane(this); } }; viewerPane.createControl(getContainer()); semanticSelectionViewer = (TreeViewer)viewerPane.getViewer(); semanticSelectionViewer.setContentProvider(new AdapterFactoryContentProvider(semanticAdapterFactory)); semanticSelectionViewer.setLabelProvider(new AdapterFactoryLabelProvider(semanticAdapterFactory)); semanticSelectionViewer.setAutoExpandLevel(2); semanticSelectionViewer.addSelectionChangedListener(new ISelectionChangedListener() { // This just notifies those things that are affected by the section. // @Override public void selectionChanged( SelectionChangedEvent selectionChangedEvent ) { if (currentViewer == semanticSelectionViewer && contentOutlineViewer != null) { contentOutlineViewer.setSelection(selectionChangedEvent.getSelection(), true); } } }); semanticSelectionViewer.setInput(new ItemProvider(Collections.singleton(getXsdSchema()))); viewerPane.setTitle(getXsdSchema()); new AdapterFactoryTreeEditor(semanticSelectionViewer.getTree(), semanticAdapterFactory); createContextMenuFor(semanticSelectionViewer); int pageIndex = addPage(viewerPane.getControl()); setPageText(pageIndex, XsdUiPlugin.Util.getString("_UI_Semantics_title")); //$NON-NLS-1$ } } protected void createSyntaxPage() { // Create a page for the selection tree view. // { ViewerPane viewerPane = new ViewerPane(getSite().getPage(), XsdEditor.this) { @Override public Viewer createViewer( Composite composite ) { Tree tree = new Tree(composite, SWT.MULTI); TreeViewer newTreeViewer = new TreeViewer(tree); return newTreeViewer; } @Override public void requestActivation() { super.requestActivation(); setCurrentViewerPane(this); } }; viewerPane.createControl(getContainer()); syntacticSelectionViewer = (TreeViewer)viewerPane.getViewer(); syntacticSelectionViewer.setContentProvider(new AdapterFactoryContentProvider(syntacticAdapterFactory)); syntacticSelectionViewer.setLabelProvider(new AdapterFactoryLabelProvider(syntacticAdapterFactory)); syntacticSelectionViewer.setAutoExpandLevel(2); syntacticSelectionViewer.setInput(new ItemProvider(Collections.singleton(getXsdSchema()))); viewerPane.setTitle(getXsdSchema()); new AdapterFactoryTreeEditor(syntacticSelectionViewer.getTree(), syntacticAdapterFactory); createContextMenuFor(syntacticSelectionViewer); int pageIndex = addPage(viewerPane.getControl()); setPageText(pageIndex, XsdUiPlugin.Util.getString("_UI_Syntax_title")); //$NON-NLS-1$ } } protected void initializeMarkerPosition( IMarker marker, XSDDiagnostic xsdDiagnostic ) throws CoreException { Node node = xsdDiagnostic.getNode(); if (node != null && node.getNodeType() == Node.ATTRIBUTE_NODE) { node = ((Attr)node).getOwnerElement(); } if (node != null && XSDParser.getUserData(node) != null) { int startLine = XSDParser.getStartLine(node) - 1; int startColumn = XSDParser.getStartColumn(node); int endLine = XSDParser.getEndLine(node) - 1; int endColumn = XSDParser.getEndColumn(node); marker.setAttribute(IMarker.LINE_NUMBER, startLine); try { IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput()); marker.setAttribute(IMarker.CHAR_START, document.getLineOffset(startLine) + startColumn - 1); marker.setAttribute(IMarker.CHAR_END, document.getLineOffset(endLine) + endColumn - 1); } catch (BadLocationException exception) { } } else { marker.setAttribute(IMarker.LINE_NUMBER, xsdDiagnostic.getLine()); } } protected void handleDiagnostics( IProgressMonitor progressMonitor ) { if (progressMonitor == null) { // Do the work within an operation because this is a long running activity that modifies the workbench. // IWorkspaceRunnable operation = new IWorkspaceRunnable() { // This is the method that gets invoked when the operation runs. // @Override public void run( IProgressMonitor localProgressMonitor ) { handleDiagnostics(localProgressMonitor); } }; try { ModelerCore.getWorkspace().run(operation, new NullProgressMonitor()); // getSite().getWorkbenchWindow().run(false, false, operation); } catch (Exception exception) { XsdUiPlugin.Util.log(exception); } } else { XSDConcreteComponent newSelection = null; try { // I assume that the input is a file object. // IFileEditorInput modelFile = (IFileEditorInput)getEditorInput(); IFile file = modelFile.getFile(); IMarker[] markers = file.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO); Collection deletableMarkers = new ArrayList(Arrays.asList(markers)); for (Iterator xsdDiagnostics = getXsdSchema().getAllDiagnostics().iterator(); xsdDiagnostics.hasNext();) { XSDDiagnostic xsdDiagnostic = (XSDDiagnostic)xsdDiagnostics.next(); String uriReferencePath = getXsdSchema().eResource().getURIFragment(xsdDiagnostic); IMarker marker = null; for (int i = 0; i < markers.length; ++i) { if (markers[i].getAttribute(XSDDiagnostic.URI_FRAGMENT_ATTRIBUTE, XsdUiPlugin.Util.getString("XsdEditor._29")).equals(uriReferencePath)) //$NON-NLS-1$ { marker = markers[i]; deletableMarkers.remove(marker); break; } } if (marker == null) { marker = file.createMarker(XSDDiagnostic.MARKER); marker.setAttribute(XSDDiagnostic.URI_FRAGMENT_ATTRIBUTE, uriReferencePath); } initializeMarkerPosition(marker, xsdDiagnostic); marker.setAttribute(IMarker.MESSAGE, xsdDiagnostic.getMessage()); switch (xsdDiagnostic.getSeverity().getValue()) { case XSDDiagnosticSeverity.FATAL: case XSDDiagnosticSeverity.ERROR: { if (newSelection == null) { newSelection = xsdDiagnostic.getPrimaryComponent(); } marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); break; } case XSDDiagnosticSeverity.WARNING: { marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING); break; } case XSDDiagnosticSeverity.INFORMATION: { marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO); break; } } } for (Iterator i = deletableMarkers.iterator(); i.hasNext();) { IMarker marker = (IMarker)i.next(); marker.delete(); } } catch (Exception exception) { XsdUiPlugin.Util.log(exception); } // This will refresh the status. // if (editorSelection != null) { setSelection(editorSelection); } // This is the startup case. // else if (newSelection != null) { final IStructuredSelection errorSelection = new StructuredSelection(newSelection); getSite().getShell().getDisplay().asyncExec(new Runnable() { @Override public void run() { if (contentOutlineViewer != null) { contentOutlineViewer.setSelection(errorSelection, true); } if (sourceViewer != null) { handleContentOutlineSelectionForTextEditor(errorSelection, true); } setSelection(errorSelection); handleSourceCaretPosition(); } }); } } } /** * This is used to track the active viewer. */ @Override protected void pageChange( int pageIndex ) { super.pageChange(pageIndex); if (pageIndex == 0) { setCurrentViewerPane(null); setCurrentViewer((Viewer)sourceViewer); } // This is a temporary workaround... EATM // Control control = getControl(pageIndex); if (control != null) { control.setVisible(true); control.setFocus(); } handleContentOutlineSelection(getContentOutlinePage().getSelection()); } /** * This is how the framework determines which interfaces we implement. */ @Override public Object getAdapter( Class key ) { if (key.equals(IContentOutlinePage.class)) { return getContentOutlinePage(); } else if (key.equals(IPropertySheetPage.class)) { return getPropertySheetPage(); } else { return textEditor.getAdapter(key); } } /** * This is a utility function to resolve a component. */ public static XSDConcreteComponent getResolvedObject( XSDConcreteComponent xsdConcreteComponent ) { XSDConcreteComponent result = (XSDConcreteComponent)new XSDSwitch() { @Override public Object caseXSDAttributeUse( XSDAttributeUse xsdAttributeUse ) { return xsdAttributeUse.getAttributeDeclaration().getResolvedAttributeDeclaration(); } @Override public Object caseXSDAttributeDeclaration( XSDAttributeDeclaration xsdAttributeDeclaration ) { return xsdAttributeDeclaration.getResolvedAttributeDeclaration(); } @Override public Object caseXSDAttributeGroupDefinition( XSDAttributeGroupDefinition xsdAttributeGroupDefinition ) { return xsdAttributeGroupDefinition.getResolvedAttributeGroupDefinition(); } @Override public Object caseXSDElementDeclaration( XSDElementDeclaration xsdElementDeclaration ) { return xsdElementDeclaration.getResolvedElementDeclaration(); } @Override public Object caseXSDModelGroupDefinition( XSDModelGroupDefinition xsdModelGroupDefinition ) { return xsdModelGroupDefinition.getResolvedModelGroupDefinition(); } @Override public Object caseXSDParticle( XSDParticle xsdParticle ) { Object resolvedObject = getResolvedObject(xsdParticle.getContent()); if (resolvedObject instanceof XSDModelGroup) { return xsdParticle; } return resolvedObject; } }.doSwitch(xsdConcreteComponent); return result == null ? xsdConcreteComponent : result; } /** * @param set */ public static void setResourceSet( ResourceSet rs ) { resourceSet = rs; } /** * This accesses a cached version of the content outliner. */ public IContentOutlinePage getContentOutlinePage() { if (contentOutlinePage == null) { // The content outline is just a tree. // class MyContentOutlinePage extends ContentOutlinePage { @Override public void createControl( Composite parent ) { super.createControl(parent); contentOutlineViewer = getTreeViewer(); contentOutlineViewer.addSelectionChangedListener(this); contentOutlineViewer.setAutoExpandLevel(2); selectNextDiagnosticsAction = new SelectDiagnosticAction(true, contentOutlineViewer); selectPreviousDiagnosticsAction = new SelectDiagnosticAction(false, contentOutlineViewer); selectNextUseAction = new SelectUseAction(true, contentOutlineViewer); selectPreviousUseAction = new SelectUseAction(false, contentOutlineViewer); contentOutlineViewer.getTree().addMouseListener(new MouseAdapter() { @Override public void mouseDoubleClick( MouseEvent event ) { // Do fancy navigation selections when double clicking. // IStructuredSelection selection = (IStructuredSelection)contentOutlineViewer.getSelection(); for (Iterator objects = selection.toList().iterator(); objects.hasNext();) { XSDConcreteComponent object = (XSDConcreteComponent)objects.next(); Object resolvedObject = getResolvedObject(object); if (object != resolvedObject) { contentOutlineViewer.setSelection(new StructuredSelection(new Object[] {resolvedObject}), true); break; } else if (object instanceof XSDAttributeDeclaration) { XSDAttributeDeclaration xsdAttributeDeclaration = (XSDAttributeDeclaration)object; XSDSimpleTypeDefinition typeDefinition = xsdAttributeDeclaration.getTypeDefinition(); if (typeDefinition != null && typeDefinition.getSchema() == xsdAttributeDeclaration.getSchema()) { contentOutlineViewer.setSelection(new StructuredSelection(new Object[] {typeDefinition}), true); break; } } else if (object instanceof XSDElementDeclaration) { XSDElementDeclaration xsdElementDeclaration = (XSDElementDeclaration)object; XSDTypeDefinition typeDefinition = xsdElementDeclaration.getTypeDefinition(); if (typeDefinition != null && typeDefinition.getSchema() == xsdElementDeclaration.getSchema()) { contentOutlineViewer.setSelection(new StructuredSelection(new Object[] {typeDefinition}), true); break; } } else if (object instanceof XSDSimpleTypeDefinition) { XSDSimpleTypeDefinition xsdSimpleTypeDefinition = (XSDSimpleTypeDefinition)object; XSDSimpleTypeDefinition baseTypeDefinition = xsdSimpleTypeDefinition.getBaseTypeDefinition(); if (baseTypeDefinition != null && baseTypeDefinition.getSchema() == xsdSimpleTypeDefinition.getSchema()) { contentOutlineViewer.setSelection(new StructuredSelection( new Object[] {baseTypeDefinition}), true); break; } XSDSimpleTypeDefinition itemTypeDefinition = xsdSimpleTypeDefinition.getItemTypeDefinition(); if (itemTypeDefinition != null && itemTypeDefinition.getSchema() == xsdSimpleTypeDefinition.getSchema()) { contentOutlineViewer.setSelection(new StructuredSelection( new Object[] {itemTypeDefinition}), true); break; } List memberTypeDefinitions = xsdSimpleTypeDefinition.getMemberTypeDefinitions(); if (!memberTypeDefinitions.isEmpty()) { contentOutlineViewer.setSelection(new StructuredSelection(memberTypeDefinitions.toArray()), true); break; } } else if (object instanceof XSDComplexTypeDefinition) { XSDComplexTypeDefinition xsdComplexTypeDefinition = (XSDComplexTypeDefinition)object; XSDTypeDefinition baseTypeDefinition = xsdComplexTypeDefinition.getBaseTypeDefinition(); if (baseTypeDefinition != null && baseTypeDefinition.getSchema() == xsdComplexTypeDefinition.getSchema()) { contentOutlineViewer.setSelection(new StructuredSelection( new Object[] {baseTypeDefinition}), true); break; } } } } }); // Set up the tree viewer. // contentOutlineViewer.setContentProvider(new AdapterFactoryContentProvider(syntacticAdapterFactory)); contentOutlineViewer.setLabelProvider(new AdapterFactoryLabelProvider(syntacticAdapterFactory)); contentOutlineViewer.setInput(new ItemProvider(Collections.singleton(getXsdSchema()))); // Make sure our popups work. // createContextMenuFor(contentOutlineViewer); // Select the root object in the view. // ArrayList selection = new ArrayList(); selection.add(getXsdSchema()); contentOutlineViewer.setSelection(new StructuredSelection(selection), true); // Listen to selection so that we can handle it is a special way. // this.addSelectionChangedListener(new ISelectionChangedListener() { // This ensures that we handle selections correctly. // @Override public void selectionChanged( SelectionChangedEvent event ) { ISelection s = event.getSelection(); if (contentOutlineViewer == currentViewer) { handleContentOutlineSelection(s); } selectNextDiagnosticsAction.setCurrentObjects(((IStructuredSelection)s).toList()); selectPreviousDiagnosticsAction.setCurrentObjects(((IStructuredSelection)s).toList()); selectNextUseAction.setCurrentObjects(((IStructuredSelection)s).toList()); selectPreviousUseAction.setCurrentObjects(((IStructuredSelection)s).toList()); } }); } @Override public void setActionBars( IActionBars actionBars ) { super.setActionBars(actionBars); contentOutlineStatusLineManager = actionBars.getStatusLineManager(); actionBars.getToolBarManager().add(selectNextUseAction); actionBars.getToolBarManager().add(selectPreviousUseAction); actionBars.getToolBarManager().add(selectNextDiagnosticsAction); actionBars.getToolBarManager().add(selectPreviousDiagnosticsAction); actionBars.getMenuManager().add(selectNextDiagnosticsAction); actionBars.getMenuManager().add(selectPreviousDiagnosticsAction); actionBars.getMenuManager().add(selectNextUseAction); actionBars.getMenuManager().add(selectPreviousUseAction); getActionBarContributor().shareGlobalActions(this, actionBars); } } contentOutlinePage = new MyContentOutlinePage(); // Listen to selection so that we can handle it is a special way. // contentOutlinePage.addSelectionChangedListener(new ISelectionChangedListener() { // This ensures that we handle selections correctly. // @Override public void selectionChanged( SelectionChangedEvent event ) { if (contentOutlineViewer == currentViewer) { handleContentOutlineSelection(event.getSelection()); } } }); } return contentOutlinePage; } /** * This accesses a cached version of the property sheet. */ public IPropertySheetPage getPropertySheetPage() { if (propertySheetPage == null) { propertySheetPage = new PropertySheetPage() { @Override public void makeContributions( IMenuManager menuManager, IToolBarManager toolBarManager, IStatusLineManager statusLineManager ) { super.makeContributions(menuManager, toolBarManager, statusLineManager); } }; propertySheetPage.setPropertySourceProvider(new AdapterFactoryContentProvider(syntacticAdapterFactory) { @Override public void notifyChanged( final Notification notification ) { getParentComposite().getDisplay().asyncExec(new Runnable() { @Override public void run() { propertySheetPage.refresh(); } }); } @Override protected IPropertySource createPropertySource( Object object, IItemPropertySource itemPropertySource ) { return new PropertySource(object, itemPropertySource) { @Override protected IPropertyDescriptor createPropertyDescriptor( IItemPropertyDescriptor itemPropertyDescriptor ) { return new PropertyDescriptor(this.object, itemPropertyDescriptor) { @Override public CellEditor createPropertyEditor( Composite composite ) { if (!this.itemPropertyDescriptor.canSetProperty(this.object)) { return null; } CellEditor result = null; Object genericFeature = this.itemPropertyDescriptor.getFeature(this.object); if (genericFeature instanceof EStructuralFeature) { EStructuralFeature feature = (EStructuralFeature)genericFeature; EObject getEType = feature.getEType(); if (getEType == ecorePackage.getEBoolean()) { Collection choiceOfValues = this.itemPropertyDescriptor.getChoiceOfValues(this.object); if (choiceOfValues != null) { result = new ExtendedComboBoxCellEditor(composite, new ArrayList(choiceOfValues), getLabelProvider(), true); } } } if (result == null) { result = super.createPropertyEditor(composite); } return result; } }; } }; } }); } return propertySheetPage; } /** * This deals with how we want selection in the outliner to affect the other views. */ public void handleContentOutlineSelection( ISelection selection ) { if ((currentViewerPane != null || getActivePage() == 0) && !selection.isEmpty() && selection instanceof IStructuredSelection) { if (getActivePage() == 0) { handleContentOutlineSelectionForTextEditor(selection, true); } else if (currentViewerPane.getViewer() == syntacticSelectionViewer) { // Set the selection to the widget. // syntacticSelectionViewer.setSelection(selection); } else if (currentViewerPane.getViewer() == semanticSelectionViewer) { ArrayList selectionList = new ArrayList(); for (Iterator elements = ((IStructuredSelection)selection).iterator(); elements.hasNext();) { selectionList.add(getResolvedObject((XSDConcreteComponent)elements.next())); } // Set the selection to the widget. // semanticSelectionViewer.setSelection(new StructuredSelection(selectionList)); } } } /** * This deals with how we want selection in the outliner to affect the text editor. */ public void handleContentOutlineSelectionForTextEditor( ISelection selection, boolean reveal ) { XSDConcreteComponent xsdConcreteComponent = (XSDConcreteComponent)((IStructuredSelection)selection).iterator().next(); if (xsdConcreteComponent instanceof XSDParticle) { XSDParticle xsdParticle = (XSDParticle)xsdConcreteComponent; XSDConcreteComponent content = xsdParticle.getContent(); if (content != null) { xsdConcreteComponent = content; } } Element element = xsdConcreteComponent.getElement(); if (element != null) { try { IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput()); int startLine = XSDParser.getStartLine(element); int startColumn = XSDParser.getStartColumn(element); int endLine = XSDParser.getEndLine(element); int endColumn = XSDParser.getEndColumn(element); int startOffset = document.getLineOffset(startLine - 1); startOffset += startColumn - 1; int endOffset = document.getLineOffset(endLine - 1); endOffset += endColumn - 1; if (startLine == endLine) { textEditor.setHighlightRange(startOffset, endOffset - startOffset, false); if (reveal) { textEditor.selectAndReveal(startOffset, endOffset - startOffset); } } else { textEditor.setHighlightRange(startOffset, endOffset - startOffset, reveal); } } catch (Exception exception) { XsdUiPlugin.Util.log(exception); } } } /** * This is for implementing {@link IEditorPart} and simply tests the command stack. */ @Override public boolean isDirty() { return ((BasicCommandStack)editingDomain.getCommandStack()).isSaveNeeded() || textEditor != null && textEditor.isDirty(); } /** * @return */ public XSDSchema getXsdSchema() { if (xsdSchema != null && xsdSchema.eResource() != null) { return xsdSchema; } if (xsdResource != null && xsdResource instanceof XSDResourceImpl) { XSDResourceImpl rsrc = (XSDResourceImpl)xsdResource; if (rsrc != null) { xsdSchema = rsrc.getSchema(); } } return xsdSchema; } /** * This is for implementing {@link IEditorPart} and simply saves the model file. */ @Override public void doSave( IProgressMonitor progressMonitor ) { final IEditorInput input = getEditorInput(); final IDocumentProvider documentProvider = textEditor.getDocumentProvider(); // Do the work within an operation because this is a long running activity that modifies the workbench. // WorkspaceModifyOperation operation = new WorkspaceModifyOperation() { // This is the method that gets invoked when the operation runs. @Override protected void execute( IProgressMonitor monitor ) { try { // Save the resource to the file system. documentProvider.saveDocument(monitor, input, documentProvider.getDocument(input), true); } catch (Exception exception) { XsdUiPlugin.Util.log(exception); } } }; try { documentProvider.aboutToChange(input); operation.run(progressMonitor); // performs the operation documentProvider.changed(input); ((BasicCommandStack)editingDomain.getCommandStack()).saveIsDone(); firePropertyChange(IEditorPart.PROP_DIRTY); } catch (Exception exception) { XsdUiPlugin.Util.log(exception); } } /** * This always returns false because it is not current supported. */ @Override public boolean isSaveAsAllowed() { return true; } /** * This also changes the editor's input. */ @Override public void doSaveAs() { SaveAsDialog saveAsDialog = new SaveAsDialog(getSite().getShell()); saveAsDialog.open(); IPath path = saveAsDialog.getResult(); if (path != null) { IFile file = ModelerCore.getWorkspace().getRoot().getFile(path); if (file != null) { if (!file.exists() || MessageDialog.openQuestion(getSite().getShell(), XsdUiPlugin.Util.getString("_UI_FileExists_title"), //$NON-NLS-1$ XsdUiPlugin.Util.getString("_UI_FileExists_description", new Object[] {file.getFullPath()}))) //$NON-NLS-1$ { getXsdSchema().eResource().setURI(URI.createURI(XsdUiPlugin.Util.getString("XsdEditor.platform_/resource_32") + file.getFullPath())); //$NON-NLS-1$ IFileEditorInput modelFile = new FileEditorInput(file); setInput(modelFile); setPartName(file.getName()); doSave(getActionBars().getStatusLineManager().getProgressMonitor()); } } } } @Override public void gotoMarker( IMarker marker ) { try { /* if (marker.getType().equals(XSDDiagnostic.MARKER) && xsdSchema != null) { XSDDiagnostic xsdDiagnostic = xsdSchema.getDiagnosticForURIReferencePath(marker.getAttribute(XSDDiagnostic.URI_FRAGMENT_ATTRIBUTE, "/0/")); } */ setActivePage(0); ((IGotoMarker)textEditor.getAdapter(IGotoMarker.class)).gotoMarker(marker); } catch (Exception exception) { XsdUiPlugin.Util.log(exception); } } /** * This is called during startup. */ @Override public void init( IEditorSite site, IEditorInput editorInput ) throws PartInitException { if (editorInput instanceof IFileEditorInput) { // get the XSD resource. try { // Get the IFile associated with the editor final IResource xsdFile = ((IFileEditorInput)editorInput).getFile(); if (xsdFile == null) { final String msg = XsdUiPlugin.Util.getString("XsdEditor.Input_Error__Model_Editor_cannot_open_{0}_2", editorInput.getName()); //$NON-NLS-1$ throw new PartInitException(msg); } // Get the EMF resource for the IFile in the workspace final String xsdLocation = xsdFile.getLocation().toString(); final URI xsdUri = URI.createFileURI(xsdLocation); xsdResource = ModelerCore.getModelContainer().getResource(xsdUri, true); // The resource must exist in the container if (xsdResource == null) { final String msg = XsdUiPlugin.Util.getString("XsdEditor.Input_Error__Model_Editor_cannot_open_{0}_1", editorInput.getName()); //$NON-NLS-1$ throw new PartInitException(msg); } // modelProject = xsdFile.getProject(); } catch (ModelWorkspaceException e) { final String msg = XsdUiPlugin.Util.getString("XsdEditor.Input_Error__Model_Editor_cannot_open_{0}_2", editorInput.getName()); //$NON-NLS-1$ throw new PartInitException(msg, e); } catch (CoreException e) { final String msg = XsdUiPlugin.Util.getString("XsdEditor.Input_Error__Model_Editor_cannot_open_{0}_2", editorInput.getName()); //$NON-NLS-1$ throw new PartInitException(msg, e); } setSite(site); setInput(editorInput); setPartName(((IFileEditorInput)editorInput).getFile().getName()); site.setSelectionProvider(new MultiPageSelectionProvider(this)); // EATM site.getPage().addPartListener(partListener); } else { throw new PartInitException( XsdUiPlugin.Util.getString("XsdEditor.Invalid_Input__Must_be_IFileEditorInput._33")); //$NON-NLS-1$ } } @Override public void setFocus() { getControl(getActivePage()).setFocus(); } /** * This implements {@link org.eclipse.jface.viewers.ISelectionProvider}. */ @Override public void addSelectionChangedListener( ISelectionChangedListener listener ) { selectionChangedListeners.add(listener); } /** * This implements {@link org.eclipse.jface.viewers.ISelectionProvider}. */ @Override public void removeSelectionChangedListener( ISelectionChangedListener listener ) { selectionChangedListeners.remove(listener); } /** * This implements {@link org.eclipse.jface.viewers.ISelectionProvider} to return this editor's overall selection. */ @Override public ISelection getSelection() { return editorSelection; } /** * This implements {@link org.eclipse.jface.viewers.ISelectionProvider} to set this editor's overall selection. Calling this * result will notify the listeners. */ @Override public void setSelection( ISelection selection ) { editorSelection = selection; SelectionChangedEvent selectionChangedEvent = new SelectionChangedEvent(this, selection); ((MultiPageSelectionProvider)getSite().getSelectionProvider()).fireSelectionChanged(selectionChangedEvent); for (Iterator listeners = selectionChangedListeners.iterator(); listeners.hasNext();) { ISelectionChangedListener listener = (ISelectionChangedListener)listeners.next(); listener.selectionChanged(selectionChangedEvent); } setStatusLineManager(selection); } /** * This shows the selection on the status line. */ public void setStatusLineManager( ISelection selection ) { IStatusLineManager statusLineManager = getActionBars().getStatusLineManager(); if (currentViewer == contentOutlineViewer) { statusLineManager = contentOutlineStatusLineManager; } if (statusLineManager != null) { if (selection instanceof IStructuredSelection) { Collection collection = ((IStructuredSelection)selection).toList(); switch (collection.size()) { case 0: { statusLineManager.setMessage(XsdUiPlugin.Util.getString("_UI_NoObjectSelected")); //$NON-NLS-1$ break; } case 1: { Object object = collection.iterator().next(); String text = new AdapterFactoryItemDelegator(syntacticAdapterFactory).getText(object); text = XsdUiPlugin.Util.getString("_UI_SingleObjectSelected", new Object[] {text}); //$NON-NLS-1$ if (object instanceof XSDConcreteComponent) { XSDConcreteComponent xsdConcreteComponent = (XSDConcreteComponent)object; if (!xsdConcreteComponent.getDiagnostics().isEmpty()) { text = (xsdConcreteComponent.getDiagnostics().get(0)).getMessage(); } } statusLineManager.setMessage(text); break; } default: { statusLineManager.setMessage(XsdUiPlugin.Util.getString("_UI_MultiObjectSelected", new Object[] {Integer.toString(collection.size())})); //$NON-NLS-1$ break; } } } else { statusLineManager.setMessage(""); //$NON-NLS-1$ } } } /** * This implements {@link org.eclipse.jface.action.IMenuListener} to help fill the context menus with contributions from the * Edit menu. */ @Override public void menuAboutToShow( IMenuManager menuManager ) { ((IMenuListener)getEditorSite().getActionBarContributor()).menuAboutToShow(menuManager); } /** * This convenience method provides typed access to the contributor. */ public EditingDomainActionBarContributor getActionBarContributor() { return (EditingDomainActionBarContributor)getEditorSite().getActionBarContributor(); } /** * This convenience method provides access to the actionbars. */ public IActionBars getActionBars() { return getActionBarContributor().getActionBars(); } /** * This is called when the editor is disposed. */ @Override public void dispose() { super.dispose(); getSite().getPage().removePartListener(partListener); ((IDisposable)semanticAdapterFactory).dispose(); ((IDisposable)syntacticAdapterFactory).dispose(); } /** * This is the base action for the outline actions. */ class SelectObjectAction extends Action { protected Collection objectsToSelect; protected StructuredViewer structuredViewer; public SelectObjectAction( StructuredViewer structuredViewer, String text, ImageDescriptor imageDescriptor ) { super(text, imageDescriptor); this.structuredViewer = structuredViewer; setEnabled(false); } public void setObjectToSelect( Object objectToSelect ) { setObjectsToSelect(objectToSelect != null ? Collections.singleton(objectToSelect) : (Collection)Collections.EMPTY_LIST); } public void setObjectsToSelect( Collection objectsToSelect ) { this.objectsToSelect = new ArrayList(objectsToSelect); setEnabled(!objectsToSelect.isEmpty()); } @Override public void run() { ISelection selection = null; if ((objectsToSelect == null) || objectsToSelect.isEmpty()) { selection = StructuredSelection.EMPTY; } else { selection = new StructuredSelection(objectsToSelect.toArray()); } structuredViewer.setSelection(selection, true); } } /** * This is used to implement the select next/previous unresolved component action. */ class SelectDiagnosticAction extends SelectObjectAction { boolean isForward; public SelectDiagnosticAction( boolean isForward, StructuredViewer structuredViewer ) { super( structuredViewer, isForward ? XsdUiPlugin.Util.getString("XsdEditor.Select_&Next_Diagnosed_Object_38") : XsdUiPlugin.Util.getString("XsdEditor.Select_&Previous_Diagnosed_Object_39"), //$NON-NLS-1$ //$NON-NLS-2$ ExtendedImageRegistry.INSTANCE.getImageDescriptor(XsdUiPlugin.INSTANCE.getImage(isForward ? "icons/full/elcl16/SelectNextDiagnosticObject.gif" : "icons/full/elcl16/SelectPreviousDiagnosticObject.gif"))); //$NON-NLS-1$ //$NON-NLS-2$ this.isForward = isForward; setHoverImageDescriptor(ExtendedImageRegistry.INSTANCE.getImageDescriptor(XsdUiPlugin.INSTANCE.getImage(isForward ? "icons/full/clcl16/SelectNextDiagnosticObject.gif" : "icons/full/clcl16/SelectPreviousDiagnosticObject.gif"))); //$NON-NLS-1$ //$NON-NLS-2$ setDisabledImageDescriptor(ExtendedImageRegistry.INSTANCE.getImageDescriptor(XsdUiPlugin.INSTANCE.getImage(isForward ? "icons/full/dlcl16/SelectNextDiagnosticObject.gif" : "icons/full/dlcl16/SelectPreviousDiagnosticObject.gif"))); //$NON-NLS-1$ //$NON-NLS-2$ setToolTipText(isForward ? XsdUiPlugin.Util.getString("XsdEditor.Select_&Next_Diagnosed_Object_38") //$NON-NLS-1$ : XsdUiPlugin.Util.getString("XsdEditor.Select_&Previous_Diagnosed_Object_39")); //$NON-NLS-1$ } public void updateAction() { setCurrentObjects(((IStructuredSelection)structuredViewer.getSelection()).toList()); } public void setCurrentObjects( List objects ) { XSDConcreteComponent result = null; boolean isStarted = false; for (TreeIterator tree = editingDomain.treeIterator(getXsdSchema()); tree.hasNext();) { XSDConcreteComponent xsdConcreteComponent = (XSDConcreteComponent)tree.next(); if (!isForward && objects.contains(xsdConcreteComponent)) { break; } else if (isStarted || !isForward) { if (!xsdConcreteComponent.getDiagnostics().isEmpty() || xsdConcreteComponent instanceof XSDParticle && !((XSDParticle)xsdConcreteComponent).getContent().getDiagnostics().isEmpty() || xsdConcreteComponent instanceof XSDAttributeUse && !((XSDAttributeUse)xsdConcreteComponent).getContent().getDiagnostics().isEmpty()) { if (isStarted) { result = xsdConcreteComponent; break; } result = xsdConcreteComponent; } } else if (objects.contains(xsdConcreteComponent)) { isStarted = true; } } setObjectToSelect(result); } } /** * This is used to implement the select next/previous component use action. */ class SelectUseAction extends SelectObjectAction { boolean isForward; public SelectUseAction( boolean isForward, StructuredViewer structuredViewer ) { super( structuredViewer, isForward ? XsdUiPlugin.Util.getString("XsdEditor.Select_&Next_Use_46") : XsdUiPlugin.Util.getString("XsdEditor.Select_&Previous_Use_47"), //$NON-NLS-1$ //$NON-NLS-2$ ExtendedImageRegistry.INSTANCE.getImageDescriptor(XsdUiPlugin.INSTANCE.getImage(isForward ? "icons/full/elcl16/SelectNextUseObject.gif" : "icons/full/elcl16/SelectPreviousUseObject.gif"))); //$NON-NLS-1$ //$NON-NLS-2$ this.isForward = isForward; setHoverImageDescriptor(ExtendedImageRegistry.INSTANCE.getImageDescriptor(XsdUiPlugin.INSTANCE.getImage(isForward ? "icons/full/clcl16/SelectNextUseObject.gif" : "icons/full/clcl16/SelectPreviousUseObject.gif"))); //$NON-NLS-1$ //$NON-NLS-2$ setDisabledImageDescriptor(ExtendedImageRegistry.INSTANCE.getImageDescriptor(XsdUiPlugin.INSTANCE.getImage(isForward ? "icons/full/dlcl16/SelectNextUseObject.gif" : "icons/full/dlcl16/SelectPreviousUseObject.gif"))); //$NON-NLS-1$ //$NON-NLS-2$ setToolTipText(isForward ? XsdUiPlugin.Util.getString("XsdEditor.Select_&Next_Use_46") //$NON-NLS-1$ : XsdUiPlugin.Util.getString("XsdEditor.Select_&Previous_Use_47")); //$NON-NLS-1$ } public void updateAction() { setCurrentObjects(((IStructuredSelection)structuredViewer.getSelection()).toList()); } public void setCurrentObjects( List objects ) { XSDConcreteComponent result = null; final List resolvedObjects = new ArrayList(); for (Iterator i = objects.iterator(); i.hasNext();) { XSDConcreteComponent xsdConcreteComponent = (XSDConcreteComponent)i.next(); XSDConcreteComponent resolvedObject = getResolvedObject(xsdConcreteComponent); if (! this.equals(resolvedObject)) { resolvedObjects.add(resolvedObject); } } boolean isStarted = false; for (TreeIterator tree = editingDomain.treeIterator(getXsdSchema()); tree.hasNext();) { XSDConcreteComponent xsdConcreteComponent = (XSDConcreteComponent)tree.next(); if (!isForward && objects.contains(xsdConcreteComponent)) { break; } else if (isStarted || !isForward) { XSDConcreteComponent resolvedObject = getResolvedObject(xsdConcreteComponent); if (resolvedObjects.contains(resolvedObject)) { if (isStarted) { result = xsdConcreteComponent; break; } result = xsdConcreteComponent; } } else if (objects.contains(xsdConcreteComponent)) { isStarted = true; } } setObjectToSelect(result); } } public static class GenericXMLResourceFactoryImpl extends XMLResourceFactoryImpl { protected XMLResource.XMLMap xmlMap = new XMLMapImpl(); public GenericXMLResourceFactoryImpl() { super(); } @Override public Resource createResource( URI uri ) { XMLResource result = new GenericXMLResourceImpl(uri); result.getDefaultSaveOptions().put(XMLResource.OPTION_XML_MAP, xmlMap); result.getDefaultLoadOptions().put(XMLResource.OPTION_XML_MAP, xmlMap); return result; } } public static class GenericXMLResourceImpl extends XMLResourceImpl { protected XSDEcoreBuilder xsdEcoreBuilder; protected XMLHelper xmlHelper; public GenericXMLResourceImpl( URI uri ) { super(uri); } @Override protected XMLHelper createXMLHelper() { if (xmlHelper == null) { xmlHelper = new XMLHelperImpl(this) { @Override protected String getQName( String uri, String name ) { if (uri == null) { return name; } EPackage pkg = xsdEcoreBuilder.getTargetNamespaceToEPackageMap().get(uri); if (pkg == null || pkg.getNsPrefix().equals("")) //$NON-NLS-1$ { return name; } packages.put(pkg, null); return pkg.getNsPrefix() + ":" + name; //$NON-NLS-1$ } }; } return xmlHelper; } @Override public void doLoad( InputStream inputStream, final Map op ) throws IOException { XMLLoad xmlStart = new XMLLoadImpl(createXMLHelper()) { @Override protected DefaultHandler makeDefaultHandler() { final XMLResource resrc = resource; SAXXMLHandler saxXMLHandler = new SAXXMLHandler(resrc, helper, op) { protected MyStack elementDeclarations = new MyStack(); protected MyStack dfaStates = new MyStack(); @Override protected void createTopObject( String prefix, String name ) { String namespaceURI = helper.getURI(prefix); for (int i = 0, size = attribs.getLength(); i < size; ++i) { String attributeName = attribs.getQName(i); int index = attributeName.indexOf(":"); //$NON-NLS-1$ String attributeNamespaceURI = null; String attributeLocalName = attributeName; if (index != -1) { attributeNamespaceURI = helper.getURI(attributeName.substring(0, index)); attributeLocalName = attributeName.substring(index + 1); } if (XSDConstants.SCHEMA_INSTANCE_URI_2001.equals(attributeNamespaceURI) && (namespaceURI == null ? XsdUiPlugin.Util.getString("XsdEditor.noSchemaLocation_57") : XsdUiPlugin.Util.getString("XsdEditor.schemaLocation_58")).equals(attributeLocalName)) //$NON-NLS-1$ //$NON-NLS-2$ { String schemaLocationHint = null; if (namespaceURI == null) { schemaLocationHint = attribs.getValue(i); } else { for (StringTokenizer stringTokenizer = new StringTokenizer(attribs.getValue(i)); stringTokenizer.hasMoreTokens();) { String namespaceURIHint = stringTokenizer.nextToken(); if (stringTokenizer.hasMoreTokens()) { if (namespaceURIHint.equals(namespaceURI)) { schemaLocationHint = stringTokenizer.nextToken(); break; } stringTokenizer.nextToken(); } else { break; } } } if (schemaLocationHint != null) { URI uri = URI.createURI(schemaLocationHint); if (resolve && uri.isRelative() && uri.hasRelativePath()) { uri = uri.resolve(resourceURI); } xsdEcoreBuilder = new XSDEcoreBuilder(); Collection resources = xsdEcoreBuilder.generateResources(uri); resrc.getResourceSet().getResources().addAll(resources); } } } if (xsdEcoreBuilder == null) { error(new XMIException( XsdUiPlugin.Util.getString("XsdEditor.Cannot_resolve_schema_location_59"), getLocation(), getLineNumber(), getColumnNumber())); //$NON-NLS-1$ } else { XSDElementDeclaration xsdElementDeclaration = xsdEcoreBuilder.getSchema().resolveElementDeclaration(namespaceURI, name); EClass eClass = (EClass)xsdEcoreBuilder.getXSDComponentToEModelElementMap().get(xsdElementDeclaration); if (eClass != null) { processTopObject(eClass.getEPackage().getEFactoryInstance().create(eClass)); elementDeclarations.push(xsdElementDeclaration); XSDParticle xsdParticle = xsdElementDeclaration.getTypeDefinition().getComplexType(); if (xsdParticle != null) { dfaStates.push(xsdParticle.getDFA().getInitialState()); } else { dfaStates.push(null); } } else { error(new XMIException( XsdUiPlugin.Util.getString("XsdEditor.Cannot_resolve_EClass__60"), getLocation(), getLineNumber(), getColumnNumber())); //$NON-NLS-1$ } } } @Override protected void processElement( String name, String prefix, String localName ) { if (isError()) { types.push(ERROR_TYPE); } else { if (objects.isEmpty()) { createTopObject(prefix, localName); } else { EObject peekObject = objects.peek(); XSDParticle.DFA.State state = (XSDParticle.DFA.State)dfaStates.peek(); if (state == null) { error(new XMIException( XsdUiPlugin.Util.getString("XsdEditor.Cannot_contain_content__61"), getLocation(), getLineNumber(), getColumnNumber())); //$NON-NLS-1$ } else { XSDParticle.DFA.Transition transition = state.accept(helper.getURI(prefix), localName); if (transition == null) { error(new XMIException( XsdUiPlugin.Util.getString("XsdEditor.Not_expecting_this_element__62"), getLocation(), getLineNumber(), getColumnNumber())); //$NON-NLS-1$ } else { dfaStates.set(dfaStates.size() - 1, transition.getState()); XSDParticle transitionXSDParticle = transition.getParticle(); XSDTerm xsdTerm = transitionXSDParticle.getTerm(); XSDElementDeclaration xsdElementDeclaration = null; if (xsdTerm instanceof XSDElementDeclaration) { xsdElementDeclaration = (XSDElementDeclaration)xsdTerm; } else { xsdElementDeclaration = xsdEcoreBuilder.getSchema().resolveElementDeclaration(helper.getURI(prefix), name); } EClass eClass = (EClass)xsdEcoreBuilder.getXSDComponentToEModelElementMap().get(xsdElementDeclaration); if (eClass != null) { EObject eObject = eClass.getEPackage().getEFactoryInstance().create(eClass); ((EList)peekObject.eGet(peekObject.eClass().getEStructuralFeature(XsdUiPlugin.Util.getString("XsdEditor.contents_63")))).add(eObject); //$NON-NLS-1$ processObject(eObject); elementDeclarations.push(xsdElementDeclaration); XSDParticle xsdParticle = xsdElementDeclaration.getTypeDefinition().getComplexType(); if (xsdParticle != null) { dfaStates.push(xsdParticle.getDFA().getInitialState()); } else { dfaStates.push(null); XSDSimpleTypeDefinition xsdSimpleTypeDefinition = xsdElementDeclaration.getTypeDefinition().getSimpleType(); if (xsdSimpleTypeDefinition != null) { EStructuralFeature valueFeature = eClass.getEStructuralFeature(XsdUiPlugin.Util.getString("XsdEditor.value_64")); //$NON-NLS-1$ if (valueFeature != null) { text = new StringBuffer(); types.set(types.size() - 1, valueFeature); } } } } else { error(new XMIException( XsdUiPlugin.Util.getString("XsdEditor.Cannot_resolve_EClass__65"), getLocation(), getLineNumber(), getColumnNumber())); //$NON-NLS-1$ } } } } } } @Override public void endElement( String uri, String localName, String name ) { EObject topObject = objects.pop(); elements.pop(); Object type = types.pop(); if (text != null) { EAttribute eAttribute = (EAttribute)type; EDataType eDataType = eAttribute.getEAttributeType(); Object value = eDataType.getEPackage().getEFactoryInstance().createFromString(eDataType, text.toString()); topObject.eSet(eAttribute, value); text = null; } XSDParticle.DFA.State state = (XSDParticle.DFA.State)dfaStates.pop(); if (state != null && !state.isAccepting()) { error(new XMIException( XsdUiPlugin.Util.getString("XsdEditor.Need_more_content__66"), getLocation(), getLineNumber(), getColumnNumber())); //$NON-NLS-1$ } elementDeclarations.pop(); } }; return saxXMLHandler; } }; xmlStart.load(this, inputStream, op); } } public static class GenericXMLLoadAction extends org.eclipse.ui.actions.ActionDelegate { protected IFile file; public GenericXMLLoadAction() { } @Override public void run( IAction action ) { ResourceSet resourceSet = new ResourceSetImpl(); resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xml", new GenericXMLResourceFactoryImpl()); //$NON-NLS-1$ Resource resource = resourceSet.getResource(URI.createPlatformResourceURI(file.getFullPath().toString(), true), true); resource.setURI(URI.createPlatformResourceURI(file.getFullPath().toString() + ".save.xml", true)); //$NON-NLS-1$ try { resource.save(Collections.EMPTY_MAP); } catch (IOException exception) { XsdUiPlugin.Util.log(exception); } } @Override public void selectionChanged( IAction action, ISelection selection ) { if (selection instanceof IStructuredSelection) { Object object = ((IStructuredSelection)selection).getFirstElement(); if (object instanceof IFile) { file = (IFile)object; action.setEnabled(true); return; } } file = null; action.setEnabled(false); } } }