1 package au.gov.amsa.ais.message;
2
3 import com.google.common.annotations.VisibleForTesting;
4 import com.google.common.base.Optional;
5
6 import au.gov.amsa.ais.AisExtractor;
7 import au.gov.amsa.ais.AisExtractorFactory;
8 import au.gov.amsa.ais.Util;
9
10 public class AisBStaticDataReportPartB extends AbstractAisBStaticDataReport {
11
12 private final static int MESSAGE_LENGTH = 168;
13
14 private final static String CALL_SIGN_NOT_AVAILABLE = "@@@@@@@";
15 private final static int DIMENSION_ZERO = 0;
16
17 private final int shipType;
18 private final String vendorManufacturerId;
19 private final int vendorUnitModelCode;
20 private final int vendorUnitSerialNumber;
21 private final Optional<String> callsign;
22 private final Optional<Integer> dimensionA;
23 private final Optional<Integer> dimensionB;
24 private final Optional<Integer> dimensionC;
25 private final Optional<Integer> dimensionD;
26
27 public AisBStaticDataReportPartB(String message, int padBits) {
28 this(message, null, padBits);
29 }
30
31 public AisBStaticDataReportPartB(String message, String source, int padBits) {
32 this(Util.getAisExtractorFactory(), message, source, padBits);
33 }
34
35 public AisBStaticDataReportPartB(AisExtractorFactory factory, String message, String source,
36 int padBits) {
37 super(PART_NUMBER_B,
38 factory,
39 source,
40 factory.create(message, MESSAGE_LENGTH, padBits));
41
42 shipType = extractShipType(getExtractor());
43 vendorManufacturerId = extractVendorManufacturerId(getExtractor());
44 vendorUnitModelCode = extractVendorUnitModelCode(getExtractor());
45 vendorUnitSerialNumber = extractVendorUnitSerialNumber(getExtractor());
46 callsign = extractCallSign(getExtractor());
47 dimensionA = extractDimensionA(getExtractor());
48 dimensionB = extractDimensionB(getExtractor());
49 dimensionC = extractDimensionC(getExtractor());
50 dimensionD = extractDimensionD(getExtractor());
51 }
52
53 @VisibleForTesting
54 static int extractShipType(AisExtractor extractor) {
55 return extractor.getValue(40, 48);
56 }
57
58 @VisibleForTesting
59 static String extractVendorManufacturerId(AisExtractor extractor) {
60 return extractor.getString(48, 66);
61 }
62
63 @VisibleForTesting
64 static int extractVendorUnitModelCode(AisExtractor extractor) {
65 return extractor.getValue(66, 70);
66 }
67
68 @VisibleForTesting
69 static int extractVendorUnitSerialNumber(AisExtractor extractor) {
70 return extractor.getValue(70, 90);
71 }
72
73 @VisibleForTesting
74 static Optional<String> extractCallSign(AisExtractor extractor) {
75
76 String value = extractor.getString(90, 132);
77 if(CALL_SIGN_NOT_AVAILABLE.contentEquals(value)) {
78 return Optional.absent();
79 } else {
80 return Optional.of(value);
81 }
82 }
83
84 @VisibleForTesting
85 static Optional<Integer> extractDimensionA(AisExtractor extractor) {
86 int value = extractor.getValue(132, 141);
87
88 return value != DIMENSION_ZERO ? Optional.of(value) : Optional.absent();
89 }
90
91 @VisibleForTesting
92 static Optional<Integer> extractDimensionB(AisExtractor extractor) {
93 int value = extractor.getValue(141, 150);
94
95 return value != DIMENSION_ZERO ? Optional.of(value) : Optional.absent();
96 }
97
98 @VisibleForTesting
99 static Optional<Integer> extractDimensionC(AisExtractor extractor) {
100 int value = extractor.getValue(150, 156);
101
102 return value != DIMENSION_ZERO ? Optional.of(value) : Optional.absent();
103 }
104
105 @VisibleForTesting
106 static Optional<Integer> extractDimensionD(AisExtractor extractor) {
107 int value = extractor.getValue(156, 162);
108
109 return value != DIMENSION_ZERO ? Optional.of(value) : Optional.absent();
110 }
111
112 @Override
113 public String toString() {
114 StringBuilder builder = new StringBuilder();
115 builder.append("AisPositionBStaticPartB [source=");
116 builder.append(getSource());
117 builder.append(", messageId=");
118 builder.append(getMessageId());
119 builder.append(", mmsi=");
120 builder.append(getMmsi());
121 builder.append(", repeatIndicator=");
122 builder.append(getRepeatIndicator());
123 builder.append(", partNumber=");
124 builder.append(getPartNumber());
125 builder.append(", typeOfShipAndCargoType=");
126 builder.append(getShipType());
127 builder.append(", vendorManufacturerId=");
128 builder.append(getVendorManufacturerId());
129 builder.append(", vendorUnitModelCode=");
130 builder.append(getVendorUnitModelCode());
131 builder.append(", vendorUnitSerialNumber=");
132 builder.append(getVendorUnitSerialNumber());
133 builder.append(", callSign=");
134 builder.append(getCallsign());
135 builder.append(", dimensionA=");
136 builder.append(getDimensionA());
137 builder.append(", dimensionB=");
138 builder.append(getDimensionB());
139 builder.append(", dimensionC=");
140 builder.append(getDimensionC());
141 builder.append(", dimensionD=");
142 builder.append(getDimensionD());
143 builder.append("]");
144 return builder.toString();
145 }
146
147 public int getShipType() {
148 return shipType;
149 }
150
151 public Optional<String> getCallsign() {
152 return callsign;
153 }
154
155 public Optional<Integer> getDimensionA() {
156
157 if(dimensionA.or(DIMENSION_ZERO)==DIMENSION_ZERO &&
158 dimensionB.or(DIMENSION_ZERO)==DIMENSION_ZERO) {
159 return Optional.absent();
160 } else {
161 return dimensionA;
162 }
163 }
164
165 public Optional<Integer> getDimensionB() {
166 if(dimensionA.or(DIMENSION_ZERO)==DIMENSION_ZERO &&
167 dimensionB.or(DIMENSION_ZERO)==DIMENSION_ZERO) {
168 return Optional.absent();
169 } else {
170 return dimensionB;
171 }
172 }
173
174 public Optional<Integer> getDimensionC() {
175 if(dimensionC.or(DIMENSION_ZERO)==DIMENSION_ZERO &&
176 dimensionD.or(DIMENSION_ZERO)==DIMENSION_ZERO) {
177 return Optional.absent();
178 } else {
179 return dimensionC;
180 }
181 }
182
183 public Optional<Integer> getDimensionD() {
184 if(dimensionC.or(DIMENSION_ZERO)==DIMENSION_ZERO &&
185 dimensionD.or(DIMENSION_ZERO)==DIMENSION_ZERO) {
186 return Optional.absent();
187 } else {
188 return dimensionD;
189 }
190 }
191
192 public Optional<Integer> getLengthMetres() {
193 Optional<Integer> a = getDimensionA();
194 if (!a.isPresent()) {
195 return Optional.absent();
196 }
197 Optional<Integer> b = getDimensionB();
198 if (!b.isPresent()) {
199 return Optional.absent();
200 }
201 return Optional.of(a.get() + b.get());
202 }
203
204 public Optional<Integer> getWidthMetres() {
205 Optional<Integer> c = getDimensionC();
206 if (!c.isPresent()) {
207 return Optional.absent();
208 }
209 Optional<Integer> d = getDimensionD();
210 if (!d.isPresent()) {
211 return Optional.absent();
212 }
213 return Optional.of(c.get() + d.get());
214 }
215
216 public String getVendorManufacturerId() {
217 return vendorManufacturerId;
218 }
219
220 public Integer getVendorUnitModelCode() {
221 return vendorUnitModelCode;
222 }
223
224 public Integer getVendorUnitSerialNumber() {
225 return vendorUnitSerialNumber;
226 }
227 }