package org.openxdm.xcap.common.uri; import java.util.Map; /** * A node selector selects an element, attribute or namespace bindings in a * element. It's defined by XCAP specs with the regular expression: * * node-selector = element-selector ["/" terminal-selector] * * @author Eduardo Martins */ public class NodeSelector { private String elementSelector = null; private String elementParentSelector = null; private String elementSelectorWithEmptyPrefix = null; private String elementParentSelectorWithEmptyPrefix = null; private String terminalSelector = null; /** * Creates a new NodeSelector instance pointing to an element. * * @param elementSelector * selects the element. */ public NodeSelector(String elementSelector) { this(elementSelector, null); } /** * Creates a new NodeSelector instance pointing to an attribute or namespace * bindings, from the specified terminal selector, in a element, selected by * an element selector. * * @param elementSelector * selects the element. * @param terminalSelector * an attribute or namespace selector. */ public NodeSelector(String elementSelector, String terminalSelector) { this.elementSelector = elementSelector; this.terminalSelector = terminalSelector; } /** * Retreives the element selector of the node selector. * * @return */ public String getElementSelector() { return elementSelector; } /** * Retrieves the terminal selector of the node selector. */ public String getTerminalSelector() { return terminalSelector; } /** * Checks if the element selector has steps with unbinded namespaces * prefixes, considering the provided map of namespace bindings. * * @param namespaceBindings * the namespace bindings map. * @return */ public boolean elementSelectorHasUnbindedPrefixes( Map<String, String> namespaceBindings) { String[] elementSelectorParts = elementSelector.split("/"); for (int i = 0; i < elementSelectorParts.length; i++) { // get index of : int index = elementSelectorParts[i].indexOf(':'); if (index >= 0) { String prefix = elementSelectorParts[i].substring(0, index); if (!namespaceBindings.containsKey(prefix)) { return true; } } } return false; } /** * Retrieves the element selector with empty prefixes instead of no prefix * at all. This is required for XPtah queries. * * @return */ public String getElementSelectorWithEmptyPrefix() { if (elementSelectorWithEmptyPrefix == null) { StringBuilder sb = new StringBuilder(); String[] elementSelectorParts = elementSelector.split("/"); // ignore the first part because its "" for (int i = 1; i < elementSelectorParts.length; i++) { if (elementSelectorParts[i].charAt(0) == '*') { // wildcard, just copy sb.append('/').append(elementSelectorParts[i]); } else if (elementSelectorParts[i].indexOf(':') > -1) { // it has at least one :, check if it's not inside an attr // value int pos = elementSelectorParts[i].indexOf('['); if (pos > 0 && elementSelectorParts[i].indexOf(':') > pos) { // insert empty prefix sb.append("/:").append(elementSelectorParts[i]); } else { // already has a prefix sb.append('/').append(elementSelectorParts[i]); } } else { // insert empty prefix sb.append("/:").append(elementSelectorParts[i]); } } elementSelectorWithEmptyPrefix = sb.toString(); } return elementSelectorWithEmptyPrefix; } /** * Retreives the element parent selector, that is, the parent of the element * selected by the element selector. * * @return */ public String getElementParentSelector() { if (elementParentSelector == null) { int elementParentSelectorSeparator = getElementSelectorWithEmptyPrefix() .lastIndexOf('/'); if (elementParentSelectorSeparator > 0) { // parent is not root elementParentSelector = elementSelectorWithEmptyPrefix .substring(0, elementParentSelectorSeparator); } else { // parent is root elementParentSelector = "/"; } } return elementParentSelector; } /** * Retrieves the element parent selector with empty prefixes instead of no * prefix at all. This is required for XPtah queries. * * @return */ public String getElementParentSelectorWithEmptyPrefix() { if (elementParentSelectorWithEmptyPrefix == null) { String elementSelectorWithEmptyPrefix = getElementSelectorWithEmptyPrefix(); int elementParentSelectorSeparator = elementSelectorWithEmptyPrefix .lastIndexOf('/'); if (elementParentSelectorSeparator > 0) { // parent is not root elementParentSelectorWithEmptyPrefix = elementSelectorWithEmptyPrefix .substring(0, elementParentSelectorSeparator); } else { // parent is not root elementParentSelectorWithEmptyPrefix = "/"; } } return elementParentSelectorWithEmptyPrefix; } }