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 package org.apache.qetest.xslwrapper; 21 22 import java.util.HashMap; 23 import java.util.Properties; 24 import javax.xml.transform.Transformer; 25 import javax.xml.transform.TransformerFactory; 26 27 /** 28 * A few default implementations of TransformWrapper methods. 29 * 30 * A TransformWrapperHelper implements a few of the common methods from 31 * TransformWrapper that don't directly interact with the underlying processor. 32 * Individual wrapper implementations are free to extend this class to get some 33 * free code. 34 */ 35 public abstract class TransformWrapperHelper implements TransformWrapper { 36 /** 37 * TransformerFactory to use; constructed in newProcessor(). 38 */ 39 protected TransformerFactory factory; 40 41 /** 42 * Cached copy of newProcessor() properties. 43 */ 44 protected Properties newProcessorOpts; 45 46 /** 47 * Constant denoting that indent should not be set. 48 */ 49 private static final int NO_INDENT = -2; 50 51 /** 52 * Set of stylesheet parameters for use in transforms. 53 */ 54 protected final HashMap<String,String> m_params = new HashMap<>(); 55 56 /** 57 * If our wrapper has a built stylesheet ready. 58 */ 59 protected volatile boolean m_stylesheetReady = false; 60 61 /** 62 * Current number of spaces to indent, default: NO_INDENT. Users call 63 * setAttribute(ATTRIBUTE_INDENT, int) to set this. If it is set, it will be 64 * applied to an underlying processor during each transform operation, where 65 * supported. 66 */ 67 protected int m_indent = NO_INDENT; 68 69 /** 70 * Reports if a pre-built/pre-compiled stylesheet is ready; presumably built 71 * by calling buildStylesheet(xslName). 72 * 73 * @return true if one is ready; false otherwise 74 * 75 * @see #buildStylesheet(String xslName) 76 */ 77 @Override 78 public boolean isStylesheetReady() { 79 return m_stylesheetReady; 80 } 81 82 /** 83 * Set a stylesheet parameter for use in later transforms. 84 * 85 * This method merely stores the triple for use later in a transform 86 * operation. Note that the actual mechanisims for setting parameters in 87 * implementation differ, especially with regards to namespaces. 88 * 89 * Note that the namespace may not contain the "{" or "}" characters, since 90 * these would be illegal XML namespaces anyways; an 91 * IllegalArgumentException will be thrown. Note that the name may not begin 92 * with the "{" character, since it would likely be an illegal XML name 93 * anyways; an IllegalArgumentException will be thrown. 94 * 95 * @param namespace for the parameter 96 * @param name of the parameter 97 * @param value of the parameter 98 * 99 * @throws IllegalArgumentException thrown if the namespace appears to be 100 * illegal. 101 */ 102 @Override 103 public void setParameter(String namespace, String name, String value) 104 throws IllegalArgumentException { 105 if (null != namespace) { 106 if ((namespace.contains("{")) 107 || (namespace.contains("}"))) { 108 throw new IllegalArgumentException("setParameter: illegal namespace includes brackets: " + namespace); 109 } 110 } 111 if (null != name) { 112 if (name.startsWith("{")) { 113 throw new IllegalArgumentException( 114 "setParameter: illegal name begins with bracket: " + name); 115 } 116 } 117 118 if (null != namespace) { 119 m_params.put("{" + namespace + "}" + name, value); 120 } else { 121 m_params.put(name, value); 122 } 123 } 124 125 /** 126 * Get a parameter that was set with setParameter. 127 * 128 * Only returns parameters set locally, not parameters exposed by the 129 * underlying processor implementation. Not terribly useful but I always 130 * like providing gets for any sets I define. 131 * 132 * @param namespace for the parameter 133 * @param name of the parameter 134 */ 135 @Override 136 public Object getParameter(String namespace, String name) { 137 if (null == m_params) { 138 return null; 139 } 140 141 if (null != namespace) { 142 return m_params.get("{" + namespace + "}" + name); 143 } else { 144 return m_params.get(name); 145 } 146 } 147 148 /** 149 * Apply the parameters that were set with setParameter to our underlying 150 * processor implementation. 151 * 152 * Subclasses may call this to apply all set parameters during each 153 * transform if they override the applyParameter() method to set a single 154 * parameter. 155 * 156 * This is a convenience method for getting data out of m_params that was 157 * encoded by our setParameter(). 158 * 159 * @param transformer a Transformer object. 160 */ 161 protected void applyParameters(Transformer transformer) { 162 m_params.forEach((key, value) -> { 163 String namespace = null; 164 String name; 165 if (key.startsWith("{")) { 166 int idx = key.indexOf("}"); 167 namespace = key.substring(1, idx); 168 name = key.substring(idx + 1); 169 } else { 170 // namespace stays null 171 name = key; 172 } 173 // Call subclassed worker method for each parameter 174 applyParameter(transformer, namespace, name, value); 175 }); 176 } 177 178 /** 179 * Apply a single parameter to our underlying processor implementation: must 180 * be overridden. 181 * 182 * Subclasses must override; this class will throw an IllegalStateException 183 * since we can't do anything. 184 * 185 * @param transformer a Transformer object. 186 * @param namespace for the parameter, may be null 187 * @param name for the parameter, should not be null 188 * @param value for the parameter, may be null 189 */ 190 protected abstract void applyParameter(Transformer transformer, String namespace, 191 String name, String value); 192 193 /** 194 * Reset our parameters and wrapper state, and optionally force creation of 195 * a new underlying processor implementation. 196 * 197 * This class clears the indent and any parameters. Subclasses are free to 198 * call us to get this default behavior or not. Note that subclasses must 199 * clear m_stylesheetReady themselves if needed. 200 * 201 * @param newProcessor ignored in this class 202 */ 203 @Override 204 public void reset(boolean newProcessor) { 205 m_params.clear(); 206 m_indent = NO_INDENT; 207 } 208 209 /** 210 * Ensure newProcessor has been called when needed. 211 * 212 * Prevent users from shooting themselves in the foot by calling a 213 * transform* API before newProcessor(). 214 * 215 * @throws java.lang.Exception 216 */ 217 public void preventFootShooting() throws Exception { 218 if (null == factory) { 219 newProcessor(newProcessorOpts); 220 } 221 } 222 }