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 }