📄 abstracttranslet.java
字号:
/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * $Id: AbstractTranslet.java,v 1.6 2006/06/19 19:49:03 spericas Exp $ */package com.sun.org.apache.xalan.internal.xsltc.runtime;import java.io.File;import java.io.FileWriter;import java.text.DecimalFormat;import java.text.DecimalFormatSymbols;import java.util.ArrayList;import java.util.Enumeration;import java.util.Vector;import javax.xml.transform.Templates;import javax.xml.parsers.DocumentBuilderFactory;import org.w3c.dom.Document;import org.w3c.dom.DOMImplementation;import javax.xml.parsers.ParserConfigurationException;import com.sun.org.apache.xml.internal.dtm.DTM;import com.sun.org.apache.xalan.internal.xsltc.DOM;import com.sun.org.apache.xalan.internal.xsltc.DOMCache;import com.sun.org.apache.xalan.internal.xsltc.DOMEnhancedForDTM;import com.sun.org.apache.xalan.internal.xsltc.Translet;import com.sun.org.apache.xalan.internal.xsltc.TransletException;import com.sun.org.apache.xalan.internal.xsltc.dom.DOMAdapter;import com.sun.org.apache.xalan.internal.xsltc.dom.KeyIndex;import com.sun.org.apache.xalan.internal.xsltc.runtime.output.TransletOutputHandlerFactory;import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;import com.sun.org.apache.xml.internal.serializer.SerializationHandler;/** * @author Jacek Ambroziak * @author Santiago Pericas-Geertsen * @author Morten Jorgensen * @author G. Todd Miller * @author John Howard, JohnH@schemasoft.com */public abstract class AbstractTranslet implements Translet { // These attributes are extracted from the xsl:output element. They also // appear as fields (with the same type, only public) in Output.java public String _version = "1.0"; public String _method = null; public String _encoding = "UTF-8"; public boolean _omitHeader = false; public String _standalone = null; public String _doctypePublic = null; public String _doctypeSystem = null; public boolean _indent = false; public String _mediaType = null; public Vector _cdata = null; public int _indentamount = -1; public static final int FIRST_TRANSLET_VERSION = 100; public static final int VER_SPLIT_NAMES_ARRAY = 101; public static final int CURRENT_TRANSLET_VERSION = VER_SPLIT_NAMES_ARRAY; // Initialize Translet version field to base value. A class that extends // AbstractTranslet may override this value to a more recent translet // version; if it doesn't override the value (because it was compiled // before the notion of a translet version was introduced, it will get // this default value). protected int transletVersion = FIRST_TRANSLET_VERSION; // DOM/translet handshaking - the arrays are set by the compiled translet protected String[] namesArray; protected String[] urisArray; protected int[] typesArray; protected String[] namespaceArray; // The Templates object that is used to create this Translet instance protected Templates _templates = null; // Boolean flag to indicate whether this translet has id functions. protected boolean _hasIdCall = false; // TODO - these should only be instanciated when needed protected StringValueHandler stringValueHandler = new StringValueHandler(); // Use one empty string instead of constantly instanciating String(""); private final static String EMPTYSTRING = ""; // This is the name of the index used for ID attributes private final static String ID_INDEX_NAME = "##id"; /************************************************************************ * Debugging ************************************************************************/ public void printInternalState() { System.out.println("-------------------------------------"); System.out.println("AbstractTranslet this = " + this); System.out.println("pbase = " + pbase); System.out.println("vframe = " + pframe); System.out.println("paramsStack.size() = " + paramsStack.size()); System.out.println("namesArray.size = " + namesArray.length); System.out.println("namespaceArray.size = " + namespaceArray.length); System.out.println(""); System.out.println("Total memory = " + Runtime.getRuntime().totalMemory()); } /** * Wrap the initial input DOM in a dom adapter. This adapter is wrapped in * a DOM multiplexer if the document() function is used (handled by compiled * code in the translet - see compiler/Stylesheet.compileTransform()). */ public final DOMAdapter makeDOMAdapter(DOM dom) throws TransletException { setRootForKeys(dom.getDocument()); return new DOMAdapter(dom, namesArray, urisArray, typesArray, namespaceArray); } /************************************************************************ * Parameter handling ************************************************************************/ // Parameter's stack: <tt>pbase</tt> and <tt>pframe</tt> are used // to denote the current parameter frame. protected int pbase = 0, pframe = 0; protected ArrayList paramsStack = new ArrayList(); /** * Push a new parameter frame. */ public final void pushParamFrame() { paramsStack.add(pframe, new Integer(pbase)); pbase = ++pframe; } /** * Pop the topmost parameter frame. */ public final void popParamFrame() { if (pbase > 0) { final int oldpbase = ((Integer)paramsStack.get(--pbase)).intValue(); for (int i = pframe - 1; i >= pbase; i--) { paramsStack.remove(i); } pframe = pbase; pbase = oldpbase; } } /** * Add a new global parameter if not already in the current frame. * To setParameters of the form {http://foo.bar}xyz * This needs to get mapped to an instance variable in the class * The mapping created so that * the global variables in the generated class become * http$colon$$flash$$flash$foo$dot$bar$colon$xyz */ public final Object addParameter(String name, Object value) { name = BasisLibrary.mapQNameToJavaName (name); return addParameter(name, value, false); } /** * Add a new global or local parameter if not already in the current frame. * The 'isDefault' parameter is set to true if the value passed is the * default value from the <xsl:parameter> element's select attribute or * element body. */ public final Object addParameter(String name, Object value, boolean isDefault) { // Local parameters need to be re-evaluated for each iteration for (int i = pframe - 1; i >= pbase; i--) { final Parameter param = (Parameter) paramsStack.get(i); if (param._name.equals(name)) { // Only overwrite if current value is the default value and // the new value is _NOT_ the default value. if (param._isDefault || !isDefault) { param._value = value; param._isDefault = isDefault; return value; } return param._value; } } // Add new parameter to parameter stack paramsStack.add(pframe++, new Parameter(name, value, isDefault)); return value; } /** * Clears the parameter stack. */ public void clearParameters() { pbase = pframe = 0; paramsStack.clear(); } /** * Get the value of a parameter from the current frame or * <tt>null</tt> if undefined. */ public final Object getParameter(String name) { name = BasisLibrary.mapQNameToJavaName (name); for (int i = pframe - 1; i >= pbase; i--) { final Parameter param = (Parameter)paramsStack.get(i); if (param._name.equals(name)) return param._value; } return null; } /************************************************************************ * Message handling - implementation of <xsl:message> ************************************************************************/ // Holds the translet's message handler - used for <xsl:message>. // The deault message handler dumps a string stdout, but anything can be // used, such as a dialog box for applets, etc. private MessageHandler _msgHandler = null; /** * Set the translet's message handler - must implement MessageHandler */ public final void setMessageHandler(MessageHandler handler) { _msgHandler = handler; } /** * Pass a message to the message handler - used by Message class. */ public final void displayMessage(String msg) { if (_msgHandler == null) { System.err.println(msg); } else { _msgHandler.displayMessage(msg); } } /************************************************************************ * Decimal number format symbol handling ************************************************************************/ // Contains decimal number formatting symbols used by FormatNumberCall public Hashtable _formatSymbols = null; /** * Adds a DecimalFormat object to the _formatSymbols hashtable. * The entry is created with the input DecimalFormatSymbols. */ public void addDecimalFormat(String name, DecimalFormatSymbols symbols) { // Instanciate hashtable for formatting symbols if needed if (_formatSymbols == null) _formatSymbols = new Hashtable(); // The name cannot be null - use empty string instead if (name == null) name = EMPTYSTRING; // Construct a DecimalFormat object containing the symbols we got final DecimalFormat df = new DecimalFormat(); if (symbols != null) { df.setDecimalFormatSymbols(symbols); } _formatSymbols.put(name, df); } /** * Retrieves a named DecimalFormat object from _formatSymbols hashtable. */ public final DecimalFormat getDecimalFormat(String name) { if (_formatSymbols != null) { // The name cannot be null - use empty string instead if (name == null) name = EMPTYSTRING; DecimalFormat df = (DecimalFormat)_formatSymbols.get(name); if (df == null) df = (DecimalFormat)_formatSymbols.get(EMPTYSTRING); return df; } return(null); } /** * Give the translet an opportunity to perform a prepass on the document * to extract any information that it can store in an optimized form. * * Currently, it only extracts information about attributes of type ID. */ public final void prepassDocument(DOM document) { setIndexSize(document.getSize()); buildIDIndex(document); } /** * Leverages the Key Class to implement the XSLT id() function. * buildIdIndex creates the index (##id) that Key Class uses. * The index contains the element node index (int) and Id value (String). */ private final void buildIDIndex(DOM document) { setRootForKeys(document.getDocument()); if (document instanceof DOMEnhancedForDTM) { DOMEnhancedForDTM enhancedDOM = (DOMEnhancedForDTM)document; // If the input source is DOMSource, the KeyIndex table is not // built at this time. It will be built later by the lookupId() // and containsId() methods of the KeyIndex class. if (enhancedDOM.hasDOMSource()) { buildKeyIndex(ID_INDEX_NAME, document); return; } else { final Hashtable elementsByID = enhancedDOM.getElementsWithIDs(); if (elementsByID == null) { return; } // Given a Hashtable of DTM nodes indexed by ID attribute values, // loop through the table copying information to a KeyIndex // for the mapping from ID attribute value to DTM node final Enumeration idValues = elementsByID.keys(); boolean hasIDValues = false; while (idValues.hasMoreElements()) { final Object idValue = idValues.nextElement(); final int element = document.getNodeHandle( ((Integer)elementsByID.get(idValue)) .intValue()); buildKeyIndex(ID_INDEX_NAME, element, idValue); hasIDValues = true; } if (hasIDValues) { setKeyIndexDom(ID_INDEX_NAME, document); } } } } /** * After constructing the translet object, this method must be called to * perform any version-specific post-initialization that's required. */ public final void postInitialization() { // If the version of the translet had just one namesArray, split // it into multiple fields. if (transletVersion < VER_SPLIT_NAMES_ARRAY) { int arraySize = namesArray.length; String[] newURIsArray = new String[arraySize]; String[] newNamesArray = new String[arraySize]; int[] newTypesArray = new int[arraySize]; for (int i = 0; i < arraySize; i++) { String name = namesArray[i]; int colonIndex = name.lastIndexOf(':'); int lNameStartIdx = colonIndex+1; if (colonIndex > -1) { newURIsArray[i] = name.substring(0, colonIndex); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -