+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.xml.codec;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Splitter;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Element;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public final class InstanceIdentifierForXmlCodec {
- private static final Pattern PREDICATE_PATTERN = Pattern.compile("\\[(.*?)\\]");
- private static final Splitter SLASH_SPLITTER = Splitter.on('/');
- private static final Splitter COLON_SPLITTER = Splitter.on(':');
- private static final Splitter AT_SPLITTER = Splitter.on('@');
- private static final Logger logger = LoggerFactory.getLogger(InstanceIdentifierForXmlCodec.class);
-
- private InstanceIdentifierForXmlCodec() {
- throw new UnsupportedOperationException("Utility class");
- }
-
- public static YangInstanceIdentifier deserialize(final Element element, final SchemaContext schemaContext) {
- Preconditions.checkNotNull(element, "Value of element for deserialization can't be null");
- Preconditions.checkNotNull(schemaContext,
- "Schema context for deserialization of instance identifier type can't be null");
-
- final String valueTrimmed = element.getTextContent().trim();
- logger.debug("Instance identifier derserialize: splitting the text {} with Slash to find path arguments", valueTrimmed);
- final Iterator<String> xPathParts = SLASH_SPLITTER.split(valueTrimmed).iterator();
-
- // must be at least "/pr:node"
- if (!xPathParts.hasNext() || !xPathParts.next().isEmpty() || !xPathParts.hasNext()) {
- logger.debug("Instance identifier derserialize: No path argument found for element.");
- return null;
- }
-
- List<PathArgument> result = new ArrayList<>();
- while (xPathParts.hasNext()) {
- String xPathPartTrimmed = xPathParts.next().trim();
-
- PathArgument pathArgument = toPathArgument(xPathPartTrimmed, element, schemaContext);
- if (pathArgument != null) {
- result.add(pathArgument);
- }
- }
- return YangInstanceIdentifier.create(result);
- }
-
- public static Element serialize(final YangInstanceIdentifier id, final Element element) {
- Preconditions.checkNotNull(id, "Variable should contain instance of instance identifier and can't be null");
- Preconditions.checkNotNull(element, "DOM element can't be null");
-
- final RandomPrefix prefixes = new RandomPrefix();
- final String str = XmlUtils.encodeIdentifier(prefixes, id);
-
- for (Entry<URI, String> e: prefixes.getPrefixes()) {
- element.setAttribute("xmlns:" + e.getValue(), e.getKey().toString());
- }
- element.setTextContent(str);
- return element;
- }
-
- private static String getIdAndPrefixAsStr(final String pathPart) {
- int predicateStartIndex = pathPart.indexOf('[');
- return predicateStartIndex == -1 ? pathPart : pathPart.substring(0, predicateStartIndex);
- }
-
- private static PathArgument toPathArgument(final String xPathArgument, final Element element, final SchemaContext schemaContext) {
- final QName mainQName = toIdentity(xPathArgument, element, schemaContext);
-
- // predicates
- final Matcher matcher = PREDICATE_PATTERN.matcher(xPathArgument);
- final Map<QName, Object> predicates = new HashMap<>();
- QName currentQName = mainQName;
-
- while (matcher.find()) {
- final String predicateStr = matcher.group(1).trim();
- final int indexOfEqualityMark = predicateStr.indexOf('=');
- if (indexOfEqualityMark != -1) {
- final Object predicateValue = toPredicateValue(predicateStr.substring(indexOfEqualityMark + 1));
- if (predicateValue == null) {
- return null;
- }
-
- if (predicateStr.charAt(0) != '.') {
- // target is not a leaf-list
- currentQName = toIdentity(predicateStr.substring(0, indexOfEqualityMark), element, schemaContext);
- if (currentQName == null) {
- return null;
- }
- }
- logger.debug("Instance identifier derserialize: finding predicates of node {}", predicateValue);
- predicates.put(currentQName, predicateValue);
- }
- }
-
- if (predicates.isEmpty()) {
- return new YangInstanceIdentifier.NodeIdentifier(mainQName);
- } else {
- return new YangInstanceIdentifier.NodeIdentifierWithPredicates(mainQName, predicates);
- }
-
- }
-
- public static QName toIdentity(final String xPathArgument, final Element element, final SchemaContext schemaContext) {
- final String xPathPartTrimmed = getIdAndPrefixAsStr(xPathArgument).trim();
- final Iterator<String> it = COLON_SPLITTER.split(xPathPartTrimmed).iterator();
-
- // Empty string
- if (!it.hasNext()) {
- return null;
- }
-
- final String prefix = it.next().trim();
- if (prefix.isEmpty()) {
- return null;
- }
-
- // it is not "prefix:value"
- if (!it.hasNext()) {
- return null;
- }
-
- final String identifier = it.next().trim();
- if (identifier.isEmpty()) {
- return null;
- }
-
- URI namespace = null;
- String namespaceStr = null;
- try {
- namespaceStr = element.getAttribute("xmlns:"+prefix);
- namespace = new URI(namespaceStr);
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException("It wasn't possible to convert " + namespaceStr + " to URI object.");
- } catch (NullPointerException e) {
- throw new IllegalArgumentException("I wasn't possible to get namespace for prefix " + prefix);
- }
-
- Module module = schemaContext.findModuleByNamespaceAndRevision(namespace, null);
- return QName.create(module.getQNameModule(), identifier);
- }
-
- private static String trimIfEndIs(final String str, final char end) {
- final int l = str.length() - 1;
- if (str.charAt(l) != end) {
- return null;
- }
-
- return str.substring(1, l);
- }
-
- private static Object toPredicateValue(final String predicatedValue) {
- logger.debug("Instance identifier derserialize: converting the predicate vstring to object {}", predicatedValue);
- final String predicatedValueTrimmed = predicatedValue.trim();
- if (predicatedValue.isEmpty()) {
- return null;
- }
- String updatedValue = null;
- switch (predicatedValueTrimmed.charAt(0)) {
- case '"':
- updatedValue = trimIfEndIs(predicatedValueTrimmed, '"');
- break;
- case '\'':
- updatedValue = trimIfEndIs(predicatedValueTrimmed, '\'');
- break;
- default:
- updatedValue = predicatedValueTrimmed;
- }
- Iterator<String> it = AT_SPLITTER.split(updatedValue).iterator();
- // Empty string
- if (!it.hasNext()) {
- return null;
- }
-
- final String value = it.next().trim();
- if (value.isEmpty()) {
- return null;
- }
-
- if (!it.hasNext()) {
- return value;
- }
-
- final String type = it.next().trim();
- if (type.isEmpty()) {
- return value;
- }
- Object predicateObject = null;
- try {
- logger.debug("Instance identifier derserialize: converting the predicate value {{}}to correct object type {{}}", value, type);
- predicateObject = Class.forName(type).getConstructor(String.class).newInstance(value);
- } catch (Exception e) {
- logger.error("Could not convert to valid type of value", e);
- }
- return predicateObject;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.xml.codec;
-
-import org.opendaylight.yangtools.yang.common.QName;
-
-import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.ThreadLocalRandom;
-
-/**
- * Picked from Yang tools because it was not public class
- */
-
-final class RandomPrefix {
- final Map<URI, String> prefixes = new HashMap<>();
-
- Iterable<Entry<URI, String>> getPrefixes() {
- return prefixes.entrySet();
- }
-
- String encodeQName(final QName qname) {
- String prefix = prefixes.get(qname.getNamespace());
- if (prefix == null) {
- final ThreadLocalRandom random = ThreadLocalRandom.current();
- do {
- final StringBuilder sb = new StringBuilder();
- for (int i = 0; i < 4; i++) {
- sb.append((char)('a' + random.nextInt(25)));
- }
-
- prefix = sb.toString();
- } while (prefixes.containsValue(prefix));
- prefixes.put(qname.getNamespace(), prefix);
- }
-
- return prefix + ':' + qname.getLocalName();
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.xml.codec;
-
-import com.google.common.base.Optional;
-import java.net.URI;
-import java.util.Collection;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-public class XmlDocumentUtils {
- public static final QName OPERATION_ATTRIBUTE_QNAME = QName.create(URI.create("urn:ietf:params:xml:ns:netconf:base:1.0"), null, "operation");
-
- public static Document getDocument() {
- final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- Document doc = null;
- try {
- final DocumentBuilder bob = dbf.newDocumentBuilder();
- doc = bob.newDocument();
- } catch (final ParserConfigurationException e) {
- throw new RuntimeException(e);
- }
- return doc;
- }
-
-
- public static QName qNameFromElement(final Element xmlElement) {
- final String namespace = xmlElement.getNamespaceURI();
- final String localName = xmlElement.getLocalName();
- return QName.create(namespace != null ? URI.create(namespace) : null, null, localName);
- }
-
- public static final Optional<DataSchemaNode> findFirstSchema(final QName qname, final Collection<DataSchemaNode> dataSchemaNode) {
- if (dataSchemaNode != null && !dataSchemaNode.isEmpty() && qname != null) {
- for (final DataSchemaNode dsn : dataSchemaNode) {
- if (qname.isEqualWithoutRevision(dsn.getQName())) {
- return Optional.<DataSchemaNode> of(dsn);
- } else if (dsn instanceof ChoiceSchemaNode) {
- for (final ChoiceCaseNode choiceCase : ((ChoiceSchemaNode) dsn).getCases()) {
- final Optional<DataSchemaNode> foundDsn = findFirstSchema(qname, choiceCase.getChildNodes());
- if (foundDsn != null && foundDsn.isPresent()) {
- return foundDsn;
- }
- }
- }
- }
- }
- return Optional.absent();
- }
-
- public static final XmlCodecProvider defaultValueCodecProvider() {
- return XmlUtils.DEFAULT_XML_CODEC_PROVIDER;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.xml.codec;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
-import java.net.URI;
-import java.util.Map.Entry;
-import javax.annotation.Nonnull;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Utility class for bridging JAXP Stream and YANG Data APIs. Note that the definition of this class
- * by no means final and subject to change as more functionality is centralized here.
- */
-@Beta
-public class XmlStreamUtils {
- private static final Logger LOG = LoggerFactory.getLogger(XmlStreamUtils.class);
- private final XmlCodecProvider codecProvider;
-
- protected XmlStreamUtils(final XmlCodecProvider codecProvider) {
- this.codecProvider = Preconditions.checkNotNull(codecProvider);
- }
-
- /**
- * Create a new instance encapsulating a particular codec provider.
- *
- * @param codecProvider XML codec provider
- * @return A new instance
- */
- public static XmlStreamUtils create(final XmlCodecProvider codecProvider) {
- return new XmlStreamUtils(codecProvider);
- }
-
- /**
- * Write an InstanceIdentifier into the output stream. Calling corresponding {@link javax.xml.stream.XMLStreamWriter#writeStartElement(String)}
- * and {@link javax.xml.stream.XMLStreamWriter#writeEndElement()} is the responsibility of the caller.
- *
- * @param writer XML Stream writer
- * @param id InstanceIdentifier
- * @throws javax.xml.stream.XMLStreamException
- */
- public static void write(final @Nonnull XMLStreamWriter writer, final @Nonnull YangInstanceIdentifier id) throws XMLStreamException {
- Preconditions.checkNotNull(writer, "Writer may not be null");
- Preconditions.checkNotNull(id, "Variable should contain instance of instance identifier and can't be null");
- LOG.debug("Writing Instance identifier with Random prefix");
- final RandomPrefix prefixes = new RandomPrefix();
- final String str = XmlUtils.encodeIdentifier(prefixes, id);
-
- for (final Entry<URI, String> e: prefixes.getPrefixes()) {
- writer.writeNamespace(e.getValue(), e.getKey().toString());
- }
- if(LOG.isDebugEnabled()) {
- LOG.debug("Instance identifier with Random prefix is now {}", str);
- }
- writer.writeCharacters(str);
- }
-
- /**
- * Write a value into a XML stream writer. This method assumes the start and end of element is
- * emitted by the caller.
- *
- * @param writer XML Stream writer
- * @param type type definitions
- * @param value object value
- * @throws javax.xml.stream.XMLStreamException if an encoding problem occurs
- */
- public void writeValue(final @Nonnull XMLStreamWriter writer, final @Nonnull TypeDefinition<?> type, final Object value) throws XMLStreamException {
- if (value == null) {
- if(LOG.isDebugEnabled()){
- LOG.debug("Value of {}:{} is null, not encoding it", type.getQName().getNamespace(), type.getQName().getLocalName());
- }
- return;
- }
-
- final TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(type);
- if (baseType instanceof IdentityrefTypeDefinition) {
- write(writer, (IdentityrefTypeDefinition) baseType, value);
- } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
- write(writer, (InstanceIdentifierTypeDefinition) baseType, value);
- } else {
- final TypeDefinitionAwareCodec<Object, ?> codec = codecProvider.codecFor(baseType);
- String text;
- if (codec != null) {
- try {
- text = codec.serialize(value);
- } catch (final ClassCastException e) {
- LOG.error("Provided node value {} did not have type {} required by mapping. Using stream instead.", value, baseType, e);
- text = String.valueOf(value);
- }
- } else {
- LOG.error("Failed to find codec for {}, falling back to using stream", baseType);
- text = String.valueOf(value);
- }
- writer.writeCharacters(text);
- }
- }
-
- private static void write(final @Nonnull XMLStreamWriter writer, final @Nonnull IdentityrefTypeDefinition type, final @Nonnull Object value) throws XMLStreamException {
- if (value instanceof QName) {
- final QName qname = (QName) value;
-
- writer.writeNamespace("x", qname.getNamespace().toString());
- writer.writeCharacters("x:" + qname.getLocalName());
- } else {
- if(LOG.isDebugEnabled()) {
- LOG.debug("Value of {}:{} is not a QName but {}", type.getQName().getNamespace(), type.getQName().getLocalName(), value.getClass());
- }
- writer.writeCharacters(String.valueOf(value));
- }
- }
-
- private static void write(final @Nonnull XMLStreamWriter writer, final @Nonnull InstanceIdentifierTypeDefinition type, final @Nonnull Object value) throws XMLStreamException {
- if (value instanceof YangInstanceIdentifier) {
- if(LOG.isDebugEnabled()) {
- LOG.debug("Writing InstanceIdentifier object {}", value);
- }
- write(writer, (YangInstanceIdentifier)value);
- } else {
- if(LOG.isDebugEnabled()) {
- LOG.debug("Value of {}:{} is not an InstanceIdentifier but {}", type.getQName().getNamespace(), type.getQName().getLocalName(), value.getClass());
- }
- writer.writeCharacters(String.valueOf(value));
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.xml.codec;
-
-import java.util.Map;
-import javax.annotation.Nonnull;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
-import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-
-/**
- * Common XML-related utility methods, which are not specific to a particular
- * JAXP API.
- */
-public class XmlUtils {
-
- public static final XmlCodecProvider DEFAULT_XML_CODEC_PROVIDER = new XmlCodecProvider() {
- @Override
- public TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codecFor(final TypeDefinition<?> baseType) {
- return TypeDefinitionAwareCodec.from(baseType);
- }
- };
-
- private XmlUtils() {
- }
-
- public static TypeDefinition<?> resolveBaseTypeFrom(final @Nonnull TypeDefinition<?> type) {
- TypeDefinition<?> superType = type;
- while (superType.getBaseType() != null) {
- superType = superType.getBaseType();
- }
- return superType;
- }
-
- /**
- * This code is picked from yangtools and modified to add type of instance identifier
- * output of instance identifier something like below for a flow ref composite node of type instance identifier,
- * which has path arguments with predicates, whose value is of type java.lang.short
- * <flow-ref xmlns:bgkj="urn:opendaylight:flow:inventory" xmlns:jdlk="urn:opendaylight:inventory">
- * /jdlk:nodes/jdlk:node[jdlk:id='openflow:205558455098190@java.lang.String']
- * /bgkj:table[bgkj:id='3@java.lang.Short']
- * /bgkj:flow[bgkj:id='156@java.lang.String']
- * </flow-ref>
- *
- */
-
- public static String encodeIdentifier(final RandomPrefix prefixes, final YangInstanceIdentifier id) {
- final StringBuilder textContent = new StringBuilder();
- for (final PathArgument pathArgument : id.getPathArguments()) {
- textContent.append('/');
- textContent.append(prefixes.encodeQName(pathArgument.getNodeType()));
- if (pathArgument instanceof NodeIdentifierWithPredicates) {
- final Map<QName, Object> predicates = ((NodeIdentifierWithPredicates) pathArgument).getKeyValues();
-
- for (final QName keyValue : predicates.keySet()) {
- final Object value = predicates.get(keyValue);
- final String type = value.getClass().getName();
- final String predicateValue = String.valueOf(value);
- textContent.append('[');
- textContent.append(prefixes.encodeQName(keyValue));
- textContent.append("='");
- textContent.append(predicateValue);
- textContent.append("@");
- textContent.append(type);
- textContent.append("']");
- }
- } else if (pathArgument instanceof NodeWithValue) {
- textContent.append("[.='");
- textContent.append(((NodeWithValue<?>) pathArgument).getValue());
- textContent.append("']");
- }
- }
-
- return textContent.toString();
- }
-}