/* * Copyright (c) 2016 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.restconf.nb.rfc8040.rests.utils; import com.google.common.base.Preconditions; import java.util.ArrayList; import java.util.List; import java.util.Optional; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; import org.opendaylight.mdsal.dom.api.DOMRpcResult; import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult; import org.opendaylight.restconf.common.context.NormalizedNodeContext; import org.opendaylight.restconf.common.errors.RestconfDocumentedException; import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag; import org.opendaylight.restconf.common.errors.RestconfError.ErrorType; import org.opendaylight.restconf.common.util.DataChangeScope; import org.opendaylight.restconf.nb.rfc8040.references.SchemaContextRef; import org.opendaylight.restconf.nb.rfc8040.streams.listeners.NotificationListenerAdapter; import org.opendaylight.restconf.nb.rfc8040.streams.listeners.Notificator; import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier; import org.opendaylight.yang.gen.v1.urn.sal.restconf.event.subscription.rev140708.NotificationOutputTypeGrouping.NotificationOutputType; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Util class for streams. * *
* {@code * { * "input": { * "path": "/toaster:toaster/toaster:toasterStatus", * "sal-remote-augment:datastore": "OPERATIONAL", * "sal-remote-augment:scope": "ONE" * } * } * } ** * @param refSchemaCtx * reference to {@link SchemaContext} - * {@link SchemaContextRef} * @return {@link DOMRpcResult} - This means output of RPC - example in JSON: * *
* {@code * { * "output": { * "stream-name": "toaster:toaster/toaster:toasterStatus/datastore=OPERATIONAL/scope=ONE" * } * } * } ** */ public static DOMRpcResult createDataChangeNotifiStream(final NormalizedNodeContext payload, final SchemaContextRef refSchemaCtx) { final ContainerNode data = (ContainerNode) payload.getData(); final QName qname = payload.getInstanceIdentifierContext().getSchemaNode().getQName(); final YangInstanceIdentifier path = preparePath(data, qname); String streamName = prepareDataChangeNotifiStreamName(path, refSchemaCtx.get(), data); final QName outputQname = QName.create(qname, "output"); final QName streamNameQname = QName.create(qname, "stream-name"); final NotificationOutputType outputType = prepareOutputType(data); if (outputType.equals(NotificationOutputType.JSON)) { streamName = streamName + "/JSON"; } if (!Notificator.existListenerFor(streamName)) { Notificator.createListener(path, streamName, outputType); } final ContainerNode output = ImmutableContainerNodeBuilder.create().withNodeIdentifier(new NodeIdentifier(outputQname)) .withChild(ImmutableNodes.leafNode(streamNameQname, streamName)).build(); return new DefaultDOMRpcResult(output); } /** * Prepare {@code NotificationOutputType}. * * @param data * data of notification * @return output type fo notification */ private static NotificationOutputType prepareOutputType(final ContainerNode data) { NotificationOutputType outputType = parseEnum(data, NotificationOutputType.class, OUTPUT_TYPE_PARAM_NAME); return outputType == null ? NotificationOutputType.XML : outputType; } private static String prepareDataChangeNotifiStreamName(final YangInstanceIdentifier path, final SchemaContext schemaContext, final ContainerNode data) { LogicalDatastoreType ds = parseEnum(data, LogicalDatastoreType.class, RestconfStreamsConstants.DATASTORE_PARAM_NAME); ds = ds == null ? RestconfStreamsConstants.DEFAULT_DS : ds; DataChangeScope scope = parseEnum(data, DataChangeScope.class, RestconfStreamsConstants.SCOPE_PARAM_NAME); scope = scope == null ? RestconfStreamsConstants.DEFAULT_SCOPE : scope; final String streamName = RestconfStreamsConstants.DATA_SUBSCR + "/" + Notificator .createStreamNameFromUri(ParserIdentifier.stringFromYangInstanceIdentifier(path, schemaContext) + RestconfStreamsConstants.DS_URI + ds + RestconfStreamsConstants.SCOPE_URI + scope); return streamName; } private static