1/* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 */ 4/* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. 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 24package com.sun.org.apache.xalan.internal.xsltc.compiler; 25 26import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodType; 27import java.util.HashMap; 28import java.util.Map; 29import java.util.Stack; 30import java.util.StringTokenizer; 31import java.util.Vector; 32 33/** 34 * @author Jacek Ambroziak 35 * @author Santiago Pericas-Geertsen 36 * @author Morten Jorgensen 37 */ 38final class SymbolTable { 39 40 // These maps are used for all stylesheets 41 private final Map<String, Stylesheet> _stylesheets = new HashMap<>(); 42 private final Map<String, Vector> _primops = new HashMap<>(); 43 44 // These maps are used for some stylesheets 45 private Map<String, VariableBase> _variables = null; 46 private Map<String, Template> _templates = null; 47 private Map<String, AttributeSet> _attributeSets = null; 48 private Map<String, String> _aliases = null; 49 private Map<String, Integer> _excludedURI = null; 50 private Stack<Map<String, Integer>> _excludedURIStack = null; 51 private Map<String, DecimalFormatting> _decimalFormats = null; 52 private Map<String, Key> _keys = null; 53 54 public DecimalFormatting getDecimalFormatting(QName name) { 55 if (_decimalFormats == null) return null; 56 return(_decimalFormats.get(name.getStringRep())); 57 } 58 59 public void addDecimalFormatting(QName name, DecimalFormatting symbols) { 60 if (_decimalFormats == null) _decimalFormats = new HashMap<>(); 61 _decimalFormats.put(name.getStringRep(), symbols); 62 } 63 64 public Key getKey(QName name) { 65 if (_keys == null) return null; 66 return _keys.get(name.getStringRep()); 67 } 68 69 public void addKey(QName name, Key key) { 70 if (_keys == null) _keys = new HashMap<>(); 71 _keys.put(name.getStringRep(), key); 72 } 73 74 public Stylesheet addStylesheet(QName name, Stylesheet node) { 75 return _stylesheets.put(name.getStringRep(), node); 76 } 77 78 public Stylesheet lookupStylesheet(QName name) { 79 return _stylesheets.get(name.getStringRep()); 80 } 81 82 public Template addTemplate(Template template) { 83 final QName name = template.getName(); 84 if (_templates == null) _templates = new HashMap<>(); 85 return _templates.put(name.getStringRep(), template); 86 } 87 88 public Template lookupTemplate(QName name) { 89 if (_templates == null) return null; 90 return _templates.get(name.getStringRep()); 91 } 92 93 public Variable addVariable(Variable variable) { 94 if (_variables == null) _variables = new HashMap<>(); 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 HashMap<>(); 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 VariableBase 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 VariableBase 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 HashMap<>(); 127 return _attributeSets.put(atts.getName().getStringRep(), atts); 128 } 129 130 public AttributeSet lookupAttributeSet(QName name) { 131 if (_attributeSets == null) return null; 132 return _attributeSets.get(name.getStringRep()); 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 = _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 _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 HashMap<>(); 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 _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 a new map of exlcuded URIs if none exists 205 if (_excludedURI == null) _excludedURI = new HashMap<>(); 206 207 // Register the namespace URI 208 Integer refcnt = _excludedURI.get(uri); 209 if (refcnt == null) 210 refcnt = 1; 211 else 212 refcnt = refcnt + 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 = _excludedURI.get(uri); 241 return (refcnt != null && refcnt > 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 = _excludedURI.get(uri); 261 if (refcnt != null) 262 _excludedURI.put(uri, refcnt - 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 = _excludedURIStack.pop(); 290 if (_excludedURIStack.isEmpty()) { 291 _excludedURIStack = null; 292 } 293 } 294 295} 296