View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 2001-2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  /*
21   * $Id: SymbolTable.java,v 1.5 2005/09/28 13:48:16 pvedula Exp $
22   */
23  
24  package com.sun.org.apache.xalan.internal.xsltc.compiler;
25  
26  import java.util.Hashtable;
27  import java.util.Stack;
28  import java.util.StringTokenizer;
29  import java.util.Vector;
30  
31  import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodType;
32  
33  /**
34   * @author Jacek Ambroziak
35   * @author Santiago Pericas-Geertsen
36   * @author Morten Jorgensen
37   */
38  final class SymbolTable {
39  
40      // These hashtables are used for all stylesheets
41      private final Hashtable _stylesheets = new Hashtable();
42      private final Hashtable _primops     = new Hashtable();
43  
44      // These hashtables are used for some stylesheets
45      private Hashtable _variables = null;
46      private Hashtable _templates = null;
47      private Hashtable _attributeSets = null;
48      private Hashtable _aliases = null;
49      private Hashtable _excludedURI = null;
50      private Stack     _excludedURIStack = null;
51      private Hashtable _decimalFormats = null;
52      private Hashtable _keys = null;
53  
54      public DecimalFormatting getDecimalFormatting(QName name) {
55          if (_decimalFormats == null) return null;
56          return((DecimalFormatting)_decimalFormats.get(name));
57      }
58  
59      public void addDecimalFormatting(QName name, DecimalFormatting symbols) {
60          if (_decimalFormats == null) _decimalFormats = new Hashtable();
61          _decimalFormats.put(name, symbols);
62      }
63  
64      public Key getKey(QName name) {
65          if (_keys == null) return null;
66          return (Key) _keys.get(name);
67      }
68  
69      public void addKey(QName name, Key key) {
70          if (_keys == null) _keys = new Hashtable();
71          _keys.put(name, key);
72      }
73  
74      public Stylesheet addStylesheet(QName name, Stylesheet node) {
75          return (Stylesheet)_stylesheets.put(name, node);
76      }
77  
78      public Stylesheet lookupStylesheet(QName name) {
79          return (Stylesheet)_stylesheets.get(name);
80      }
81  
82      public Template addTemplate(Template template) {
83          final QName name = template.getName();
84          if (_templates == null) _templates = new Hashtable();
85          return (Template)_templates.put(name, template);
86      }
87  
88      public Template lookupTemplate(QName name) {
89          if (_templates == null) return null;
90          return (Template)_templates.get(name);
91      }
92  
93      public Variable addVariable(Variable variable) {
94          if (_variables == null) _variables = new Hashtable();
95          final String name = variable.getName().getStringRep();
96          return (Variable)_variables.put(name, variable);
97      }
98  
99      public Param addParam(Param parameter) {
100         if (_variables == null) _variables = new Hashtable();
101         final String name = parameter.getName().getStringRep();
102         return (Param)_variables.put(name, parameter);
103     }
104 
105     public Variable lookupVariable(QName qname) {
106         if (_variables == null) return null;
107         final String name = qname.getStringRep();
108         final Object obj = _variables.get(name);
109         return obj instanceof Variable ? (Variable)obj : null;
110     }
111 
112     public Param lookupParam(QName qname) {
113         if (_variables == null) return null;
114         final String name = qname.getStringRep();
115         final Object obj = _variables.get(name);
116         return obj instanceof Param ? (Param)obj : null;
117     }
118 
119     public SyntaxTreeNode lookupName(QName qname) {
120         if (_variables == null) return null;
121         final String name = qname.getStringRep();
122         return (SyntaxTreeNode)_variables.get(name);
123     }
124 
125     public AttributeSet addAttributeSet(AttributeSet atts) {
126         if (_attributeSets == null) _attributeSets = new Hashtable();
127         return (AttributeSet)_attributeSets.put(atts.getName(), atts);
128     }
129 
130     public AttributeSet lookupAttributeSet(QName name) {
131         if (_attributeSets == null) return null;
132         return (AttributeSet)_attributeSets.get(name);
133     }
134 
135     /**
136      * Add a primitive operator or function to the symbol table. To avoid
137      * name clashes with user-defined names, the prefix <tt>PrimopPrefix</tt>
138      * is prepended.
139      */
140     public void addPrimop(String name, MethodType mtype) {
141         Vector methods = (Vector)_primops.get(name);
142         if (methods == null) {
143             _primops.put(name, methods = new Vector());
144         }
145         methods.addElement(mtype);
146     }
147 
148     /**
149      * Lookup a primitive operator or function in the symbol table by
150      * prepending the prefix <tt>PrimopPrefix</tt>.
151      */
152     public Vector lookupPrimop(String name) {
153         return (Vector)_primops.get(name);
154     }
155 
156     /**
157      * This is used for xsl:attribute elements that have a "namespace"
158      * attribute that is currently not defined using xmlns:
159      */
160     private int _nsCounter = 0;
161 
162     public String generateNamespacePrefix() {
163         return("ns"+(_nsCounter++));
164     }
165 
166     /**
167      * Use a namespace prefix to lookup a namespace URI
168      */
169     private SyntaxTreeNode _current = null;
170 
171     public void setCurrentNode(SyntaxTreeNode node) {
172         _current = node;
173     }
174 
175     public String lookupNamespace(String prefix) {
176         if (_current == null) return(Constants.EMPTYSTRING);
177         return(_current.lookupNamespace(prefix));
178     }
179 
180     /**
181      * Adds an alias for a namespace prefix
182      */
183     public void addPrefixAlias(String prefix, String alias) {
184         if (_aliases == null) _aliases = new Hashtable();
185         _aliases.put(prefix,alias);
186     }
187 
188     /**
189      * Retrieves any alias for a given namespace prefix
190      */
191     public String lookupPrefixAlias(String prefix) {
192         if (_aliases == null) return null;
193         return (String)_aliases.get(prefix);
194     }
195 
196     /**
197      * Register a namespace URI so that it will not be declared in the output
198      * unless it is actually referenced in the output.
199      */
200     public void excludeURI(String uri) {
201         // The null-namespace cannot be excluded
202         if (uri == null) return;
203 
204         // Create new hashtable of exlcuded URIs if none exists
205         if (_excludedURI == null) _excludedURI = new Hashtable();
206 
207         // Register the namespace URI
208         Integer refcnt = (Integer)_excludedURI.get(uri);
209         if (refcnt == null)
210             refcnt = new Integer(1);
211         else
212             refcnt = new Integer(refcnt.intValue() + 1);
213         _excludedURI.put(uri,refcnt);
214     }
215 
216     /**
217      * Exclude a series of namespaces given by a list of whitespace
218      * separated namespace prefixes.
219      */
220     public void excludeNamespaces(String prefixes) {
221         if (prefixes != null) {
222             StringTokenizer tokens = new StringTokenizer(prefixes);
223             while (tokens.hasMoreTokens()) {
224                 final String prefix = tokens.nextToken();
225                 final String uri;
226                 if (prefix.equals("#default"))
227                     uri = lookupNamespace(Constants.EMPTYSTRING);
228                 else
229                     uri = lookupNamespace(prefix);
230                 if (uri != null) excludeURI(uri);
231             }
232         }
233     }
234 
235     /**
236      * Check if a namespace should not be declared in the output (unless used)
237      */
238     public boolean isExcludedNamespace(String uri) {
239         if (uri != null && _excludedURI != null) {
240             final Integer refcnt = (Integer)_excludedURI.get(uri);
241             return (refcnt != null && refcnt.intValue() > 0);
242         }
243         return false;
244     }
245 
246     /**
247      * Turn of namespace declaration exclusion
248      */
249     public void unExcludeNamespaces(String prefixes) {
250         if (_excludedURI == null) return;
251         if (prefixes != null) {
252             StringTokenizer tokens = new StringTokenizer(prefixes);
253             while (tokens.hasMoreTokens()) {
254                 final String prefix = tokens.nextToken();
255                 final String uri;
256                 if (prefix.equals("#default"))
257                     uri = lookupNamespace(Constants.EMPTYSTRING);
258                 else
259                     uri = lookupNamespace(prefix);
260                 Integer refcnt = (Integer)_excludedURI.get(uri);
261                 if (refcnt != null)
262                     _excludedURI.put(uri, new Integer(refcnt.intValue() - 1));
263             }
264         }
265     }
266     /**
267      * Exclusion of namespaces by a stylesheet does not extend to any stylesheet
268      * imported or included by the stylesheet.  Upon entering the context of a
269      * new stylesheet, a call to this method is needed to clear the current set
270      * of excluded namespaces temporarily.  Every call to this method requires
271      * a corresponding call to {@link #popExcludedNamespacesContext()}.
272      */
273     public void pushExcludedNamespacesContext() {
274         if (_excludedURIStack == null) {
275             _excludedURIStack = new Stack();
276         }
277         _excludedURIStack.push(_excludedURI);
278         _excludedURI = null;
279     }
280 
281     /**
282      * Exclusion of namespaces by a stylesheet does not extend to any stylesheet
283      * imported or included by the stylesheet.  Upon exiting the context of a
284      * stylesheet, a call to this method is needed to restore the set of
285      * excluded namespaces that was in effect prior to entering the context of
286      * the current stylesheet.
287      */
288     public void popExcludedNamespacesContext() {
289         _excludedURI = (Hashtable) _excludedURIStack.pop();
290         if (_excludedURIStack.isEmpty()) {
291             _excludedURIStack = null;
292         }
293     }
294 
295 }