001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019
020package lucee.runtime.functions.xml;
021
022import javax.xml.transform.TransformerException;
023
024import lucee.commons.lang.StringUtil;
025import lucee.runtime.PageContext;
026import lucee.runtime.exp.PageException;
027import lucee.runtime.ext.function.Function;
028import lucee.runtime.op.Caster;
029import lucee.runtime.text.xml.XMLCaster;
030import lucee.runtime.text.xml.struct.XMLObject;
031import lucee.runtime.text.xml.struct.XMLStruct;
032import lucee.runtime.type.Array;
033import lucee.runtime.type.ArrayImpl;
034
035import org.apache.xpath.XPathAPI;
036import org.apache.xpath.objects.XObject;
037import org.w3c.dom.Node;
038import org.w3c.dom.NodeList;
039
040/**
041 * Implements the CFML Function xmlsearch
042 */
043public final class XmlSearch implements Function {
044
045        public static Object call(PageContext pc , Node node, String expr) throws PageException {
046                boolean caseSensitive=true;
047                if(node instanceof XMLObject) {
048                        caseSensitive=((XMLObject)node).getCaseSensitive();
049                }
050                if(node instanceof XMLStruct) {
051                        node=((XMLStruct)node).toNode();
052                }
053                return _call(node,expr,caseSensitive);
054                
055        }
056        public static Object _call(Node node, String expr, boolean caseSensitive) throws PageException {
057                if(StringUtil.endsWith(expr,'/')) 
058                        expr = expr.substring(0,expr.length()-1);
059                try {
060                        XObject rs = XPathAPI.eval(node,expr);
061                        
062                        switch(rs.getType()){
063                        case XObject.CLASS_NODESET:
064                                return nodelist(rs,caseSensitive);
065                        case XObject.CLASS_BOOLEAN:
066                                return Caster.toBoolean(rs.bool());
067                        case XObject.CLASS_NULL:
068                                return "";
069                        case XObject.CLASS_NUMBER:
070                                return Caster.toDouble(rs.num());
071                        case XObject.CLASS_STRING:
072                                return rs.str();
073                        default:
074                                return rs.object();
075                        }
076                } catch (Throwable e) {
077                        throw Caster.toPageException(e);
078                }
079                
080                
081                
082        }
083        private static Array nodelist(XObject rs, boolean caseSensitive) throws TransformerException, PageException {
084                
085                NodeList list = rs.nodelist();
086                int len=list.getLength();
087                Array rtn=new ArrayImpl();
088                for(int i=0;i<len;i++) {
089                        Node n=list.item(i);
090                        if(n !=null)
091                        rtn.append(XMLCaster.toXMLStruct(n,caseSensitive));
092                }
093                return rtn;
094        }
095}