public NetconfMessageTransformer(final SchemaContext schemaContext, final boolean strictParsing) { this.counter = new MessageCounter(); this.schemaContext = schemaContext; parserFactory = DomToNormalizedNodeParserFactory.getInstance( XmlUtils.DEFAULT_XML_CODEC_PROVIDER, schemaContext, strictParsing); mappedRpcs = Maps.uniqueIndex(schemaContext.getOperations(), QNAME_FUNCTION); mappedNotifications = Multimaps.index(schemaContext.getNotifications(), QNAME_NOREV_FUNCTION); }
@Override public synchronized DOMNotification toNotification(final NetconfMessage message) { final Map.Entry<Date, XmlElement> stripped = stripNotification(message); final QName notificationNoRev; try { notificationNoRev = QName.create(stripped.getValue().getNamespace(), stripped.getValue().getName()) .withoutRevision(); } catch (final MissingNameSpaceException e) { throw new IllegalArgumentException( "Unable to parse notification " + message + ", cannot find namespace", e); } final Collection<NotificationDefinition> notificationDefinitions = mappedNotifications.get(notificationNoRev); Preconditions.checkArgument( notificationDefinitions.size() > 0, "Unable to parse notification %s, unknown notification. Available notifications: %s", notificationDefinitions, mappedNotifications.keySet()); // FIXME if multiple revisions for same notifications are present, we should pick the most // recent. Or ? // We should probably just put the most recent notification versions into our map. We can expect // that the device sends the data according to the latest available revision of a model. final NotificationDefinition next = notificationDefinitions.iterator().next(); // We wrap the notification as a container node in order to reuse the parsers and builders for // container node final ContainerSchemaNode notificationAsContainerSchemaNode = NetconfMessageTransformUtil.createSchemaForNotification(next); final Element element = stripped.getValue().getDomElement(); final ContainerNode content; try { content = parserFactory .getContainerNodeParser() .parse(Collections.singleton(element), notificationAsContainerSchemaNode); } catch (IllegalArgumentException e) { throw new IllegalArgumentException( String.format("Failed to parse notification %s", element), e); } return new NetconfDeviceNotification(content, stripped.getKey()); }
@Override public synchronized DOMRpcResult toRpcResult(final NetconfMessage message, final SchemaPath rpc) { final NormalizedNode<?, ?> normalizedNode; final QName rpcQName = rpc.getLastComponent(); if (NetconfMessageTransformUtil.isDataRetrievalOperation(rpcQName)) { final Element xmlData = NetconfMessageTransformUtil.getDataSubtree(message.getDocument()); final ContainerSchemaNode schemaForDataRead = NetconfMessageTransformUtil.createSchemaForDataRead(schemaContext); final ContainerNode dataNode; try { dataNode = parserFactory .getContainerNodeParser() .parse(Collections.singleton(xmlData), schemaForDataRead); } catch (IllegalArgumentException e) { throw new IllegalArgumentException( String.format("Failed to parse data response %s", xmlData), e); } normalizedNode = Builders.containerBuilder() .withNodeIdentifier( new YangInstanceIdentifier.NodeIdentifier( NetconfMessageTransformUtil.NETCONF_RPC_REPLY_QNAME)) .withChild(dataNode) .build(); } else { Map<QName, RpcDefinition> currentMappedRpcs = mappedRpcs; // Determine whether a base netconf operation is being invoked and also check if the device // exposed model for base netconf // If no, use pre built base netconf operations model final boolean needToUseBaseCtx = mappedRpcs.get(rpcQName) == null && isBaseRpc(rpcQName); if (needToUseBaseCtx) { currentMappedRpcs = MAPPED_BASE_RPCS; } final RpcDefinition rpcDefinition = currentMappedRpcs.get(rpcQName); Preconditions.checkArgument( rpcDefinition != null, "Unable to parse response of %s, the rpc is unknown", rpcQName); // In case no input for rpc is defined, we can simply construct the payload here if (rpcDefinition.getOutput() == null) { Preconditions.checkArgument( XmlElement.fromDomDocument(message.getDocument()) .getOnlyChildElementWithSameNamespaceOptionally("ok") .isPresent(), "Unexpected content in response of rpc: %s, %s", rpcDefinition.getQName(), message); normalizedNode = null; } else { final Element element = message.getDocument().getDocumentElement(); try { normalizedNode = parserFactory .getContainerNodeParser() .parse(Collections.singleton(element), rpcDefinition.getOutput()); } catch (IllegalArgumentException e) { throw new IllegalArgumentException( String.format("Failed to parse RPC response %s", element), e); } } } return new DefaultDOMRpcResult(normalizedNode); }