| /******************************************************************************* |
| * Copyright (c) 2007, 2008 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.wst.jsdt.web.ui.views.contentoutline; |
| |
| import java.util.Vector; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.jface.text.Position; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.wst.html.ui.internal.contentoutline.JFaceNodeAdapterForHTML; |
| import org.eclipse.wst.jsdt.core.IJavaScriptUnit; |
| import org.eclipse.wst.jsdt.core.IJavaScriptElement; |
| import org.eclipse.wst.jsdt.core.ISourceRange; |
| import org.eclipse.wst.jsdt.core.IType; |
| import org.eclipse.wst.jsdt.core.JavaScriptModelException; |
| import org.eclipse.wst.jsdt.internal.core.JavaElement; |
| import org.eclipse.wst.jsdt.internal.core.Member; |
| import org.eclipse.wst.jsdt.internal.core.SourceRefElement; |
| import org.eclipse.wst.jsdt.ui.JavaScriptElementLabelProvider; |
| import org.eclipse.wst.jsdt.ui.StandardJavaScriptElementContentProvider; |
| import org.eclipse.wst.jsdt.web.core.internal.Logger; |
| import org.eclipse.wst.jsdt.web.core.javascript.IJsTranslation; |
| import org.eclipse.wst.jsdt.web.core.javascript.JsTranslation; |
| import org.eclipse.wst.jsdt.web.core.javascript.JsTranslationAdapter; |
| import org.eclipse.wst.sse.core.StructuredModelManager; |
| import org.eclipse.wst.sse.core.internal.provisional.IModelManager; |
| import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter; |
| import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; |
| import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; |
| import org.eclipse.wst.sse.ui.internal.contentoutline.IJFaceNodeAdapter; |
| import org.eclipse.wst.xml.core.internal.document.NodeImpl; |
| 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.ui.internal.contentoutline.JFaceNodeAdapterFactory; |
| import org.w3c.dom.Node; |
| /** |
| * |
| |
| * Provisional API: This class/interface is part of an interim API that is still under development and expected to |
| * change significantly before reaching stability. It is being made available at this early stage to solicit feedback |
| * from pioneering adopters on the understanding that any code that uses this API will almost certainly be broken |
| * (repeatedly) as the API evolves. |
| */ |
| public class JFaceNodeAdapterForJs extends JFaceNodeAdapterForHTML { |
| |
| public JFaceNodeAdapterForJs(JFaceNodeAdapterFactory adapterFactory) { |
| super(adapterFactory); |
| } |
| |
| private IJavaScriptUnit lazyCu; |
| private IProgressMonitor monitor; |
| private JavaScriptElementLabelProvider javaElementLabelProvider; |
| |
| public Object[] getChildren(Object object) { |
| if (object instanceof IJavaScriptElement) { |
| return getJavaElementProvider().getChildren(object); |
| } |
| if (object instanceof IJavaWebNode) { |
| JavaElement enclosedElement = (JavaElement) ((IJavaWebNode) object).getJavaElement(); |
| if (enclosedElement != null) { |
| try { |
| IJavaScriptElement[] children = enclosedElement.getChildren(); |
| if (children == null) { |
| return new IJavaScriptElement[0]; |
| } |
| Object[] nodes = new Object[children.length]; |
| Node parent = ((IJavaWebNode) object).getParentNode(); |
| |
| for (int i = 0; i < children.length; i++) { |
| // int htmllength = ((SourceRefElement) (children[i])).getSourceRange().getLength(); |
| // int htmloffset = ((SourceRefElement) (children[i])).getSourceRange().getOffset(); |
| IJavaScriptElement javaElement = children[i]; |
| ISourceRange range = null; |
| if (javaElement instanceof Member) { |
| range = ((Member) javaElement).getNameRange(); |
| } else { |
| range = ((SourceRefElement) javaElement).getSourceRange(); |
| } |
| int htmllength = range.getLength(); |
| int htmloffset = range.getOffset(); |
| |
| |
| Position position = new Position(htmloffset, htmllength); |
| nodes[i] = getJsNode(parent, javaElement, position); |
| } |
| return nodes; |
| } catch (JavaScriptModelException ex) { |
| } |
| } |
| } |
| Node node = (Node) object; |
| if (isJSElementParent(node)) { |
| Object[] results = getJSElementsFromNode(node.getFirstChild(), true); |
| |
| |
| return filter( results ); |
| } |
| return super.getChildren(object); |
| } |
| |
| /* |
| * @GINO: Anonymous -- matches anonymous types on the top level |
| */ |
| protected boolean matches(Object elementObj) { |
| |
| if( elementObj instanceof IJavaWebNode ){ |
| IJavaScriptElement element = ((IJavaWebNode)elementObj).getJavaElement(); |
| if (element.getElementType() == IJavaScriptElement.TYPE && element.getParent().getElementType() == IJavaScriptElement.JAVASCRIPT_UNIT ) { |
| |
| IType type = (IType)element; |
| try { |
| return type.isAnonymous(); |
| } catch (JavaScriptModelException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| /* |
| * @GINO: Anonymous Filter from top level |
| * |
| */ |
| protected Object[] filter(Object[] children) { |
| boolean initializers= false; |
| for (int i= 0; i < children.length; i++) { |
| if (matches(children[i])) { |
| initializers= true; |
| break; |
| } |
| } |
| |
| if (!initializers) |
| return children; |
| |
| Vector v= new Vector(); |
| for (int i= 0; i < children.length; i++) { |
| if (matches(children[i])) |
| continue; |
| v.addElement(children[i]); |
| } |
| |
| Object[] result= new Object[v.size()]; |
| v.copyInto(result); |
| return result; |
| } |
| |
| public Object[] getElements(Object object) { |
| if (object instanceof IJavaScriptElement) { |
| return getJavaElementProvider().getElements(object); |
| } |
| return super.getElements(object); |
| } |
| |
| private JavaScriptElementLabelProvider getJavaElementLabelProvider() { |
| if(javaElementLabelProvider==null) { |
| javaElementLabelProvider = new JavaScriptElementLabelProvider(); |
| } |
| return javaElementLabelProvider; |
| } |
| |
| private StandardJavaScriptElementContentProvider getJavaElementProvider() { |
| return new StandardJavaScriptElementContentProvider(true); |
| } |
| |
| private Object[] filterChildrenForRange(IJavaScriptElement[] allChildren, Node node) { |
| // int javaPositionStart = ((NodeImpl) node).getStartOffset(); |
| // int javaPositionEnd = ((NodeImpl) node).getEndOffset(); |
| |
| // Object[] result =new Object[0]; |
| |
| int javaPositionEnd = ((NodeImpl) node).getEndOffset(); |
| int javaPositionStart = ((NodeImpl) node).getStartOffset(); |
| |
| Vector validChildren = new Vector(); |
| for (int i = 0; i < allChildren.length; i++) { |
| if (allChildren[i] instanceof IJavaScriptElement && allChildren[i].getElementType() != IJavaScriptElement.PACKAGE_DECLARATION) { |
| ISourceRange range = null; |
| if (allChildren[i] instanceof Member) { |
| try { |
| range = ((Member) allChildren[i]).getNameRange(); |
| } catch (JavaScriptModelException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| } else if (allChildren[i] instanceof SourceRefElement) { |
| try { |
| range = ((SourceRefElement)allChildren[i] ).getSourceRange(); |
| } catch (JavaScriptModelException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| } |
| if (allChildren[i].getElementType() == IJavaScriptElement.TYPE || (javaPositionStart <= range.getOffset() && range.getLength() + range.getOffset() <= (javaPositionEnd))) { |
| |
| |
| int htmllength = range == null ? 0 : range.getLength(); |
| int htmloffset = range == null ? 0 : range.getOffset(); |
| if (htmllength < 0 || htmloffset < 0) { |
| continue; |
| } |
| Position position = new Position(htmloffset, htmllength); |
| validChildren.add(getJsNode(node.getParentNode(), allChildren[i], position)); |
| |
| |
| } |
| } |
| } |
| Object[] result = new Object[0]; |
| |
| |
| if (validChildren.size() > 0) { |
| result = validChildren.toArray(); |
| } |
| if (result == null || result.length == 0) { |
| return new IJavaScriptElement[0]; |
| } |
| return result; |
| } |
| |
| private synchronized Object[] getJSElementsFromNode(Node node, boolean ensureConsistant) { |
| |
| int startOffset = 0; |
| int endOffset = 0; |
| int type = node.getNodeType(); |
| Object[] result = null; |
| JsTranslation translation = null; |
| if (node.getNodeType() == Node.TEXT_NODE && (node instanceof NodeImpl)) { |
| startOffset = ((NodeImpl) node).getStartOffset(); |
| endOffset = ((NodeImpl) node).getEndOffset(); |
| IJavaScriptUnit unit = getLazyCu(node); |
| try { |
| if(ensureConsistant) unit.makeConsistent(getProgressMonitor()); |
| } catch (JavaScriptModelException ex1) { |
| // TODO Auto-generated catch block |
| ex1.printStackTrace(); |
| } |
| try { |
| result = filterChildrenForRange(unit.getChildren(),node); |
| } catch (JavaScriptModelException ex) { |
| // TODO Auto-generated catch block |
| ex.printStackTrace(); |
| result = new Object[0]; |
| lazyCu=null; |
| } |
| |
| //translation = getTranslation(node); |
| //result = translation.getAllElementsInJsRange(startOffset, endOffset); |
| } |
| return result; |
| } |
| |
| private IProgressMonitor getProgressMonitor() { |
| if(monitor==null) { |
| monitor = new NullProgressMonitor(); |
| } |
| |
| return monitor; |
| |
| } |
| |
| private Object getJsNode(Node parent, IJavaScriptElement root, Position position) { |
| JsJfaceNode instance = null; |
| if (root.getElementType() == IJavaScriptElement.TYPE) { |
| instance = new JsJfaceNode(parent, root, position, ((SourceRefElement) root).getElementName()); |
| } else if (root.getElementType() == IJavaScriptElement.FIELD) { |
| /* Field refrence, possibly to a type may need to implement later */ |
| instance = new JsJfaceNode(parent, root, position); |
| } else { |
| instance = new JsJfaceNode(parent, root, position); |
| } |
| String name = getJavaElementLabelProvider().getText(root); |
| instance.setName(name); |
| // ((JsJfaceNode)instance).setAdapterRegistry(registry); |
| INodeAdapter adapter = (instance).getAdapterFor(IJFaceNodeAdapter.class); |
| if (!(adapter instanceof JFaceNodeAdapterForJs)) { |
| (instance).removeAdapter(adapter); |
| (instance).addAdapter(this); |
| } |
| return instance; |
| } |
| |
| |
| public Image getLabelImage(Object node) { |
| if (node instanceof JsJfaceNode) { |
| return ((JsJfaceNode) node).getImage(); |
| } |
| if (node instanceof IJavaScriptElement) { |
| return getJavaElementLabelProvider().getImage(node); |
| } |
| return super.getLabelImage(node); |
| } |
| |
| |
| public String getLabelText(Object node) { |
| // if (node instanceof JsJfaceNode) { |
| // return ((JsJfaceNode) node).getName(); |
| // } |
| if (node instanceof IJavaScriptElement) { |
| return getJavaElementLabelProvider().getText(node); |
| } |
| return super.getLabelText(node); |
| } |
| |
| |
| public Object getParent(Object element) { |
| if (element instanceof IJavaScriptElement) { |
| return getJavaElementProvider().getParent(element); |
| } |
| return super.getParent(element); |
| } |
| |
| private IJavaScriptUnit getLazyCu(Node node) { |
| if(lazyCu==null) { |
| lazyCu = getTranslation(node).getCompilationUnit(); |
| try { |
| lazyCu.makeConsistent( new NullProgressMonitor() ); |
| } catch (JavaScriptModelException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| } |
| return lazyCu; |
| } |
| |
| private IJsTranslation getTranslation(Node node) { |
| IStructuredModel model = null; |
| IModelManager modelManager = StructuredModelManager.getModelManager(); |
| IDOMDocument xmlDoc = null; |
| try { |
| if (modelManager != null) { |
| IStructuredDocument doc = ((NodeImpl) node).getStructuredDocument(); |
| model = modelManager.getExistingModelForRead(doc); |
| // model = modelManager.getModelForRead(doc); |
| } |
| IDOMModel domModel = (IDOMModel) model; |
| xmlDoc = domModel.getDocument(); |
| } catch (Exception e) { |
| Logger.logException(e); |
| } finally { |
| if (model != null) { |
| // model.changedModel(); |
| model.releaseFromRead(); |
| } |
| } |
| if (xmlDoc == null) { |
| return null; |
| } |
| JsTranslationAdapter translationAdapter = (JsTranslationAdapter) xmlDoc.getAdapterFor(IJsTranslation.class); |
| return translationAdapter.getJSPTranslation(true); |
| } |
| |
| |
| public boolean hasChildren(Object object) { |
| if (object instanceof IJavaScriptElement) { |
| return getJavaElementProvider().hasChildren(object); |
| } |
| Node node = (Node) object; |
| if (node instanceof IJavaWebNode) { |
| return ((IJavaWebNode) object).hasChildren(); |
| |
| } |
| if (isJSElementParent(node)) { |
| Object[] nodes = getJSElementsFromNode(node.getFirstChild(),false); |
| boolean hasElements = (nodes != null && nodes.length > 0); |
| return hasElements; |
| } |
| return super.hasChildren(object); |
| } |
| |
| private boolean isJSElementParent(Node node) { |
| return (node.hasChildNodes() && node.getNodeName().equalsIgnoreCase("script")); //$NON-NLS-1$ |
| } |
| } |