View Javadoc
1   package au.gov.amsa.ais;
2   
3   import au.gov.amsa.util.SixBit;
4   import au.gov.amsa.util.SixBitException;
5   
6   /**
7    * Utility class for extracting parts of an ais message as unsigned integers,
8    * signed integers or strings.
9    * 
10   * @author dxm
11   * 
12   */
13  public class AisExtractor {
14  
15      private final boolean[] bitSet;
16      private final boolean[] calculated;
17      private final int padBits;
18      private final String message;
19  
20      /**
21       * Constructor. If message once decoded is less than minLength then throws
22       * {@link AisParseException}.
23       * 
24       * @param message
25       * @param minLength
26       */
27      public AisExtractor(String message, Integer minLength, int padBits) {
28          if (message.length() == 0)
29              throw new AisParseException("message length cannot be 0");
30          if (padBits > 6 || padBits < 0)
31              throw new AisParseException("padBits must be between 0 and 6");
32          this.message = message;
33          boolean[] bits = new boolean[message.length() * 6 - padBits];
34          boolean[] calculated = new boolean[message.length()];
35          this.bitSet = bits;
36          this.calculated = calculated;
37          this.padBits = padBits;
38          if (minLength != null && bitSet.length < minLength) {
39              throw new AisParseException(AisParseException.NOT_CONSISTENT_DECODED_STRING
40                      + ", length was " + bitSet.length + " and should be >=" + minLength);
41          }
42      }
43  
44      /**
45       * Returns the message id field (the first 6 characters of the decoded
46       * message).
47       * 
48       * @return
49       */
50      public int getMessageId() {
51          return getValue(0, 6);
52      }
53  
54      /**
55       * Returns an unsigned integer value using the bits from character position
56       * start to position stop in the decoded message.
57       * 
58       * @param from
59       * @param to
60       * @return
61       */
62      public synchronized int getValue(int from, int to) {
63          try {
64              // is synchronized so that values of bitSet and calculated can be
65              // lazily
66              // calculated and safely published (thread safe).
67              SixBit.convertSixBitToBits(message, padBits, bitSet, calculated, from, to);
68              return (int) SixBit.getValue(from, to, bitSet);
69          } catch (SixBitException | ArrayIndexOutOfBoundsException e) {
70              throw new AisParseException(e);
71          }
72      }
73  
74      /**
75       * Returns a signed integer value using the bits from character position
76       * start to position stop in the decoded message.
77       * 
78       * @param from
79       * @param to
80       * @return
81       */
82      public synchronized int getSignedValue(int from, int to) {
83          try {
84              // is synchronized so that values of bitSet and calculated can be
85              // lazily
86              // calculated and safely published (thread safe).
87              SixBit.convertSixBitToBits(message, padBits, bitSet, calculated, from, to);
88              return (int) SixBit.getSignedValue(from, to, bitSet);
89          } catch (SixBitException e) {
90              throw new AisParseException(e);
91          }
92      }
93  
94      public synchronized String getString(int from, int to) {
95          try {
96              // is synchronized so that values of bitSet and calculated can be
97              // lazily
98              // calculated and safely published (thread safe).
99              SixBit.convertSixBitToBits(message, padBits, bitSet, calculated, from, to);
100             return SixBit.getString(from, to, bitSet);
101         } catch (SixBitException e) {
102             throw new AisParseException(e);
103         }
104     }
105 
106 }