package org.openxdm.xcap.common.uri; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; /** * * A element selector points to an element in a document resource. * * It's defined in the XCAP protocol specs by the regular expression * element-selector = step *( "/" step) * * Usage Examples: * * 1) Select 'list' element, with name 'friends', being child of the root document element 'resource-lists'. * * LinkedList<ElementSelectorStep> elementSelectorSteps = new LinkedList<ElementSelectorStep>(); * ElementSelectorStep step1 = new ElementSelectorStep("resource-lists"); * ElementSelectorStep step2 = new ElementSelectorStepByAttr("list","name","friends"); * elementSelectorSteps.add(step1); * elementSelectorSteps.addLast(step2); * ElementSelector elementSelector = new ElementSelector(elementSelectorSteps); * * 2) Select first 'list' element, being child of the root document element 'resource-lists'. * * LinkedList<ElementSelectorStep> elementSelectorSteps = new LinkedList<ElementSelectorStep>(); * ElementSelectorStep step1 = new ElementSelectorStep("resource-lists"); * ElementSelectorStep step2 = new ElementSelectorStepByPos("list",1); * elementSelectorSteps.add(step1); * elementSelectorSteps.addLast(step2); * ElementSelector elementSelector = new ElementSelector(elementSelectorSteps); * * @author Eduardo Martins * */ public class ElementSelector { private LinkedList<ElementSelectorStep> steps; /** * Creates a new instance of an element selector from the specified linked list of steps. * @param elementSelectorSteps the linked list with the element selector steps. */ public ElementSelector(LinkedList<ElementSelectorStep> elementSelectorSteps) { this.steps = elementSelectorSteps; } /** * Retreives a element selector step by position. * @param index the index of the step to retreive. * @return * @throws IndexOutOfBoundsException thrown when the index is invalid. */ public ElementSelectorStep getStep(int index) throws IndexOutOfBoundsException { return steps.get(index); } /** * Retrieves the last step of the element selector. * @return */ public ElementSelectorStep getLastStep() { return steps.getLast(); } /** * Retrieves the number of steps in this element selector. * @return */ public int getStepsSize() { return steps.size(); } /** * 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 hasUnbindedPrefixes(Map<String,String> namespaceBindings) { for(Iterator<ElementSelectorStep> i=steps.iterator();i.hasNext();) { ElementSelectorStep step = i.next(); String prefix = step.getPrefix(); if (!namespaceBindings.containsKey(prefix)) { return false; } } return true; } public String toString() { if (toString == null) { StringBuilder sb = new StringBuilder(); for(int i=0;i<getStepsSize();i++){ ElementSelectorStep step = getStep(i); if (step instanceof ElementSelectorStepByPosAttr) { sb = appendElementSelectorStepByPosAttr(sb,(ElementSelectorStepByPosAttr)step); } else if (step instanceof ElementSelectorStepByAttr) { sb = appendElementSelectorStepByAttr(sb,(ElementSelectorStepByAttr)step); } else if (step instanceof ElementSelectorStepByPos) { sb = appendElementSelectorStepByPos(sb,(ElementSelectorStepByPos)step); } else { sb = appendElementSelectorStep(sb,step); } } toString = sb.toString(); } return toString; } private String toString = null; private static StringBuilder appendElementSelectorStepByAttr(StringBuilder sb, ElementSelectorStepByAttr ess) { return sb.append("/").append(ess.getName()).append("[@").append(ess.getAttrName()).append("='").append(ess.getAttrValue()).append("']"); } private static StringBuilder appendElementSelectorStep(StringBuilder sb, ElementSelectorStep e) { return sb.append("/").append(e.getName()); } private static StringBuilder appendElementSelectorStepByPos(StringBuilder sb, ElementSelectorStepByPos e) { return sb.append("/").append(e.getName()).append('[').append(e.getPos()).append(']'); } private static StringBuilder appendElementSelectorStepByPosAttr(StringBuilder sb, ElementSelectorStepByPosAttr e) { return sb.append("/").append(e.getName()).append('[').append(e.getPos()).append("][@").append(e.getAttrName()).append("='").append(e.getAttrValue()).append("']"); } }