From: Robert Varga Date: Sun, 24 Oct 2021 12:19:24 +0000 (+0200) Subject: Use FilterParameter for communicating its value X-Git-Tag: v2.0.6~22 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=7a581ea80aeeb1194f1e77076e5bd044beb32bdb;p=netconf.git Use FilterParameter for communicating its value This improves type-safety and moves concerns. JIRA: NETCONF-773 Change-Id: I806563be3520feb31711b7e45f4956231b6e11b2 Signed-off-by: Robert Varga --- diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/FilterParameter.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/FilterParameter.java index 5c6aed3efe..2c2777081e 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/FilterParameter.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/FilterParameter.java @@ -10,12 +10,8 @@ package org.opendaylight.restconf.nb.rfc8040; import static java.util.Objects.requireNonNull; import java.net.URI; -import javax.xml.xpath.XPathExpressionException; import org.eclipse.jdt.annotation.NonNullByDefault; import org.opendaylight.yangtools.concepts.Immutable; -import org.opendaylight.yangtools.yang.xpath.api.YangXPathExpression; -import org.opendaylight.yangtools.yang.xpath.api.YangXPathMathMode; -import org.opendaylight.yangtools.yang.xpath.api.YangXPathParserFactory; /** * This class represents a {@code filter} parameter as defined in @@ -25,25 +21,25 @@ import org.opendaylight.yangtools.yang.xpath.api.YangXPathParserFactory; public final class FilterParameter implements Immutable { private static final URI CAPABILITY = URI.create("urn:ietf:params:restconf:capability:filter:1.0"); - private final YangXPathExpression value; + // FIXME: can we have a parsed, but not bound version of an XPath, please? + private final String value; - private FilterParameter(final YangXPathExpression value) { + private FilterParameter(final String value) { this.value = requireNonNull(value); } - public static FilterParameter forUriValue(final YangXPathParserFactory parserFactory, final String uriValue) - throws XPathExpressionException { - return new FilterParameter(parserFactory.newParser(YangXPathMathMode.EXACT).parseExpression(uriValue)); - } - - public YangXPathExpression value() { - return value; + public static FilterParameter forUriValue(final String uriValue) { + return new FilterParameter(uriValue); } public static String uriName() { return "filter"; } + public String uriValue() { + return value; + } + public static URI capabilityUri() { return CAPABILITY; } 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 e2d95d9fab..35cdea9e87 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,21 +8,13 @@ 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; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.time.format.DateTimeParseException; -import java.time.temporal.ChronoField; -import java.time.temporal.TemporalAccessor; import java.util.List; import java.util.Map.Entry; 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; @@ -36,7 +28,6 @@ import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload; import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfStreamsSubscriptionService; import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfStreamsConstants; import org.opendaylight.restconf.nb.rfc8040.streams.Configuration; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; @@ -167,33 +158,23 @@ public class RestconfStreamsSubscriptionServiceImpl implements RestconfStreamsSu * Parser and holder of query paramteres from uriInfo for notifications. */ public static final class NotificationQueryParams { - private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder() - .appendValue(ChronoField.YEAR, 4).appendLiteral('-') - .appendValue(ChronoField.MONTH_OF_YEAR, 2).appendLiteral('-') - .appendValue(ChronoField.DAY_OF_MONTH, 2).appendLiteral('T') - .appendValue(ChronoField.HOUR_OF_DAY, 2).appendLiteral(':') - .appendValue(ChronoField.MINUTE_OF_HOUR, 2).appendLiteral(':') - .appendValue(ChronoField.SECOND_OF_MINUTE, 2) - .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true) - .appendOffset("+HH:MM", "Z").toFormatter(); - - private final @NonNull Instant startTime; - private final Instant stopTime; - private final String filter; + private final StartTimeParameter startTime; + private final StopTimeParameter stopTime; + private final FilterParameter filter; private final boolean skipNotificationData; - private NotificationQueryParams(final Instant startTime, final Instant stopTime, final String filter, - final boolean skipNotificationData) { - this.startTime = requireNonNull(startTime); + private NotificationQueryParams(final StartTimeParameter startTime, final StopTimeParameter stopTime, + final FilterParameter filter, final boolean skipNotificationData) { + this.startTime = startTime; this.stopTime = stopTime; this.filter = filter; this.skipNotificationData = skipNotificationData; } static NotificationQueryParams fromUriInfo(final UriInfo uriInfo) { - Instant startTime = null; - Instant stopTime = null; - String filter = null; + StartTimeParameter startTime = null; + StopTimeParameter stopTime = null; + FilterParameter filter = null; boolean skipNotificationData = false; for (final Entry> entry : uriInfo.getQueryParameters().entrySet()) { @@ -204,7 +185,12 @@ public class RestconfStreamsSubscriptionServiceImpl implements RestconfStreamsSu case 0: break; case 1: - startTime = parseDateFromQueryParam(paramValues.get(0)); + final String str = paramValues.get(0); + try { + startTime = StartTimeParameter.forUriValue(str); + } catch (IllegalArgumentException e) { + throw new RestconfDocumentedException("Invalid start-time date: " + str, e); + } break; default: throw new RestconfDocumentedException("Start-time parameter can be used only once."); @@ -214,15 +200,19 @@ public class RestconfStreamsSubscriptionServiceImpl implements RestconfStreamsSu case 0: break; case 1: - stopTime = parseDateFromQueryParam(paramValues.get(0)); + final String str = paramValues.get(0); + try { + stopTime = StopTimeParameter.forUriValue(str); + } catch (IllegalArgumentException e) { + throw new RestconfDocumentedException("Invalid stop-time date: " + str, e); + } break; default: throw new RestconfDocumentedException("Stop-time parameter can be used only once."); } } else if (paramName.equals(FilterParameter.uriName())) { if (!paramValues.isEmpty()) { - // FIXME: use FilterParameter - filter = paramValues.get(0); + filter = FilterParameter.forUriValue(paramValues.get(0)); } } else if (paramName.equals("odl-skip-notification-data")) { switch (paramValues.size()) { @@ -243,26 +233,7 @@ public class RestconfStreamsSubscriptionServiceImpl implements RestconfStreamsSu throw new RestconfDocumentedException("Stop-time parameter has to be used with start-time parameter."); } - return new NotificationQueryParams(startTime == null ? Instant.now() : startTime, stopTime, filter, - skipNotificationData); - } - - - /** - * Parse input of query parameters - start-time or stop-time - from {@link DateAndTime} format - * to {@link Instant} format. - * - * @param uriValue Start-time or stop-time as string in {@link DateAndTime} format. - * @return Parsed {@link Instant} by entry. - */ - private static @NonNull Instant parseDateFromQueryParam(final String uriValue) { - final TemporalAccessor accessor; - try { - 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); + return new NotificationQueryParams(startTime, stopTime, filter, skipNotificationData); } /** @@ -270,7 +241,7 @@ public class RestconfStreamsSubscriptionServiceImpl implements RestconfStreamsSu * * @return start-time */ - public @NonNull Instant startTime() { + public @Nullable StartTimeParameter startTime() { return startTime; } @@ -279,7 +250,7 @@ public class RestconfStreamsSubscriptionServiceImpl implements RestconfStreamsSu * * @return stop-time */ - public @Nullable Instant stopTime() { + public @Nullable StopTimeParameter stopTime() { return stopTime; } @@ -288,7 +259,7 @@ public class RestconfStreamsSubscriptionServiceImpl implements RestconfStreamsSu * * @return filter */ - public @Nullable String filter() { + public @Nullable FilterParameter 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 e9ac883752..6d872c8227 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 @@ -140,7 +140,7 @@ abstract class SubscribeToStreamUtil { notificationListenerAdapter.setCloseVars(dataBroker, handlersHolder.getSchemaHandler()); final MapEntryNode mapToStreams = RestconfMappingNodeUtil.mapYangNotificationStreamByIetfRestconfMonitoring( notificationListenerAdapter.getSchemaPath().lastNodeIdentifier(), - schemaContext.getNotifications(), notificationQueryParams.startTime(), + schemaContext.getNotifications(), notificationListenerAdapter.getStart(), notificationListenerAdapter.getOutputType(), uri); // FIXME: how does this correlate with the transaction notificationListenerAdapter.close() will do? @@ -200,7 +200,7 @@ abstract class SubscribeToStreamUtil { final MapEntryNode mapToStreams = RestconfMappingNodeUtil.mapDataChangeNotificationStreamByIetfRestconfMonitoring(listener.getPath(), - notificationQueryParams.startTime(), listener.getOutputType(), uri, schemaContext, serializedPath); + listener.getStart(), 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 1e7ad2b5df..d9248e3cce 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 @@ -7,25 +7,43 @@ */ package org.opendaylight.restconf.nb.rfc8040.streams.listeners; -import static java.util.Objects.requireNonNull; - -import com.google.common.annotations.VisibleForTesting; import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoField; +import java.time.temporal.TemporalAccessor; +import javax.xml.xpath.XPathExpressionException; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime; /** * Features of query parameters part of both notifications. */ abstract class AbstractQueryParams extends AbstractNotificationsData { + private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder() + .appendValue(ChronoField.YEAR, 4).appendLiteral('-') + .appendValue(ChronoField.MONTH_OF_YEAR, 2).appendLiteral('-') + .appendValue(ChronoField.DAY_OF_MONTH, 2).appendLiteral('T') + .appendValue(ChronoField.HOUR_OF_DAY, 2).appendLiteral(':') + .appendValue(ChronoField.MINUTE_OF_HOUR, 2).appendLiteral(':') + .appendValue(ChronoField.SECOND_OF_MINUTE, 2) + .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true) + .appendOffset("+HH:MM", "Z").toFormatter(); + // FIXME: these should be final - private Instant startTime = null; - private Instant stopTime = null; + private Instant start = null; + private Instant stop = null; private boolean leafNodesOnly = false; private boolean skipNotificationData = false; - @VisibleForTesting public final Instant getStart() { - return startTime; + return start; } /** @@ -36,16 +54,40 @@ abstract class AbstractQueryParams extends AbstractNotificationsData { * @param filter Indicates which subset of all possible events are of interest. * @param leafNodesOnly If TRUE, notifications will contain changes of leaf nodes only. */ - public abstract void setQueryParams(Instant startTime, Instant stopTime, String filter, - boolean leafNodesOnly, boolean skipNotificationData); - @SuppressWarnings("checkstyle:hiddenField") - final void setQueryParams(final Instant startTime, final Instant stopTime, final boolean leafNodesOnly, - final boolean skipNotificationData) { - this.startTime = requireNonNull(startTime); - this.stopTime = stopTime; + public final void setQueryParams(final StartTimeParameter startTime, final StopTimeParameter stopTime, + final FilterParameter filter, final boolean leafNodesOnly, final boolean skipNotificationData) { + start = startTime == null ? Instant.now() : parseDateAndTime(startTime.value()); + stop = stopTime == null ? null : parseDateAndTime(stopTime.value()); this.leafNodesOnly = leafNodesOnly; this.skipNotificationData = skipNotificationData; + + if (filter != null) { + try { + setFilter(filter.uriValue()); + } catch (XPathExpressionException e) { + throw new IllegalArgumentException("Failed to get filter", e); + } + } + } + + abstract void setFilter(@Nullable String xpathString) throws XPathExpressionException; + + /** + * Parse input of query parameters - start-time or stop-time - from {@link DateAndTime} format + * to {@link Instant} format. + * + * @param uriValue Start-time or stop-time as string in {@link DateAndTime} format. + * @return Parsed {@link Instant} by entry. + */ + private static @NonNull Instant parseDateAndTime(final DateAndTime dateAndTime) { + final TemporalAccessor accessor; + try { + accessor = FORMATTER.parse(dateAndTime.getValue()); + } catch (final DateTimeParseException e) { + throw new RestconfDocumentedException("Cannot parse of value in date: " + dateAndTime, e); + } + return Instant.from(accessor); } /** @@ -68,20 +110,20 @@ abstract class AbstractQueryParams extends AbstractNotificationsData { @SuppressWarnings("checkstyle:IllegalCatch") boolean checkStartStop(final Instant now, final T listener) { - if (stopTime != null) { - if (startTime.compareTo(now) < 0 && stopTime.compareTo(now) > 0) { + if (stop != null) { + if (start.compareTo(now) < 0 && stop.compareTo(now) > 0) { return true; } - if (stopTime.compareTo(now) < 0) { + if (stop.compareTo(now) < 0) { try { listener.close(); } catch (final Exception e) { throw new RestconfDocumentedException("Problem with unregister listener." + e); } } - } else if (startTime != null) { - if (startTime.compareTo(now) < 0) { - startTime = null; + } else if (start != null) { + if (start.compareTo(now) < 0) { + start = null; return true; } } else { diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/ListenerAdapter.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/ListenerAdapter.java index 416a4c6271..8094d7be44 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/ListenerAdapter.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/ListenerAdapter.java @@ -78,20 +78,10 @@ public class ListenerAdapter extends AbstractCommonSubscriber implements Cluster } } - private DataTreeCandidateFormatter getFormatter(final String filter) throws XPathExpressionException { - final DataTreeCandidateFormatterFactory factory = getFormatterFactory(); - return filter == null || filter.isEmpty() ? factory.getFormatter() : factory.getFormatter(filter); - } - @Override - public void setQueryParams(final Instant startTime, final Instant stopTime, final String filter, - final boolean leafNodesOnly, final boolean skipNotificationData) { - setQueryParams(startTime, stopTime, leafNodesOnly, skipNotificationData); - try { - formatter = getFormatter(filter); - } catch (final XPathExpressionException e) { - throw new IllegalArgumentException("Failed to get filter", e); - } + final void setFilter(final String filter) throws XPathExpressionException { + final DataTreeCandidateFormatterFactory factory = getFormatterFactory(); + formatter = filter == null || filter.isEmpty() ? factory.getFormatter() : factory.getFormatter(filter); } @Override 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 ce76d77ed5..3fc2c7af47 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 @@ -15,6 +15,7 @@ import com.google.common.base.MoreObjects; import java.time.Instant; import java.util.Optional; import javax.xml.xpath.XPathExpressionException; +import org.eclipse.jdt.annotation.Nullable; import org.opendaylight.mdsal.dom.api.DOMNotification; import org.opendaylight.mdsal.dom.api.DOMNotificationListener; import org.opendaylight.mdsal.dom.api.DOMNotificationService; @@ -74,20 +75,10 @@ public class NotificationListenerAdapter extends AbstractCommonSubscriber implem } } - private NotificationFormatter getFormatter(final String filter) throws XPathExpressionException { - NotificationFormatterFactory factory = getFormatterFactory(); - return filter == null || filter.isEmpty() ? factory.getFormatter() : factory.getFormatter(filter); - } - @Override - public void setQueryParams(final Instant startTime, final Instant stopTime, final String filter, - final boolean leafNodesOnly, final boolean skipNotificationData) { - setQueryParams(startTime, stopTime, leafNodesOnly, skipNotificationData); - try { - formatter = getFormatter(filter); - } catch (XPathExpressionException e) { - throw new IllegalArgumentException("Failed to get filter", e); - } + final void setFilter(final @Nullable String filter) throws XPathExpressionException { + final NotificationFormatterFactory factory = getFormatterFactory(); + formatter = filter == null || filter.isEmpty() ? factory.getFormatter() : factory.getFormatter(filter); } /** diff --git a/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/ListenerAdapterTest.java b/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/ListenerAdapterTest.java index 6d8999c3ea..aa1bab6682 100644 --- a/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/ListenerAdapterTest.java +++ b/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/ListenerAdapterTest.java @@ -7,7 +7,6 @@ */ package org.opendaylight.restconf.nb.rfc8040.streams.listeners; -import static java.time.Instant.EPOCH; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; @@ -35,6 +34,7 @@ import org.opendaylight.mdsal.dom.api.DOMDataBroker; import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService; import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier; import org.opendaylight.mdsal.dom.api.DOMSchemaService; +import org.opendaylight.restconf.nb.rfc8040.StartTimeParameter; import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler; import org.opendaylight.yang.gen.v1.instance.identifier.patch.module.rev151121.PatchCont; import org.opendaylight.yang.gen.v1.instance.identifier.patch.module.rev151121.patch.cont.MyList1; @@ -120,12 +120,13 @@ public class ListenerAdapterTest extends AbstractConcurrentDataBrokerTest { final NotificationOutputTypeGrouping.NotificationOutputType outputType, final boolean leafNodesOnly, final boolean skipNotificationData) { super(path, streamName, outputType); - setQueryParams(EPOCH, null, null, leafNodesOnly, skipNotificationData); + setQueryParams(StartTimeParameter.forUriValue("1970-01-01T00:00:00Z"), null, null, leafNodesOnly, + skipNotificationData); } @Override protected void post(final String data) { - this.lastNotification = data; + lastNotification = data; notificationLatch.countDown(); } @@ -140,11 +141,11 @@ public class ListenerAdapterTest extends AbstractConcurrentDataBrokerTest { LOG.info("Comparing: \n{}\n{}", json, withFakeDate); JSONAssert.assertEquals(json, withFakeDate, false); - this.lastNotification = null; + lastNotification = null; notificationLatch = new CountDownLatch(1); } - public void assertXmlSimilar(String xml) { + public void assertXmlSimilar(final String xml) { awaitUntillNotification(xml); LOG.info("lastNotification: {}", lastNotification); @@ -152,11 +153,11 @@ public class ListenerAdapterTest extends AbstractConcurrentDataBrokerTest { LOG.info("Comparing: \n{}\n{}", xml, withFakeDate); XmlAssert.assertThat(xml).and(withFakeDate).ignoreWhitespace().ignoreChildNodesOrder().areSimilar(); - this.lastNotification = null; + lastNotification = null; notificationLatch = new CountDownLatch(1); } - public String awaitUntillNotification(String xml) { + public String awaitUntillNotification(final String xml) { // FIXME: use awaitility if (!Uninterruptibles.awaitUninterruptibly(notificationLatch, 500, TimeUnit.SECONDS)) { fail("Timed out waiting for notification for: " + xml); @@ -180,7 +181,7 @@ public class ListenerAdapterTest extends AbstractConcurrentDataBrokerTest { return doc.toString(); } - static String withFakeXmlDate(String in) { + static String withFakeXmlDate(final String in) { return in.replaceAll(".*", "someDate"); }