|
What this is
This file is included in the DevDaily.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
Other links
The source code
/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.xsl.grammar;
import java.io.IOException;
import java.util.*;
import javax.swing.Icon;
//import org.apache.xpath.XPathAPI;
import org.netbeans.api.xml.services.UserCatalog;
import org.netbeans.modules.xml.api.model.*;
import org.netbeans.modules.xml.dtd.grammar.*;
import org.netbeans.modules.xml.spi.dom.*;
import org.netbeans.modules.xml.api.cookies.ScenarioCookie;
import org.netbeans.modules.xsl.api.XSLCustomizer;
import org.netbeans.modules.xsl.api.XSLScenario;
import org.openide.filesystems.Repository;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileSystem;
import org.openide.loaders.FolderLookup;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.loaders.InstanceDataObject;
import org.openide.nodes.PropertySupport;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.w3c.dom.*;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* This class implements code completion for XSL transformation files.
* XSL elements in the completion are hardcoded from the XSLT spec, but the
* result elements are gathered from the "doctype-public" and "doctype-system"
* attributes of the xsl:output element.
*
* @author asgeir@dimonsoftware.com
*/
public final class XSLGrammarQuery implements GrammarQuery{
private DataObject dataObject;
private ScenarioCookie scenarioCookie;
/** Contains a mapping from XSL namespace element names to set of names of
* allowed XSL children. Neither the element name keys nor the names in the
* value set should contain the namespace prefix.
*/
private static Map elementDecls;
/** Contains a mapping from XSL namespace element names to set of names of
* allowed XSL attributes for that element. The element name keys should
* not contain the namespace prefix.
*/
private static Map attrDecls;
/** A Set of XSL attributes which should be allowd for result elements*/
private static Set resultElementAttr;
/** An object which indicates that result element should be allowed in a element Set */
private static String resultElements = "RESULT_ELEMENTS_DUMMY_STRING"; // NOI18N
/** A Set of elements which should be allowed at template level in XSL stylesheet */
private static Set template;
/** Contains a mapping from XSL namespace element names to an attribute name which
* should contain XPath expression. The element name keys should
* not contain the namespace prefix.
*/
private static Map exprAttributes;
/** A set containing all functions allowed in XSLT */
private static Set xslFunctions;
/** A set containing XPath axes */
private static Set xpathAxes;
/** A list of prefixes using the "http://www.w3.org/1999/XSL/Transform" namespace
* defined in the context XSL document. The first prefix in the list is the actual XSL
* transformation prefix, which is normally defined on the xsl:stylesheet element.
*/
private List prefixList = new LinkedList();
/** A GrammarQuery for the result elements created for the doctype-public" and
* "doctype-system" attributes of the xsl:output element.*/
private GrammarQuery resultGrammarQuery;
/** The value of the system identifier of the DTD which was used when
* resultGrammarQuery was previously created */
private String lastDoctypeSystem;
/** The value of the public identifier of the DTD which was used when
* resultGrammarQuery was previously created */
private String lastDoctypePublic;
// we cannot parse SGML DTD for HTML, let emulate it by XHTML DTD
private final static String XHTML_PUBLIC_ID =
System.getProperty("netbeans.xsl.html.public", "-//W3C//DTD XHTML 1.0 Transitional//EN"); // NOI18N
// we cannot parse SGML DTD for HTML, let emulate it by XHTML DTD
private final static String XHTML_SYSTEM_ID =
System.getProperty("netbeans.xsl.html.system", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"); // NOI18N
// namespace that this grammar supports
public static final String XSLT_NAMESPACE_URI = "http://www.w3.org/1999/XSL/Transform"; // NOI18N
/** Folder which stores instances of custom external XSL customizers */
private static final String CUSTOMIZER_FOLDER = "Plugins/XML/XSLCustomizer"; // NOI18N
private XSLCustomizer customizer = null;
private ResourceBundle bundle = NbBundle.getBundle(XSLGrammarQuery.class);
/** Creates a new instance of XSLGrammarQuery */
public XSLGrammarQuery(DataObject dataObject) {
this.dataObject = dataObject;
scenarioCookie = (ScenarioCookie)dataObject.getCookie(ScenarioCookie.class);
}
//////////////////////////////////////////7
// Getters for the static members
private static Map getElementDecls() {
if (elementDecls == null) {
elementDecls = new HashMap();
attrDecls = new HashMap();
// Commonly used variables
Set emptySet = new TreeSet();
String spaceAtt = "xml:space"; // NOI18N
Set tmpSet;
////////////////////////////////////////////////
// Initialize common sets
Set charInstructions = new TreeSet(Arrays.asList(new String[]{"apply-templates", // NOI18N
"call-template","apply-imports","for-each","value-of", // NOI18N
"copy-of","number","choose","if","text","copy", // NOI18N
"variable","message","fallback"})); // NOI18N
Set instructions = new TreeSet(charInstructions);
instructions.addAll(Arrays.asList(new String[]{"processing-instruction", // NOI18N
"comment","element","attribute"})); // NOI18N
Set charTemplate = charInstructions; // We don't care about PCDATA
template = new TreeSet(instructions);
template.add(resultElements);
Set topLevel = new TreeSet(Arrays.asList(new String[]{"import","include","strip-space", // NOI18N
"preserve-space","output","key","decimal-format","attribute-set", // NOI18N
"variable","param","template","namespace-alias"})); // NOI18N
Set topLevelAttr = new TreeSet(Arrays.asList(new String[]{"extension-element-prefixes", // NOI18N
"exclude-result-prefixes","id","version",spaceAtt})); // NOI18N
resultElementAttr = new TreeSet(Arrays.asList(new String[]{"extension-element-prefixes", // NOI18N
"exclude-result-prefixes","use-attribute-sets","version"})); // NOI18N
////////////////////////////////////////////////
// Add items to elementDecls and attrDecls maps
// xsl:stylesheet
elementDecls.put("stylesheet", topLevel); // NOI18N
attrDecls.put("stylesheet", topLevelAttr); // NOI18N
// xsl:transform
elementDecls.put("transform", topLevel); // NOI18N
attrDecls.put("transform", topLevelAttr); // NOI18N
// xsl:import
elementDecls.put("import", emptySet); // NOI18N
attrDecls.put("import", new TreeSet(Arrays.asList(new String[]{"href"}))); // NOI18N
// xxsl:include
elementDecls.put("include", emptySet); // NOI18N
attrDecls.put("include", new TreeSet(Arrays.asList(new String[]{"href"}))); // NOI18N
// xsl:strip-space
elementDecls.put("strip-space", emptySet); // NOI18N
attrDecls.put("strip-space", new TreeSet(Arrays.asList(new String[]{"elements"}))); // NOI18N
// xsl:preserve-space
elementDecls.put("preserve-space", emptySet); // NOI18N
attrDecls.put("preserve-space", new TreeSet(Arrays.asList(new String[]{"elements"}))); // NOI18N
// xsl:output
elementDecls.put("output", emptySet); // NOI18N
attrDecls.put("output", new TreeSet(Arrays.asList(new String[]{"method", // NOI18N
"version","encoding","omit-xml-declaration","standalone","doctype-public", // NOI18N
"doctype-system","cdata-section-elements","indent","media-type"}))); // NOI18N
// xsl:key
elementDecls.put("key", emptySet); // NOI18N
attrDecls.put("key", new TreeSet(Arrays.asList(new String[]{"name","match","use"}))); // NOI18N
// xsl:decimal-format
elementDecls.put("decimal-format", emptySet); // NOI18N
attrDecls.put("decimal-format", new TreeSet(Arrays.asList(new String[]{"name", // NOI18N
"decimal-separator","grouping-separator","infinity","minus-sign","NaN", // NOI18N
"percent","per-mille","zero-digit","digit","pattern-separator"}))); // NOI18N
// xsl:namespace-alias
elementDecls.put("namespace-alias", emptySet); // NOI18N
attrDecls.put("namespace-alias", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"stylesheet-prefix","result-prefix"}))); // NOI18N
// xsl:template
tmpSet = new TreeSet(instructions);
tmpSet.add(resultElements);
tmpSet.add("param"); // NOI18N
elementDecls.put("template", tmpSet); // NOI18N
attrDecls.put("template", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"match","name","priority","mode",spaceAtt}))); // NOI18N
// xsl:value-of
elementDecls.put("value-of", emptySet); // NOI18N
attrDecls.put("value-of", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"select","disable-output-escaping"}))); // NOI18N
// xsl:copy-of
elementDecls.put("copy-of", emptySet); // NOI18N
attrDecls.put("copy-of", new TreeSet(Arrays.asList(new String[]{"select"}))); // NOI18N
// xsl:number
elementDecls.put("number", emptySet); // NOI18N
attrDecls.put("number", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"level","count","from","value","format","lang","letter-value", // NOI18N
"grouping-separator","grouping-size"}))); // NOI18N
// xsl:apply-templates
elementDecls.put("apply-templates", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"sort","with-param"}))); // NOI18N
attrDecls.put("apply-templates", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"select","mode"}))); // NOI18N
// xsl:apply-imports
elementDecls.put("apply-imports", emptySet); // NOI18N
attrDecls.put("apply-imports", emptySet); // NOI18N
// xsl:for-each
tmpSet = new TreeSet(instructions);
tmpSet.add(resultElements);
tmpSet.add("sort"); // NOI18N
elementDecls.put("for-each", tmpSet); // NOI18N
attrDecls.put("for-each", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"select",spaceAtt}))); // NOI18N
// xsl:sort
elementDecls.put("sort", emptySet); // NOI18N
attrDecls.put("sort", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"select","lang","data-type","order","case-order"}))); // NOI18N
// xsl:if
elementDecls.put("if", template); // NOI18N
attrDecls.put("if", new TreeSet(Arrays.asList(new String[]{"test",spaceAtt}))); // NOI18N
// xsl:choose
elementDecls.put("choose", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"when","otherwise"}))); // NOI18N
attrDecls.put("choose", new TreeSet(Arrays.asList(new String[]{spaceAtt}))); // NOI18N
// xsl:when
elementDecls.put("when", template); // NOI18N
attrDecls.put("when", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"test",spaceAtt}))); // NOI18N
// xsl:otherwise
elementDecls.put("otherwise", template); // NOI18N
attrDecls.put("otherwise", new TreeSet(Arrays.asList(new String[]{spaceAtt}))); // NOI18N
// xsl:attribute-set
elementDecls.put("sort", new TreeSet(Arrays.asList(new String[]{"attribute"}))); // NOI18N
attrDecls.put("attribute-set", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"name","use-attribute-sets"}))); // NOI18N
// xsl:call-template
elementDecls.put("call-template", new TreeSet(Arrays.asList(new String[]{"with-param"}))); // NOI18N
attrDecls.put("call-template", new TreeSet(Arrays.asList(new String[]{"name"}))); // NOI18N
// xsl:with-param
elementDecls.put("with-param", template); // NOI18N
attrDecls.put("with-param", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"name","select"}))); // NOI18N
// xsl:variable
elementDecls.put("variable", template); // NOI18N
attrDecls.put("variable", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"name","select"}))); // NOI18N
// xsl:param
elementDecls.put("param", template); // NOI18N
attrDecls.put("param", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"name","select"}))); // NOI18N
// xsl:text
elementDecls.put("text", emptySet); // NOI18N
attrDecls.put("text", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"disable-output-escaping"}))); // NOI18N
// xsl:processing-instruction
elementDecls.put("processing-instruction", charTemplate); // NOI18N
attrDecls.put("processing-instruction", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"name",spaceAtt}))); // NOI18N
// xsl:element
elementDecls.put("element", template); // NOI18N
attrDecls.put("element", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"name","namespace","use-attribute-sets",spaceAtt}))); // NOI18N
// xsl:attribute
elementDecls.put("attribute", charTemplate); // NOI18N
attrDecls.put("attribute", new TreeSet(Arrays.asList(new String[]{ // NOI18N
"name","namespace",spaceAtt}))); // NOI18N
// xsl:comment
elementDecls.put("comment", charTemplate); // NOI18N
attrDecls.put("comment", new TreeSet(Arrays.asList(new String[]{spaceAtt}))); // NOI18N
// xsl:copy
elementDecls.put("copy", template); // NOI18N
attrDecls.put("copy", new TreeSet(Arrays.asList(new String[]{ // NOI18N
spaceAtt,"use-attribute-sets"}))); // NOI18N
// xsl:message
elementDecls.put("message", template); // NOI18N
attrDecls.put("message", new TreeSet(Arrays.asList(new String[]{ // NOI18N
spaceAtt,"terminate"}))); // NOI18N
// xsl:fallback
elementDecls.put("fallback", template); // NOI18N
attrDecls.put("fallback", new TreeSet(Arrays.asList(new String[]{spaceAtt}))); // NOI18N
}
return elementDecls;
}
private static Map getAttrDecls() {
if (attrDecls == null) {
getElementDecls();
}
return attrDecls;
}
private static Set getResultElementAttr() {
if (resultElementAttr == null) {
getElementDecls();
}
return resultElementAttr;
}
private static Set getTemplate() {
if (template == null) {
getElementDecls();
}
return template;
}
private static Set getXslFunctions() {
if (xslFunctions == null) {
xslFunctions = new TreeSet(Arrays.asList(new String[]{
"boolean(","ceiling(","concat(", "contains(","count(","current()","document(", // NOI18N
"false()", "floor(","format-number(","generate-id(", // NOI18N
"id(","local-name(","key(","lang(","last()","name(","namespace-uri(", "normalize-space(", // NOI18N
"not(","number(","position()","round(","starts-with(","string(", // NOI18N
"string-length(", "substring(","substring-after(","substring-before(", "sum(", // NOI18N
"system-property(","translate(", "true()","unparsed-entity-uri("})); // NOI18N
}
return xslFunctions;
}
private static Set getXPathAxes() {
if (xpathAxes == null) {
xpathAxes = new TreeSet(Arrays.asList(new String[]{"ancestor::", "ancestor-or-self::", // NOI18N
"attribute::", "child::", "descendant::", "descendant-or-self::", "following::", // NOI18N
"following-sibling::", "namespace::", "parent::", "preceding::", // NOI18N
"preceding-sibling::", "self::"})); // NOI18N
}
return xpathAxes;
}
private static Map getExprAttributes() {
if (exprAttributes == null) {
exprAttributes = new HashMap();
exprAttributes.put("key", "use"); // NOI18N
exprAttributes.put("value-of", "select"); // NOI18N
exprAttributes.put("copy-of", "select"); // NOI18N
exprAttributes.put("number", "value"); // NOI18N
//??? what about match one
exprAttributes.put("apply-templates", "select"); // NOI18N
exprAttributes.put("for-each", "select"); // NOI18N
exprAttributes.put("sort", "select"); // NOI18N
exprAttributes.put("if", "test"); // NOI18N
exprAttributes.put("when", "test"); // NOI18N
exprAttributes.put("with-param", "select"); // NOI18N
exprAttributes.put("variable", "select"); // NOI18N
exprAttributes.put("param", "select"); // NOI18N
}
return exprAttributes;
}
////////////////////////////////////////////////////////////////////////////////
// GrammarQuery interface fulfillment
/**
* Support completions of elements defined by XSLT spec and by the
|