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=dd6f855d7a7c654df667f688ce501f2209bf094b;hpb=a90cf823b75109338d980cc367234da10c35f341;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 dd6f855d7a..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,10 +7,13 @@ */ package org.opendaylight.netconf.sal.connect.netconf; -import static javax.xml.bind.DatatypeConverter.printBase64Binary; +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 com.google.common.base.Optional; -import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import com.google.gson.stream.JsonReader; @@ -19,17 +22,41 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; -import java.util.AbstractMap; -import java.util.Collections; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.AbstractMap.SimpleImmutableEntry; +import java.util.Base64; +import java.util.Collection; +import java.util.HashMap; import java.util.Map; -import org.opendaylight.controller.config.util.xml.XmlUtil; -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.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext; +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.stream.XMLStreamException; +import javax.xml.transform.dom.DOMSource; +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.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; @@ -37,240 +64,317 @@ 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.impl.codec.xml.XmlUtils; +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.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory; -import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; -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; +import org.w3c.dom.Element; +import org.w3c.dom.Node; import org.xml.sax.SAXException; /** * Holds URLs with YANG schema resources for all yang modules reported in - * ietf-netconf-yang-library/modules-state/modules node + * ietf-netconf-yang-library/modules-state/modules node. */ -public class LibraryModulesSchemas { +public final class LibraryModulesSchemas implements NetconfDeviceSchemas { private static final Logger LOG = LoggerFactory.getLogger(LibraryModulesSchemas.class); - - private static SchemaContext libraryContext; - - private final Map availableModels; - - 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()); - libraryContext = moduleInfoBackedContext.tryToCreateSchemaContext().get(); - } - - private LibraryModulesSchemas(final Map availableModels) { - this.availableModels = availableModels; + private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{4}-\\d{2}-\\d{2})"); + 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.create(MODULES_STATE_NID, MODULE_NID); + + 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(); + + private final ImmutableMap availableModels; + + private LibraryModulesSchemas(final ImmutableMap availableModels) { + this.availableModels = requireNonNull(availableModels); } public Map getAvailableModels() { - return availableModels; - } + 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 + * * @param url URL pointing to yang library * @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) { + if (connection instanceof HttpURLConnection) { connection.setRequestProperty("Accept", "application/xml"); - String userpass = username + ":" + password; - String basicAuth = "Basic " + printBase64Binary(userpass.getBytes()); - - connection.setRequestProperty("Authorization", basicAuth); + final String userpass = username + ":" + password; + connection.setRequestProperty("Authorization", + "Basic " + Base64.getEncoder().encodeToString(userpass.getBytes(StandardCharsets.UTF_8))); } return createFromURLConnection(connection); - } catch (IOException e) { + } catch (final IOException e) { LOG.warn("Unable to download yang library from {}", url, e); - return new LibraryModulesSchemas(Collections.emptyMap()); + return new LibraryModulesSchemas(ImmutableMap.of()); } } - private static LibraryModulesSchemas createFromURLConnection(URLConnection connection) { - - String contentType = connection.getContentType(); + public static LibraryModulesSchemas create(final NetconfDeviceRpc deviceRpc, final RemoteDeviceId deviceId) { + final DOMRpcResult moduleListNodeResult; + try { + moduleListNodeResult = + deviceRpc.invokeRpc(NETCONF_GET_QNAME, GET_MODULES_STATE_MODULE_LIST_RPC).get(); + } catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + 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(ImmutableMap.of()); + } - // TODO try to guess Json also from intput stream - if (guessJsonFromFileName(connection.getURL().getFile())) { - contentType = "application/json"; + if (!moduleListNodeResult.errors().isEmpty()) { + LOG.warn("{}: Unable to detect available schemas, get to {} failed, {}", + deviceId, MODULES_STATE_MODULE_LIST, moduleListNodeResult.errors()); + return new LibraryModulesSchemas(ImmutableMap.of()); } - Preconditions.checkNotNull(contentType, "Content type unknown"); - Preconditions.checkState(contentType.equals("application/json") || contentType.equals("application/xml"), - "Only XML and JSON types are supported."); - try (final InputStream in = connection.getInputStream()) { - final Optional> optionalModulesStateNode = - contentType.equals("application/json") ? readJson(in) : readXml(in); + final Optional modulesStateNode = + findModulesStateNode(moduleListNodeResult.value()); + if (modulesStateNode.isPresent()) { + final DataContainerChild node = modulesStateNode.get(); + checkState(node instanceof ContainerNode, "Expecting container containing schemas, but was %s", node); + return create((ContainerNode) node); + } - if (!optionalModulesStateNode.isPresent()) { - 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()); + } - 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()); - } + private static LibraryModulesSchemas create(final ContainerNode modulesStateNode) { + 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); } - - return new LibraryModulesSchemas(schemasMapping.build()); - } catch (IOException e) { - LOG.warn("Unable to download yang library from {}", connection.getURL(), e); - return new LibraryModulesSchemas(Collections.emptyMap()); } + + return new LibraryModulesSchemas(schemasMapping.build()); } /** - * Resolves URLs with YANG schema resources from modules-state + * Resolves URLs with YANG schema resources from modules-state. * @param url URL pointing to yang library * @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"); - } + connection = new URL(requireNonNull(url)).openConnection(); + } catch (final IOException e) { + LOG.warn("Unable to download yang library from {}", url, e); + return new LibraryModulesSchemas(ImmutableMap.of()); + } - return createFromURLConnection(connection); + if (connection instanceof HttpURLConnection) { + connection.setRequestProperty("Accept", "application/xml"); + } + return createFromURLConnection(connection); + } - } catch (IOException e) { - LOG.warn("Unable to download yang library from {}", url, e); - return new LibraryModulesSchemas(Collections.emptyMap()); + private static Optional findModulesStateNode(final NormalizedNode result) { + if (result == null) { + return Optional.empty(); + } + final Optional dataNode = ((DataContainerNode) result).findChildByArg(NETCONF_DATA_NODEID); + if (dataNode.isEmpty()) { + return Optional.empty(); } + + return ((DataContainerNode) dataNode.get()).findChildByArg(MODULES_STATE_NID); } - private static boolean guessJsonFromFileName(final String fileName) { - String extension = ""; - final int i = fileName.lastIndexOf(46); - if(i != -1) { - extension = fileName.substring(i).toLowerCase(); + private static LibraryModulesSchemas createFromURLConnection(final URLConnection connection) { + + String contentType = connection.getContentType(); + + // TODO try to guess Json also from intput stream + if (guessJsonFromFileName(connection.getURL().getFile())) { + contentType = "application/json"; + } + + requireNonNull(contentType, "Content type unknown"); + checkState(contentType.equals("application/json") || contentType.equals("application/xml"), + "Only XML and JSON types are supported."); + + 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); + } + + 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, libraryContext); - final JsonReader reader = new JsonReader(new InputStreamReader(in)); + final JsonParserStream jsonParser = JsonParserStream.create(writer, JSON_CODECS); + final JsonReader reader = new JsonReader(new InputStreamReader(in, Charset.defaultCharset())); jsonParser.parse(reader); - return resultHolder.isFinished() ? - Optional.of(resultHolder.getResult()) : - Optional.>absent(); + return resultHolder.isFinished() ? Optional.of(resultHolder.getResult()) : Optional.empty(); } - private static Optional> readXml(final InputStream in) { - final DomToNormalizedNodeParserFactory parserFactory = - DomToNormalizedNodeParserFactory.getInstance(XmlUtils.DEFAULT_XML_CODEC_PROVIDER, libraryContext); - + private static Optional readXml(final InputStream in) { try { - final NormalizedNode parsed = - parserFactory.getContainerNodeParser().parse(Collections.singleton(XmlUtil.readXmlToElement(in)), - (ContainerSchemaNode) libraryContext.getDataChildByName(ModulesState.QNAME)); - return Optional.of(parsed); - } catch (IOException|SAXException e) { + final DocumentBuilder docBuilder = UntrustedXML.newDocumentBuilder(); + + final Document read = docBuilder.parse(in); + final Document doc = docBuilder.newDocument(); + final Element rootElement = doc.createElementNS("urn:ietf:params:xml:ns:yang:ietf-yang-library", + "modules"); + doc.appendChild(rootElement); + + for (int i = 0; i < read.getElementsByTagName("revision").getLength(); i++) { + final String revision = read.getElementsByTagName("revision").item(i).getTextContent(); + if (DATE_PATTERN.matcher(revision).find() || revision.isEmpty()) { + final Node module = doc.importNode(read.getElementsByTagName("module").item(i), true); + rootElement.appendChild(module); + } else { + LOG.warn("Xml contains wrong revision - {} - on module {}", revision, + read.getElementsByTagName("module").item(i).getTextContent()); + } + } + + final NormalizedNodeResult resultHolder = new NormalizedNodeResult(); + final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder); + final XmlParserStream xmlParser = XmlParserStream.create(writer, MODULES_STATE_INFERENCE); + xmlParser.traverse(new DOMSource(doc.getDocumentElement())); + return Optional.of(resultHolder.getResult()); + } catch (XMLStreamException | URISyntaxException | IOException | SAXException e) { LOG.warn("Unable to parse yang library xml content", e); } - return Optional.>absent(); + return Optional.empty(); } - private static Optional> createFromEntry(final MapEntryNode moduleNode) { - Preconditions.checkArgument( - moduleNode.getNodeType().equals(Module.QNAME), "Wrong QName %s", moduleNode.getNodeType()); + private static @Nullable Entry createFromEntry(final MapEntryNode moduleNode) { + final QName moduleNodeId = moduleNode.getIdentifier().getNodeType(); + checkArgument(moduleNodeId.equals(Module.QNAME), "Wrong QName %s", moduleNodeId); - YangInstanceIdentifier.NodeIdentifier childNodeId = - new YangInstanceIdentifier.NodeIdentifier(QName.create(Module.QNAME, "name")); - final String moduleName = getSingleChildNodeValue(moduleNode, childNodeId).get(); - - childNodeId = new YangInstanceIdentifier.NodeIdentifier(QName.create(Module.QNAME, "revision")); - final Optional revision = getSingleChildNodeValue(moduleNode, childNodeId); - if(revision.isPresent()) { - if(!SourceIdentifier.REVISION_PATTERN.matcher(revision.get()).matches()) { + 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.>absent(); + 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); - + final Optional schemaUriAsString = getSingleChildNodeValue(moduleNode, SCHEMA_NID); + final String moduleNameSpace = getSingleChildNodeValue(moduleNode, NAMESPACE_NID).get(); - final SourceIdentifier sourceId = revision.isPresent() - ? RevisionSourceIdentifier.create(moduleName, revision.get()) - : RevisionSourceIdentifier.create(moduleName); + final QName moduleQName = revision.isPresent() + ? QName.create(moduleNameSpace, revision.get(), moduleName) + : QName.create(XMLNamespace.of(moduleNameSpace), moduleName); try { - return Optional.>of(new AbstractMap.SimpleImmutableEntry<>( - sourceId, new URL(schemaUriAsString.get()))); - } catch (MalformedURLException e) { + 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.>absent(); + 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 Object value = node.getValue(); - return value == null || Strings.isNullOrEmpty(value.toString()) - ? Optional.absent() : Optional.of(value.toString().trim()); + private static Optional getValueOfSimpleNode(final NormalizedNode node) { + final String valueStr = node.body().toString(); + return Strings.isNullOrEmpty(valueStr) ? Optional.empty() : Optional.of(valueStr.trim()); } + @Override + public Set getAvailableYangSchemasQNames() { + return null; + } }