1   /* Copyright 2002-2025 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.gnss.metric.ntrip;
18  
19  import org.orekit.gnss.metric.messages.ParsedMessage;
20  
21  /** Interface for objects that needs to be notified when new encoded messages are available.
22   * @author Luc Maisonobe
23   * @since 11.0
24   */
25  public interface MessageObserver {
26  
27      /** Notify that an encoded message is available.
28       * <p>
29       * Beware that this method <em>will</em> be called from an internal
30       * dedicated stream-reading thread. Implementations <em>must</em>
31       * take to:
32       * </p>
33       * <ul>
34       *   <li>not perform long processing there to avoid blocking the stream-reading thread</li>
35       *   <li>take care of thread-safety when extracting data from the message</li>
36       * </ul>
37       * <p>
38       * The only filtering that can be specified when {@link
39       * NtripClient#addObserver(int, String, MessageObserver) adding} an observer to a
40       * {@link NtripClient} is based on message type and mount point. If additional filtering
41       * is needed (for example on message content like satellites ids, it must be performed
42       * by the observer itself when notified (see example below).
43       * </p>
44       * <p>
45       * The recommended way to implement this method is to simply build a domain object
46       * from the message fields (for example a gnss propagator) and to store it in the
47       * observer class as an instance field using a {@link java.util.concurrent.atomic.AtomicReference
48       * AtomicReference} as follows:
49       * </p>
50       * <pre>
51       * public class GPSProvider implements PVCoordinatesProvider, RTCMMessageObserver {
52       *
53       *     private final int                                filteringId;
54       *     private final AtomicReference&lt;GPSPropagator&gt; propagator;
55       *
56       *     public void messageAvailable(String mountPoint, ParsedMessage message) {
57       *         MessageXXX msg = (MessageXXX) message;
58       *         GPSPropagator oldPropagator = propagator.get();
59       *         if (msg.getSatId() == filteringId) {
60       *             GPSPropagator newPropagator = new GPSPropagator(msg.get...(),
61       *                                                             msg.get...(),
62       *                                                             msg.get...());
63       *             // only set propagator if no other observer was notified
64       *             // while we were asleep
65       *             propagator.compareAndSet(oldPropagator, newPropagator);
66       *         }
67       *     }
68       *
69       *     public TimeStampedPVCoordinates getPVCoordinates(AbsoluteDate date, Frame frame) {
70       *         GPSPropagator lastAvailablePropagator = propagator.get();
71       *         // use the retrieved propagator to compute position-velocity
72       *     }
73       *
74       * }
75       * </pre>
76       * @param mountPoint mount point from which the message comes
77       * @param message last available message
78       */
79      void messageAvailable(String mountPoint, ParsedMessage message);
80  
81  }