001/*-----------------------------------------------------------------------+
002 | com.teamscale.checks
003 |                                                                       |
004   $Id$            
005 |                                                                       |
006 | Copyright (c)  2009-2015 CQSE GmbH                                 |
007 +-----------------------------------------------------------------------*/
008package eu.cqse.check.framework.core.xpath;
009
010import java.util.HashMap;
011import java.util.Map;
012import java.util.Map.Entry;
013
014import org.conqat.lib.commons.string.StringUtils;
015import org.jaxen.BaseXPath;
016import org.jaxen.Function;
017import org.jaxen.JaxenException;
018import org.jaxen.SimpleFunctionContext;
019
020import eu.cqse.check.framework.core.CheckException;
021import eu.cqse.check.framework.core.xpath.functions.AllModifiersSelectionFunction;
022import eu.cqse.check.framework.core.xpath.functions.AllTokensSelectionFunction;
023import eu.cqse.check.framework.core.xpath.functions.AnyModifierSelectionFunction;
024import eu.cqse.check.framework.core.xpath.functions.AnyTokenSelectionFunction;
025import eu.cqse.check.framework.core.xpath.functions.NameMatchesFunction;
026import eu.cqse.check.framework.core.xpath.functions.SubTypeSelectionFunction;
027import eu.cqse.check.framework.core.xpath.functions.TokenSequenceFunction;
028import eu.cqse.check.framework.core.xpath.functions.TypeSelectionFunction;
029
030/**
031 * Utilities for handling of xPath.
032 */
033public class CheckXPathUtils {
034
035        /** Mapping from function names to functions. */
036        private static final Map<String, Function> NAME_TO_FUNCTION_MAP = new HashMap<>();
037
038        /** Used to cache the created xPaths to avoid parsing it multiple times */
039        private static final Map<String, BaseXPath> XPATH_CACHE = new HashMap<>();
040
041        static {
042                NAME_TO_FUNCTION_MAP.put(TypeSelectionFunction.NAME, new TypeSelectionFunction());
043                NAME_TO_FUNCTION_MAP.put(SubTypeSelectionFunction.NAME, new SubTypeSelectionFunction());
044                NAME_TO_FUNCTION_MAP.put(NameMatchesFunction.NAME, new NameMatchesFunction());
045                NAME_TO_FUNCTION_MAP.put(AllModifiersSelectionFunction.NAME, new AllModifiersSelectionFunction());
046                NAME_TO_FUNCTION_MAP.put(AnyModifierSelectionFunction.NAME, new AnyModifierSelectionFunction());
047                NAME_TO_FUNCTION_MAP.put(AllTokensSelectionFunction.NAME, new AllTokensSelectionFunction());
048                NAME_TO_FUNCTION_MAP.put(AnyTokenSelectionFunction.NAME, new AnyTokenSelectionFunction());
049                NAME_TO_FUNCTION_MAP.put(TokenSequenceFunction.NAME, new TokenSequenceFunction());
050        }
051
052        /** Return the xPath object for the given xPath. */
053        public static BaseXPath getXPath(String xPath) throws CheckException {
054                if (XPATH_CACHE.containsKey(xPath)) {
055                        return XPATH_CACHE.get(xPath);
056                }
057                BaseXPath path;
058                try {
059                        path = new BaseXPath(xPath, new ShallowEntityNavigator());
060                } catch (JaxenException e) {
061                        throw new CheckException("Error compiling xpath: " + e.getMessage(), e);
062                }
063                SimpleFunctionContext context = (SimpleFunctionContext) path.getFunctionContext();
064                for (Entry<String, Function> entry : NAME_TO_FUNCTION_MAP.entrySet()) {
065                        context.registerFunction(StringUtils.EMPTY_STRING, entry.getKey(), entry.getValue());
066                }
067                XPATH_CACHE.put(xPath, path);
068                return path;
069        }
070}