blob: 9f830e4ea4e53193932ea5fbf1e5a551bd299742 [file] [log] [blame]
/**
* Copyright (c) 2002-2007 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 - Initial API and implementation
*/
package org.eclipse.xsd.presentation;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EventObject;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.helpers.DefaultHandler;
import org.eclipse.core.resources.IContainer;
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.resources.ResourcesPlugin;
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.core.runtime.SubProgressMonitor;
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.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.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.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.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.emf.common.command.AbstractCommand;
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.ui.ViewerPane;
import org.eclipse.emf.common.ui.celleditor.ExtendedComboBoxCellEditor;
import org.eclipse.emf.common.ui.viewer.IViewerProvider;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
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.util.EcoreUtil;
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.XMLLoadImpl;
import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl;
import org.eclipse.emf.ecore.xml.type.internal.DataValue.EncodingMap;
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.ComposedAdapterFactory;
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.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.emf.edit.ui.util.EditUIUtil;
import org.eclipse.emf.edit.ui.view.ExtendedPropertySheetPage;
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.XSDPackage;
import org.eclipse.xsd.XSDParticle;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
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.XSDParser;
import org.eclipse.xsd.util.XSDResourceFactoryImpl;
import org.eclipse.xsd.util.XSDResourceImpl;
import org.eclipse.xsd.util.XSDSwitch;
/**
* This is a an example of a xsd model editor.
*/
public class XSDEditor
extends MultiPageEditorPart
implements IEditingDomainProvider, ISelectionProvider, IMenuListener, IViewerProvider
{
/**
* 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 syntactic views of the model.
*/
protected ComposedAdapterFactory syntacticAdapterFactory;
/**
* This is the adapter factory used for providing the semantic views of the model.
*/
protected ComposedAdapterFactory 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<ISelectionChangedListener> selectionChangedListeners = new ArrayList<ISelectionChangedListener>();
/**
* This keeps track of the selection of the editor as a whole.
*/
protected ISelection editorSelection = StructuredSelection.EMPTY;
/**
* 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 listens for when things becomes active.
*/
protected IPartListener partListener =
new IPartListener()
{
public void partActivated(IWorkbenchPart p)
{
handlePartActivated(p);
}
public void partBroughtToTop(IWorkbenchPart p)
{
// Ignore
}
public void partClosed(IWorkbenchPart p)
{
// Ignore
}
public void partDeactivated(IWorkbenchPart p)
{
// Ignore
}
public void partOpened(IWorkbenchPart p)
{
// Ignore
}
};
/**
* This creates a model editor.
*/
public XSDEditor()
{
super();
// Create an adapter factory that yields item providers.
//
syntacticAdapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
syntacticAdapterFactory.addAdapterFactory(new XSDItemProviderAdapterFactory());
semanticAdapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
semanticAdapterFactory.addAdapterFactory(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()
{
public void commandStackChanged(final EventObject event)
{
getContainer().getDisplay().asyncExec
(new Runnable()
{
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());
}
if (!(mostRecentCommand instanceof AbstractCommand.NonDirtying))
{
handleStructuredModelChange();
}
updateActions();
if (propertySheetPage != null)
{
propertySheetPage.refresh();
}
}
});
}
});
// Create the editing domain with a special command stack.
//
editingDomain = new AdapterFactoryEditingDomain(syntacticAdapterFactory, commandStack);
// Register our xsd resource factory for this context.
//
editingDomain.getResourceSet().getResourceFactoryRegistry().getExtensionToFactoryMap().put("xsd", new XSDResourceFactoryImpl());
}
protected void updateActions()
{
if (selectNextDiagnosticsAction != null)
{
selectNextDiagnosticsAction.updateAction();
selectPreviousDiagnosticsAction.updateAction();
selectNextUseAction.updateAction();
selectPreviousUseAction.updateAction();
}
}
protected String determineEncoding()
{
String encoding = (String)((XSDResourceImpl)xsdSchema.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 (xsdSchema.getElement() == null)
{
xsdSchema.updateElement();
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
try
{
xsdSchema.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);
}
catch (Exception exception)
{
XSDEditorPlugin.INSTANCE.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())
{
Runnable runnable =
new Runnable()
{
public void run()
{
Viewer viewer = currentViewer;
if (viewer == sourceViewer)
{
if (contentOutlineViewer != null && !contentOutlineViewer.getControl().isDisposed())
{
viewer = contentOutlineViewer;
}
}
// Try to select the items in the current content viewer of the editor.
//
if (viewer != null)
{
StructuredSelection selection = new StructuredSelection(collection.toArray());
viewer.setSelection(selection, true);
if (currentViewer == sourceViewer)
{
handleContentOutlineSelectionForTextEditor(selection, true);
}
}
}
};
getSite().getShell().getDisplay().asyncExec(runnable);
}
}
/**
* 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 org.eclipse.emf.edit.ui.action.CommandAction}.
*/
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.
//
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 action refreshes the viewer of the current editor if the editor
* implements {@link org.eclipse.emf.common.ui.viewer.IViewerProvider}.
*/
protected IAction refreshViewerAction =
new Action(XSDEditorPlugin.INSTANCE.getString("_UI_RefreshViewer_menu_item"))
{
@Override
public boolean isEnabled()
{
return activeEditorPart instanceof IViewerProvider;
}
@Override
public void run()
{
if (activeEditorPart instanceof IViewerProvider)
{
Viewer viewer = ((IViewerProvider)activeEditorPart).getViewer();
if (viewer != null)
{
viewer.refresh();
}
}
}
};
/**
* This action opens the Properties view.
*/
protected IAction showPropertiesViewAction =
new Action(XSDEditorPlugin.INSTANCE.getString("_UI_ShowPropertiesView_menu_item"))
{
@Override
public void run()
{
try
{
getPage().showView("org.eclipse.ui.views.PropertySheet");
}
catch (PartInitException exception)
{
XSDEditorPlugin.INSTANCE.log(exception);
}
}
};
/**
* This action enable or disable automatic validation.
*/
protected IAction validateAutomaticallyAction =
new Action(XSDEditorPlugin.INSTANCE.getString("_UI_ValidateAutomatically_menu_item"))
{
@Override
public void run()
{
((XSDEditor)activeEditorPart).setValidateAutomatically(isChecked());
}
};
/**
* This will contain one CreateChildAction corresponding to each
* descriptor generated for the current selection.
*/
protected Collection<IAction> createChildActions = Collections.emptyList();
/**
* 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<IAction> createSiblingActions = Collections.emptyList();
/**
* 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()
{
super(ADDITIONS_LAST_STYLE);
}
/**
* 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(XSDEditorPlugin.INSTANCE.getString("_UI_XSDEditor_menu"), "org.eclipse.xsdMenuID");
menuManager.insertAfter("additions", submenuManager);
submenuManager.add(new Separator("settings"));
submenuManager.add(new Separator("actions"));
submenuManager.add(new Separator("additions"));
submenuManager.add(new Separator("additions-end"));
// prepare for child and sibling creation item addition/removal
createChildMenuManager = new MenuManager(XSDEditorPlugin.INSTANCE.getString("_UI_CreateChild_menu_item"));
createSiblingMenuManager = new MenuManager(XSDEditorPlugin.INSTANCE.getString("_UI_CreateSibling_menu_item"));
submenuManager.insertBefore("additions", new Separator("actions"));
submenuManager.insertBefore("additions", createChildMenuManager);
submenuManager.insertBefore("additions", createSiblingMenuManager);
// Force an update because Eclipse hides empty menus now.
//
submenuManager.addMenuListener
(new IMenuListener()
{
public void menuAboutToShow(IMenuManager menuManager)
{
menuManager.updateAll(true);
}
});
validateAutomaticallyAction.setChecked(true);
submenuManager.insertAfter("additions-end", validateAutomaticallyAction);
addGlobalActions(submenuManager);
}
/**
* This adds Separators to the tool bar.
*/
@Override
public void contributeToToolBar(IToolBarManager toolBarManager)
{
toolBarManager.add(new Separator("xsd-settings"));
toolBarManager.add(new Separator("xsd-additions"));
}
/**
* 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()));
if (part instanceof XSDEditor)
{
validateAutomaticallyAction.setChecked(((XSDEditor)part).isValidateAutomatically());
}
}
/**
* 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.
*/
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.emptyList();
Collection<?> newSiblingDescriptors = Collections.emptyList();
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<IAction> generateCreateChildActions(Collection<?> descriptors, ISelection selection)
{
Collection<IAction> actions = new LinkedList<IAction>();
for (Object descriptor : descriptors)
{
actions.add(new CreateChildAction(activeEditorPart, selection, descriptor));
}
return actions;
}
/**
* This generates a {@link CreateSiblingAction} for each object in
* <code>descriptors</code>, and returns the collection of these actions.
*/
protected Collection<IAction> generateCreateSiblingActions(Collection<?> descriptors, ISelection selection)
{
Collection<IAction> actions = new LinkedList<IAction>();
for (Object descriptor : descriptors)
{
actions.add(new CreateSiblingAction(activeEditorPart, selection, descriptor));
}
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<IAction> actions, String ID)
{
for (IAction action : actions)
{
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<IAction> 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 submenuManager = new MenuManager(XSDEditorPlugin.INSTANCE.getString("_UI_CreateChild_menu_item"));
populateManager(submenuManager, createChildActions, null);
menuManager.insertBefore("edit", submenuManager);
submenuManager = new MenuManager(XSDEditorPlugin.INSTANCE.getString("_UI_CreateSibling_menu_item"));
populateManager(submenuManager, createSiblingActions, null);
menuManager.insertBefore("edit", submenuManager);
}
/**
* This inserts global actions before the "additions-end" separator.
*/
@Override
protected void addGlobalActions(IMenuManager menuManager)
{
menuManager.insertAfter("additions-end", new Separator("ui-actions"));
menuManager.insertAfter("ui-actions", showPropertiesViewAction);
refreshViewerAction.setEnabled(refreshViewerAction.isEnabled());
menuManager.insertAfter("ui-actions", refreshViewerAction);
super.addGlobalActions(menuManager);
}
}
/**
* This returns the viewer as required by the {@link IViewerProvider} interface.
*/
public Viewer getViewer()
{
return currentViewer;
}
/**
* 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");
contextMenu.add(new Separator("additions"));
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().createResource(URI.createURI(uri), XSDPackage.eCONTENT_TYPE);
xsdResource.load(editingDomain.getResourceSet().getLoadOptions());
xsdSchema = xsdResource.getSchema();
}
catch (Exception exception)
{
XSDEditorPlugin.INSTANCE.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) throws CoreException
{
try
{
progressMonitor.beginTask("", 12);
editingDomain.getResourceSet().getLoadOptions().put(XSDResourceImpl.XSD_PROGRESS_MONITOR, progressMonitor);
createResource(EditUIUtil.getURI(getEditorInput()).toString());
editingDomain.getResourceSet().getLoadOptions().remove(XSDResourceImpl.XSD_PROGRESS_MONITOR);
progressMonitor.worked(1);
progressMonitor.subTask(XSDEditorPlugin.INSTANCE.getString("_UI_Validating_message"));
if (xsdSchema.getDiagnostics().isEmpty())
{
xsdSchema.validate();
}
if (determineEncoding() != null && getEditorInput() instanceof IFileEditorInput)
{
((IFileEditorInput)getEditorInput()).getFile().setCharset(determineEncoding(), new SubProgressMonitor(progressMonitor, 2));
}
progressMonitor.worked(1);
progressMonitor.subTask(XSDEditorPlugin.INSTANCE.getString("_UI_ReportingErrors_message"));
}
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)
{
XSDEditorPlugin.INSTANCE.log(exception);
}
}
protected void handleSourceCaretPosition()
{
int offset = sourceViewer.getTextWidget().getCaretOffset();
Element element = xsdSchema.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)
{
// Ignore
}
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<? extends Node> nodes)
{
Collection<Object> selection = new ArrayList<Object>();
for (Node node : nodes)
{
XSDConcreteComponent bestXSDConcreteComponent = xsdSchema.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();
xsdParser.parseString(documentContent);
xsdSchema.clearDiagnostics();
xsdParser.setSchema(xsdSchema);
if (validateAutomatically)
{
xsdSchema.validate();
handleDiagnostics(null);
}
}
catch (Exception exception)
{
XSDEditorPlugin.INSTANCE.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;
}
};
createModel();
int pageIndex = addPage(textEditor, getEditorInput());
handleDiagnostics(null);
setPageText(pageIndex, XSDEditorPlugin.INSTANCE.getString("_UI_Source_title"));
IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
document.addDocumentListener
(new IDocumentListener()
{
protected Timer timer = new Timer();
protected TimerTask timerTask;
public void documentAboutToBeChanged(DocumentEvent documentEvent)
{
// Ingore
}
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()
{
public void run()
{
handleDocumentChange();
}
});
}
};
timer.schedule(timerTask, 1000);
}
}
catch (Exception exception)
{
XSDEditorPlugin.INSTANCE.log(exception);
}
}
});
}
catch (Exception exception)
{
XSDEditorPlugin.INSTANCE.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.
//
public void selectionChanged(SelectionChangedEvent selectionChangedEvent)
{
if (currentViewer == semanticSelectionViewer && contentOutlineViewer != null)
{
contentOutlineViewer.setSelection(selectionChangedEvent.getSelection(), true);
}
}
});
semanticSelectionViewer.setInput(new ItemProvider(Collections.singleton(xsdSchema)));
viewerPane.setTitle(xsdSchema);
new AdapterFactoryTreeEditor(semanticSelectionViewer.getTree(), semanticAdapterFactory);
createContextMenuFor(semanticSelectionViewer);
int pageIndex = addPage(viewerPane.getControl());
setPageText(pageIndex, XSDEditorPlugin.INSTANCE.getString("_UI_Semantics_title"));
}
}
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(xsdSchema)));
viewerPane.setTitle(xsdSchema);
new AdapterFactoryTreeEditor(syntacticSelectionViewer.getTree(), syntacticAdapterFactory);
createContextMenuFor(syntacticSelectionViewer);
int pageIndex = addPage(viewerPane.getControl());
setPageText(pageIndex, XSDEditorPlugin.INSTANCE.getString("_UI_Syntax_title"));
}
}
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 && /* !xsdDiagnostic.isSetLine() && */ 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)
{
// Ignore
}
}
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.
//
public void run(IProgressMonitor localProgressMonitor) throws CoreException
{
handleDiagnostics(localProgressMonitor);
}
};
try
{
ResourcesPlugin.getWorkspace().run(operation, new NullProgressMonitor());
// getSite().getWorkbenchWindow().run(false, false, operation);
}
catch (Exception exception)
{
XSDEditorPlugin.INSTANCE.log(exception);
}
}
else
{
XSDConcreteComponent newSelection = null;
if (getEditorInput() instanceof IFileEditorInput)
{
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<IMarker> deletableMarkers = new ArrayList<IMarker>(Arrays.asList(markers));
if (validateAutomatically)
{
for (XSDDiagnostic xsdDiagnostic : xsdSchema.getAllDiagnostics())
{
String uriReferencePath = xsdSchema.eResource().getURIFragment(xsdDiagnostic);
IMarker marker = null;
for (int i = 0; i < markers.length; ++i)
{
if (markers[i].getAttribute(XSDDiagnostic.URI_FRAGMENT_ATTRIBUTE, "").equals(uriReferencePath))
{
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 (IMarker marker : deletableMarkers)
{
marker.delete();
}
}
catch (Exception exception)
{
XSDEditorPlugin.INSTANCE.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()
{
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);
}
if (contentOutlinePage != null)
{
handleContentOutlineSelection(contentOutlinePage.getSelection());
}
}
/**
* This is how the framework determines which interfaces we implement.
*/
@SuppressWarnings("rawtypes")
@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<Object>()
{
@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;
}
else
{
return resolvedObject;
}
}
}.doSwitch(xsdConcreteComponent);
return result == null ? xsdConcreteComponent : result;
}
/**
* 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 (Object object : selection.toList())
{
XSDConcreteComponent xsdConcreteComponent = (XSDConcreteComponent)object;
Object resolvedObject = getResolvedObject(xsdConcreteComponent);
if (xsdConcreteComponent != resolvedObject)
{
contentOutlineViewer.setSelection(new StructuredSelection(new Object [] {resolvedObject}), true);
break;
}
else if (xsdConcreteComponent instanceof XSDAttributeDeclaration)
{
XSDAttributeDeclaration xsdAttributeDeclaration = (XSDAttributeDeclaration)xsdConcreteComponent;
XSDSimpleTypeDefinition typeDefinition = xsdAttributeDeclaration.getTypeDefinition();
if (typeDefinition != null && typeDefinition.getSchema() == xsdAttributeDeclaration.getSchema())
{
contentOutlineViewer.setSelection(new StructuredSelection(new Object [] {typeDefinition}), true);
break;
}
}
else if (xsdConcreteComponent instanceof XSDElementDeclaration)
{
XSDElementDeclaration xsdElementDeclaration = (XSDElementDeclaration)xsdConcreteComponent;
XSDTypeDefinition typeDefinition = xsdElementDeclaration.getTypeDefinition();
if (typeDefinition != null && typeDefinition.getSchema() == xsdElementDeclaration.getSchema())
{
contentOutlineViewer.setSelection(new StructuredSelection(new Object [] {typeDefinition}), true);
break;
}
}
else if (xsdConcreteComponent instanceof XSDSimpleTypeDefinition)
{
XSDSimpleTypeDefinition xsdSimpleTypeDefinition = (XSDSimpleTypeDefinition)xsdConcreteComponent;
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 (xsdConcreteComponent instanceof XSDComplexTypeDefinition)
{
XSDComplexTypeDefinition xsdComplexTypeDefinition = (XSDComplexTypeDefinition)xsdConcreteComponent;
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(xsdSchema)));
// Make sure our popups work.
//
createContextMenuFor(contentOutlineViewer);
// Select the root object in the view.
//
ArrayList<Object> selection = new ArrayList<Object>();
selection.add(xsdSchema);
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.
//
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.
//
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 ExtendedPropertySheetPage(editingDomain)
{
@Override
public void makeContributions(IMenuManager menuManager, IToolBarManager toolBarManager, IStatusLineManager statusLineManager)
{
super.makeContributions(menuManager, toolBarManager, statusLineManager);
}
@Override
public void setSelectionToViewer(List<?> selection)
{
XSDEditor.this.setSelectionToViewer(selection);
XSDEditor.this.setFocus();
}
@Override
public void setActionBars(IActionBars actionBars)
{
super.setActionBars(actionBars);
getActionBarContributor().shareGlobalActions(this, actionBars);
}
};
propertySheetPage.setPropertySourceProvider
(new AdapterFactoryContentProvider(syntacticAdapterFactory)
{
@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<Object>(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<Object> selectionList = new ArrayList<Object>();
for (Object object : ((IStructuredSelection)selection).toList())
{
selectionList.add(getResolvedObject((XSDConcreteComponent)object));
}
// 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)
{
XSDEditorPlugin.INSTANCE.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();
}
/**
* This is for implementing {@link IEditorPart} and simply saves the model file.
*/
@Override
public void doSave(IProgressMonitor progressMonitor)
{
// 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) throws CoreException
{
try
{
// Save the resource to the file system.
//
xsdSchema.eResource().save(Collections.EMPTY_MAP);
}
catch (Exception exception)
{
XSDEditorPlugin.INSTANCE.log(exception);
}
}
};
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);
// Refresh the necessary state.
//
((BasicCommandStack)editingDomain.getCommandStack()).saveIsDone();
textEditor.doRevertToSaved();
firePropertyChange(IEditorPart.PROP_DIRTY);
}
catch (Exception exception)
{
// Something went wrong that shouldn't.
//
XSDEditorPlugin.INSTANCE.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 = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
if (file != null)
{
xsdSchema.eResource().setURI(URI.createPlatformResourceURI(file.getFullPath().toString(), true));
IFileEditorInput modelFile = new FileEditorInput(file);
setInput(modelFile);
setPartName(file.getName());
doSave(getActionBars().getStatusLineManager().getProgressMonitor());
}
}
}
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)
{
XSDEditorPlugin.INSTANCE.log(exception);
}
}
/**
* This is called during startup.
*/
@Override
public void init(IEditorSite site, IEditorInput editorInput) throws PartInitException
{
setSite(site);
setInput(editorInput);
setPartName(editorInput.getName());
site.setSelectionProvider(new MultiPageSelectionProvider(this));
site.getPage().addPartListener(partListener);
}
@Override
public void setFocus()
{
if (currentViewerPane != null)
{
currentViewerPane.setFocus();
}
else
{
getControl(getActivePage()).setFocus();
}
}
/**
* This implements {@link org.eclipse.jface.viewers.ISelectionProvider}.
*/
public void addSelectionChangedListener(ISelectionChangedListener listener)
{
selectionChangedListeners.add(listener);
}
/**
* This implements {@link org.eclipse.jface.viewers.ISelectionProvider}.
*/
public void removeSelectionChangedListener(ISelectionChangedListener listener)
{
selectionChangedListeners.remove(listener);
}
/**
* This implements {@link org.eclipse.jface.viewers.ISelectionProvider} to return this editor's overall selection.
*/
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.
*/
public void setSelection(ISelection selection)
{
editorSelection = selection;
SelectionChangedEvent selectionChangedEvent = new SelectionChangedEvent(this, selection);
((MultiPageSelectionProvider)getSite().getSelectionProvider()).fireSelectionChanged(selectionChangedEvent);
for (ISelectionChangedListener listener : selectionChangedListeners)
{
listener.selectionChanged(selectionChangedEvent);
}
setStatusLineManager(selection);
}
/**
* This shows the selection on the status line.
*/
public void setStatusLineManager(ISelection selection)
{
IStatusLineManager statusLineManager = currentViewer != null && currentViewer == contentOutlineViewer ?
contentOutlineStatusLineManager : getActionBars().getStatusLineManager();
if (statusLineManager != null)
{
if (selection instanceof IStructuredSelection)
{
Collection<?> collection = ((IStructuredSelection)selection).toList();
switch (collection.size())
{
case 0:
{
statusLineManager.setMessage(XSDEditorPlugin.INSTANCE.getString("_UI_NoObjectSelected"));
break;
}
case 1:
{
Object object = collection.iterator().next();
String text = new AdapterFactoryItemDelegator(syntacticAdapterFactory).getText(object);
text = XSDEditorPlugin.INSTANCE.getString("_UI_SingleObjectSelected", new Object [] { text });
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
(XSDEditorPlugin.INSTANCE.getString("_UI_MultiObjectSelected", new Object [] { Integer.toString(collection.size()) }));
break;
}
}
}
else
{
statusLineManager.setMessage("");
}
}
}
/**
* This implements {@link org.eclipse.jface.action.IMenuListener} to help fill the context menus with contributions from the Edit menu.
*/
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();
}
protected boolean validateAutomatically = true;
public void setValidateAutomatically(boolean validateAutomatically)
{
this.validateAutomatically = validateAutomatically;
if (validateAutomatically)
{
handleDocumentChange();
}
else
{
handleDiagnostics(null);
}
}
public boolean isValidateAutomatically()
{
return validateAutomatically;
}
/**
* 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) :
Collections.EMPTY_LIST);
}
public void setObjectsToSelect(Collection<?> objectsToSelect)
{
this.objectsToSelect = new ArrayList<Object>(objectsToSelect);
setEnabled(!objectsToSelect.isEmpty());
}
@Override
public void run()
{
structuredViewer.setSelection(new StructuredSelection(objectsToSelect.toArray()), 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 ? "Select &Next Diagnosed Object" : "Select &Previous Diagnosed Object",
ExtendedImageRegistry.INSTANCE.getImageDescriptor
(XSDEditorPlugin.INSTANCE.getImage
(isForward ? "full/elcl16/SelectNextDiagnosticObject" : "full/elcl16/SelectPreviousDiagnosticObject")));
this.isForward = isForward;
setHoverImageDescriptor
(ExtendedImageRegistry.INSTANCE.getImageDescriptor
(XSDEditorPlugin.INSTANCE.getImage
(isForward ? "full/clcl16/SelectNextDiagnosticObject" : "full/clcl16/SelectPreviousDiagnosticObject")));
setDisabledImageDescriptor
(ExtendedImageRegistry.INSTANCE.getImageDescriptor
(XSDEditorPlugin.INSTANCE.getImage
(isForward ? "full/dlcl16/SelectNextDiagnosticObject" : "full/dlcl16/SelectPreviousDiagnosticObject")));
}
public void updateAction()
{
setCurrentObjects(((IStructuredSelection)structuredViewer.getSelection()).toList());
}
public void setCurrentObjects(List<?> objects)
{
XSDConcreteComponent result = null;
boolean isStarted = false;
for (TreeIterator<?> tree = editingDomain.treeIterator(xsdSchema); 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;
}
else
{
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 ? "Select &Next Use" : "Select &Previous Use",
ExtendedImageRegistry.INSTANCE.getImageDescriptor
(XSDEditorPlugin.INSTANCE.getImage
(isForward ? "full/elcl16/SelectNextUseObject" : "full/elcl16/SelectPreviousUseObject")));
this.isForward = isForward;
setHoverImageDescriptor
(ExtendedImageRegistry.INSTANCE.getImageDescriptor
(XSDEditorPlugin.INSTANCE.getImage
(isForward ? "full/clcl16/SelectNextUseObject" : "full/clcl16/SelectPreviousUseObject")));
setDisabledImageDescriptor
(ExtendedImageRegistry.INSTANCE.getImageDescriptor
(XSDEditorPlugin.INSTANCE.getImage
(isForward ? "full/dlcl16/SelectNextUseObject" : "full/dlcl16/SelectPreviousUseObject")));
}
public void updateAction()
{
setCurrentObjects(((IStructuredSelection)structuredViewer.getSelection()).toList());
}
public void setCurrentObjects(List<?> objects)
{
XSDConcreteComponent result = null;
final List<Object> resolvedObjects = new ArrayList<Object>();
for (Object object : objects)
{
XSDConcreteComponent xsdConcreteComponent = (XSDConcreteComponent)object;
XSDConcreteComponent resolvedObject = getResolvedObject(xsdConcreteComponent);
if (resolvedObject != this)
{
resolvedObjects.add(resolvedObject);
}
}
boolean isStarted = false;
for (TreeIterator<?> tree = editingDomain.treeIterator(xsdSchema); 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;
}
else
{
result = xsdConcreteComponent;
}
}
}
else if (objects.contains(xsdConcreteComponent))
{
isStarted = true;
}
}
setObjectToSelect(result);
}
}
public static class GenericXMLResourceFactoryImpl extends XMLResourceFactoryImpl
{
public GenericXMLResourceFactoryImpl()
{
super();
}
@Override
public Resource createResource(URI uri)
{
XMLResource result = new GenericXMLResourceImpl(uri);
result.getDefaultSaveOptions().put(XMLResource.OPTION_EXTENDED_META_DATA, Boolean.TRUE);
result.getDefaultLoadOptions().put(XMLResource.OPTION_EXTENDED_META_DATA, Boolean.TRUE);
result.getDefaultLoadOptions().put(XMLResource.OPTION_USE_LEXICAL_HANDLER, Boolean.TRUE);
result.getDefaultSaveOptions().put(XMLResource.OPTION_LINE_WIDTH, 80);
result.getDefaultSaveOptions().put(XMLResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
return result;
}
}
public static class GenericXMLResourceImpl extends XMLResourceImpl
{
protected XSDEcoreBuilder xsdEcoreBuilder;
public GenericXMLResourceImpl(URI uri)
{
super(uri);
}
@Override
protected XMLLoad createXMLLoad()
{
return
new XMLLoadImpl(createXMLHelper())
{
@Override
protected DefaultHandler makeDefaultHandler()
{
return
new SAXXMLHandler(resource, helper, options)
{
@Override
protected void handleTopLocations(String prefix, String name)
{
if (urisToLocations != null)
{
xsdEcoreBuilder = new XSDEcoreBuilder(extendedMetaData);
Collection<Resource> resources = xsdEcoreBuilder.generateResources(urisToLocations.values());
resource.getResourceSet().getResources().addAll(resources);
}
// Ensure that anything can be handled, even if it's not recognized.
//
String namespaceURI = helper.getURI(prefix);
if (extendedMetaData.getPackage(namespaceURI) == null)
{
extendedMetaData.demandFeature(namespaceURI, name, true);
}
}
};
}
};
}
/*
public void doLoad(InputStream inputStream, final Map op) throws IOException
{
XMLLoad xmlStart =
new XMLLoadImpl(createXMLHelper())
{
protected DefaultHandler makeDefaultHandler()
{
SAXXMLHandler saxXMLHandler =
new SAXXMLHandler(resource, helper, op)
{
protected MyStack elementDeclarations = new MyStack();
protected MyStack dfaStates = new MyStack();
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(":");
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 ? "noNamespaceSchemaLocation" : "schemaLocation").equals(attributeLocalName))
{
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;
}
else
{
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);
resource.getResourceSet().getResources().addAll(resources);
}
}
}
if (xsdEcoreBuilder == null)
{
error(new XMIException("Cannot resolve schema location", getLocation(), getLineNumber(), getColumnNumber()));
}
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("Cannot resolve EClass ", getLocation(), getLineNumber(), getColumnNumber()));
}
}
}
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 = (EObject)objects.peek();
XSDParticle.DFA.State state = (XSDParticle.DFA.State)dfaStates.peek();
if (state == null)
{
error(new XMIException("Cannot contain content ", getLocation(), getLineNumber(), getColumnNumber()));
}
else
{
XSDParticle.DFA.Transition transition = state.accept(helper.getURI(prefix), localName);
if (transition == null)
{
error(new XMIException("Not expecting this element ", getLocation(), getLineNumber(), getColumnNumber()));
}
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("contents"))).add(eObject);
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("value");
if (valueFeature != null)
{
text = new StringBuffer();
types.set(types.size() - 1, valueFeature);
}
}
}
}
else
{
error(new XMIException("Cannot resolve EClass ", getLocation(), getLineNumber(), getColumnNumber()));
}
}
}
}
}
}
public void endElement(String uri, String localName, String name)
{
EObject topObject = (EObject)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("Need more content ", getLocation(), getLineNumber(), getColumnNumber()));
}
elementDeclarations.pop();
}
};
return new SAXWrapper(saxXMLHandler);
}
};
xmlStart.load(this, inputStream, op);
}
*/
}
public static class GenericXMLLoadAction extends org.eclipse.ui.actions.ActionDelegate implements org.eclipse.ui.IActionDelegate
{
protected IFile file;
protected IContainer container;
public GenericXMLLoadAction()
{
super();
}
@Override
public void run(IAction action)
{
if (file != null)
{
execute(file);
}
else
{
execute(container);
}
}
public void execute(IContainer container)
{
try
{
IResource [] contents = container.members();
for (int i = 0; i < contents.length; ++i)
{
IResource resource = contents[i];
if (resource.getType() == IResource.FILE)
{
if ("xml".equals(resource.getLocation().getFileExtension()) &&
resource.getName().indexOf(".xml") == resource.getName().lastIndexOf(".xml"))
{
execute((IFile)resource);
}
}
else
{
execute((IContainer)resource);
}
}
}
catch (CoreException exception)
{
XSDEditorPlugin.INSTANCE.log(exception);
exception.printStackTrace();
}
}
public void execute(IFile file)
{
System.err.println("Processing: " + file.getFullPath());
ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xml", new GenericXMLResourceFactoryImpl());
Resource resource = resourceSet.getResource(URI.createPlatformResourceURI(file.getFullPath().toString(), true), true);
resource.setURI(URI.createPlatformResourceURI(file.getFullPath().toString() + ".save.xml", true));
try
{
resource.save(Collections.EMPTY_MAP);
}
catch (IOException exception)
{
XSDEditorPlugin.INSTANCE.log(exception);
exception.printStackTrace();
}
List<EPackage> ePackages = new ArrayList<EPackage>();
for (Resource otherResource : resourceSet.getResources())
{
for (Object object : otherResource.getContents())
{
if (object instanceof EPackage)
{
ePackages.add((EPackage)object);
}
}
}
Resource ePackagesResource = resourceSet.createResource(URI.createPlatformResourceURI(file.getFullPath().toString() + ".ecore", true));
ePackagesResource.getContents().addAll(EcoreUtil.copyAll(ePackages));
try
{
ePackagesResource.save(Collections.EMPTY_MAP);
}
catch (IOException exception)
{
XSDEditorPlugin.INSTANCE.log(exception);
exception.printStackTrace();
}
try
{
XSDParser xsdParser = new XSDParser(null);
xsdParser.parse(URI.createPlatformResourceURI(file.getFullPath().toString(), true).toString());
Document document = xsdParser.getDocument();
OutputStream outputStream =
resourceSet.getURIConverter().createOutputStream
(URI.createPlatformResourceURI(file.getFullPath().toString() + ".format.xml", true));
XSDResourceImpl.serialize(outputStream, document);
outputStream.close();
}
catch (IOException exception)
{
XSDEditorPlugin.INSTANCE.log(exception);
exception.printStackTrace();
}
try
{
XSDParser xsdParser = new XSDParser(null);
xsdParser.parse(URI.createPlatformResourceURI(file.getFullPath().toString() + ".save.xml", true).toString());
Document document = xsdParser.getDocument();
OutputStream outputStream =
resourceSet.getURIConverter().createOutputStream
(URI.createPlatformResourceURI(file.getFullPath().toString() + ".save.format.xml", true));
XSDResourceImpl.serialize(outputStream, document);
outputStream.close();
}
catch (IOException exception)
{
XSDEditorPlugin.INSTANCE.log(exception);
exception.printStackTrace();
}
}
@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;
}
else if (object instanceof IContainer)
{
container = (IContainer)object;
action.setEnabled(true);
return;
}
}
file = null;
container = null;
action.setEnabled(false);
}
}
}