/** * Returns a new {@link Path} instance based upon the current state of the * builder. */ public Path build() { // No exception thrown here because the path is validated as its built return new Path(this); } }
/** * The {@link #toString()} implementation is overridden to return the XPath * string that represents the path. */ @Override public String toString() { if (steps.isEmpty()) { return "."; } StringBuilder builder = new StringBuilder(); for (MetadataKey<?> step : steps) { addPathSeparator(builder); if (step instanceof AttributeKey) { builder.append('@'); } builder.append(step.getId()); } return builder.toString(); }
/** * Returns the attribute creator at the end of the path by looking it up * directly in the registry. */ private AttributeCreatorImpl getAttributeCreator(Path path) { Preconditions.checkArgument(path.selectsAttribute(), "Must be an attribute path"); ElementKey<?, ?> parent = path.getParentKey(); if (parent == null) { parent = elementKey; } AttributeKey<?> selected = path.getSelectedAttributeKey(); return (AttributeCreatorImpl) registry.build( parent, selected, transformKey.getContext()); }
/** * Parses a value through a path. This will find the element or attribute * that is at the end of the path, and parse the value into the element's * text content or the attribute's value as appropriate. */ public void parse(Element element, ElementMetadata<?, ?> metadata, Object value) throws ParseException { Path bound = path.toAbsolute(metadata); element = createFinalElement(path, element); if (bound.selectsAttribute()) { parseAttributeValue(element, bound.getSelectedElement(), bound.getSelectedAttributeKey(), bound.getSelectedAttribute(), value); } else { parseTextValue(element, bound.getSelectedElement(), value); } } }
/** * Returns the element creator at the end of the path by looking it up * directly in the registry (not traversing). */ private ElementCreatorImpl getElementCreator(Path path) { Preconditions.checkArgument(path.selectsElement(), "Must be an element path"); ElementKey<?, ?> parent = path.getParentKey(); if (parent == null) { parent = elementKey; } ElementKey<?, ?> selected = path.getSelectedElementKey(); return (ElementCreatorImpl) registry.build( parent, selected, transformKey.getContext()); }
Collection<Element> elements, ElementMetadata<?, ?> metadata) throws ParseException { Preconditions.checkState(path.selectsElement(), "An attribute path cannot be used to parse elements."); Path bound = path.toAbsolute(parentMetadata); ElementKey<?, ?> childKey = bound.getSelectedElementKey(); ElementMetadata<?, ?> childMetadata = bound.getSelectedElement();
/** * Returns the last element along the path, starting with the given root * element. If at any point there is no valid element this method will return * {@code null}. If the path ends in an attribute key this will return the * parent of that attribute, if it ends in an element key it will return that * element. * * @throws NullPointerException if the root or path is null. * @throws IllegalArgumentException if there are any repeating elements along * the path. */ static Element getFinalElement(Path path, Element rootElement) { Element parent = getParentElement(path, rootElement); if (path.selectsAttribute() || parent == null) { return parent; } return parent.getElement(path.getSelectedElementKey()); }
List<? extends Element> parents = ImmutableList.of(rootElement); for (MetadataKey<?> part : path.getSteps()) { if (part instanceof AttributeKey<?>) { break;
/** * Parses a single element using this path. This will follow the path until * the second to last element on the path, and then parse into the final * element using the real parent instead of the path's parent. * * elements along it. */ public void parse(Element parent, ElementMetadata<?, ?> parentMetadata, Element element, ElementMetadata<?, ?> metadata) throws ParseException { Preconditions.checkState(path.selectsElement(), "An attribute path cannot be used to parse elements."); parent = createParentElement(path, parent); ElementKey<?, ?> lastKey = path.getSelectedElementKey(); try { Element child = Element.createElement(lastKey, element); parent.addElement(child); } catch (ContentCreationException e) { throw new ParseException(e); } }
/** * Generate multiple elements based on this path. This only allows a single * multiple cardinality element in the path, but that multiple cardinality * element can be anywhere in the path. Once found we only follow single * cardinality children after that point. * * cardinality along the path. */ public Collection<? extends Element> generateMultiple(Element parent, ElementMetadata<?, ?> parentMetadata, ElementMetadata<?, ?> metadata) { Preconditions.checkState(path.selectsElement(), "An attribute path cannot be used to generate elements."); Collection<? extends Element> elements = getFinalElements(path, parent); if (elements.isEmpty()) { return elements; } List<Element> result = Lists.newArrayListWithCapacity(elements.size()); for (Element e : elements) { try { ElementKey<?, ?> realKey = mergeKeys( e.getElementKey(), metadata.getKey()); result.add(Element.createElement(realKey, e)); } catch (ContentCreationException ex) { throw new IllegalArgumentException("Invalid metadata", ex); } } return result; }
/** * Adds a virtual attribute, which marks the source attribute as moved and * creates a new virtual attribute in this element with the source path. */ public AttributeCreator moveAttribute(AttributeKey<?> attKey, Path path) { Preconditions.checkArgument(path.selectsAttribute(), "Path must refer to an attribute."); AttributeCreatorImpl dest = replaceAttribute(attKey); AttributeCreatorImpl source = getAttributeCreator(path); dest.setSource(path, source.getTransformKey()); source.moved(); return dest; }
/** * Generate a text value through the path. If the path ends in an element, * the value will be the text content of the final element. If the path * ends in an attribute, the value will be the value of that attribute. */ public Object generate(Element element, ElementMetadata<?, ?> metadata) { Path bound = path.toAbsolute(metadata); element = getFinalElement(bound, element); if (element == null) { return null; } // Generate the value at the end of the path. if (bound.selectsAttribute()) { return generateAttributeValue(element, bound.getSelectedElement(), bound.getSelectedAttributeKey(), bound.getSelectedAttribute()); } else { return generateTextValue(element, bound.getSelectedElement()); } }
Collection<Element> elements, ElementMetadata<?, ?> metadata) throws ParseException { Preconditions.checkState(path.selectsElement(), "An attribute path cannot be used to parse elements."); Path bound = path.toAbsolute(parentMetadata); ElementKey<?, ?> childKey = bound.getSelectedElementKey(); ElementMetadata<?, ?> childMetadata = bound.getSelectedElement();
/** * Returns the element creator at the end of the path by looking it up * directly in the registry (not traversing). */ private ElementCreatorImpl getElementCreator(Path path) { Preconditions.checkArgument(path.selectsElement(), "Must be an element path"); ElementKey<?, ?> parent = path.getParentKey(); if (parent == null) { parent = elementKey; } ElementKey<?, ?> selected = path.getSelectedElementKey(); return (ElementCreatorImpl) registry.build( parent, selected, transformKey.getContext()); }
/** * Returns the last element along the path, starting with the given root * element. If at any point there is no valid element this method will return * {@code null}. If the path ends in an attribute key this will return the * parent of that attribute, if it ends in an element key it will return that * element. * * @throws NullPointerException if the root or path is null. * @throws IllegalArgumentException if there are any repeating elements along * the path. */ static Element getFinalElement(Path path, Element rootElement) { Element parent = getParentElement(path, rootElement); if (path.selectsAttribute() || parent == null) { return parent; } return parent.getElement(path.getSelectedElementKey()); }
List<? extends Element> parents = ImmutableList.of(rootElement); for (MetadataKey<?> part : path.getSteps()) { if (part instanceof AttributeKey<?>) { break;
/** * Parses a single element using this path. This will follow the path until * the second to last element on the path, and then parse into the final * element using the real parent instead of the path's parent. * * elements along it. */ public void parse(Element parent, ElementMetadata<?, ?> parentMetadata, Element element, ElementMetadata<?, ?> metadata) throws ParseException { Preconditions.checkState(path.selectsElement(), "An attribute path cannot be used to parse elements."); parent = createParentElement(path, parent); ElementKey<?, ?> lastKey = path.getSelectedElementKey(); try { Element child = Element.createElement(lastKey, element); parent.addElement(child); } catch (ContentCreationException e) { throw new ParseException(e); } }
/** * Generate multiple elements based on this path. This only allows a single * multiple cardinality element in the path, but that multiple cardinality * element can be anywhere in the path. Once found we only follow single * cardinality children after that point. * * cardinality along the path. */ public Collection<? extends Element> generateMultiple(Element parent, ElementMetadata<?, ?> parentMetadata, ElementMetadata<?, ?> metadata) { Preconditions.checkState(path.selectsElement(), "An attribute path cannot be used to generate elements."); Collection<? extends Element> elements = getFinalElements(path, parent); if (elements.isEmpty()) { return elements; } List<Element> result = Lists.newArrayListWithCapacity(elements.size()); for (Element e : elements) { try { ElementKey<?, ?> realKey = mergeKeys( e.getElementKey(), metadata.getKey()); result.add(Element.createElement(realKey, e)); } catch (ContentCreationException ex) { throw new IllegalArgumentException("Invalid metadata", ex); } } return result; }
/** * Adds a virtual attribute, which marks the source attribute as moved and * creates a new virtual attribute in this element with the source path. */ public AttributeCreator moveAttribute(AttributeKey<?> attKey, Path path) { Preconditions.checkArgument(path.selectsAttribute(), "Path must refer to an attribute."); AttributeCreatorImpl dest = replaceAttribute(attKey); AttributeCreatorImpl source = getAttributeCreator(path); dest.setSource(path, source.getTransformKey()); source.moved(); return dest; }
/** * Parses a value through a path. This will find the element or attribute * that is at the end of the path, and parse the value into the element's * text content or the attribute's value as appropriate. */ public void parse(Element element, ElementMetadata<?, ?> metadata, Object value) throws ParseException { Path bound = path.toAbsolute(metadata); element = createFinalElement(path, element); if (bound.selectsAttribute()) { parseAttributeValue(element, bound.getSelectedElement(), bound.getSelectedAttributeKey(), bound.getSelectedAttribute(), value); } else { parseTextValue(element, bound.getSelectedElement(), value); } } }