/* * 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.xsd.ui.editor; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; 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.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.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.edit.provider.INotifyChangedListener; import org.eclipse.jface.dialogs.ProgressMonitorDialog; 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.ILabelProvider; 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.swt.SWT; 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.ui.IEditorInput; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.PartInitException; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.eclipse.ui.editors.text.IEncodingSupport; import org.eclipse.ui.editors.text.TextEditor; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.texteditor.IElementStateListener; import org.eclipse.xsd.XSDAttributeUse; import org.eclipse.xsd.XSDConcreteComponent; import org.eclipse.xsd.XSDDiagnostic; import org.eclipse.xsd.XSDDiagnosticSeverity; import org.eclipse.xsd.XSDParticle; import org.eclipse.xsd.XSDSchema; import org.eclipse.xsd.util.XSDParser; import org.eclipse.xsd.util.XSDResourceImpl; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.ValidationDescriptor; import org.teiid.designer.core.ValidationPreferences; import org.teiid.designer.core.transaction.SourcedNotification; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.core.workspace.ModelUtil; import org.teiid.designer.core.workspace.ModelWorkspaceException; import org.teiid.designer.ui.common.eventsupport.SelectionUtilities; import org.teiid.designer.ui.common.util.UiUtil; import org.teiid.designer.ui.editors.AbstractModelEditorPageActionBarContributor; import org.teiid.designer.ui.editors.ModelEditorPage; import org.teiid.designer.ui.editors.ModelEditorPageOutline; import org.teiid.designer.ui.event.ModelResourceEvent; import org.teiid.designer.ui.viewsupport.ModelUtilities; import org.teiid.designer.xsd.ui.ModelerXsdUiConstants; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * XsdTextEditorPage is a ModelEditorPage for displaying the source of an XMLSchema file. * * @since 8.0 */ public class XsdTextEditorPage extends TextEditor implements ModelEditorPage, ISelectionProvider, IDocumentListener { private static final String NAME = ModelerXsdUiConstants.Util.getString("xsdTextEditor.name"); //$NON-NLS-1$ private static final String TOOLTIP = ModelerXsdUiConstants.Util.getString("xsdTextEditor.tooltip"); //$NON-NLS-1$ protected ISourceViewer sourceViewer; protected Timer timer = new Timer(); protected TimerTask timerTask; protected boolean timerCancelled = false; protected ModelResource modelResource; /** This keeps track of the root object of the model. */ protected XSDSchema xsdSchema; /** This is the model resource for the current xsd file being displayed in the editor */ private Resource xsdResource; /** This keeps track eclipse text document. */ protected IDocument document; /** 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 listens to selections from other viewers. */ protected ISelectionChangedListener selectionChangedListener; protected INotifyChangedListener notifyChangedListener = new INotifyChangedListener() { @Override public void notifyChanged( Notification notification ) { if (getXsdSchema() != null) { if (notification instanceof SourcedNotification) { if (((SourcedNotification)notification).getSource() != null) { // then it was not produced by this editor // Still need to check the damn notifier and be sure that we only respond to changes // to this resource. Else this listener will respond to every sourced notification. BAD!!!! Object changedObject = ModelerCore.getModelEditor().getChangedObject(notification); if (changedObject != null) { ModelResource mr = null; if (changedObject instanceof EObject) { mr = ModelUtilities.getModelResourceForModelObject((EObject)changedObject); } else if (changedObject instanceof ModelResource) { mr = (ModelResource)changedObject; } if (mr != null && mr.equals(modelResource)) { handleStructuredModelChange(true); } else if (changedObject.equals(xsdSchema)) { handleStructuredModelChange(true); } } } } } } }; /** * Construct an instance of XsdTextEditorPage. */ public XsdTextEditorPage() { super(); } /** * @see org.eclipse.ui.texteditor.AbstractTextEditor#createSourceViewer(org.eclipse.swt.widgets.Composite, * org.eclipse.jface.text.source.IVerticalRuler, int) */ @Override protected 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; } } protected void initDocument() { boolean requiredStart = ModelerCore.startTxn(false, false, "Create XSD Editor Model", this); //$NON-NLS-1$ boolean succeeded = false; try { createModel(); succeeded = true; } finally { // If we start txn, commit it if (requiredStart) { if (succeeded) { ModelerCore.commitTxn(); } else { ModelerCore.rollbackTxn(); } } } String encoding = determineEncoding(); IEncodingSupport encodingSupport = (IEncodingSupport)getAdapter(IEncodingSupport.class); if (encodingSupport != null && encoding != null) { encodingSupport.setEncoding(encoding); } document = getDocumentProvider().getDocument(getEditorInput()); document.addDocumentListener(this); modelResource = ModelUtilities.getModelResource(xsdResource, false); } 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(ModelerXsdUiConstants.Util.getString("XsdEditor._22"), 10); //$NON-NLS-1$ IFileEditorInput modelFile = (IFileEditorInput)getEditorInput(); IFile file = modelFile.getFile(); ResourceSet resourceSet = ModelerCore.getModelContainer(); resourceSet.getLoadOptions().put(XSDResourceImpl.XSD_PROGRESS_MONITOR, progressMonitor); createResource(file.getLocation().toString(), resourceSet); resourceSet.getLoadOptions().remove(XSDResourceImpl.XSD_PROGRESS_MONITOR); progressMonitor.worked(1); final String msg = ModelerXsdUiConstants.Util.getString("_UI_Validating_message"); //$NON-NLS-1$ progressMonitor.subTask(msg); // only validate if user pref is on and no diagnostics exist if (isValidateSchemaPreferenceOn() && getXsdSchema().getAllDiagnostics().isEmpty()) { getXsdSchema().validate(); getXsdSchema().eResource().setModified(false); } progressMonitor.worked(1); progressMonitor.subTask(ModelerXsdUiConstants.Util.getString("_UI_ReportingErrors_message")); //$NON-NLS-1$ // must do this to get the DOM objects properly synched with the display handleDocumentChange(false); // handleStructuredModelChange(); } catch (Throwable t) { ModelerXsdUiConstants.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) { ModelerXsdUiConstants.Util.log(exception); } } /** * Indicates if the preference for validating schema has been set to perform validation. * * @return <code>true</code>if the schema should be validated; <code>false</code> otherwise. * @since 4.2 */ boolean isValidateSchemaPreferenceOn() { boolean result = false; String pref = getValidateSchemaUserPreference(); if (pref.equals(ValidationDescriptor.ERROR) || pref.equals(ValidationDescriptor.WARNING) || pref.equals(ValidationDescriptor.INFO)) { result = true; } return result; } /** * Obtains the user preference for schema validation. * * @return the preference * @since 4.2 * @see ValidationDescriptor#ERROR * @see ValidationDescriptor#WARNING * @see ValidationDescriptor#INFO * @see ValidationDescriptor#IGNORE * @see ValidationDescriptor#NOT_SET */ private String getValidateSchemaUserPreference() { IEclipsePreferences prefs = ModelerCore.getPreferences(ModelerCore.PLUGIN_ID); String value = prefs.get(ValidationPreferences.XSD_MODEL_VALIDATION, null); if (value == null) { prefs = ModelerCore.getDefaultPreferences(ModelerCore.PLUGIN_ID); value = prefs.get(ValidationPreferences.XSD_MODEL_VALIDATION, ValidationDescriptor.WARNING); } return value; } /** * Obtains the {@link IMarker} severity attribute level for the validate schema user preference. This is the highest level of * severity the user wants to see. * * @return the severity level or -1 if user preference is set to not validate the schema * @since 4.2 */ private int getValidateSchemaUserPreferenceMarkerSeverity() { int result = -1; String pref = getValidateSchemaUserPreference(); if (pref.equals(ValidationDescriptor.ERROR)) { result = IMarker.SEVERITY_ERROR; } else if (pref.equals(ValidationDescriptor.WARNING)) { result = IMarker.SEVERITY_WARNING; } else if (pref.equals(ValidationDescriptor.INFO)) { result = IMarker.SEVERITY_INFO; } return result; } protected void createResource( String uri, ResourceSet resourceSet ) { extendedCreateResource(uri, resourceSet); } protected void extendedCreateResource( String uri, ResourceSet resourceSet ) { resourceSet.getLoadOptions().put(XSDResourceImpl.XSD_TRACK_LOCATION, Boolean.TRUE); try { XSDResourceImpl xsdResource = (XSDResourceImpl)resourceSet.getResource(URI.createFileURI(uri), true); xsdSchema = xsdResource.getSchema(); // code to close the editor when the resource is deleted 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(XsdTextEditorPage.this, false); } } }); } @Override public void elementMoved( Object originalElement, Object movedElement ) { } }); } catch (Exception exception) { ModelerXsdUiConstants.Util.log(exception); } } protected void handleDocumentChange( boolean setModified ) { if (sourceViewer != null) { try { XSDParser xsdParser = new XSDParser(null); IDocument iDocument = sourceViewer.getDocument(); if (iDocument != null) { String documentContent = iDocument.get(); byte[] bytes = documentContent.getBytes(); xsdParser.parse(new ByteArrayInputStream(bytes)); xsdParser.setSchema(getXsdSchema()); // only validate if user pref is on and no diagnostics exist if (isValidateSchemaPreferenceOn() && getXsdSchema().getAllDiagnostics().isEmpty()) { getXsdSchema().validate(); } if (setModified) { getXsdSchema().eResource().setModified(true); } handleDiagnostics(null); } } catch (Exception exception) { ModelerXsdUiConstants.Util.log(exception); } } } protected boolean handledStructuredModelChange = false; protected void handleStructuredModelChange( boolean setModified ) { final IDocument document = getDocumentProvider().getDocument(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; } final int start = startIndex; final String replacement = newContent.substring(startIndex, newEndIndex + 1); final int length = oldEndIndex - startIndex + 1; handledStructuredModelChange = true; UiUtil.runInSwtThread(new Runnable() { @Override public void run() { try { document.replace(start, length, replacement); } catch (Exception exception) { ModelerXsdUiConstants.Util.log(exception); } } }, false); if (setModified) { getXsdSchema().eResource().setModified(true); } } catch (Exception exception) { ModelerXsdUiConstants.Util.log(exception); } } 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; } /** * Called when the mouse is clicked inside the document. */ protected void handleSourceCaretPosition() { if (sourceViewer != null) { 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)); } } } } /** * Called by handleSourceCaretPosition to find an Element for a given location in the document * * @param element * @param line * @param column * @return */ protected 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()); handleContentOutlineSelectionForTextEditor(newSelection, false); } } /** * This deals with how we want selection in the outliner to affect the text editor. */ public void handleContentOutlineSelectionForTextEditor( ISelection selection, boolean reveal ) { Object o = ((IStructuredSelection)selection).iterator().next(); if (o instanceof XSDConcreteComponent) { XSDConcreteComponent xsdConcreteComponent = (XSDConcreteComponent)o; 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 = getDocumentProvider().getDocument(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) { setHighlightRange(startOffset, endOffset - startOffset, false); if (reveal) { selectAndReveal(startOffset, endOffset - startOffset); } } else { setHighlightRange(startOffset, endOffset - startOffset, reveal); } } catch (Exception exception) { ModelerXsdUiConstants.Util.log(exception); } } } } protected 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; } 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 = getDocumentProvider().getDocument(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 (!isValidateSchemaPreferenceOn()) { return; } 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) { ModelerXsdUiConstants.Util.log(exception); } } else { XSDConcreteComponent newSelection = null; try { // the userPref will be used to determine if the marker severity should be changed int userPref = getValidateSchemaUserPreferenceMarkerSeverity(); // 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, ModelerXsdUiConstants.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; } } // if necessary adjust severity based on user preferences Object markerSeverity = marker.getAttribute(IMarker.SEVERITY); if ((userPref != -1) && (markerSeverity != null) && (markerSeverity instanceof Integer)) { int severity = ((Integer)markerSeverity).intValue(); if (severity > userPref) { do { --severity; } while (severity > userPref); marker.setAttribute(IMarker.SEVERITY, severity); } } } for (Iterator i = deletableMarkers.iterator(); i.hasNext();) { IMarker marker = (IMarker)i.next(); marker.delete(); } } catch (Exception exception) { ModelerXsdUiConstants.Util.log(exception); } // This will refresh the status. // if (editorSelection != null) { setSelectionInternal(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() { setSelectionInternal(errorSelection); handleSourceCaretPosition(); } }); } } } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#canDisplay(org.eclipse.ui.IEditorInput) */ @Override public boolean canDisplay( IEditorInput input ) { if (input instanceof IFileEditorInput) { return ModelUtil.isXsdFile(((IFileEditorInput)input).getFile()); } return false; } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#canOpenContext(java.lang.Object) */ @Override public boolean canOpenContext( Object input ) { return false; } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#getActionBarContributor() */ @Override public AbstractModelEditorPageActionBarContributor getActionBarContributor() { return null; } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#getControl() */ @Override public Control getControl() { return super.getSourceViewer().getTextWidget(); } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#getModelObjectSelectionChangedListener() */ @Override public ISelectionChangedListener getModelObjectSelectionChangedListener() { 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()); } }; } return selectionChangedListener; } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#getModelObjectSelectionProvider() */ @Override public ISelectionProvider getModelObjectSelectionProvider() { return this; } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#getNotifyChangedListener() */ @Override public INotifyChangedListener getNotifyChangedListener() { return notifyChangedListener; } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#getOutlineContribution() */ @Override public ModelEditorPageOutline getOutlineContribution() { return null; } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#openContext(java.lang.Object) */ @Override public void openContext( Object input ) { } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#openContext(java.lang.Object) */ @Override public void openContext( Object input, boolean forceRefresh ) { } /** * (non-Javadoc) * * @see org.teiid.designer.ui.editors.ModelEditorPage#initializeEditorPage() * @since 5.0.2 */ @Override public void initializeEditorPage() { } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#setLabelProvider(org.eclipse.jface.viewers.ILabelProvider) */ @Override public void setLabelProvider( ILabelProvider provider ) { } /** * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) */ @Override public void createPartControl( Composite parent ) { super.createPartControl(parent); handleStructuredModelChange(false); } /** * @see org.eclipse.ui.IEditorPart#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput) */ @Override public void init( IEditorSite site, IEditorInput input ) throws PartInitException { super.init(site, input); if (input instanceof IFileEditorInput) { // get the XSD resource. try { // Get the IFile associated with the editor final IResource xsdFile = ((IFileEditorInput)input).getFile(); if (xsdFile == null) { final String msg = ModelerXsdUiConstants.Util.getString("XsdEditor.Input_Error__Model_Editor_cannot_open_{0}_2", input.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 = ModelerXsdUiConstants.Util.getString("XsdEditor.Input_Error__Model_Editor_cannot_open_{0}_1", input.getName()); //$NON-NLS-1$ throw new PartInitException(msg); } initDocument(); ModelUtilities.addNotifyChangedListener(notifyChangedListener); } catch (ModelWorkspaceException e) { final String msg = ModelerXsdUiConstants.Util.getString("XsdEditor.Input_Error__Model_Editor_cannot_open_{0}_2", input.getName()); //$NON-NLS-1$ throw new PartInitException(msg, e); } catch (CoreException e) { final String msg = ModelerXsdUiConstants.Util.getString("XsdEditor.Input_Error__Model_Editor_cannot_open_{0}_2", input.getName()); //$NON-NLS-1$ throw new PartInitException(msg, e); } } else { throw new PartInitException( ModelerXsdUiConstants.Util.getString("XsdEditor.Invalid_Input__Must_be_IFileEditorInput._33")); //$NON-NLS-1$ } } /** * @see org.eclipse.ui.IWorkbenchPart#getTitle() */ @Override public String getTitle() { return NAME; } /** * @see org.eclipse.ui.IWorkbenchPart#getTitleToolTip() */ @Override public String getTitleToolTip() { return TOOLTIP; } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#setTitleText(java.lang.String) */ @Override public void setTitleText( String title ) { // do nothing; } /** * This implements {@link org.eclipse.jface.viewers.ISelectionProvider}. */ @Override public void addSelectionChangedListener( ISelectionChangedListener listener ) { if (listener != null && !selectionChangedListeners.contains(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 ) { if (SelectionUtilities.isSingleSelection(selection)) { if (SelectionUtilities.isAllEObjects(selection)) { EObject selectedObject = SelectionUtilities.getSelectedEObject(selection); if (this.xsdResource.equals(selectedObject.eResource())) { editorSelection = selection; handleContentOutlineSelectionForTextEditor(selection, true); } } } } void setSelectionInternal( ISelection selection ) { editorSelection = selection; for (Iterator iter = this.selectionChangedListeners.iterator(); iter.hasNext();) { SelectionChangedEvent event = new SelectionChangedEvent(this, selection); ((ISelectionChangedListener)iter.next()).selectionChanged(event); } } /** * @see org.eclipse.ui.IWorkbenchPart#dispose() */ @Override public void dispose() { cancelRunningTimer(); if (document != null) document.removeDocumentListener(this); ModelUtilities.removeNotifyChangedListener(notifyChangedListener); notifyChangedListener = null; if (getSite() != null) super.dispose(); } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#preDispose() */ @Override public void preDispose() { ModelUtilities.removeNotifyChangedListener(notifyChangedListener); if (document != null) document.removeDocumentListener(this); notifyChangedListener = null; cancelRunningTimer(); if (timer != null) { timer.cancel(); } } private boolean cancelRunningTimer() { if (!timerCancelled) { timerCancelled = true; if (timerTask != null) { timerTask.cancel(); } return true; } return false; } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#updateReadOnlyState(boolean) */ @Override public void updateReadOnlyState( boolean isReadOnly ) { } /** * @see org.eclipse.ui.ISaveablePart#isDirty() */ @Override public boolean isDirty() { return false; } /** * @see org.teiid.core.designer.event.EventObjectListener#processEvent(java.util.EventObject) * @since 4.2 */ @Override public void processEvent( EventObject obj ) { if (getEditorInput() != null) { ModelResourceEvent event = (ModelResourceEvent)obj; final IResource file = event.getResource(); final IFile currentFile = ((FileEditorInput)getEditorInput()).getFile(); if (file.equals(currentFile)) { if (event.getType() == ModelResourceEvent.RELOADED || event.getType() == ModelResourceEvent.CHANGED) { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { setInput(getEditorInput()); handleStructuredModelChange(true); } }); } } } } /** * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent) * @since 4.2 */ @Override public void documentAboutToBeChanged( DocumentEvent documentEvent ) { } /** * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent) * @since 4.2 */ @Override public void documentChanged( final DocumentEvent documentEvent ) { try { // This is need for the Properties view. // cancelRunningTimer(); if (handledStructuredModelChange) { handledStructuredModelChange = false; // defect 18435 -- make sure we don't infinitely recurse by calling // handleDocumentChange(true), which eventually will cause things // to come back here. // the following line displays errors, but they won't get updated // unless the user types a change in the source editor. handleDiagnostics(null); } else { timerTask = new TimerTask() { @Override public void run() { getSite().getShell().getDisplay().asyncExec(new Runnable() { @Override public void run() { handleDocumentChange(true); } }); } }; timerCancelled = false; timer.schedule(timerTask, 1000); } } catch (Exception exception) { ModelerXsdUiConstants.Util.log(exception); } } /** * @see org.teiid.designer.ui.editors.ModelEditorPage#openComplete() * @since 4.2 */ @Override public void openComplete() { // Default Implementation } /** * @return False. * @see org.teiid.designer.ui.editors.ModelEditorPage#isSelectedFirst(org.eclipse.ui.IEditorInput) * @since 5.0.1 */ @Override public boolean isSelectedFirst( IEditorInput input ) { return false; } }