/******************************************************************************* * Copyright (c) 2009 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.jst.jsp.core.internal.modelquery; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.Path; import org.eclipse.jst.jsp.core.internal.contentmodel.JSPCMDocumentFactory; import org.eclipse.jst.jsp.core.internal.contenttype.DeploymentDescriptorPropertyCache; import org.eclipse.jst.jsp.core.internal.provisional.JSP12Namespace; import org.eclipse.jst.jsp.core.internal.provisional.JSP20Namespace; import org.eclipse.jst.jsp.core.internal.provisional.contenttype.ContentTypeIdForJSP; import org.eclipse.wst.html.core.internal.contentmodel.JSPCMDocument; import org.eclipse.wst.sse.core.internal.provisional.IModelManager; import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument; import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration; import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap; import org.eclipse.wst.xml.core.internal.contentmodel.CMNode; import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery; import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension.ModelQueryExtension; import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocType; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; import org.eclipse.wst.xml.core.internal.ssemodelquery.ModelQueryAdapter; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * An implementation of {@link ModelQueryExtension} for JSP tags in JSP documents */ public class JSPModelQueryExtension extends ModelQueryExtension { private static final String TAG_JSP_ROOT = "jsp:root"; /** * Originally taken from JSPContentAssistProcessor * * @see org.eclipse.wst.xml.core.internal.contentmodel.modelquery.extension.ModelQueryExtension#getAvailableElementContent(org.w3c.dom.Element, java.lang.String, int) */ public CMNode[] getAvailableElementContent(Element parentElement, String namespace, int includeOptions) { CMNode[] nodes = EMPTY_CMNODE_ARRAY; ArrayList nodeList = new ArrayList(); //only returns anything if looking for child nodes if(((includeOptions & ModelQuery.INCLUDE_CHILD_NODES) != 0) && parentElement instanceof IDOMNode) { IDOMNode node = (IDOMNode)parentElement; // get position dependent CMDocuments and insert their tags as // proposals ModelQueryAdapter mqAdapter = null; if (node.getNodeType() == Node.DOCUMENT_NODE) { mqAdapter = (ModelQueryAdapter) node.getAdapterFor(ModelQueryAdapter.class); } else { mqAdapter = (ModelQueryAdapter) ((IDOMNode) node.getOwnerDocument()).getAdapterFor(ModelQueryAdapter.class); } if (mqAdapter != null) { CMDocument doc = mqAdapter.getModelQuery().getCorrespondingCMDocument(node); if (doc != null) { CMDocument jcmdoc = getDefaultJSPCMDocument(node); CMNamedNodeMap jspelements = jcmdoc.getElements(); /* For a built-in JSP action the content model is properly * set up, so don't just blindly add the rest--unless this * will be a direct child of the document */ if (jspelements != null && (!(doc instanceof JSPCMDocument) || node.getNodeType() == Node.DOCUMENT_NODE)) { List rejectElements = new ArrayList(); // determine if the document is in XML form Document domDoc = null; if (node.getNodeType() == Node.DOCUMENT_NODE) { domDoc = (Document) node; } else { domDoc = node.getOwnerDocument(); } // Show XML tag forms of JSP markers if jsp:root is // the document element OR it's HTML but // isn't really in the text. // If the document isn't strictly XML, pull out the // XML tag forms it is xml format rejectElements.add(JSP12Namespace.ElementName.SCRIPTLET); rejectElements.add(JSP12Namespace.ElementName.EXPRESSION); rejectElements.add(JSP12Namespace.ElementName.DECLARATION); rejectElements.add(JSP12Namespace.ElementName.DIRECTIVE_INCLUDE); rejectElements.add(JSP12Namespace.ElementName.DIRECTIVE_PAGE); rejectElements.add(JSP12Namespace.ElementName.TEXT); rejectElements.add(JSP12Namespace.ElementName.DIRECTIVE_TAGLIB); rejectElements.add(JSP20Namespace.ElementName.DIRECTIVE_TAG); rejectElements.add(JSP20Namespace.ElementName.DIRECTIVE_ATTRIBUTE); rejectElements.add(JSP20Namespace.ElementName.DIRECTIVE_VARIABLE); if (isXMLFormat(domDoc)) { // jsp actions rejectElements.add(JSP12Namespace.ElementName.FALLBACK); rejectElements.add(JSP12Namespace.ElementName.USEBEAN); rejectElements.add(JSP12Namespace.ElementName.GETPROPERTY); rejectElements.add(JSP12Namespace.ElementName.SETPROPERTY); rejectElements.add(JSP12Namespace.ElementName.INCLUDE); rejectElements.add(JSP12Namespace.ElementName.FORWARD); rejectElements.add(JSP12Namespace.ElementName.PLUGIN); rejectElements.add(JSP12Namespace.ElementName.FALLBACK); rejectElements.add(JSP12Namespace.ElementName.PARAM); rejectElements.add(JSP12Namespace.ElementName.PARAMS); } // don't show jsp:root if a document element already // exists Element docElement = domDoc.getDocumentElement(); if (docElement != null &&((docElement.getNodeName().equals(TAG_JSP_ROOT)) || ((((IDOMNode) docElement).getStartStructuredDocumentRegion() != null || ((IDOMNode) docElement).getEndStructuredDocumentRegion() != null)))) { rejectElements.add(JSP12Namespace.ElementName.ROOT); } for (int j = 0; j < jspelements.getLength(); j++) { CMElementDeclaration ed = (CMElementDeclaration) jspelements.item(j); if (!rejectElements.contains(ed.getNodeName())) { nodeList.add(ed); } } } } // No cm document (such as for the Document (a non-Element) node itself) else { CMNamedNodeMap jspElements = getDefaultJSPCMDocument(node).getElements(); int length = jspElements.getLength(); for (int i = 0; i < length; i++) { nodeList.add(jspElements.item(i)); } } } nodes = (CMNode[])nodeList.toArray(new CMNode[nodeList.size()]); } return nodes; } /** * <p>For JSP files and segments, this is just the JSP * document, but when editing tag files and their fragments, it * should be the tag document.</p> * * <p>It may also vary based on the model being edited in the future.</p> * * <p><b>NOTE:</b>Copied from JSPContentAssistProcessor</p> * * @return the default non-embedded CMDocument for the document being * edited. */ private CMDocument getDefaultJSPCMDocument(IDOMNode node) { CMDocument jcmdoc = null; // handle tag files here String contentType = node.getModel().getContentTypeIdentifier(); if (ContentTypeIdForJSP.ContentTypeID_JSPTAG.equals(contentType)) { jcmdoc = JSPCMDocumentFactory.getCMDocument(CMDocType.TAG20_DOC_TYPE); } else { String modelPath = node.getModel().getBaseLocation(); if (modelPath != null && !IModelManager.UNMANAGED_MODEL.equals(modelPath)) { float version = DeploymentDescriptorPropertyCache.getInstance().getJSPVersion(new Path(modelPath)); jcmdoc = JSPCMDocumentFactory.getCMDocument(version); } if (jcmdoc == null) { jcmdoc = JSPCMDocumentFactory.getCMDocument(); } } return jcmdoc; } /** * <p><b>NOTE:</b>Copied from JSPContentAssistProcessor</p> * * @param doc determine if this {@link Document} is in an XML format * @return is the given document in an XML format */ private boolean isXMLFormat(Document doc) { boolean result = false; if (doc != null) { Element docElement = doc.getDocumentElement(); result = docElement != null && ((docElement.getNodeName().equals(TAG_JSP_ROOT)) || ((((IDOMNode) docElement).getStartStructuredDocumentRegion() == null && ((IDOMNode) docElement).getEndStructuredDocumentRegion() == null))); } return result; } }