1 16 package org.apache.cocoon.transformation; 17 18 import java.io.IOException ; 19 import java.util.HashMap ; 20 import java.util.Map ; 21 22 import org.apache.avalon.framework.activity.Initializable; 23 import org.apache.avalon.framework.parameters.Parameters; 24 import org.apache.cocoon.ProcessingException; 25 import org.apache.cocoon.components.flow.FlowHelper; 26 import org.apache.cocoon.components.flow.WebContinuation; 27 import org.apache.cocoon.environment.SourceResolver; 28 import org.apache.commons.jxpath.JXPathContext; 29 import org.apache.regexp.RE; 30 import org.xml.sax.Attributes ; 31 import org.xml.sax.SAXException ; 32 import org.xml.sax.helpers.AttributesImpl ; 33 34 59 public class JPathTransformer extends AbstractSAXTransformer 60 implements Initializable { 61 62 63 public static final String JPATH_NAMESPACE_URI = "http://apache.org/xsp/jpath/1.0"; 64 65 66 public static final String JPATH_ACTION = "jpath:action"; 67 68 69 public static final String JPATH_VALUEOF = "value-of"; 70 71 72 public static final String JPATH_VALUEOF_SELECT = "select"; 73 74 75 public static final String JPATH_CONTINUATION = "continuation"; 76 77 78 public static final String JPATH_CONTINUATION_SELECT = "select"; 79 80 81 public static final String JPATH_IF = "if"; 82 83 84 public static final String JPATH_TEST = "test"; 85 86 private WebContinuation m_kont; 88 89 private RE m_re; 91 92 private JXPathContext m_jxpathContext; 94 95 private Map m_cache; 97 98 103 public void initialize() throws Exception { 104 this.defaultNamespaceURI = JPATH_NAMESPACE_URI; 105 m_re = new RE("id"); 106 m_cache = new HashMap (); 107 } 108 109 120 public void setup(SourceResolver resolver, Map objectModel, 121 String src, Parameters parameters) 122 throws ProcessingException, SAXException , IOException { 123 124 super.setup(resolver, objectModel, src, parameters); 125 126 Object bean = FlowHelper.getContextObject(objectModel); 128 m_kont = FlowHelper.getWebContinuation(objectModel); 129 m_jxpathContext = JXPathContext.newContext(bean); 130 } 131 132 142 public void startElement(String uri, String loc, String raw, Attributes a) 143 throws SAXException { 144 145 AttributesImpl impl = new AttributesImpl (a); 146 checkJPathAction(impl); 147 148 super.startElement(uri, loc, raw, impl); 149 } 150 151 162 public void startTransformingElement( 163 String uri, String name, String raw, Attributes attr 164 ) 165 throws ProcessingException ,IOException , SAXException { 166 167 if (JPATH_VALUEOF.equals(name)) { 168 doValueOf(attr); 169 } else if (JPATH_CONTINUATION.equals(name)) { 170 doContinuation(attr); 171 } else if (JPATH_IF.equals(name)) { 172 doIf(attr); 173 } else { 174 super.startTransformingElement(uri, name, raw, attr); 175 } 176 } 177 178 188 public void endTransformingElement( 189 String uri, String name, String raw 190 ) 191 throws ProcessingException, IOException , SAXException { 192 193 if (JPATH_VALUEOF.equals(name) || 194 JPATH_CONTINUATION.equals(name)) { 195 return; } else if (JPATH_IF.equals(name)) { 197 finishIf(); 198 } else { 199 super.endTransformingElement(uri, name, raw); 200 } 201 } 202 203 210 private void checkJPathAction(final AttributesImpl a) { 211 212 int idx = a.getIndex(JPATH_ACTION); 214 215 if (idx != -1 && JPATH_NAMESPACE_URI.equals(a.getURI(idx))) { 216 if (getLogger().isDebugEnabled()) { 217 getLogger().debug("found jpath:action, adjusting"); 218 } 219 220 String value = a.getValue(idx); 221 222 String id = m_kont.getContinuation(0).getId(); 224 225 a.removeAttribute(idx); 226 a.addAttribute( 227 "", "action", "action", "CDATA", m_re.subst(value, id) 228 ); 229 } 230 } 231 232 238 private Object getValue(final String variable) { 239 240 Object value; 241 242 if (m_cache.containsKey(variable)) { 243 value = m_cache.get(variable); 244 } else { 245 value = JXPathContext.compile(variable).getValue(m_jxpathContext); 246 247 if (value == null) { 248 if (getLogger().isWarnEnabled()) { 249 final String msg = 250 "Value for jpath variable '" + variable + "' does not exist"; 251 getLogger().warn(msg); 252 } 253 } 254 255 m_cache.put(variable, value); 256 } 257 258 return value; 259 } 260 261 268 private void doValueOf(final Attributes a) 269 throws SAXException , ProcessingException { 270 271 final String select = a.getValue(JPATH_VALUEOF_SELECT); 272 273 if (null != select) { 274 sendTextEvent((String )getValue(select)); 275 } else { 276 throw new ProcessingException( 277 "jpath:" + JPATH_VALUEOF + " specified without a select attribute" 278 ); 279 } 280 } 281 282 288 private void doContinuation(final Attributes a) 289 throws SAXException { 290 291 final String level = a.getValue(JPATH_CONTINUATION_SELECT); 292 293 final String id = (level != null) 294 ? m_kont.getContinuation(Integer.decode(level).intValue()).getId() 295 : m_kont.getContinuation(0).getId(); 296 297 sendTextEvent(id); 298 } 299 300 306 private void doIf(final Attributes a) 307 throws SAXException { 308 309 313 if (ignoreEventsCount > 0) { 314 ++ignoreEventsCount; 315 return; 316 } 317 318 final Object value = getValue(a.getValue(JPATH_TEST)); 320 321 final boolean isTrueBoolean = 322 value instanceof Boolean && ((Boolean )value).booleanValue() == true; 323 final boolean isNonNullNonBoolean = 324 value != null && !(value instanceof Boolean ); 325 326 if (isTrueBoolean || isNonNullNonBoolean) { 327 if (getLogger().isDebugEnabled()) { 329 getLogger().debug("jpath:if results in allowing subelements"); 330 } 331 } else { 332 if (getLogger().isDebugEnabled()) { 334 getLogger().debug("jpath:if results in disallowing subelements"); 335 } 336 ++ignoreEventsCount; 337 } 338 } 339 340 345 private void finishIf() 346 throws SAXException { 347 348 if (ignoreEventsCount > 0) { 351 --ignoreEventsCount; 352 } 353 354 if (getLogger().isDebugEnabled()) { 355 getLogger().debug("jpath:if closed"); 356 } 357 } 358 359 362 public void recycle() { 363 m_cache.clear(); 364 m_kont = null; 365 m_jxpathContext = null; 366 367 super.recycle(); 368 } 369 } 370 | Popular Tags |