/******************************************************************************* * Copyright (c) 2004, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - Initial API and implementation * Jens Lukowski/Innoopract - initial renaming/restructuring *******************************************************************************/ package org.eclipse.wst.xsd.ui.internal.editor; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.hyperlink.IHyperlink; import org.eclipse.wst.sse.core.StructuredModelManager; import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; import org.eclipse.wst.xsd.ui.internal.text.XSDModelAdapter; import org.eclipse.xsd.XSDConcreteComponent; import org.eclipse.xsd.XSDSchema; import org.eclipse.xsd.util.XSDConstants; import org.w3c.dom.Attr; /** * Detects hyperlinks for XSD files. Used by the XSD text editor to provide a * "Go to declaration" functionality similar with the one provided by the Java * editor. */ public class XSDHyperlinkDetector extends BaseHyperlinkDetector { /** * Determines whether an attribute is "linkable" that is, the component it * points to can be the target of a "go to definition" navigation. Derived * classes should override. * * @param name the attribute name. Must not be null. * @return true if the attribute is linkable, false otherwise. */ protected boolean isLinkableAttribute(String name) { boolean isLinkable = name.equals(XSDConstants.TYPE_ATTRIBUTE) || name.equals(XSDConstants.REFER_ATTRIBUTE) || name.equals(XSDConstants.REF_ATTRIBUTE) || name.equals(XSDConstants.BASE_ATTRIBUTE) || name.equals(XSDConstants.SCHEMALOCATION_ATTRIBUTE) || name.equals(XSDConstants.SUBSTITUTIONGROUP_ATTRIBUTE) || name.equals(XSDConstants.ITEMTYPE_ATTRIBUTE) || name.equals(XSDConstants.MEMBERTYPES_ATTRIBUTE) ; return isLinkable; } /** * Creates a hyperlink based on the selected node. Derived classes should * override. * * @param document the source document. * @param node the node under the cursor. * @param region the text region to use to create the hyperlink. * @return a new IHyperlink for the node or null if one cannot be created. */ protected IHyperlink createHyperlink(IDocument document, IDOMNode node, IRegion region) { XSDSchema xsdSchema = getXSDSchema(document); if (xsdSchema == null) { return null; } XSDConcreteComponent targetComponent = getTargetXSDComponent(xsdSchema, node); if (targetComponent != null) { IRegion nodeRegion = getHyperlinkRegion(node); return new XSDHyperlink(nodeRegion, targetComponent); } return null; } /** * Finds the XSD component for the given node. * * @param xsdSchema cannot be null * @param node cannot be null * @return XSDConcreteComponent */ private XSDConcreteComponent getTargetXSDComponent(XSDSchema xsdSchema, IDOMNode node) { XSDConcreteComponent xsdComponent = xsdSchema.getCorrespondingComponent(node); String attributeName = null; if (node instanceof Attr) { Attr attribute = (Attr)node; attributeName = attribute != null ? attribute.getName(): null; } XSDHyperlinkTargetLocator xsdHyperlinkTargetLocator = new XSDHyperlinkTargetLocator(); XSDConcreteComponent component = xsdHyperlinkTargetLocator.locate(xsdComponent, attributeName); return component; } /** * Gets the xsd schema from document * * @param document * @return XSDSchema or null of one does not exist yet for document */ private XSDSchema getXSDSchema(IDocument document) { XSDSchema schema = null; IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForRead(document); if (model != null) { try { if (model instanceof IDOMModel) { IDOMDocument domDoc = ((IDOMModel) model).getDocument(); if (domDoc != null) { XSDModelAdapter modelAdapter = (XSDModelAdapter) domDoc.getExistingAdapter(XSDModelAdapter.class); /* * ISSUE: Didn't want to go through initializing schema if it does * not already exist, so just attempted to get existing adapter. If * doesn't exist, just don't bother working. */ if (modelAdapter != null) schema = modelAdapter.getSchema(); } } } finally { model.releaseFromRead(); } } return schema; } }