From 92228cd087187f9d2b253fdc4acb6704069a8762 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sun, 24 Oct 2021 13:31:39 +0200 Subject: [PATCH] Use parameters in StreamSubscriptionServiceImpl We have proper definitions fo parameters pertaining to streams, use them to tie things together. JIRA: NETCONF-773 Change-Id: I26a2e346bb61e13ec3a8a9e39892cd0952186671 Signed-off-by: Robert Varga --- ...estconfStreamsSubscriptionServiceImpl.java | 121 +++++++++--------- .../services/impl/SubscribeToStreamUtil.java | 16 +-- .../listeners/AbstractQueryParams.java | 33 ++--- .../NotificationListenerAdapter.java | 4 +- 4 files changed, 90 insertions(+), 84 deletions(-) diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfStreamsSubscriptionServiceImpl.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfStreamsSubscriptionServiceImpl.java index 9e31cfba3c..e2d95d9fab 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfStreamsSubscriptionServiceImpl.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfStreamsSubscriptionServiceImpl.java @@ -8,6 +8,7 @@ package org.opendaylight.restconf.nb.rfc8040.rests.services.impl; import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; import java.net.URI; import java.time.Instant; @@ -22,10 +23,14 @@ import java.util.Optional; import javax.ws.rs.Path; import javax.ws.rs.core.UriInfo; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.mdsal.dom.api.DOMDataBroker; import org.opendaylight.mdsal.dom.api.DOMNotificationService; import org.opendaylight.restconf.common.context.InstanceIdentifierContext; import org.opendaylight.restconf.common.errors.RestconfDocumentedException; +import org.opendaylight.restconf.nb.rfc8040.FilterParameter; +import org.opendaylight.restconf.nb.rfc8040.StartTimeParameter; +import org.opendaylight.restconf.nb.rfc8040.StopTimeParameter; import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler; import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload; import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSubscriptionService; @@ -172,72 +177,74 @@ public class RestconfStreamsSubscriptionServiceImpl implements RestconfStreamsSu .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true) .appendOffset("+HH:MM", "Z").toFormatter(); - private final Instant start; - private final Instant stop; + private final @NonNull Instant startTime; + private final Instant stopTime; private final String filter; private final boolean skipNotificationData; - private NotificationQueryParams(final Instant start, final Instant stop, final String filter, + private NotificationQueryParams(final Instant startTime, final Instant stopTime, final String filter, final boolean skipNotificationData) { - this.start = start == null ? Instant.now() : start; - this.stop = stop; + this.startTime = requireNonNull(startTime); + this.stopTime = stopTime; this.filter = filter; this.skipNotificationData = skipNotificationData; } static NotificationQueryParams fromUriInfo(final UriInfo uriInfo) { - Instant start = null; - boolean startTimeUsed = false; - Instant stop = null; - boolean stopTimeUsed = false; + Instant startTime = null; + Instant stopTime = null; String filter = null; - boolean filterUsed = false; - boolean skipNotificationDataUsed = false; boolean skipNotificationData = false; for (final Entry> entry : uriInfo.getQueryParameters().entrySet()) { - switch (entry.getKey()) { - case "start-time": - if (!startTimeUsed) { - startTimeUsed = true; - start = parseDateFromQueryParam(entry); - } else { + final String paramName = entry.getKey(); + final List paramValues = entry.getValue(); + if (paramName.equals(StartTimeParameter.uriName())) { + switch (paramValues.size()) { + case 0: + break; + case 1: + startTime = parseDateFromQueryParam(paramValues.get(0)); + break; + default: throw new RestconfDocumentedException("Start-time parameter can be used only once."); - } - break; - case "stop-time": - if (!stopTimeUsed) { - stopTimeUsed = true; - stop = parseDateFromQueryParam(entry); - } else { + } + } else if (paramName.equals(StopTimeParameter.uriName())) { + switch (paramValues.size()) { + case 0: + break; + case 1: + stopTime = parseDateFromQueryParam(paramValues.get(0)); + break; + default: throw new RestconfDocumentedException("Stop-time parameter can be used only once."); - } - break; - case "filter": - if (!filterUsed) { - filterUsed = true; - filter = entry.getValue().iterator().next(); - } - break; - case "odl-skip-notification-data": - if (!skipNotificationDataUsed) { - skipNotificationDataUsed = true; - skipNotificationData = Boolean.parseBoolean(entry.getValue().iterator().next()); - } else { + } + } else if (paramName.equals(FilterParameter.uriName())) { + if (!paramValues.isEmpty()) { + // FIXME: use FilterParameter + filter = paramValues.get(0); + } + } else if (paramName.equals("odl-skip-notification-data")) { + switch (paramValues.size()) { + case 0: + break; + case 1: + skipNotificationData = Boolean.parseBoolean(paramValues.get(0)); + break; + default: throw new RestconfDocumentedException( - "Odl-skip-notification-data parameter can be used only once."); - } - break; - default: - throw new RestconfDocumentedException( - "Bad parameter used with notifications: " + entry.getKey()); + "Odl-skip-notification-data parameter can be used only once."); + } + } else { + throw new RestconfDocumentedException("Bad parameter used with notifications: " + paramName); } } - if (!startTimeUsed && stopTimeUsed) { + if (startTime == null && stopTime != null) { throw new RestconfDocumentedException("Stop-time parameter has to be used with start-time parameter."); } - return new NotificationQueryParams(start, stop, filter, skipNotificationData); + return new NotificationQueryParams(startTime == null ? Instant.now() : startTime, stopTime, filter, + skipNotificationData); } @@ -245,17 +252,15 @@ public class RestconfStreamsSubscriptionServiceImpl implements RestconfStreamsSu * Parse input of query parameters - start-time or stop-time - from {@link DateAndTime} format * to {@link Instant} format. * - * @param entry Start-time or stop-time as string in {@link DateAndTime} format. + * @param uriValue Start-time or stop-time as string in {@link DateAndTime} format. * @return Parsed {@link Instant} by entry. */ - private static Instant parseDateFromQueryParam(final Entry> entry) { - final DateAndTime event = new DateAndTime(entry.getValue().iterator().next()); - final String value = event.getValue(); + private static @NonNull Instant parseDateFromQueryParam(final String uriValue) { final TemporalAccessor accessor; try { - accessor = FORMATTER.parse(value); - } catch (final DateTimeParseException e) { - throw new RestconfDocumentedException("Cannot parse of value in date: " + value, e); + accessor = FORMATTER.parse(new DateAndTime(uriValue).getValue()); + } catch (final DateTimeParseException | IllegalArgumentException e) { + throw new RestconfDocumentedException("Cannot parse of value in date: " + uriValue, e); } return Instant.from(accessor); } @@ -265,8 +270,8 @@ public class RestconfStreamsSubscriptionServiceImpl implements RestconfStreamsSu * * @return start-time */ - public @NonNull Instant getStart() { - return start; + public @NonNull Instant startTime() { + return startTime; } /** @@ -274,8 +279,8 @@ public class RestconfStreamsSubscriptionServiceImpl implements RestconfStreamsSu * * @return stop-time */ - public Optional getStop() { - return Optional.ofNullable(stop); + public @Nullable Instant stopTime() { + return stopTime; } /** @@ -283,8 +288,8 @@ public class RestconfStreamsSubscriptionServiceImpl implements RestconfStreamsSu * * @return filter */ - public Optional getFilter() { - return Optional.ofNullable(filter); + public @Nullable String filter() { + return filter; } /** diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/SubscribeToStreamUtil.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/SubscribeToStreamUtil.java index d841061ea7..e9ac883752 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/SubscribeToStreamUtil.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/SubscribeToStreamUtil.java @@ -132,15 +132,15 @@ abstract class SubscribeToStreamUtil { final URI uri = prepareUriByStreamName(uriInfo, streamName); notificationListenerAdapter.listen(handlersHolder.getNotificationServiceHandler()); notificationListenerAdapter.setQueryParams( - notificationQueryParams.getStart(), - notificationQueryParams.getStop().orElse(null), - notificationQueryParams.getFilter().orElse(null), + notificationQueryParams.startTime(), + notificationQueryParams.stopTime(), + notificationQueryParams.filter(), false, notificationQueryParams.isSkipNotificationData()); final DOMDataBroker dataBroker = handlersHolder.getDataBroker(); notificationListenerAdapter.setCloseVars(dataBroker, handlersHolder.getSchemaHandler()); final MapEntryNode mapToStreams = RestconfMappingNodeUtil.mapYangNotificationStreamByIetfRestconfMonitoring( notificationListenerAdapter.getSchemaPath().lastNodeIdentifier(), - schemaContext.getNotifications(), notificationQueryParams.getStart(), + schemaContext.getNotifications(), notificationQueryParams.startTime(), notificationListenerAdapter.getOutputType(), uri); // FIXME: how does this correlate with the transaction notificationListenerAdapter.close() will do? @@ -184,9 +184,9 @@ abstract class SubscribeToStreamUtil { ErrorType.APPLICATION, ErrorTag.DATA_MISSING)); listener.setQueryParams( - notificationQueryParams.getStart(), - notificationQueryParams.getStop().orElse(null), - notificationQueryParams.getFilter().orElse(null), + notificationQueryParams.startTime(), + notificationQueryParams.stopTime(), + notificationQueryParams.filter(), false, notificationQueryParams.isSkipNotificationData()); final DOMDataBroker dataBroker = handlersHolder.getDataBroker(); @@ -200,7 +200,7 @@ abstract class SubscribeToStreamUtil { final MapEntryNode mapToStreams = RestconfMappingNodeUtil.mapDataChangeNotificationStreamByIetfRestconfMonitoring(listener.getPath(), - notificationQueryParams.getStart(), listener.getOutputType(), uri, schemaContext, serializedPath); + notificationQueryParams.startTime(), listener.getOutputType(), uri, schemaContext, serializedPath); final DOMDataTreeWriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction(); writeDataToDS(writeTransaction, mapToStreams); submitData(writeTransaction); diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/AbstractQueryParams.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/AbstractQueryParams.java index 9df8cb8e0c..ab644b406f 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/AbstractQueryParams.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/AbstractQueryParams.java @@ -48,30 +48,30 @@ abstract class AbstractQueryParams extends AbstractNotificationsData { } // FIXME: these should be final - private Instant start = null; - private Instant stop = null; + private Instant startTime = null; + private Instant stopTime = null; private String filter = null; private boolean leafNodesOnly = false; private boolean skipNotificationData = false; @VisibleForTesting public final Instant getStart() { - return start; + return startTime; } /** * Set query parameters for listener. * - * @param start Start-time of getting notification. - * @param stop Stop-time of getting notification. + * @param startTime Start-time of getting notification. + * @param stopTime Stop-time of getting notification. * @param filter Indicates which subset of all possible events are of interest. * @param leafNodesOnly If TRUE, notifications will contain changes of leaf nodes only. */ @SuppressWarnings("checkstyle:hiddenField") - public void setQueryParams(final Instant start, final Instant stop, final String filter, + public void setQueryParams(final Instant startTime, final Instant stopTime, final String filter, final boolean leafNodesOnly, final boolean skipNotificationData) { - this.start = requireNonNull(start); - this.stop = stop; + this.startTime = requireNonNull(startTime); + this.stopTime = stopTime; this.filter = filter; this.leafNodesOnly = leafNodesOnly; this.skipNotificationData = skipNotificationData; @@ -97,20 +97,20 @@ abstract class AbstractQueryParams extends AbstractNotificationsData { @SuppressWarnings("checkstyle:IllegalCatch") boolean checkStartStop(final Instant now, final T listener) { - if (this.stop != null) { - if (this.start.compareTo(now) < 0 && this.stop.compareTo(now) > 0) { + if (stopTime != null) { + if (startTime.compareTo(now) < 0 && stopTime.compareTo(now) > 0) { return true; } - if (this.stop.compareTo(now) < 0) { + if (stopTime.compareTo(now) < 0) { try { listener.close(); } catch (final Exception e) { throw new RestconfDocumentedException("Problem with unregister listener." + e); } } - } else if (this.start != null) { - if (this.start.compareTo(now) < 0) { - this.start = null; + } else if (startTime != null) { + if (startTime.compareTo(now) < 0) { + startTime = null; return true; } } else { @@ -125,8 +125,9 @@ abstract class AbstractQueryParams extends AbstractNotificationsData { * @param xml XML data of notification. */ @SuppressWarnings("checkstyle:IllegalCatch") + // FIXME: this method is never called, have we lost functionality compared to bierman02? boolean checkFilter(final String xml) { - if (this.filter == null) { + if (filter == null) { return true; } try { @@ -146,6 +147,6 @@ abstract class AbstractQueryParams extends AbstractNotificationsData { final Document docOfXml = DBF.newDocumentBuilder().parse(new InputSource(new StringReader(xml))); final XPath xPath = XPathFactory.newInstance().newXPath(); // FIXME: BUG-7956: xPath.setNamespaceContext(nsContext); - return (boolean) xPath.compile(this.filter).evaluate(docOfXml, XPathConstants.BOOLEAN); + return (boolean) xPath.compile(filter).evaluate(docOfXml, XPathConstants.BOOLEAN); } } diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationListenerAdapter.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationListenerAdapter.java index c7c0963d3a..806ee31d47 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationListenerAdapter.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationListenerAdapter.java @@ -80,9 +80,9 @@ public class NotificationListenerAdapter extends AbstractCommonSubscriber implem } @Override - public void setQueryParams(final Instant start, final Instant stop, final String filter, + public void setQueryParams(final Instant startTime, final Instant stopTime, final String filter, final boolean leafNodesOnly, final boolean skipNotificationData) { - super.setQueryParams(start, stop, filter, leafNodesOnly, skipNotificationData); + super.setQueryParams(startTime, stopTime, filter, leafNodesOnly, skipNotificationData); try { this.formatter = getFormatter(filter); } catch (XPathExpressionException e) { -- 2.36.6