Author: lektran
Date: Sat May 2 08:45:22 2009 New Revision: 770915 URL: http://svn.apache.org/viewvc?rev=770915&view=rev Log: OFBIZ-2397 Implement a custom JUEL ELResolver that handles string properties for objects implementing org.w3c.dom.Node and org.apache.xerces.dom.NodeImpl. It takes the String and compiles it into an XPathExpression which is then evaluated against the base Node. The JUEL evaluation returns either null, a single Node or a NodeList depending on the result of the XPath evaluation. Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/NodeELResolver.java (with props) Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/ObjectType.java ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/UelUtil.java ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Iterate.java Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/ObjectType.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/ObjectType.java?rev=770915&r1=770914&r2=770915&view=diff ============================================================================== --- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/ObjectType.java (original) +++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/ObjectType.java Sat May 2 08:45:22 2009 @@ -28,6 +28,8 @@ import java.util.*; import java.nio.*; +import org.w3c.dom.Node; + import javolution.util.FastList; import javolution.util.FastMap; import javolution.util.FastSet; @@ -979,6 +981,14 @@ } else { throw new GeneralException("Conversion from " + fromType + " to " + type + " not currently supported"); } + } else if (obj instanceof Node) { + Node node = (Node) obj; + String nodeValue = node.getTextContent(); + if ("String".equals(type) || "java.lang.String".equals(type)) { + return nodeValue; + } else { + return simpleTypeConvert(nodeValue, type, format, timeZone, locale, noTypeFail); + } } else { // we can pretty much always do a conversion to a String, so do that here if ("String".equals(type) || "java.lang.String".equals(type)) { Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/NodeELResolver.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/NodeELResolver.java?rev=770915&view=auto ============================================================================== --- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/NodeELResolver.java (added) +++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/NodeELResolver.java Sat May 2 08:45:22 2009 @@ -0,0 +1,156 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + *******************************************************************************/ +package org.ofbiz.base.util.string; + +import java.beans.FeatureDescriptor; +import java.util.Iterator; + +import javax.el.CompositeELResolver; +import javax.el.ELContext; +import javax.el.ELResolver; +import javax.el.PropertyNotWritableException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.apache.xerces.dom.NodeImpl; +import org.ofbiz.base.util.Debug; +import org.ofbiz.base.util.cache.UtilCache; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * Defines property resolution behavior on Nodes. This resolver handles base objects that implement + * org.w3c.dom.Node or org.apache.xerces.dom.NodeImpl. It accepts a String as a property and compiles + * that String into an XPathExpression. The resulting value is the evaluation of the XPathExpression + * in the context of the base Node. This resolver is currently only available in read-only mode, which + * means that isReadOnly will always return true and {@link #setValue(ELContext, Object, Object, Object)} + * will always throw PropertyNotWritableException. ELResolvers are combined together using {@link CompositeELResolver} + * s, to define rich semantics for evaluating an expression. See the javadocs for {@link ELResolver} + * for details. + */ +public class NodeELResolver extends ELResolver { + private final XPath xpath; + private final UtilCache<String, XPathExpression> exprCache = new UtilCache<String, XPathExpression>("nodeElResolver.ExpressionCache"); + private static final String module = NodeELResolver.class.getName(); + + /** + * Creates a new read-only NodeELResolver. + */ + public NodeELResolver() { + XPathFactory factory = XPathFactory.newInstance(); + xpath = factory.newXPath(); + } + + @Override + public Class<?> getCommonPropertyType(ELContext context, Object base) { + return isResolvable(base) ? String.class : null; + } + + @Override + public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) { + return null; + } + + @Override + public Class<?> getType(ELContext context, Object base, Object property) { + if (context == null) { + throw new NullPointerException("context is null"); + } + Class<?> result = null; + if (isResolvable(base)) { + result = Node.class; + context.setPropertyResolved(true); + } + return result; + } + + @Override + public Object getValue(ELContext context, Object base, Object property) { + if (context == null) { + throw new NullPointerException("context is null"); + } + Object result = null; + if (isResolvable(base)) { + try { + Node node = (Node) base; + String propertyString = (String) property; + XPathExpression expr = getXPathExpressionInstance(propertyString); + NodeList nodeList = (NodeList) expr.evaluate(node, XPathConstants.NODESET); + if (nodeList.getLength() == 0) { + return null; + } else if (nodeList.getLength() == 1) { + result = nodeList.item(0); + } else { + result = nodeList; + } + context.setPropertyResolved(true); + } catch (XPathExpressionException e) { + Debug.logError("An error occurred during XPath expression evaluation, error was: " + e, module); + } + + } + return result; + } + + @Override + public boolean isReadOnly(ELContext context, Object base, Object property) { + if (context == null) { + throw new NullPointerException("context is null"); + } + if (isResolvable(base)) { + context.setPropertyResolved(true); + } + return true; + } + + @Override + public void setValue(ELContext context, Object base, Object property, Object value) { + if (context == null) { + throw new NullPointerException("context is null"); + } + if (isResolvable(base)) { + throw new PropertyNotWritableException("resolver is read-only"); + } + } + + private final boolean isResolvable(Object base) { + return base != null && (base instanceof Node || base instanceof NodeImpl); + } + + private XPathExpression getXPathExpressionInstance(String xPathString) { + XPathExpression xpe = exprCache.get(xPathString); + if (xpe == null) { + synchronized (exprCache) { + xpe = exprCache.get(xPathString); + if (xpe == null) { + try { + xpe = xpath.compile(xPathString); + exprCache.put(xPathString, xpe); + } catch (XPathExpressionException e) { + Debug.logError("An error occurred during XPath expression compilation, error was: " + e, module); + } + } + } + } + return xpe; + } +} Propchange: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/NodeELResolver.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/NodeELResolver.java ------------------------------------------------------------------------------ svn:keywords = "Date Rev Author URL Id" Propchange: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/NodeELResolver.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/UelUtil.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/UelUtil.java?rev=770915&r1=770914&r2=770915&view=diff ============================================================================== --- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/UelUtil.java (original) +++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/string/UelUtil.java Sat May 2 08:45:22 2009 @@ -41,6 +41,7 @@ add(new ExtendedMapResolver(false)); add(new ExtendedListResolver(false)); add(new ArrayELResolver(false)); + add(new NodeELResolver()); // Below the most common but must be kept above BeanELResolver add(new ResourceBundleELResolver()); add(new BeanELResolver(false)); } Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Iterate.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Iterate.java?rev=770915&r1=770914&r2=770915&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Iterate.java (original) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Iterate.java Sat May 2 08:45:22 2009 @@ -34,6 +34,8 @@ import org.ofbiz.minilang.method.MethodContext; import org.ofbiz.minilang.method.MethodOperation; import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; /** * Process sub-operations for each entry in the list @@ -101,7 +103,7 @@ } return false; } - } else { + } else if (objList instanceof Iterable) { Collection<Object> theList = UtilGenerics.checkList(objList); if (theList == null) { @@ -121,6 +123,17 @@ return false; } } + } else if (objList instanceof NodeList) { + NodeList theList = (NodeList) objList; + for (int i = 0; i < theList.getLength(); i++) { + Node theEntry = theList.item(i); + entryAcsr.put(methodContext, theEntry); + + if (!SimpleMethod.runSubOps(subOps, methodContext)) { + // only return here if it returns false, otherwise just carry on + return false; + } + } } entryAcsr.put(methodContext, oldEntryValue); return true; |
Free forum by Nabble | Edit this page |