/* # Copyright (c) 2007 Laurent Morissette # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFINTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIEDOR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE., INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS */ package com.mor.blogengine.xpath; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import org.dom4j.tree.DefaultAttribute; /** * * @author Laurent * Builder class that can supply either XPATH 1.0 and 2.0 if VERSION_SUPPORT is set to 2.0f */ public class XPathExpressionBuilder { /** * */ public static final float VERSION_SUPPORT = 1.0f; final boolean considerPrefix = false; /** * Namespace prefix as i.e 'site' */ private String mPrefix = null; /** * Root node */ private String mRootNode = null; /** *list of child nodes requiered until reaching searched */ private String[] mSubNodeList = null; /** *Searched nodes attributes */ private String[] mAttributes = null; /** *
     * Build an XPATH expression builder Object with Following parameters
     * @param pPrefix an element can have a prefix or not i.e <XXX:YYY>
     * @param pRootNode Main node of document
     * @param pNodeList sub-Node list that compose a tree i.e Node1,Node2,Node3
     * @param pAttributesList final node attributes list
     * Usage:
     * 
     *  String prefix="aPrfix";
     *  String root="Root";
     *  List nodes=new Arraylist();
     *  nodes.add("Node1");
     *  Attribute attrib=new Attribute("number","1");
     *  List attributes=new ArrayList();
     *  attributes.add(attrib);
     * //in the end with would do:
     * String expression=new  XPathExpressionBuilder(prefix,root,nodes,attributes).compileExpression();
     * //expression would then be:
     * /aPrefix:root//aPrefix:Node1[@nuber="1"]
     * 
     * 
*/ public XPathExpressionBuilder(String pPrefix, String pRootNode, List pNodeList, List pAttributesList) { if (considerPrefix) { setPrefix(pPrefix); } setRootNode(pRootNode); setNodes(pNodeList); addAttributesList(pAttributesList); } /** * Rien */ public XPathExpressionBuilder() { } /** * * @param pPrefix */ private void setPrefix(String pPrefix) { mPrefix = pPrefix; } /** * * @param pNodes */ private void setNodes( final List pNodes) { if (mSubNodeList == null) { mSubNodeList = convertNodesListToStringArray(pNodes); } } /** * * @param pRootNode */ private void setRootNode(String pRootNode) { mRootNode = pRootNode; } /** * * @param pAttribList */ private void addAttributesList( final List pAttribList) { if (pAttribList != null) { mAttributes = convertAttributeListToStringArray(pAttribList); } } /** * * @return */ public String compileExpression() { String lExpression = new String(); if (considerPrefix) { lExpression += "/" + mPrefix + ":" + mRootNode; } else { lExpression += "/" + mRootNode; } lExpression += addNodesToExpression(considerPrefix); lExpression += addAttributesToExpression(); return lExpression; } /** * * @param pList * @return */ private String[] convertAttributeListToStringArray(List pList) { Object[] lAttribArray = null; Iterator lKeysIt = pList.listIterator(); ArrayList lList = new ArrayList(); while (lKeysIt.hasNext()) { DefaultAttribute lAttribute = (DefaultAttribute) lKeysIt.next(); String lCurrentKey = lAttribute.getName(); String lCurrentValue = lAttribute.getValue(); String lKeyValueString = formatKeyAttributeValue(lCurrentKey, lCurrentValue); lList.add(lKeyValueString); lAttribArray = lList.toArray(); Arrays.sort(lAttribArray); } return transferArrayData(lAttribArray); } /** * * @param pList * @return */ private String[] convertNodesListToStringArray( final List pList) { return transferArrayData(pList.toArray()); } /** * * @param a * @return */ private String[] transferArrayData(final Object[] a) { String[] strArray = new String[a.length]; for (int currentDataIndex = 0; currentDataIndex < strArray.length; currentDataIndex++) { strArray[currentDataIndex] = a[currentDataIndex].toString(); } return strArray; } /** * * @return */ private String addNodesToExpression( final boolean includePrefix) { int lLength = mSubNodeList.length; String nodes = new String(); if (includePrefix) {//Include prefix if ns is present if (lLength > 1) { //check nodes count for (int currenNodeIndex = 0; currenNodeIndex < lLength; currenNodeIndex++) { nodes += ("//" + mPrefix + ":" + mSubNodeList[currenNodeIndex]); } } else { nodes += ("//" + mPrefix + ":" + mSubNodeList[0]); } } else { if (lLength > 1) { for (int i = 0; i < lLength; i++) { nodes += ("//" + mSubNodeList[i]); } } else { nodes += ("//" + mSubNodeList[0]); } } return nodes; } /** * * @return */ private String addAttributesToExpression() { if (mAttributes != null) { int lLength = mAttributes.length; String lExpression = new String(); if (lLength > 1) { lExpression += "["; for (int currentAttributeIndex = 0; currentAttributeIndex < lLength; currentAttributeIndex++) { if (currentAttributeIndex == lLength - 1) { lExpression += ("@" + mAttributes[currentAttributeIndex]); } else { lExpression += ("@" + mAttributes[currentAttributeIndex] + " and "); } } lExpression += "]"; } else { lExpression += ("[@" + mAttributes[0] + "]"); } return lExpression; } return ""; } /** * * @param pValue * @return */ private String formatKeyAttributeValue(String pKey, String pValue) { String lKeyValueString = ""; // strong typing was introduced in XPATH 2.0 only if (VERSION_SUPPORT == 2.0f) { if (pKey.equalsIgnoreCase("ID")) { lKeyValueString = pKey + "=" + "'" + (pValue) + "'"; } else if (isNumber(pValue)) { lKeyValueString = pKey + "=" + "xs:double(" + pValue + ")"; } else if (isBolean(pValue)) { lKeyValueString = pKey + "=" + "xs:boolean(" + pValue + ")"; } } else { lKeyValueString = pKey + "=" + "'" + (pValue) + "'"; } return lKeyValueString; } /** * * @param pValue * @return */ private boolean isNumber(String pValue) { try { Integer.parseInt(pValue); return true; } catch (NumberFormatException e) { return false; } } /** * * @param pValue * @return */ private boolean isBolean(String pValue) { return Boolean.parseBoolean(pValue); } }