/* 
 * Copyright (C) 2001-2013 Michael Fuchs
 *
 * This file is part of herold.
 * 
 * herold is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * herold is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with herold.  If not, see <http://www.gnu.org/licenses/>.  
 */
package org.dbdoclet.xiphias;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.jxpath.CompiledExpression;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.JXPathException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Node;

public class XPathServices {

    private static Log logger = LogFactory.getLog(XPathServices.class);

    public static Object getValue(Object contextBean, String query) {
        return getValue(contextBean, null, null, query);
    }

    /**
     * Die Methode <code>getValue</code> liefert den Wert eines Kontent.
     * 
     * @param contextBean
     *            <code>Object</code>
     * @param query
     *            <code>String</code>
     * @return <code>Object</code>
     */
    public static Object getValue(Object contextBean, String namespace, String namespaceUrl, String query) {

        Object obj = null;

        JXPathContext context = JXPathContext.newContext(contextBean);

        if (namespace != null && namespaceUrl != null) {
            context.registerNamespace(namespace, namespaceUrl);
        }

        CompiledExpression expr = JXPathContext.compile(query);

        try {

            obj = expr.getValue(context);

        } catch (JXPathException oops) {

            logger.debug("JXPathException: " + oops.getMessage());
            obj = null;
        }

        return obj;
    }

    public static ArrayList<String> getValues(Object contextBean, String query) {
        return getValues(contextBean, null, null, query);
    }

    @SuppressWarnings("unchecked")
    public static ArrayList<String> getValues(Object contextBean, String namespace, String namespaceUrl, String query) {

        Object obj = null;

        JXPathContext context = JXPathContext.newContext(contextBean);

        if (namespace != null && namespaceUrl != null) {
            context.registerNamespace(namespace, namespaceUrl);
        }

        CompiledExpression expr = JXPathContext.compile(query);

        Iterator<Object> iterator;
        ArrayList<String> list = new ArrayList<String>();

        try {

            // Unchecked iterator
            iterator = expr.iterate(context);

            while (iterator.hasNext()) {

                obj = iterator.next();

                if (obj != null) {
                    list.add(obj.toString());
                }
            }

        } catch (JXPathException oops) {

            oops.printStackTrace();
        }

        return list;
    }

    public static ArrayList<Node> getNodes(Object contextBean, String query) {

        return getNodes(contextBean, null, null, query);
    }

    public static ArrayList<Node> getNodes(Object contextBean, String namespace, String namespaceUrl, String query) {

        JXPathContext context = JXPathContext.newContext(contextBean);

        if (namespace != null && namespaceUrl != null) {
            context.registerNamespace(namespace, namespaceUrl);
        }

        List<?> list = context.selectNodes(query);

        ArrayList<Node> nodeList = new ArrayList<Node>();

        for (Object obj : list) {

            if (obj instanceof Node) {
                nodeList.add((Node) obj);
            }
        }

        return nodeList;
    }

    public static Node getNode(Object contextBean, String query) {
        return getNode(contextBean, null, null, query);
    }

    public static Node getNode(Object contextBean, String namespace, String namespaceUrl, String query) {

        ArrayList<Node> list = getNodes(contextBean, namespace, namespaceUrl, query);

        if (list.size() > 0) {
            return list.get(0);
        } else {
            return null;
        }
    }

}
