diff --git a/src/main/java/net/sf/marineapi/provider/AbstractProvider.java b/src/main/java/net/sf/marineapi/provider/AbstractProvider.java index 06c9d4ce..96ef7bea 100644 --- a/src/main/java/net/sf/marineapi/provider/AbstractProvider.java +++ b/src/main/java/net/sf/marineapi/provider/AbstractProvider.java @@ -1,20 +1,20 @@ -/* +/* * AbstractProvider.java * Copyright (C) 2011 Kimmo Tuukkanen - * + * * This file is part of Java Marine API. * - * + * * Java Marine API is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. - * + * * Java Marine API is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with Java Marine API. If not, see . */ @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import net.sf.marineapi.nmea.event.SentenceEvent; import net.sf.marineapi.nmea.event.SentenceListener; @@ -56,7 +57,7 @@ public abstract class AbstractProvider implements /** * Creates a new instance of AbstractProvider. - * + * * @param reader Sentence reader to be used as data source * @param ids Types of sentences to capture for creating provider events */ @@ -69,7 +70,7 @@ public AbstractProvider(SentenceReader reader, String... ids) { /** * Creates a new instance of AbstractProvider. - * + * * @param reader Sentence reader to be used as data source * @param ids Types of sentences to capture for creating provider events */ @@ -82,7 +83,7 @@ public AbstractProvider(SentenceReader reader, SentenceId... ids) { /** * Inserts a listener to provider. - * + * * @param listener Listener to add */ public void addListener(ProviderListener listener) { @@ -91,14 +92,14 @@ public void addListener(ProviderListener listener) { /** * Creates a {@code ProviderEvent} of type {@code T}. - * + * * @return Created event, or null if failed. */ protected abstract T createProviderEvent(); /** * Dispatch the TPV event to all listeners. - * + * * @param event TPVUpdateEvent to dispatch */ private void fireProviderEvent(T event) { @@ -109,7 +110,7 @@ private void fireProviderEvent(T event) { /** * Returns the collected sentences. - * + * * @return List of sentences. */ protected final List getSentences() { @@ -122,7 +123,7 @@ protected final List getSentences() { /** * Tells if the provider has captured all the specified sentences. - * + * * @param id Sentence type IDs to look for. * @return True if all specified IDs match the captured sentences. */ @@ -138,7 +139,7 @@ protected final boolean hasAll(String... id) { /** * Tells if the provider has captured at least one of the specified * sentences. - * + * * @param id Sentence type IDs to look for, in prioritized order. * @return True if any of the specified IDs matches the type of at least one * captured sentences. @@ -156,7 +157,7 @@ protected final boolean hasOne(String... id) { /** * Tells if provider has captured the required sentences for creating new * ProviderEvent. - * + * * @return true if ready to create ProviderEvent, otherwise false. */ protected abstract boolean isReady(); @@ -164,7 +165,7 @@ protected final boolean hasOne(String... id) { /** * Tells if the captured sentence events contain valid data to be dispatched * to ProviderListeners. - * + * * @return true if valid, otherwise false. */ protected abstract boolean isValid(); @@ -196,7 +197,7 @@ public void readingStopped() { /** * Removes the specified listener from provider. - * + * * @param listener Listener to remove */ public void removeListener(ProviderListener listener) { @@ -210,6 +211,19 @@ private void reset() { events.clear(); } + /** + * Expunge collected events that are older than {@code timeout} to prevent + * the {@code events} list growing when sentences are being delivered + * without valid data (e.g. during device warm-up or offline state). + */ + private void expunge() { + long now = System.currentTimeMillis(); + List expired = this.events.stream() + .filter(event -> now - event.getTimeStamp() > this.timeout) + .collect(Collectors.toList()); + this.events.removeAll(expired); + } + /* * (non-Javadoc) * @see net.sf.marineapi.nmea.event.SentenceListener#sentenceRead( @@ -223,6 +237,8 @@ public void sentenceRead(SentenceEvent event) { fireProviderEvent(pEvent); } reset(); + } else { + expunge(); } } @@ -249,7 +265,7 @@ public void setTimeout(int millis) { * Validates the collected sentences by checking the ages of each sentence * and then by calling {@link #isValid()}. If extending implementation has * no validation criteria, it should return always {@code true}. - * + * * @return true if valid, otherwise false */ private boolean validate() {