X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=netconf%2Fsal-netconf-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Fsal%2Fconnect%2Fnetconf%2FLibraryModulesSchemas.java;h=87d2a47d69c75a4b3ae8352e27962a389126c4dc;hb=68d52ef8ea8ee2ee6cda8bbc4a864c3fa897297e;hp=9e62919cf688852953d57c428f2e363d22262c31;hpb=47c1b8e3d9835d336c79d6b4ca4e61417a05039e;p=netconf.git diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/LibraryModulesSchemas.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/LibraryModulesSchemas.java index 9e62919cf6..87d2a47d69 100644 --- a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/LibraryModulesSchemas.java +++ b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/LibraryModulesSchemas.java @@ -7,52 +7,56 @@ */ package org.opendaylight.netconf.sal.connect.netconf; -import static javax.xml.bind.DatatypeConverter.printBase64Binary; -import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_DATA_QNAME; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; +import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_DATA_NODEID; +import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_NODEID; import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.NETCONF_GET_QNAME; -import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toId; -import static org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil.toPath; -import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; import com.google.gson.stream.JsonReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; -import java.util.AbstractMap; -import java.util.Collections; -import java.util.Locale; +import java.util.AbstractMap.SimpleImmutableEntry; +import java.util.Base64; +import java.util.Collection; +import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.regex.Pattern; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.ParserConfigurationException; import javax.xml.stream.XMLStreamException; import javax.xml.transform.dom.DOMSource; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult; -import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.mdsal.binding.runtime.spi.BindingRuntimeHelpers; +import org.opendaylight.mdsal.dom.api.DOMRpcResult; import org.opendaylight.netconf.sal.connect.api.NetconfDeviceSchemas; import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceRpc; import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil; import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160409.ModulesState; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev160409.module.list.Module; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.ModulesState; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.YangLibrary; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.Module; import org.opendaylight.yangtools.util.xml.UntrustedXML; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.Revision; +import org.opendaylight.yangtools.yang.common.XMLNamespace; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode; @@ -60,14 +64,17 @@ import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; +import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactory; +import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactorySupplier; import org.opendaylight.yangtools.yang.data.codec.gson.JsonParserStream; import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream; import org.opendaylight.yangtools.yang.data.impl.schema.Builders; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; +import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack; +import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -83,45 +90,50 @@ public final class LibraryModulesSchemas implements NetconfDeviceSchemas { private static final Logger LOG = LoggerFactory.getLogger(LibraryModulesSchemas.class); private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{4}-\\d{2}-\\d{2})"); - private static final SchemaContext LIBRARY_CONTEXT; - - static { - final ModuleInfoBackedContext moduleInfoBackedContext = ModuleInfoBackedContext.create(); - moduleInfoBackedContext.registerModuleInfo(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang - .library.rev160409.$YangModuleInfoImpl.getInstance()); - LIBRARY_CONTEXT = moduleInfoBackedContext.tryToCreateSchemaContext().get(); - } - - private final Map availableModels; + private static final EffectiveModelContext LIBRARY_CONTEXT = BindingRuntimeHelpers.createEffectiveModel( + YangLibrary.class); + private static final Inference MODULES_STATE_INFERENCE = + SchemaInferenceStack.ofDataTreePath(LIBRARY_CONTEXT, ModulesState.QNAME).toInference(); + + // FIXME: this is legacy RFC7895, add support for RFC8525 containers, too + private static final NodeIdentifier MODULES_STATE_NID = NodeIdentifier.create(ModulesState.QNAME); + private static final NodeIdentifier MODULE_NID = NodeIdentifier.create(Module.QNAME); + private static final NodeIdentifier NAME_NID = NodeIdentifier.create(QName.create(Module.QNAME, "name").intern()); + private static final NodeIdentifier REVISION_NID = NodeIdentifier.create( + QName.create(Module.QNAME, "revision").intern()); + private static final NodeIdentifier SCHEMA_NID = NodeIdentifier.create( + QName.create(Module.QNAME, "schema").intern()); + private static final NodeIdentifier NAMESPACE_NID = NodeIdentifier.create( + QName.create(Module.QNAME, "namespace").intern()); + + private static final JSONCodecFactory JSON_CODECS = JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02 + .getShared(LIBRARY_CONTEXT); private static final YangInstanceIdentifier MODULES_STATE_MODULE_LIST = - YangInstanceIdentifier.builder().node(ModulesState.QNAME).node(Module.QNAME).build(); + YangInstanceIdentifier.create(MODULES_STATE_NID, MODULE_NID); - private static final ContainerNode GET_MODULES_STATE_MODULE_LIST_RPC; + private static final @NonNull ContainerNode GET_MODULES_STATE_MODULE_LIST_RPC = Builders.containerBuilder() + .withNodeIdentifier(NETCONF_GET_NODEID) + .withChild(NetconfMessageTransformUtil.toFilterStructure(MODULES_STATE_MODULE_LIST, LIBRARY_CONTEXT)) + .build(); - static { - final DataContainerChild filter = - NetconfMessageTransformUtil.toFilterStructure(MODULES_STATE_MODULE_LIST, LIBRARY_CONTEXT); - GET_MODULES_STATE_MODULE_LIST_RPC = - Builders.containerBuilder().withNodeIdentifier(toId(NETCONF_GET_QNAME)).withChild(filter).build(); - } + private final ImmutableMap availableModels; - private LibraryModulesSchemas(final Map availableModels) { - this.availableModels = availableModels; + private LibraryModulesSchemas(final ImmutableMap availableModels) { + this.availableModels = requireNonNull(availableModels); } public Map getAvailableModels() { - final Map result = Maps.newHashMap(); - for (final Map.Entry entry : availableModels.entrySet()) { - final SourceIdentifier sId = RevisionSourceIdentifier - .create(entry.getKey().getLocalName(), entry.getKey().getRevision()); + final Map result = new HashMap<>(); + for (final Entry entry : availableModels.entrySet()) { + final SourceIdentifier sId = new SourceIdentifier(entry.getKey().getLocalName(), + entry.getKey().getRevision().map(Revision::toString).orElse(null)); result.put(sId, entry.getValue()); } return result; } - /** * Resolves URLs with YANG schema resources from modules-state. Uses basic http authenticaiton * @@ -129,24 +141,22 @@ public final class LibraryModulesSchemas implements NetconfDeviceSchemas { * @return Resolved URLs with YANG schema resources for all yang modules from yang library */ public static LibraryModulesSchemas create(final String url, final String username, final String password) { - Preconditions.checkNotNull(url); try { - final URL urlConnection = new URL(url); + final URL urlConnection = new URL(requireNonNull(url)); final URLConnection connection = urlConnection.openConnection(); if (connection instanceof HttpURLConnection) { connection.setRequestProperty("Accept", "application/xml"); final String userpass = username + ":" + password; - final String basicAuth = "Basic " + printBase64Binary(userpass.getBytes(StandardCharsets.UTF_8)); - - connection.setRequestProperty("Authorization", basicAuth); + connection.setRequestProperty("Authorization", + "Basic " + Base64.getEncoder().encodeToString(userpass.getBytes(StandardCharsets.UTF_8))); } return createFromURLConnection(connection); } catch (final IOException e) { LOG.warn("Unable to download yang library from {}", url, e); - return new LibraryModulesSchemas(Collections.emptyMap()); + return new LibraryModulesSchemas(ImmutableMap.of()); } } @@ -155,52 +165,49 @@ public final class LibraryModulesSchemas implements NetconfDeviceSchemas { final DOMRpcResult moduleListNodeResult; try { moduleListNodeResult = - deviceRpc.invokeRpc(toPath(NETCONF_GET_QNAME), GET_MODULES_STATE_MODULE_LIST_RPC).get(); + deviceRpc.invokeRpc(NETCONF_GET_QNAME, GET_MODULES_STATE_MODULE_LIST_RPC).get(); } catch (final InterruptedException e) { Thread.currentThread().interrupt(); - throw new RuntimeException(deviceId + ": Interrupted while waiting for response to " + throw new IllegalStateException(deviceId + ": Interrupted while waiting for response to " + MODULES_STATE_MODULE_LIST, e); } catch (final ExecutionException e) { LOG.warn("{}: Unable to detect available schemas, get to {} failed", deviceId, MODULES_STATE_MODULE_LIST, e); - return new LibraryModulesSchemas(Collections.emptyMap()); + return new LibraryModulesSchemas(ImmutableMap.of()); } - if (moduleListNodeResult.getErrors().isEmpty() == false) { + if (!moduleListNodeResult.errors().isEmpty()) { LOG.warn("{}: Unable to detect available schemas, get to {} failed, {}", - deviceId, MODULES_STATE_MODULE_LIST, moduleListNodeResult.getErrors()); - return new LibraryModulesSchemas(Collections.emptyMap()); + deviceId, MODULES_STATE_MODULE_LIST, moduleListNodeResult.errors()); + return new LibraryModulesSchemas(ImmutableMap.of()); } - - final Optional> modulesStateNode = - findModulesStateNode(moduleListNodeResult.getResult()); + final Optional modulesStateNode = + findModulesStateNode(moduleListNodeResult.value()); if (modulesStateNode.isPresent()) { - Preconditions.checkState(modulesStateNode.get() instanceof ContainerNode, - "Expecting container containing schemas, but was %s", modulesStateNode.get()); - return create((ContainerNode) modulesStateNode.get()); + final DataContainerChild node = modulesStateNode.get(); + checkState(node instanceof ContainerNode, "Expecting container containing schemas, but was %s", node); + return create((ContainerNode) node); } - LOG.warn("{}: Unable to detect available schemas, get to {} was empty", deviceId, toId(ModulesState.QNAME)); - return new LibraryModulesSchemas(Collections.emptyMap()); + LOG.warn("{}: Unable to detect available schemas, get to {} was empty", deviceId, MODULES_STATE_NID); + return new LibraryModulesSchemas(ImmutableMap.of()); } private static LibraryModulesSchemas create(final ContainerNode modulesStateNode) { - final YangInstanceIdentifier.NodeIdentifier moduleListNodeId = - new YangInstanceIdentifier.NodeIdentifier(Module.QNAME); - final Optional> moduleListNode = - modulesStateNode.getChild(moduleListNodeId); - Preconditions.checkState(moduleListNode.isPresent(), - "Unable to find list: %s in %s", moduleListNodeId, modulesStateNode); - Preconditions.checkState(moduleListNode.get() instanceof MapNode, - "Unexpected structure for container: %s in : %s. Expecting a list", - moduleListNodeId, modulesStateNode); - - final ImmutableMap.Builder schemasMapping = new ImmutableMap.Builder<>(); - for (final MapEntryNode moduleNode : ((MapNode) moduleListNode.get()).getValue()) { - final Optional> schemaMappingEntry = createFromEntry(moduleNode); - if (schemaMappingEntry.isPresent()) { - schemasMapping.put(createFromEntry(moduleNode).get()); + final Optional moduleListNode = modulesStateNode.findChildByArg(MODULE_NID); + checkState(moduleListNode.isPresent(), "Unable to find list: %s in %s", MODULE_NID, modulesStateNode); + final DataContainerChild node = moduleListNode.get(); + checkState(node instanceof MapNode, "Unexpected structure for container: %s in : %s. Expecting a list", + MODULE_NID, modulesStateNode); + + final MapNode moduleList = (MapNode) node; + final Collection modules = moduleList.body(); + final ImmutableMap.Builder schemasMapping = ImmutableMap.builderWithExpectedSize(modules.size()); + for (final MapEntryNode moduleNode : modules) { + final Entry entry = createFromEntry(moduleNode); + if (entry != null) { + schemasMapping.put(entry); } } @@ -213,34 +220,30 @@ public final class LibraryModulesSchemas implements NetconfDeviceSchemas { * @return Resolved URLs with YANG schema resources for all yang modules from yang library */ public static LibraryModulesSchemas create(final String url) { - Preconditions.checkNotNull(url); + final URLConnection connection; try { - final URL urlConnection = new URL(url); - final URLConnection connection = urlConnection.openConnection(); - - if (connection instanceof HttpURLConnection) { - connection.setRequestProperty("Accept", "application/xml"); - } - - return createFromURLConnection(connection); - + connection = new URL(requireNonNull(url)).openConnection(); } catch (final IOException e) { LOG.warn("Unable to download yang library from {}", url, e); - return new LibraryModulesSchemas(Collections.emptyMap()); + return new LibraryModulesSchemas(ImmutableMap.of()); + } + + if (connection instanceof HttpURLConnection) { + connection.setRequestProperty("Accept", "application/xml"); } + return createFromURLConnection(connection); } - private static Optional> findModulesStateNode(final NormalizedNode result) { + private static Optional findModulesStateNode(final NormalizedNode result) { if (result == null) { return Optional.empty(); } - final Optional> dataNode = - ((DataContainerNode) result).getChild(toId(NETCONF_DATA_QNAME)); - if (dataNode.isPresent() == false) { + final Optional dataNode = ((DataContainerNode) result).findChildByArg(NETCONF_DATA_NODEID); + if (dataNode.isEmpty()) { return Optional.empty(); } - return ((DataContainerNode) dataNode.get()).getChild(toId(ModulesState.QNAME)); + return ((DataContainerNode) dataNode.get()).findChildByArg(MODULES_STATE_NID); } private static LibraryModulesSchemas createFromURLConnection(final URLConnection connection) { @@ -252,63 +255,41 @@ public final class LibraryModulesSchemas implements NetconfDeviceSchemas { contentType = "application/json"; } - Preconditions.checkNotNull(contentType, "Content type unknown"); - Preconditions.checkState(contentType.equals("application/json") || contentType.equals("application/xml"), + requireNonNull(contentType, "Content type unknown"); + checkState(contentType.equals("application/json") || contentType.equals("application/xml"), "Only XML and JSON types are supported."); - try (InputStream in = connection.getInputStream()) { - final Optional> optionalModulesStateNode = - contentType.equals("application/json") ? readJson(in) : readXml(in); - - if (!optionalModulesStateNode.isPresent()) { - return new LibraryModulesSchemas(Collections.emptyMap()); - } - - final NormalizedNode modulesStateNode = optionalModulesStateNode.get(); - Preconditions.checkState(modulesStateNode.getNodeType().equals(ModulesState.QNAME), - "Wrong QName %s", modulesStateNode.getNodeType()); - Preconditions.checkState(modulesStateNode instanceof ContainerNode, - "Expecting container containing module list, but was %s", modulesStateNode); - - final YangInstanceIdentifier.NodeIdentifier moduleListNodeId = - new YangInstanceIdentifier.NodeIdentifier(Module.QNAME); - final Optional> moduleListNode = - ((ContainerNode) modulesStateNode).getChild(moduleListNodeId); - Preconditions.checkState(moduleListNode.isPresent(), - "Unable to find list: %s in %s", moduleListNodeId, modulesStateNode); - Preconditions.checkState(moduleListNode.get() instanceof MapNode, - "Unexpected structure for container: %s in : %s. Expecting a list", - moduleListNodeId, modulesStateNode); - - final ImmutableMap.Builder schemasMapping = new ImmutableMap.Builder<>(); - for (final MapEntryNode moduleNode : ((MapNode) moduleListNode.get()).getValue()) { - final Optional> schemaMappingEntry = createFromEntry(moduleNode); - if (schemaMappingEntry.isPresent()) { - schemasMapping.put(createFromEntry(moduleNode).get()); - } - } - return new LibraryModulesSchemas(schemasMapping.build()); + Optional optionalModulesStateNode = Optional.empty(); + try (InputStream in = connection.getInputStream()) { + optionalModulesStateNode = contentType.equals("application/json") ? readJson(in) : readXml(in); } catch (final IOException e) { LOG.warn("Unable to download yang library from {}", connection.getURL(), e); - return new LibraryModulesSchemas(Collections.emptyMap()); } - } - private static boolean guessJsonFromFileName(final String fileName) { - String extension = ""; - final int i = fileName.lastIndexOf(46); - if (i != -1) { - extension = fileName.substring(i).toLowerCase(Locale.ROOT); + if (optionalModulesStateNode.isEmpty()) { + return new LibraryModulesSchemas(ImmutableMap.of()); } - return extension.equals(".json"); + final NormalizedNode modulesStateNode = optionalModulesStateNode.get(); + checkState(modulesStateNode instanceof ContainerNode, "Expecting container containing module list, but was %s", + modulesStateNode); + final ContainerNode modulesState = (ContainerNode) modulesStateNode; + final NodeIdentifier nodeName = modulesState.getIdentifier(); + checkState(MODULES_STATE_NID.equals(nodeName), "Wrong container identifier %s", nodeName); + + return create((ContainerNode) modulesStateNode); + } + + private static boolean guessJsonFromFileName(final String fileName) { + final int i = fileName.lastIndexOf('.'); + return i != 1 && ".json".equalsIgnoreCase(fileName.substring(i)); } - private static Optional> readJson(final InputStream in) { + private static Optional readJson(final InputStream in) { final NormalizedNodeResult resultHolder = new NormalizedNodeResult(); final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder); - final JsonParserStream jsonParser = JsonParserStream.create(writer, LIBRARY_CONTEXT); + final JsonParserStream jsonParser = JsonParserStream.create(writer, JSON_CODECS); final JsonReader reader = new JsonReader(new InputStreamReader(in, Charset.defaultCharset())); jsonParser.parse(reader); @@ -316,7 +297,7 @@ public final class LibraryModulesSchemas implements NetconfDeviceSchemas { return resultHolder.isFinished() ? Optional.of(resultHolder.getResult()) : Optional.empty(); } - private static Optional> readXml(final InputStream in) { + private static Optional readXml(final InputStream in) { try { final DocumentBuilder docBuilder = UntrustedXML.newDocumentBuilder(); @@ -339,69 +320,56 @@ public final class LibraryModulesSchemas implements NetconfDeviceSchemas { final NormalizedNodeResult resultHolder = new NormalizedNodeResult(); final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder); - final XmlParserStream xmlParser = XmlParserStream.create(writer, LIBRARY_CONTEXT, - LIBRARY_CONTEXT.getDataChildByName(ModulesState.QNAME)); + final XmlParserStream xmlParser = XmlParserStream.create(writer, MODULES_STATE_INFERENCE); xmlParser.traverse(new DOMSource(doc.getDocumentElement())); - final NormalizedNode parsed = resultHolder.getResult(); - return Optional.of(parsed); - } catch (XMLStreamException | URISyntaxException | IOException | ParserConfigurationException - | SAXException e) { + return Optional.of(resultHolder.getResult()); + } catch (XMLStreamException | URISyntaxException | IOException | SAXException e) { LOG.warn("Unable to parse yang library xml content", e); } return Optional.empty(); } - private static Optional> createFromEntry(final MapEntryNode moduleNode) { - Preconditions.checkArgument( - moduleNode.getNodeType().equals(Module.QNAME), "Wrong QName %s", moduleNode.getNodeType()); - - YangInstanceIdentifier.NodeIdentifier childNodeId = - new YangInstanceIdentifier.NodeIdentifier(QName.create(Module.QNAME, "name")); - final String moduleName = getSingleChildNodeValue(moduleNode, childNodeId).get(); + private static @Nullable Entry createFromEntry(final MapEntryNode moduleNode) { + final QName moduleNodeId = moduleNode.getIdentifier().getNodeType(); + checkArgument(moduleNodeId.equals(Module.QNAME), "Wrong QName %s", moduleNodeId); - childNodeId = new YangInstanceIdentifier.NodeIdentifier(QName.create(Module.QNAME, "revision")); - final Optional revision = getSingleChildNodeValue(moduleNode, childNodeId); + final String moduleName = getSingleChildNodeValue(moduleNode, NAME_NID).get(); + final Optional revision = getSingleChildNodeValue(moduleNode, REVISION_NID); if (revision.isPresent()) { if (!Revision.STRING_FORMAT_PATTERN.matcher(revision.get()).matches()) { LOG.warn("Skipping library schema for {}. Revision {} is in wrong format.", moduleNode, revision.get()); - return Optional.empty(); + return null; } } // FIXME leaf schema with url that represents the yang schema resource for this module is not mandatory // don't fail if schema node is not present, just skip the entry or add some default URL - childNodeId = new YangInstanceIdentifier.NodeIdentifier(QName.create(Module.QNAME, "schema")); - final Optional schemaUriAsString = getSingleChildNodeValue(moduleNode, childNodeId); - - childNodeId = new YangInstanceIdentifier.NodeIdentifier(QName.create(Module.QNAME, "namespace")); - final String moduleNameSpace = getSingleChildNodeValue(moduleNode, childNodeId).get(); + final Optional schemaUriAsString = getSingleChildNodeValue(moduleNode, SCHEMA_NID); + final String moduleNameSpace = getSingleChildNodeValue(moduleNode, NAMESPACE_NID).get(); final QName moduleQName = revision.isPresent() ? QName.create(moduleNameSpace, revision.get(), moduleName) - : QName.create(URI.create(moduleNameSpace), moduleName); + : QName.create(XMLNamespace.of(moduleNameSpace), moduleName); try { - return Optional.>of(new AbstractMap.SimpleImmutableEntry<>( - moduleQName, new URL(schemaUriAsString.get()))); + return new SimpleImmutableEntry<>(moduleQName, new URL(schemaUriAsString.get())); } catch (final MalformedURLException e) { LOG.warn("Skipping library schema for {}. URL {} representing yang schema resource is not valid", moduleNode, schemaUriAsString.get()); - return Optional.empty(); + return null; } } - private static Optional getSingleChildNodeValue(final DataContainerNode schemaNode, - final YangInstanceIdentifier.NodeIdentifier childNodeId) { - final Optional> node = - schemaNode.getChild(childNodeId); - Preconditions.checkArgument(node.isPresent(), "Child node %s not present", childNodeId.getNodeType()); + private static Optional getSingleChildNodeValue(final DataContainerNode schemaNode, + final NodeIdentifier childNodeId) { + final Optional node = schemaNode.findChildByArg(childNodeId); + checkArgument(node.isPresent(), "Child node %s not present", childNodeId.getNodeType()); return getValueOfSimpleNode(node.get()); } - private static Optional getValueOfSimpleNode( - final NormalizedNode node) { - final String valueStr = node.getValue().toString(); + private static Optional getValueOfSimpleNode(final NormalizedNode node) { + final String valueStr = node.body().toString(); return Strings.isNullOrEmpty(valueStr) ? Optional.empty() : Optional.of(valueStr.trim()); }