001 /* 002 * $Id: LocalAddeEntry.java,v 1.33 2012/02/19 17:35:49 davep Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2012 007 * Space Science and Engineering Center (SSEC) 008 * University of Wisconsin - Madison 009 * 1225 W. Dayton Street, Madison, WI 53706, USA 010 * https://www.ssec.wisc.edu/mcidas 011 * 012 * All Rights Reserved 013 * 014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 015 * some McIDAS-V source code is based on IDV and VisAD source code. 016 * 017 * McIDAS-V is free software; you can redistribute it and/or modify 018 * it under the terms of the GNU Lesser Public License as published by 019 * the Free Software Foundation; either version 3 of the License, or 020 * (at your option) any later version. 021 * 022 * McIDAS-V is distributed in the hope that it will be useful, 023 * but WITHOUT ANY WARRANTY; without even the implied warranty of 024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 025 * GNU Lesser Public License for more details. 026 * 027 * You should have received a copy of the GNU Lesser Public License 028 * along with this program. If not, see http://www.gnu.org/licenses. 029 */ 030 package edu.wisc.ssec.mcidasv.servermanager; 031 032 import java.util.Collections; 033 import java.util.List; 034 import java.util.Map; 035 036 import org.slf4j.Logger; 037 import org.slf4j.LoggerFactory; 038 039 import edu.wisc.ssec.mcidasv.servermanager.AddeEntry.EntryType; 040 041 /** 042 * 043 * 044 * 045 */ 046 public class LocalAddeEntry implements AddeEntry { 047 048 /** Friendly neighborhood logging object. */ 049 static final Logger logger = LoggerFactory.getLogger(LocalAddeEntry.class); 050 051 /** Represents a {@literal "bad"} local ADDE entry. */ 052 // seriously, don't use null unless you REALLY need it. 053 public static final LocalAddeEntry INVALID_ENTRY = new Builder("INVALID", "INVALID", "/dev/null", AddeFormat.INVALID).build(); 054 055 /** Represents a {@literal "bad"} collection of local ADDE entries. */ 056 public static final List<LocalAddeEntry> INVALID_ENTRIES = Collections.singletonList(INVALID_ENTRY); 057 058 /** */ 059 private static final String CYGWIN_PREFIX = "/cygdrive/"; 060 061 /** */ 062 private static final int CYGWIN_PREFIX_LEN = CYGWIN_PREFIX.length(); 063 064 /** */ 065 private EntryStatus entryStatus = EntryStatus.INVALID; 066 067 // RESOLV.SRV FIELDS 068 /** N1 */ 069 private final String group; 070 071 /** N2 */ 072 // this value is built in a non-obvious way. plz to be dox. 073 private final String descriptor; 074 075 /** RT */ 076 private final boolean realtime; 077 078 /** MCV */ 079 private final AddeFormat format; 080 081 /** R1 */ 082 private final String start; 083 084 /** R2 */ 085 private final String end; 086 087 /** MASK */ 088 private final String fileMask; 089 090 /** C */ 091 private final String name; 092 // END RESOLV.SRV FIELDS 093 094 private String asStringId; 095 096 public enum ServerName { 097 AREA, AMSR, AMRR, GINI, FSDX, OMTP, LV1B, MODS, MODX, MOD4, MOD8, 098 MODR, MSGT, MTST, SMIN, TMIN, MD, INVALID; 099 } 100 101 /** 102 * The various kinds of local ADDE data understood by McIDAS-V, along with 103 * some helpful metadata. 104 * 105 * <p><ul> 106 * <li>{@literal "Human readable"} format names ({@link #friendlyName}).</li> 107 * <li>Optional tooltip description ({@link #tooltip}).</li> 108 * <li>Type of data ({@link #type}).</li> 109 * <li>File naming pattern {@link #fileFilter}.</li> 110 * </ul> 111 * 112 * <p>None of {@code AddeFormat}'s fields should contain {@code null}. 113 */ 114 public enum AddeFormat { 115 MCIDAS_AREA(ServerName.AREA, "McIDAS AREA"), 116 MCIDAS_MD(ServerName.MD, "McIDAS MD", "McIDAS MD", EntryType.POINT), 117 AMSRE_L1B(ServerName.AMSR, "AMSR-E L 1b", "AMSR-E Level 1b"), 118 AMSRE_RAIN_PRODUCT(ServerName.AMRR, "AMSR-E Rain Product"), 119 GINI(ServerName.GINI, "GINI"), 120 LRIT_GOES9(ServerName.FSDX, "LRIT GOES-9", "EUMETCast LRIT GOES-9"), 121 LRIT_GOES10(ServerName.FSDX, "LRIT GOES-10", "EUMETCast LRIT GOES-10"), 122 LRIT_GOES11(ServerName.FSDX, "LRIT GOES-11", "EUMETCast LRIT GOES-11"), 123 LRIT_GOES12(ServerName.FSDX, "LRIT GOES-12", "EUMETCast LRIT GOES-12"), 124 LRIT_MET5(ServerName.FSDX, "LRIT MET-5", "EUMETCast LRIT MET-5"), 125 LRIT_MET7(ServerName.FSDX, "LRIT MET-7", "EUMETCast LRIT MET-7"), 126 LRIT_MTSAT1R(ServerName.FSDX, "LRIT MTSAT-1R", "EUMETCast LRIT MTSAT-1R"), 127 METEOSAT_OPENMTP(ServerName.OMTP, "Meteosat OpenMTP"), 128 METOP_AVHRR_L1B(ServerName.LV1B, "Metop AVHRR L 1b", "Metop AVHRR Level 1b"), 129 MODIS_L1B_MOD02(ServerName.MODS, "MODIS MOD 02 - Level-1B Calibrated Geolocated Radiances", "MODIS Level 1b"), 130 MODIS_L2_MOD06(ServerName.MODX, "MODIS MOD 06 - Cloud Product", "MODIS Level 2 (Cloud Top Properties)"), 131 MODIS_L2_MOD07(ServerName.MODX, "MODIS MOD 07 - Atmospheric Profiles", "MODIS Level 2 (Atmospheric Profile)"), 132 MODIS_L2_MOD35(ServerName.MODX, "MODIS MOD 35 - Cloud Mask", "MODIS Level 2 (Cloud Mask)"), 133 MODIS_L2_MOD04(ServerName.MOD4, "MODIS MOD 04 - Aerosol Product", "MODIS Level 2 (Aerosol)"), 134 MODIS_L2_MOD28(ServerName.MOD8, "MODIS MOD 28 - Sea Surface Temperature", "MODIS Level 2 (Sea Surface Temperature)"), 135 MODIS_L2_MODR(ServerName.MODR, "MODIS MOD R - Corrected Reflectance", "MODIS Level 2 (Corrected Reflectance)"), 136 MSG_HRIT_FD(ServerName.MSGT, "MSG HRIT FD", "MSG HRIT (Full Disk)"), 137 MSG_HRIT_HRV(ServerName.MSGT, "MSG HRIT HRV", "MSG HRIT (High Resolution Visible)"), 138 MTSAT_HRIT(ServerName.MTST, "MTSAT HRIT"), 139 NOAA_AVHRR_L1B(ServerName.LV1B, "NOAA AVHRR L 1b", "NOAA AVHRR Level 1b"), 140 SSMI(ServerName.SMIN, "SSMI", "Terrascan netCDF (SMIN)"), 141 TRMM(ServerName.TMIN, "TRMM", "Terrascan netCDF (TMIN)"), 142 INVALID(ServerName.INVALID, "", "", EntryType.INVALID); 143 144 /** Name of the McIDAS-X server. */ 145 private final ServerName servName; 146 147 /** {@literal "Human readable"} format name. This is returned by {@link #toString()}. */ 148 private final String friendlyName; 149 150 /** Description of the format. */ 151 private final String tooltip; 152 153 /** Data type. Corresponds to {@code TYPE} in {@literal "RESOLV.SRV"}. */ 154 private final EntryType type; 155 156 /** 157 * Filename pattern used when listing files in a directory. 158 * If {@link #servName} is {@link ServerName#MSGT} then 159 * {@literal "*PRO*"} is used, otherwise {@literal "*"}. 160 */ 161 private final String fileFilter; 162 163 /** 164 * Builds an {@literal "ADDE format"} and its associated metadata in 165 * a typesafe way. 166 * 167 * @param servName {@link ServerName} that McIDAS-X uses for this format. 168 * @param friendlyName {@literal "Human readable"} name of the format; returned by {@link #toString()}. 169 * @param tooltip If non-empty, this is used as a tooltip in the local entry editor. 170 * @param type {@link EntryType} used by this format. 171 */ 172 private AddeFormat(final ServerName servName, final String friendlyName, final String tooltip, final EntryType type) { 173 this.servName = servName; 174 this.friendlyName = friendlyName; 175 this.tooltip = tooltip; 176 this.type = type; 177 this.fileFilter = (servName != ServerName.MSGT) ? "*" : "*PRO*"; 178 } 179 180 /** 181 * Builds an {@literal "imagery ADDE Format"} <b>without</b> a tooltip. 182 * 183 * @param servName {@link ServerName} that McIDAS-X uses for this format. 184 * @param friendlyName {@literal "Human readable"} name of the format; returned by {@link #toString()}. 185 */ 186 private AddeFormat(final ServerName servName, final String friendlyName) { 187 this(servName, friendlyName, "", EntryType.IMAGE); 188 } 189 190 /** 191 * Builds an {@literal "imagery ADDE Format"} <b>with</b> a tooltip. 192 * 193 * @param servName {@link ServerName} that McIDAS-X uses for this format. 194 * @param friendlyName {@literal "Human readable"} name of the format; returned by {@link #toString()}. 195 * @param tooltip If non-empty, this is used as a tooltip in the local entry editor. 196 */ 197 private AddeFormat(final ServerName servName, final String friendlyName, final String tooltip) { 198 this(servName, friendlyName, tooltip, EntryType.IMAGE); 199 } 200 201 /** 202 * Gets the McIDAS-X {@link ServerName} for this format. 203 * 204 * @return Either the name of this format's McIDAS-X server, or {@link ServerName#INVALID}. 205 */ 206 public ServerName getServerName() { 207 return servName; 208 } 209 210 /** 211 * Gets the tooltip text to use in the server manager GUI for this 212 * format. 213 * 214 * @return Text to use as a GUI tooltip. Cannot be {@code null}, though 215 * empty {@code String} values are permitted. 216 */ 217 public String getTooltip() { 218 return tooltip; 219 } 220 221 /** 222 * Gets the type of data used by this format. This value dictates the 223 * chooser(s) where this format can appear. 224 * 225 * @return One of {@link EntryType}, or {@link EntryType#INVALID}. 226 */ 227 public EntryType getType() { 228 return type; 229 } 230 231 /** 232 * Gets the string used to filter out files that match this format. 233 * 234 * @return Either a specialized {@code String}, like {@literal "*PRO*"} or {@literal "*"}. 235 */ 236 public String getFileFilter() { 237 return fileFilter; 238 } 239 240 /** 241 * Gets the {@code String} representation of this format. 242 * 243 * @return the value of {@link #friendlyName}. 244 */ 245 @Override public String toString() { 246 return friendlyName; 247 } 248 } 249 250 /** 251 * 252 * 253 * @param builder 254 * 255 * @see LocalAddeEntry.Builder 256 */ 257 private LocalAddeEntry(final Builder builder) { 258 this.group = builder.group; 259 this.descriptor = builder.descriptor; 260 this.realtime = builder.realtime; 261 this.format = builder.format; 262 this.fileMask = builder.mask; 263 this.name = builder.name; 264 this.start = builder.start; 265 this.end = builder.end; 266 this.entryStatus = builder.status; 267 logger.debug("created local: {}", this); 268 } 269 270 @Override public AddeAccount getAccount() { 271 return RemoteAddeEntry.DEFAULT_ACCOUNT; 272 } 273 274 @Override public String getAddress() { 275 return "localhost"; 276 } 277 278 @Override public EntrySource getEntrySource() { 279 return EntrySource.USER; 280 } 281 282 @Override public EntryStatus getEntryStatus() { 283 return entryStatus; 284 } 285 286 @Override public String getEntryText() { 287 return "localhost/"+getGroup(); 288 } 289 290 @Override public EntryType getEntryType() { 291 return format.getType(); 292 } 293 294 @Override public EntryValidity getEntryValidity() { 295 return (isValid()) ? EntryValidity.VERIFIED : EntryValidity.INVALID; 296 } 297 298 // TODO(jon): fix this noop 299 @Override public String getEntryAlias() { 300 return ""; 301 } 302 303 // TODO(jon): fix this noop 304 @Override public void setEntryAlias(final String newAlias) { 305 if (newAlias == null) { 306 throw new NullPointerException("Null aliases are not allowable."); 307 } 308 } 309 310 @Override public void setEntryStatus(EntryStatus newStatus) { 311 entryStatus = newStatus; 312 } 313 314 @Override public String getGroup() { 315 return group; 316 } 317 318 @Override public String getName() { 319 return name; 320 } 321 322 /** 323 * Gets the ADDE descriptor for the current local ADDE entry. 324 * 325 * @return ADDE descriptor (corresponds to the {@literal "N2"} section of a RESOLV.SRV 326 * entry). 327 */ 328 public String getDescriptor() { 329 return descriptor; 330 } 331 332 /** 333 * Gets the ADDE dataset format for the current local ADDE entry. 334 * 335 * @return ADDE format (corresponds to the {@literal "MCV"} section of a RESOLV.SRV 336 * entry). 337 */ 338 public AddeFormat getFormat() { 339 return format; 340 } 341 342 /** 343 * Gets the ADDE file mask for the current local ADDE entry. 344 * 345 * @return ADDE file mask (corresponds to the {@literal "MASK"} section of a RESOLV.SRV 346 * entry). 347 */ 348 public String getMask() { 349 return fileMask; 350 } 351 352 /** 353 * Gets the ADDE file mask for the current local ADDE entry. 354 * 355 * @return ADDE file mask (corresponds to the {@literal "MASK"} section of a RESOLV.SRV 356 * entry). 357 */ 358 public String getFileMask() { 359 return fileMask; 360 } 361 362 /** 363 * Gets the ADDE realtime status of the current local ADDE entry. 364 * 365 * @return Whether or not the current dataset is {@literal "realtime"}. 366 * Corresponds to the {@literal "RT"} section of a RESOLV.SRV entry. 367 */ 368 public boolean getRealtime() { 369 return realtime; 370 } 371 372 /** 373 * Gets the starting number of the current local ADDE dataset. 374 * 375 * @return Corresponds to the {@literal "R1"} section of a RESOLV.SRV entry. 376 */ 377 public String getStart() { 378 return start; 379 } 380 381 /** 382 * Gets the ending number of the current local ADDE dataset. 383 * 384 * @return Corresponds to the {@literal "R2"} section of a RESOLV.SRV entry. 385 */ 386 public String getEnd() { 387 return end; 388 } 389 390 /** 391 * Tests the current local ADDE dataset for validity. 392 * 393 * @return {@code true} iff {@link #group} and {@link #name} are not empty. 394 */ 395 public boolean isValid() { 396 // return !((group.isEmpty()) || (descriptor.isEmpty()) || (name.isEmpty())); 397 return !((group.isEmpty()) || (name.isEmpty())); 398 } 399 400 /** 401 * Gets the local ADDE dataset's realtime status as a value suitable for 402 * RESOLV.SRV (one of {@literal "Y"} or {@literal "N"}). 403 * 404 * @return RESOLV.SRV-friendly representation of the current realtime status. 405 */ 406 public String getRealtimeAsString() { 407 return (realtime) ? "Y" : "N"; 408 } 409 410 /** 411 * @see LocalAddeEntry#generateHashCode(String, String, String, AddeFormat) 412 */ 413 @Override public int hashCode() { 414 return generateHashCode(name, group, fileMask, format); 415 } 416 417 /** 418 * Checks a given object for equality with the current {@code LocalAddeEntry} 419 * instance. 420 * 421 * @param obj Object to check. {@code null} values allowed. 422 * 423 * @return {@code true} if {@code obj} is {@literal "equal"} to the current 424 * {@code LocalAddeEntry} instance. 425 */ 426 @Override public boolean equals(Object obj) { 427 if (this == obj) { 428 return true; 429 } 430 if (obj == null) { 431 return false; 432 } 433 if (!(obj instanceof LocalAddeEntry)) { 434 return false; 435 } 436 LocalAddeEntry other = (LocalAddeEntry) obj; 437 if (fileMask == null) { 438 if (other.fileMask != null) { 439 return false; 440 } 441 } else if (!fileMask.equals(other.fileMask)) { 442 return false; 443 } 444 if (format == null) { 445 if (other.format != null) { 446 return false; 447 } 448 } else if (!format.toString().equals(other.format.toString())) { 449 return false; 450 } 451 if (group == null) { 452 if (other.group != null) { 453 return false; 454 } 455 } else if (!group.equals(other.group)) { 456 return false; 457 } 458 if (name == null) { 459 if (other.name != null) { 460 return false; 461 } 462 } else if (!name.equals(other.name)) { 463 return false; 464 } 465 return true; 466 } 467 468 @Override public String asStringId() { 469 if (asStringId == null) { 470 asStringId = "localhost!"+group+'!'+EntryType.IMAGE.name()+'!'+name; 471 } 472 return asStringId; 473 } 474 475 @Override public String toString() { 476 return String.format( 477 "[LocalAddeEntry@%x: name=%s, group=%s, fileMask=\"%s\", descriptor=%s, serverName=%s, format=%s, description=%s, type=%s, status=%s]", 478 hashCode(), name, group, fileMask, descriptor, format.getServerName().name(), format.name(), format.getTooltip(), format.getType(), entryStatus.name()); 479 480 } 481 482 public static int generateHashCode(final LocalAddeEntry entry) { 483 return generateHashCode(entry.getName(), entry.getGroup(), entry.getMask(), entry.getFormat()); 484 } 485 486 public static int generateHashCode(String name, String group, String fileMask, AddeFormat format) { 487 final int prime = 31; 488 int result = 1; 489 result = prime * result 490 + ((fileMask == null) ? 0 : fileMask.hashCode()); 491 result = prime * result + ((format == null) ? 0 : format.toString().hashCode()); 492 result = prime * result + ((group == null) ? 0 : group.hashCode()); 493 result = prime * result + ((name == null) ? 0 : name.hashCode()); 494 return result; 495 } 496 497 /** 498 * A builder of (mostly) immutable {@link LocalAddeEntry} instances. 499 * 500 * <p>Usage example: <pre> {@code 501 * LocalAddeEntry entry = new LocalAddeEntry 502 * .Builder(group, name, format, mask) 503 * .realtime("Y") 504 * .range(start, end) 505 * .type(EntryType.POINT) 506 * .build();}</pre> 507 * 508 * Only the values required by the Builder constructor are required. 509 */ 510 public static class Builder { 511 // required 512 /** Corresponds to RESOLV.SRV's {@literal "N1"} section. */ 513 private final String group; 514 515 /** Corresponds to RESOLV.SRV's {@literal "C"} section. */ 516 private final String name; 517 518 /** Corresponds to RESOLV.SRV's {@literal "MCV"} section. */ 519 private final AddeFormat format; 520 521 /** Corresponds to RESOLV.SRV's {@literal "MASK"} section. */ 522 private final String mask; 523 524 // generated 525 private String descriptor; 526 527 // optional 528 /** 529 * Corresponds to RESOLV.SRV's {@literal "RT"} section. 530 * Defaults to {@code false}. 531 */ 532 private boolean realtime = false; 533 534 /** 535 * Corresponds to RESOLV.SRV's {@literal "R1"} section. 536 * Defaults to {@literal "1"}. 537 */ 538 private String start = "1"; 539 540 /** 541 * Corresponds to RESOLV.SRV's {@literal "R2"} section. 542 * Defaults to {@literal "999999"}. 543 */ 544 private String end = "999999"; 545 546 /** 547 * Defaults to {@link edu.wisc.ssec.mcidasv.servermanager.AddeEntry.EntryStatus#INVALID}. 548 */ 549 private EntryStatus status = EntryStatus.INVALID; 550 551 /** 552 * Corresponds to RESOLV.SRV's {@literal "TYPE"} section. 553 * Defaults to {@link EntryType#IMAGE}. 554 */ 555 private EntryType type = EntryType.IMAGE; 556 557 /** 558 * Corresponds to RESOLV.SRV's {@literal "K"} section. 559 * Defaults to {@literal "NOT_SET"}. 560 */ 561 private String kind = "NOT_SET"; 562 563 /** 564 * Defaults to {@link ServerName#INVALID}. 565 */ 566 private ServerName safeKind = ServerName.INVALID; 567 568 public Builder(final Map<String, String> map) { 569 if (!map.containsKey("C") || !map.containsKey("N1") || !map.containsKey("MASK") || !map.containsKey("MCV")) { 570 throw new IllegalArgumentException("Cannot build a LocalAddeEntry without the following keys: C, N1, MASK, and MCV."); 571 } 572 573 this.name = map.get("C"); 574 this.group = map.get("N1"); 575 this.mask = map.get("MASK"); 576 this.format = EntryTransforms.strToAddeFormat(map.get("MCV")); 577 578 // descriptor(map.get("N2")); 579 type(EntryTransforms.strToEntryType(map.get("TYPE"))); 580 kind(map.get("K").toUpperCase()); 581 realtime(map.get("RT")); 582 start(map.get("R1")); 583 end(map.get("R2")); 584 } 585 586 /** 587 * Creates a new {@code LocalAddeEntry} {@literal "builder"} with the 588 * required fields for a {@code LocalAddeEntry} object. 589 * 590 * @param name 591 * @param group 592 * @param mask 593 * @param format 594 */ 595 public Builder(final String name, final String group, final String mask, final AddeFormat format) { 596 this.name = name; 597 this.group = group; 598 this.mask = mask; 599 this.format = format; 600 } 601 602 /** 603 * This method is currently a no-op. 604 * 605 * @param descriptor 606 * 607 * @return {@code LocalAddeEntry.Builder} with ADDE descriptor. 608 */ 609 public Builder descriptor(final String descriptor) { 610 // if (descriptor != null) { 611 // this.descriptor = descriptor; 612 // } 613 return this; 614 } 615 616 /** 617 * 618 * 619 * @param realtimeAsStr 620 * 621 * @return {@code LocalAddeEntry.Builder} with ADDE realtime flag. 622 */ 623 // looks like mcidasx understands ("Y"/"N"/"A") 624 // should probably ignore case and accept "YES"/"NO"/"ARCHIVE" 625 // in addition to the normal boolean conversion from String 626 public Builder realtime(final String realtimeAsStr) { 627 if (realtimeAsStr == null) { 628 return this; 629 } 630 631 if ("Y".equalsIgnoreCase(realtimeAsStr) || "YES".equalsIgnoreCase(realtimeAsStr)) { 632 this.realtime = true; 633 } else { 634 this.realtime = Boolean.valueOf(realtimeAsStr); 635 } 636 return this; 637 } 638 639 /** 640 * 641 * 642 * @param realtime 643 * 644 * @return {@code LocalAddeEntry.Builder} with ADDE realtime flag. 645 */ 646 public Builder realtime(final boolean realtime) { 647 this.realtime = realtime; 648 return this; 649 } 650 651 /** 652 * 653 * 654 * @param type 655 * 656 * @return {@code LocalAddeEntry.Builder} with ADDE data type. 657 */ 658 // my assumption is that if "format" is known, you can infer "type" 659 public Builder type(final EntryType type) { 660 if (type != null) { 661 this.type = type; 662 } 663 return this; 664 } 665 666 /** 667 * 668 * 669 * @param kind 670 * 671 * @return {@code LocalAddeEntry.Builder} with ADDE kind. 672 */ 673 // my assumption is that if "format" is known, you can infer "kind" 674 public Builder kind(final String kind) { 675 if (kind == null) { 676 return this; 677 } 678 679 this.kind = kind; 680 try { 681 this.safeKind = ServerName.valueOf(kind); 682 } catch (IllegalArgumentException e) { 683 this.safeKind = ServerName.INVALID; 684 } 685 return this; 686 } 687 688 /** 689 * 690 * 691 * @param start 692 * 693 * @return {@code LocalAddeEntry.Builder} with ADDE dataset {@literal "start"}. 694 */ 695 public Builder start(final String start) { 696 if (start != null) { 697 this.start = start; 698 } 699 return this; 700 } 701 702 /** 703 * 704 * 705 * @param end 706 * 707 * @return {@code LocalAddeEntry.Builder} with ADDE dataset {@literal "end"}. 708 */ 709 public Builder end(final String end) { 710 if (end != null) { 711 this.end = end; 712 } 713 return this; 714 } 715 716 /** 717 * 718 * 719 * @param start 720 * @param end 721 * 722 * @return {@code LocalAddeEntry.Builder} with ADDE dataset {@literal "start" and "end"} values. 723 */ 724 public Builder range(final String start, final String end) { 725 if (start != null && end != null) { 726 this.start = start; 727 this.end = end; 728 } 729 return this; 730 } 731 732 /** 733 * 734 * 735 * @param status 736 * 737 * @return {@code LocalAddeEntry.Builder} with {@link AddeEntry.EntryStatus}. 738 */ 739 public Builder status(final String status) { 740 if (status != null && status.length() > 0) { 741 this.status = EntryTransforms.strToEntryStatus(status); 742 } 743 return this; 744 } 745 746 /** 747 * 748 * 749 * @param status 750 * 751 * @return {@code LocalAddeEntry.Builder} with {@link AddeEntry.EntryStatus}. 752 */ 753 public Builder status(final EntryStatus status) { 754 if (status != null) { 755 this.status = status; 756 } 757 return this; 758 } 759 760 /** 761 * 762 * 763 * @return New {@code LocalAddeEntry} instance. 764 */ 765 public LocalAddeEntry build() { 766 // apparently need to hack up the descriptor for certain formats 767 switch (format) { 768 case MSG_HRIT_FD: this.descriptor = "FD"; break; 769 case MSG_HRIT_HRV: this.descriptor = "HRV"; break; 770 case LRIT_GOES9: this.descriptor = "GOES9"; break; 771 case LRIT_GOES10: this.descriptor = "GOES10"; break; 772 case LRIT_GOES11: this.descriptor = "GOES11"; break; 773 case LRIT_GOES12: this.descriptor = "GOES12"; break; 774 case LRIT_MET5: this.descriptor = "MET5"; break; 775 case LRIT_MET7: this.descriptor = "MET7"; break; 776 case LRIT_MTSAT1R: this.descriptor = "MTSAT1R"; break; 777 default: 778 this.descriptor = Integer.toHexString(generateHashCode(name, group, mask, format)); 779 break; 780 } 781 return new LocalAddeEntry(this); 782 } 783 } 784 }