001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2017 005 * Space Science and Engineering Center (SSEC) 006 * University of Wisconsin - Madison 007 * 1225 W. Dayton Street, Madison, WI 53706, USA 008 * https://www.ssec.wisc.edu/mcidas 009 * 010 * All Rights Reserved 011 * 012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 013 * some McIDAS-V source code is based on IDV and VisAD source code. 014 * 015 * McIDAS-V is free software; you can redistribute it and/or modify 016 * it under the terms of the GNU Lesser Public License as published by 017 * the Free Software Foundation; either version 3 of the License, or 018 * (at your option) any later version. 019 * 020 * McIDAS-V is distributed in the hope that it will be useful, 021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 023 * GNU Lesser Public License for more details. 024 * 025 * You should have received a copy of the GNU Lesser Public License 026 * along with this program. If not, see http://www.gnu.org/licenses. 027 */ 028 029package edu.wisc.ssec.mcidasv.data.adde; 030 031import java.awt.Component; 032import java.awt.Container; 033import java.awt.Dimension; 034import java.awt.event.ActionEvent; 035import java.awt.event.ActionListener; 036import java.io.File; 037import java.io.RandomAccessFile; 038import java.rmi.RemoteException; 039import java.text.SimpleDateFormat; 040import java.util.ArrayList; 041import java.util.Arrays; 042import java.util.Collections; 043import java.util.Date; 044import java.util.Enumeration; 045import java.util.HashMap; 046import java.util.Hashtable; 047import java.util.Iterator; 048import java.util.List; 049import java.util.Map; 050import java.util.StringTokenizer; 051import java.util.TimeZone; 052import java.util.TreeMap; 053 054import javax.swing.BoxLayout; 055import javax.swing.JCheckBox; 056import javax.swing.JComponent; 057import javax.swing.JLabel; 058import javax.swing.JPanel; 059import javax.swing.JScrollPane; 060import javax.swing.JTabbedPane; 061 062import org.slf4j.Logger; 063import org.slf4j.LoggerFactory; 064 065import edu.wisc.ssec.mcidas.AREAnav; 066import edu.wisc.ssec.mcidas.AreaDirectory; 067import edu.wisc.ssec.mcidas.AreaDirectoryList; 068import edu.wisc.ssec.mcidas.AreaFile; 069import edu.wisc.ssec.mcidas.AreaFileException; 070import edu.wisc.ssec.mcidas.adde.AddeImageURL; 071import edu.wisc.ssec.mcidas.adde.AddeTextReader; 072import edu.wisc.ssec.mcidas.adde.AddeURL; 073import edu.wisc.ssec.mcidasv.data.GeoLatLonSelection; 074import edu.wisc.ssec.mcidasv.data.GeoPreviewSelection; 075 076import visad.CommonUnit; 077import visad.Data; 078import visad.DateTime; 079import visad.FlatField; 080import visad.FunctionType; 081import visad.MathType; 082import visad.RealType; 083import visad.Set; 084import visad.VisADException; 085import visad.data.DataRange; 086import visad.data.mcidas.AREACoordinateSystem; 087import visad.data.mcidas.AreaAdapter; 088import visad.georef.MapProjection; 089import visad.meteorology.ImageSequence; 090import visad.meteorology.ImageSequenceImpl; 091import visad.meteorology.SingleBandedImage; 092 093import ucar.nc2.iosp.mcidas.McIDASAreaProjection; 094import ucar.unidata.data.BadDataException; 095import ucar.unidata.data.CompositeDataChoice; 096import ucar.unidata.data.DataCategory; 097import ucar.unidata.data.DataChoice; 098import ucar.unidata.data.DataSelection; 099import ucar.unidata.data.DataSelectionComponent; 100import ucar.unidata.data.DataSourceDescriptor; 101import ucar.unidata.data.DirectDataChoice; 102import ucar.unidata.data.GeoLocationInfo; 103import ucar.unidata.data.GeoSelection; 104import ucar.unidata.data.imagery.AddeImageDataSource; 105import ucar.unidata.data.imagery.AddeImageDescriptor; 106import ucar.unidata.data.imagery.AddeImageInfo; 107import ucar.unidata.data.imagery.BandInfo; 108import ucar.unidata.data.imagery.ImageDataset; 109import ucar.unidata.geoloc.LatLonPoint; 110import ucar.unidata.geoloc.ProjectionImpl; 111import ucar.unidata.idv.DisplayControl; 112import ucar.unidata.util.GuiUtils; 113import ucar.unidata.util.IOUtil; 114import ucar.unidata.util.LogUtil; 115import ucar.unidata.util.PollingInfo; 116import ucar.unidata.util.StringUtil; 117import ucar.unidata.util.ThreeDSize; 118import ucar.unidata.util.TwoFacedObject; 119import ucar.visad.UtcDate; 120import ucar.visad.Util; 121import ucar.visad.data.AreaImageFlatField; 122 123/** 124 * Abstract DataSource class for images files. 125 */ 126 127public class AddeImageParameterDataSource extends AddeImageDataSource { 128 129 private static final Logger logger = LoggerFactory.getLogger(AddeImageParameterDataSource.class); 130 131 /** 132 * Public keys for server, group, dataset, user, project. 133 */ 134 public final static String SIZE_KEY = "size"; 135 public final static String PLACE_KEY = "place"; 136 public final static String LATLON_KEY = "latlon"; 137 public final static String LINELE_KEY = "linele"; 138 public final static String MAG_KEY = "mag"; 139 public final static String BAND_KEY = "band"; 140 public final static String BANDINFO_KEY = "bandinfo"; 141 public final static String UNIT_KEY = "unit"; 142 public final static String PREVIEW_KEY = "preview"; 143 public final static String SPAC_KEY = "spac"; 144 public final static String NAV_KEY = "nav"; 145 public final static String AUX_KEY = "aux"; 146 public final static String DOC_KEY = "doc"; 147 public final static String SPACING_BRIT = "1"; 148 public final static String SPACING_NON_BRIT = "4"; 149 150 /** The first projection we find */ 151 protected ProjectionImpl sampleProjection; 152 public MapProjection sampleMapProjection; 153 154 /* ADDE request string */ 155 private String source; 156 private String baseSource; 157 158 /* properties for this data source */ 159 private Hashtable sourceProps; 160 private Hashtable selectionProps; 161 162 private int lineResolution; 163 private int elementResolution; 164 private float lRes; 165 private float eRes; 166 private int lineMag = 1; 167 private int elementMag = 1; 168 169 private GeoSelection lastGeoSelection; 170 private DataChoice lastChoice = null; 171 private Boolean showPreview = Boolean.FALSE; 172 private FlatField previewImage = null; 173 private MapProjection previewProjection; 174 private Hashtable initProps; 175 176 private AreaDirectory previewDir = null; 177 private AREAnav previewNav = null; 178 private boolean haveDataSelectionComponents = false; 179 180 private GeoPreviewSelection previewSel; 181 private GeoLatLonSelection laLoSel; 182 183 private String choiceName; 184 185 private String saveCoordType; 186 private String savePlace; 187 private double saveLat; 188 private double saveLon; 189 private int saveNumLine; 190 private int saveNumEle; 191 private int saveLineMag; 192 private int saveEleMag; 193 private Boolean saveShowPreview; 194 195 private String displaySource; 196 197 protected List<DataChoice> stashedChoices = null; 198 private List iml = new ArrayList(); 199 private List saveImageList = new ArrayList(); 200 201 private int previewLineRes = 1; 202 private int previewEleRes = 1; 203 204 // Do binary search on preview bounds for GEO sensors to speed up overall response time 205 boolean doGeoSpeedup = false; 206 207 /** Whether or not this DataSource was loaded from a bundle. */ 208 private boolean fromBundle = false; 209 210 /** Are any of the data choices based upon remote files? */ 211 private boolean hasRemoteChoices = false; 212 213 private Map<String, AreaDirectory> requestIdToDirectory = new HashMap<String, AreaDirectory>(); 214 215 public AddeImageParameterDataSource() {} 216 217 /** 218 * Creates a {@code AddeImageParameterDataSource} with a single ADDE URL. 219 * <b>Note:</b> the URLs should point at {@literal "image"} data. 220 * 221 * @param descriptor {@link ucar.unidata.data.DataSourceDescriptor DataSourceDescriptor} for this data source. 222 * @param image ADDE URL 223 * @param properties The properties for this data source. 224 * 225 * @throws VisADException 226 */ 227 public AddeImageParameterDataSource(DataSourceDescriptor descriptor, String image, 228 Hashtable properties) 229 throws VisADException { 230 super(descriptor, new String[] { image }, properties); 231 logger.trace("1: desc={}, image={}, properties={}", new Object[] { descriptor, image, properties }); 232 } 233 234 /** 235 * Create a new AddeImageParameterDataSource with an array of ADDE URL strings. 236 * <b>Note:</b> the URLs should point at {@literal "image"} data. 237 * 238 * @param descriptor {@link ucar.unidata.data.DataSourceDescriptor DataSourceDescriptor} for this data source. 239 * @param images Array of ADDE URLs. 240 * @param properties Properties for this data source. 241 * 242 * @throws VisADException 243 */ 244 public AddeImageParameterDataSource(DataSourceDescriptor descriptor, String[] images, 245 Hashtable properties) throws VisADException { 246 super(descriptor, images, properties); 247 logger.trace("2: desc={}, images={}, properties={}", new Object[] { descriptor, images, properties }); 248 } 249 250 /** 251 * Creates a new {@code AddeImageParameterDataSource} with an 252 * {@link java.util.List List} of ADDE URL strings. 253 * <b>Note:</b> the URLs should point at {@literal "image"} data. 254 * 255 * @param descriptor {@link ucar.unidata.data.DataSourceDescriptor DataSourceDescriptor} for this data source. 256 * @param images {@code List} of ADDE URL strings. 257 * @param properties Properties for this data source. 258 * 259 * @throws VisADException 260 */ 261 public AddeImageParameterDataSource(DataSourceDescriptor descriptor, List images, 262 Hashtable properties) throws VisADException { 263 super(descriptor, images, properties); 264 logger.trace("3: desc={}, images={}, properties={}", new Object[] { descriptor, images, properties }); 265 } 266 267 /** 268 * Create a new AddeImageParameterDataSource with the given dataset. 269 * 270 * @param descriptor {@link ucar.unidata.data.DataSourceDescriptor DataSourceDescriptor} for this data source. 271 * @param ids Dataset. 272 * @param properties Properties for this data source. 273 * 274 * @throws VisADException 275 */ 276 277 public AddeImageParameterDataSource(DataSourceDescriptor descriptor, ImageDataset ids, 278 Hashtable properties) throws VisADException { 279 super(descriptor, ids, properties); 280 logger.trace("4: desc={}, ids={}, properties={}", new Object[] { descriptor, ids, properties }); 281 this.sourceProps = properties; 282 if (properties.containsKey((Object)PREVIEW_KEY)) { 283 this.showPreview = (Boolean)(properties.get((Object)PREVIEW_KEY)); 284 saveShowPreview = showPreview; 285 } else { 286 if (saveShowPreview != null) { 287 showPreview = saveShowPreview; 288 } 289 } 290 291 List descs = ids.getImageDescriptors(); 292 AddeImageDescriptor aid = (AddeImageDescriptor)descs.get(0); 293 this.source = aid.getSource(); 294 if (this.source.contains("localhost")) { 295 AreaDirectory areaDirectory = aid.getDirectory(); 296 if (!sourceProps.containsKey((Object)UNIT_KEY)) { 297 if (!sourceProps.containsKey((Object)BAND_KEY)) { 298 String calType = areaDirectory.getCalibrationType(); 299 if (!calType.equals("RAW")) { 300 sourceProps.put(UNIT_KEY, calType); 301 int[] bandNums = areaDirectory.getBands(); 302 String bandString = new Integer(bandNums[0]).toString(); 303 sourceProps.put(BAND_KEY, bandString); 304 } 305 } 306 } 307 } 308 setMag(); 309 getAreaDirectory(properties); 310 } 311 312 @Override protected void propertiesChanged() { 313 logger.trace("fired"); 314 super.propertiesChanged(); 315 } 316 317 @Override protected boolean initDataFromPollingInfo() { 318 boolean result = super.initDataFromPollingInfo(); 319 logger.trace("result={}", result); 320 return result; 321 } 322 323 @Override protected boolean isPolling() { 324 boolean result = super.isPolling(); 325 logger.trace("isPolling={}", result); 326 return result; 327 } 328 329 @Override public void setPollingInfo(PollingInfo value) { 330 logger.trace("value={}", value); 331 super.setPollingInfo(value); 332 } 333 334 @Override protected boolean hasPollingInfo() { 335 boolean result = super.hasPollingInfo(); 336 logger.trace("hasPollingInfo={}", result); 337 return result; 338 } 339 340 @Override public PollingInfo getPollingInfo() { 341 PollingInfo result = super.getPollingInfo(); 342 logger.trace("getPollingInfo={}", result); 343 return result; 344 } 345 346 @Override public void initAfterUnpersistence() { 347 logger.trace("unbundled!"); 348 super.initAfterUnpersistence(); 349 350 if (this.sourceProps.containsKey(PREVIEW_KEY)) { 351 this.showPreview = (Boolean)this.sourceProps.get(PREVIEW_KEY); 352 if (this.showPreview == null) { 353 this.showPreview = Boolean.FALSE; 354 } 355 this.saveShowPreview = this.showPreview; 356 } 357 358 this.fromBundle = true; 359 List<AddeImageDescriptor> descriptors = (List<AddeImageDescriptor>) getImageList(); 360 this.source = descriptors.get(0).getSource(); // TODO: why not use the source from 361 // each AddeImageDescriptor? 362 for (AddeImageDescriptor descriptor : descriptors) { 363 if (!isFromFile(descriptor)) { 364 this.hasRemoteChoices = true; 365 break; 366 } 367 } 368 } 369 370 @Override public boolean canSaveDataToLocalDisk() { 371 return true; 372 } 373 374 private Hashtable<String, DataSelection> choiceToSel = new Hashtable<String, DataSelection>(); 375 376 public DataSelection getSelForChoice(final DataChoice choice) { 377 String key = choice.getName(); 378 return choiceToSel.get(key); 379 } 380 public boolean hasSelForChoice(final DataChoice choice) { 381 String key = choice.getName(); 382 return choiceToSel.containsKey(key); 383 } 384 public void putSelForChoice(final DataChoice choice, final DataSelection sel) { 385 String key = choice.getName(); 386 choiceToSel.put(key, sel); 387 } 388 389 /** 390 * Save files to local disk 391 * 392 * @param prefix destination dir and file prefix 393 * @param loadId For JobManager 394 * @param changeLinks Change internal file references 395 * 396 * @return Files copied 397 * 398 * @throws Exception On badness 399 */ 400 401 @Override protected List saveDataToLocalDisk(String prefix, Object loadId, boolean changeLinks) throws Exception { 402 logger.trace("prefix={} loadId={} changeLinks={}", new Object[] { prefix, loadId, changeLinks }); 403 final List<JCheckBox> checkboxes = new ArrayList<JCheckBox>(); 404 List categories = new ArrayList(); 405 Hashtable catMap = new Hashtable(); 406 Hashtable currentDataChoices = new Hashtable(); 407 408 List displays = getIdv().getDisplayControls(); 409 for (int i = 0; i < displays.size(); i++) { 410 List dataChoices = ((DisplayControl)displays.get(i)).getDataChoices(); 411 if (dataChoices == null) { 412 continue; 413 } 414 List finalOnes = new ArrayList(); 415 for (int j = 0; j < dataChoices.size(); j++) { 416 ((DataChoice)dataChoices.get(j)).getFinalDataChoices(finalOnes); 417 } 418 for (int dcIdx = 0; dcIdx < finalOnes.size(); dcIdx++) { 419 DataChoice dc = (DataChoice)finalOnes.get(dcIdx); 420 if (!(dc instanceof DirectDataChoice)) { 421 continue; 422 } 423 DirectDataChoice ddc = (DirectDataChoice) dc; 424 if (ddc.getDataSource() != this) { 425 continue; 426 } 427 currentDataChoices.put(ddc.getName(), ""); 428 } 429 } 430 431 for (int i = 0; i < dataChoices.size(); i++) { 432 DataChoice dataChoice = (DataChoice) dataChoices.get(i); 433 if (!(dataChoice instanceof DirectDataChoice)) { 434 continue; 435 } 436 437 // skip over datachoices that the user has not already loaded. 438 // (but fill the "slot" with null (it's a hack to signify that 439 // the "download" loop should skip over the data choice associated 440 // with this slot) 441 if (!currentDataChoices.containsKey(dataChoice.getName())) { 442 checkboxes.add(null); // 443 continue; 444 } 445 446 String label = dataChoice.getDescription(); 447 if (label.length() > 30) { 448 label = label.substring(0, 29) + "..."; 449 } 450 JCheckBox cbx = 451 new JCheckBox(label, 452 currentDataChoices.get(dataChoice.getName()) 453 != null); 454 ThreeDSize size = (ThreeDSize)dataChoice.getProperty(SIZE_KEY); 455 cbx.setToolTipText(dataChoice.getName()); 456 checkboxes.add(cbx); 457 DataCategory dc = dataChoice.getDisplayCategory(); 458 if (dc == null) { 459 dc = DataCategory.createCategory(DataCategory.CATEGORY_IMAGE); 460 } 461 List comps = (List)catMap.get(dc); 462 if (comps == null) { 463 comps = new ArrayList(); 464 catMap.put(dc, comps); 465 categories.add(dc); 466 } 467 comps.add(cbx); 468 comps.add(GuiUtils.filler()); 469 if (size != null) { 470 JLabel sizeLabel = GuiUtils.rLabel(size.getSize() + " "); 471 sizeLabel.setToolTipText(size.getLabel()); 472 comps.add(sizeLabel); 473 } else { 474 comps.add(new JLabel("")); 475 } 476 } 477 final JCheckBox allCbx = new JCheckBox("Select All"); 478 allCbx.addActionListener(new ActionListener() { 479 public void actionPerformed(ActionEvent ae) { 480 for (JCheckBox cbx : checkboxes) { 481 if (cbx != null) { 482 cbx.setSelected(allCbx.isSelected()); 483 } 484 } 485 } 486 }); 487 488 JTabbedPane tab = new JTabbedPane(JTabbedPane.LEFT); 489 490 for (int i = 0; i < categories.size(); i++) { 491 List comps = (List) catMap.get(categories.get(i)); 492 JPanel innerPanel = GuiUtils.doLayout(comps, 3, GuiUtils.WT_NYN, GuiUtils.WT_N); 493 JScrollPane sp = new JScrollPane(GuiUtils.top(innerPanel)); 494 sp.setPreferredSize(new Dimension(500, 400)); 495 JPanel top = GuiUtils.right(GuiUtils.rLabel(" ")); 496 JComponent inner = GuiUtils.inset(GuiUtils.topCenter(top, sp), 5); 497 tab.addTab(categories.get(i).toString(), inner); 498 } 499 500 JComponent contents = tab; 501 contents = GuiUtils.topCenter( 502 GuiUtils.inset( 503 GuiUtils.leftRight( 504 new JLabel("Select the fields to download"), 505 allCbx), 5), contents); 506 JLabel label = new JLabel(getNameForDataSource(this, 50, true)); 507 contents = GuiUtils.topCenter(label, contents); 508 contents = GuiUtils.inset(contents, 5); 509 if (!GuiUtils.showOkCancelDialog(null, "", contents, null)) { 510 return null; 511 } 512 513 // iterate through user's selection to build list of things to download 514 List<String> realUrls = new ArrayList<String>(); 515 List<AddeImageDescriptor> descriptorsToSave = new ArrayList<AddeImageDescriptor>(); 516 List<BandInfo> bandInfos = (List<BandInfo>)getProperty(PROP_BANDINFO, (Object)null); 517 List<BandInfo> savedBands = new ArrayList<BandInfo>(); 518 for (int i = 0; i < dataChoices.size(); i++) { 519 DataChoice dataChoice = (DataChoice)dataChoices.get(i); 520 if (!(dataChoice instanceof DirectDataChoice)) { 521 continue; 522 } 523 JCheckBox cbx = (JCheckBox)checkboxes.get(i); 524 if (cbx == null || !cbx.isSelected()) { 525 continue; 526 } 527 528 if (dataChoice.getDataSelection() == null) { 529 dataChoice.setDataSelection(getSelForChoice(dataChoice)); 530 } 531 logger.trace("selected choice={} id={}", dataChoice.getName(), dataChoice.getId()); 532 List<AddeImageDescriptor> descriptors = getDescriptors(dataChoice, dataChoice.getDataSelection()); 533 logger.trace("descriptors={}", descriptors); 534 535 BandInfo bandInfo; 536 Object dataChoiceId = dataChoice.getId(); 537 if (dataChoiceId instanceof BandInfo) { 538 bandInfo = (BandInfo)dataChoiceId; 539 } else { 540 bandInfo = bandInfos.get(0); 541 } 542 String preferredUnit = bandInfo.getPreferredUnit(); 543 List<TwoFacedObject> filteredCalUnits = new ArrayList<TwoFacedObject>(); 544 for (TwoFacedObject tfo : (List<TwoFacedObject>)bandInfo.getCalibrationUnits()) { 545 if (preferredUnit.equals(tfo.getId())) { 546 filteredCalUnits.add(tfo); 547 } 548 } 549 bandInfo.setCalibrationUnits(filteredCalUnits); 550 savedBands.add(bandInfo); 551 552 DataSelection selection = dataChoice.getDataSelection(); 553 if (selection == null) { 554 if (getSelForChoice(dataChoice) != null) { 555 selection = getSelForChoice(dataChoice); 556 } else { 557 selection = getDataSelection(); 558 } 559 } 560 561 Hashtable selectionProperties = selection.getProperties(); 562// Hashtable selectionProperties; 563// if (selection != null) { 564// selectionProperties = selection.getProperties(); 565// } else { 566// DataSelection sel = this.getDataSelection(); 567// selectionProperties = new Hashtable(); 568// } 569 logger.trace("bandinfo.getUnit={} selection props={}", bandInfo.getPreferredUnit(), selectionProperties); 570 for (AddeImageDescriptor descriptor : descriptors) { 571// AddeImageInfo aii = (AddeImageInfo)descriptor.getImageInfo().clone(); 572 if (!isFromFile(descriptor)) { 573 String src = descriptor.getSource(); 574 logger.trace("src before={}", src); 575 src = replaceKey(src, AddeImageURL.KEY_UNIT, bandInfo.getPreferredUnit()); 576 if (selectionProperties.containsKey(AddeImageURL.KEY_PLACE)) { 577 src = replaceKey(src, AddeImageURL.KEY_PLACE, selectionProperties.get(AddeImageURL.KEY_PLACE)); 578 } 579 if (selectionProperties.containsKey(AddeImageURL.KEY_LATLON)) { 580 src = replaceKey(src, AddeImageURL.KEY_LINEELE, AddeImageURL.KEY_LATLON, selectionProperties.get(AddeImageURL.KEY_LATLON)); 581 } 582 if (selectionProperties.containsKey(AddeImageURL.KEY_LINEELE)) { 583 src = removeKey(src, AddeImageURL.KEY_LATLON); 584 src = replaceKey(src, AddeImageURL.KEY_LINEELE, selectionProperties.get(AddeImageURL.KEY_LINEELE)); 585 } 586 if (selectionProperties.containsKey(AddeImageURL.KEY_MAG)) { 587 src = replaceKey(src, AddeImageURL.KEY_MAG, selectionProperties.get(AddeImageURL.KEY_MAG)); 588 } 589 if (selectionProperties.containsKey(AddeImageURL.KEY_SIZE)) { 590 src = replaceKey(src, AddeImageURL.KEY_SIZE, selectionProperties.get(AddeImageURL.KEY_SIZE)); 591 } 592 logger.trace("src after={}", src); 593 descriptor.setSource(src); 594 } 595 descriptorsToSave.add(descriptor); 596 } 597// descriptorsToSave.addAll(descriptors); 598 } 599 if (!savedBands.isEmpty()) { 600 setProperty(PROP_BANDINFO, savedBands); 601 } 602 if (descriptorsToSave.isEmpty()) { 603 return null; 604 } 605 606 // Start the load, showing the dialog 607 List<String> suffixes = new ArrayList<String>(); 608 SimpleDateFormat sdf = new SimpleDateFormat("_" + DATAPATH_DATE_FORMAT); 609 sdf.setTimeZone(TimeZone.getTimeZone("GMT")); 610 for (int i = 0; i < descriptorsToSave.size(); i++) { 611 AddeImageDescriptor descriptor = descriptorsToSave.get(i); 612 AddeImageInfo aii = descriptor.getImageInfo(); 613 DateTime dttm = (DateTime)timeMap.get(descriptor.getSource()); 614 if (dttm != null) { 615 suffixes.add(sdf.format(ucar.visad.Util.makeDate(dttm)) + ".area"); 616 } else if (aii != null) { 617 String suffix = "_Band"+aii.getBand()+"_Unit"+aii.getUnit()+"_Pos"+i+".area"; 618 suffixes.add(suffix); 619 logger.trace("test suffix={}", suffix); 620 } else { 621 suffixes.add(i + ".area"); 622 } 623 realUrls.add(descriptor.getSource()); 624 } 625 logger.trace("urls={}", realUrls); 626 logger.trace("prefix={}", prefix); 627 logger.trace("suffixes={}", suffixes); 628 logger.trace("loadId={}", loadId); 629 List newFiles = IOUtil.writeTo(realUrls, prefix, suffixes, loadId); 630 logger.trace("files={}", newFiles); 631 if (newFiles == null) { 632 logger.trace("failed while in writeTo?"); 633 return null; 634 } else { 635 logger.trace("finished writeTo!"); 636 } 637 if (changeLinks) { 638 imageList = newFiles; 639 } 640 641 // write 0 as the first word 642 for (int i = 0; i < newFiles.size(); i++) { 643 try { 644 RandomAccessFile to = new RandomAccessFile((String)newFiles.get(i), "rw"); 645 to.seek(0); 646 to.writeInt(0); 647 to.close(); 648 } catch (Exception e) { 649 logger.error("unable to set first word to zero", e); 650 } 651 } 652 653 654// if (geoSubset != null) { 655// geoSubset.clearStride(); 656// geoSubset.setBoundingBox(null); 657// if (geoSelectionPanel != null) { 658// geoSelectionPanel.initWith(doMakeGeoSelectionPanel()); 659// } 660// } 661 662// List newFiles = Misc.newList(path); 663// if (changeLinks) { 664// //Get rid of the resolver URL 665// getProperties().remove(PROP_RESOLVERURL); 666// setNewFiles(newFiles); 667// } 668// 669 logger.trace("returning={}", newFiles); 670 return newFiles; 671 } 672 673 @Override protected String getDataPrefix() { 674 String tmp = StringUtil.replace(getName(), ' ', ""); 675 tmp = StringUtil.replace(tmp, '/', ""); 676 tmp = StringUtil.replace(tmp, "(AllBands)", ""); 677 tmp = IOUtil.cleanFileName(tmp); 678 logger.trace("data prefix={}", tmp); 679 return tmp; 680 } 681 682 /** 683 * A utility method that helps us deal with legacy bundles that used to 684 * have String file names as the id of a data choice. 685 * 686 * @param object May be an AddeImageDescriptor (for new bundles) or a 687 * String that is converted to an image descriptor. 688 * @return The image descriptor. 689 */ 690 @Override public AddeImageDescriptor getDescriptor(Object object) { 691// logger.trace("--------------------"); 692 if (object == null) { 693// logger.trace("null obj"); 694 return null; 695 } 696 if (object instanceof DataChoice) { 697 object = ((DataChoice)object).getId(); 698 logger.trace("datachoice getId={}", object); 699 } 700 if (object instanceof ImageDataInfo) { 701 int index = ((ImageDataInfo) object).getIndex(); 702 if (index < myDataChoices.size()) { 703 DataChoice dc = (DataChoice)myDataChoices.get(index); 704 Object tmpObject = dc.getId(); 705 if (tmpObject instanceof ImageDataInfo) { 706// logger.trace("returning imagedatainfo"); 707 return ((ImageDataInfo)tmpObject).getAid(); 708 } 709 } 710// logger.trace("invalid idx for imagedatainfo? (idx={} vs size={})", index, myDataChoices.size()); 711 return null; 712 // return ((ImageDataInfo) object).getAid(); 713 } 714 715 if (object instanceof AddeImageDescriptor) { 716// logger.trace("already addeimagedesc! desc={}", object); 717 return (AddeImageDescriptor)object; 718 } 719 AddeImageDescriptor tmp = new AddeImageDescriptor(object.toString()); 720// logger.trace("return descriptor={}", tmp); 721// logger.trace("--------------------"); 722 return tmp; 723 } 724 725 /** 726 * Overwrite base class method to return the name of this class. 727 * 728 * @return The name. 729 */ 730 public String getImageDataSourceName() { 731 return "Adde Image Data Source (Parameter)"; 732 } 733 734 private void setMag() { 735 Object magKey = (Object)"mag"; 736 if (sourceProps.containsKey(magKey)) { 737 String magVal = (String)(sourceProps.get(magKey)); 738 String[] magVals = magVal.split(" "); 739 this.lineMag = new Integer(magVals[0]).intValue(); 740 this.elementMag = new Integer(magVals[1]).intValue(); 741 } 742 } 743 744 private void getAreaDirectory(Hashtable properties) { 745 String addeCmdBuff = source; 746 if (addeCmdBuff.contains("BAND=")) { 747 String bandStr = getKey(addeCmdBuff, "BAND"); 748 if (bandStr.length() == 0) { 749 addeCmdBuff = replaceKey(addeCmdBuff, "BAND", "1"); 750 } 751 } 752 if (addeCmdBuff.contains("MAG=")) { 753 String[] segs = addeCmdBuff.split("MAG="); 754 String seg0 = segs[0]; 755 String seg1 = segs[1]; 756 int indx = seg1.indexOf("&"); 757 seg1 = seg1.substring(indx); 758 String magString = lineMag + " " + elementMag; 759 addeCmdBuff = seg0 + "MAG=" + magString + seg1; 760 } 761 addeCmdBuff = addeCmdBuff.replace("imagedata", "imagedir"); 762 AreaDirectoryList dirList = null; 763 try { 764 dirList = new AreaDirectoryList(addeCmdBuff); 765 } catch (Exception e) { 766 try { 767 List<BandInfo> bandInfos = (List<BandInfo>)getProperty(PROP_BANDINFO, (Object)null); 768 BandInfo bi = bandInfos.get(0); 769// String bandStr = new Integer(bi.getBandNumber()).toString(); 770 addeCmdBuff = replaceKey(addeCmdBuff, "BAND", bi.getBandNumber()); 771 dirList = new AreaDirectoryList(addeCmdBuff); 772 } catch (Exception eOpen) { 773 setInError(true); 774 logger.error("problem opening AREA file", eOpen); 775 } 776 } 777 778 try { 779 List areaDirs = dirList.getDirs(); 780 AreaDirectory ad = (AreaDirectory)areaDirs.get(0); 781 float[] res = getLineEleResolution(ad); 782 float resol = res[0]; 783 if (this.lineMag < 0) { 784 resol *= Math.abs(this.lineMag); 785 } 786// this.lineResolution = ad.getValue(11); 787 this.lineResolution = ad.getValue(AreaFile.AD_LINERES); 788 this.lRes = resol; 789 resol = res[1]; 790 if (this.elementMag < 0) { 791 resol *= Math.abs(this.elementMag); 792 } 793// this.elementResolution = ad.getValue(12); 794 this.elementResolution = ad.getValue(AreaFile.AD_ELEMRES); 795 this.eRes = resol; 796 } catch (Exception e) { 797 setInError(true); 798 logger.error("getting area directory", e); 799 } 800 baseSource = addeCmdBuff; 801 } 802 803 protected void initDataSelectionComponents( 804 List components, final DataChoice dataChoice) 805 { 806 if (fromBundle && !hasRemoteChoices) { 807 components.add(new BundlePreviewSelection("Region (Disabled)")); 808 components.add(new BundlePreviewSelection("Advanced (Disabled)")); 809 return; 810 } 811 812 getIdv().showWaitCursor(); 813 814 boolean hasImagePreview = true; 815 if (this.showPreview == null) { 816 this.showPreview = true; 817 } 818 boolean basically = false; 819 if (this.lastChoice != null) { 820 basically = dataChoice.basicallyEquals(this.lastChoice); 821 } 822 logger.trace("dataChoice={}", dataChoice); 823 // check for comps and whether or not dataChoice is hooping right back into line 824 if (this.haveDataSelectionComponents && dataChoice.equals(this.lastChoice)) { 825 try { 826 // did the datachoice ever actually get data? 827 if (dataChoice.getDataSelection() == null) { 828 if (!basically) { 829 logger.trace("creating geolatlonselection"); 830 this.laLoSel = new GeoLatLonSelection(this, 831 dataChoice, this.initProps, this.previewProjection, 832 previewDir, previewNav); 833 834 this.lineMag = this.laLoSel.getLineMag(); 835 this.elementMag = this.laLoSel.getElementMag(); 836 837 /* DAVEP: Force preview on. "No preview" means blank image */ 838// this.previewSel = new GeoPreviewSelection(this, dataChoice, this.previewImage, 839// this.laLoSel, this.previewProjection, 840// this.lineMag, this.elementMag, this.showPreview); 841 logger.trace("1: creating geopreviewselection: has geoprevsel: {}", this.previewSel!=null); 842 this.previewSel = new GeoPreviewSelection(this, dataChoice, this.previewImage, 843 this.laLoSel, this.previewProjection, 844 this.lineMag, this.elementMag, true); 845 } 846// this.lineMag = this.laLoSel.getLineMag(); 847// this.elementMag = this.laLoSel.getElementMag(); 848// 849// /* DAVEP: Force preview on. "No preview" means blank image */ 850//// this.previewSel = new GeoPreviewSelection(this, dataChoice, this.previewImage, 851//// this.laLoSel, this.previewProjection, 852//// this.lineMag, this.elementMag, this.showPreview); 853// logger.trace("1: creating geopreviewselection: has geoprevsel: {}", this.previewSel!=null); 854// this.previewSel = new GeoPreviewSelection(this, dataChoice, this.previewImage, 855// this.laLoSel, this.previewProjection, 856// this.lineMag, this.elementMag, true); 857 } 858 components.add(this.previewSel); 859 components.add(this.laLoSel); 860 } catch (Exception e) { 861 logger.error("error while repeating addition of selection components", e); 862 getIdv().showNormalCursor(); 863 } 864 } else { 865 try { 866 hasImagePreview = makePreviewImage(dataChoice); 867 if (basically) { 868 getSaveComponents(); 869 } 870 } catch (Exception e) { 871 JLabel label = new JLabel("Can't make preview image"); 872 JPanel contents = GuiUtils.top(GuiUtils.inset(label, label.getText().length() + 12)); 873 GuiUtils.showOkDialog(null, "No Preview Image", contents, null); 874 getIdv().showNormalCursor(); 875 logger.error("problem creating preview image", e); 876 return; 877 } 878 this.lastChoice = dataChoice; 879 if (hasImagePreview) { 880 try { 881 String magStr = getKey(baseSource, MAG_KEY); 882 String saveMagStr = magStr; 883 String[] vals = StringUtil.split(magStr, " ", 2); 884 Integer iVal = new Integer(vals[0]); 885 int lMag = iVal.intValue() * -1; 886 if (lMag == -1) { 887 lMag = 1; 888 } 889 iVal = new Integer(vals[1]); 890 int eMag = iVal.intValue() * -1; 891 if (eMag == -1) { 892 eMag = 1; 893 } 894 magStr = lMag + " " + eMag; 895 replaceKey(MAG_KEY, magStr); 896// String saveStr = baseSource; 897// if (!showPreview) { 898// replaceKey(SIZE_KEY, "2 2"); 899// } 900 AreaAdapter aa = null; 901 AREACoordinateSystem acs = null; 902 try { 903 logger.trace("creating AreaFile from src={}", baseSource); 904 if (showPreview) { 905 aa = new AreaAdapter(baseSource, false); 906 this.previewImage = (FlatField)aa.getImage(); 907 } else { 908 this.previewImage = Util.makeField(0, 1, 1, 0, 1, 1, 0, "TEMP"); 909 } 910 911 AreaFile af = new AreaFile(baseSource); 912 previewNav = af.getNavigation(); 913 AreaDirectory ad = af.getAreaDirectory(); 914 this.lineResolution = ad.getValue(AreaFile.AD_LINERES); 915 this.elementResolution = ad.getValue(AreaFile.AD_ELEMRES); 916 acs = new AREACoordinateSystem(af); 917 } catch (Exception e) { 918 String excp = e.toString(); 919 int indx = excp.lastIndexOf(":"); 920 String errorText = excp.substring(indx+1); 921 JLabel label = new JLabel(errorText); 922 JPanel contents = GuiUtils.top(GuiUtils.inset(label, label.getText().length() + 12)); 923 GuiUtils.showOkDialog(null, "Can't Make Geographical Selection Tabs", contents, null); 924 getIdv().showNormalCursor(); 925 logger.error("problem creating preview image", e); 926 return; 927 } 928 this.initProps = new Hashtable(); 929 Enumeration propEnum = sourceProps.keys(); 930 for (int i = 0; propEnum.hasMoreElements(); i++) { 931 String key = propEnum.nextElement().toString(); 932 Object val = sourceProps.get(key); 933 key = key.toUpperCase(); 934 if (val instanceof String) { 935 String str = (String)val; 936 val = (Object)(str.toUpperCase()); 937 } 938 this.initProps.put(key,val); 939 } 940 replaceKey(MAG_KEY, saveMagStr); 941 magStr = getKey(baseSource, MAG_KEY); 942 vals = StringUtil.split(magStr, " ", 2); 943 iVal = new Integer(vals[0]); 944 lMag = iVal.intValue(); 945 iVal = new Integer(vals[1]); 946 eMag = iVal.intValue(); 947 948 this.initProps.put("LRES", String.valueOf((this.lRes))); 949 this.initProps.put("ERES", String.valueOf((this.eRes))); 950 this.initProps.put("PLRES", String.valueOf((this.previewLineRes))); 951 this.initProps.put("PERES", String.valueOf((this.previewEleRes))); 952 this.previewProjection = (MapProjection)acs; 953 954 String coordType = ""; 955 double coords[] = { 0.0, 0.0 }; 956 957 logger.trace("basically={} laLoSel==null?={}", basically, (this.laLoSel==null)); 958 if (!basically) { 959 if (this.laLoSel != null) { 960 coordType = this.laLoSel.getCoordinateType(); 961 if (coordType.equals(this.laLoSel.getLatLonType())) { 962 coords[0] = this.laLoSel.getLatitude(); 963 coords[1] = this.laLoSel.getLongitude(); 964 } else { 965 coords[0] = (double)this.laLoSel.getLine(); 966 coords[1] = (double)this.laLoSel.getElement(); 967 } 968 969 // turns out that laLoSel is reused for datachoices 970 // from the same source. if you don't update laLoSel's 971 // dataChoice, it'll apply whatever data selection 972 // you set up... to the first data choice that you 973 // loaded! (and causing an NPE when attempting to 974 // bundle the dataselection for the newly-selected 975 // datachoice. 976 this.previewSel.setDataChoice(dataChoice); 977 this.laLoSel.setDataChoice(dataChoice); 978 this.laLoSel.setPreviewLineRes(this.previewLineRes); 979 this.laLoSel.setPreviewEleRes(this.previewEleRes); 980 this.laLoSel.update(previewDir, this.previewProjection, previewNav, 981 coordType, coords); 982 983 } else { 984 this.laLoSel = new GeoLatLonSelection(this, 985 dataChoice, this.initProps, this.previewProjection, 986 previewDir, previewNav); 987 this.lineMag = this.laLoSel.getLineMag(); 988 this.elementMag = this.laLoSel.getElementMag(); 989 } 990 } else { 991 if (this.laLoSel != null) { 992 this.previewSel.setDataChoice(dataChoice); 993 this.laLoSel.setDataChoice(dataChoice); 994 } 995 } 996 /* DAVEP: Force preview on. "No preview" means blank image */ 997// this.previewSel = new GeoPreviewSelection(this, dataChoice, this.previewImage, 998// this.laLoSel, this.previewProjection, 999// this.lineMag, this.elementMag, this.showPreview); 1000 logger.trace("even reaching this point?"); 1001 this.previewSel = new GeoPreviewSelection(this, dataChoice, this.previewImage, 1002 this.laLoSel, this.previewProjection, 1003 this.lineMag, this.elementMag, showPreview); 1004 logger.trace("how about this one?"); 1005 } catch (Exception e) { 1006 logger.error("problem making selection components", e); 1007 getIdv().showNormalCursor(); 1008 } 1009 this.haveDataSelectionComponents = true; 1010// replaceKey(MAG_KEY, (Object)(this.lineMag + " " + this.elementMag)); 1011 replaceKey(MAG_KEY, (this.lineMag + " " + this.elementMag)); 1012 components.add(this.previewSel); 1013 components.add(this.laLoSel); 1014 } 1015 } 1016 if (this.previewSel != null) { 1017 this.previewSel.initBox(); 1018 } 1019 getIdv().showNormalCursor(); 1020 } 1021 1022 /** 1023 * A hook to allow this data source to add data selection components 1024 * to the IDV field selector 1025 * 1026 * @param dataChoice the data choice 1027 * 1028 * @return list of components 1029 */ 1030// @Override public List<DataSelectionComponent> getDataSelectionComponents(DataChoice dataChoice) { 1031//// List<DataSelectionComponent> dataSelectionComponents = new ArrayList<DataSelectionComponent>(); 1032//// initDataSelectionComponents(dataSelectionComponents, dataChoice); 1033//// return dataSelectionComponents; 1034// return new ArrayList<DataSelectionComponent>(); 1035// } 1036 1037 private boolean makePreviewImage(DataChoice dataChoice) { 1038 logger.trace("starting with dataChoice={}", dataChoice); 1039 getIdv().showWaitCursor(); 1040 1041 boolean msgFlag = false; 1042 showPreview = saveShowPreview; 1043 List<BandInfo> bandInfos = (List<BandInfo>)getProperty(PROP_BANDINFO, (Object) null); 1044 BandInfo bi = null; 1045 1046 String saveBand = getKey(source, BAND_KEY); 1047 1048 int bandIdx = 0; 1049 1050 logger.trace("band index stuff: saveBand={}, bandIdx={}, source={}", new Object[] { saveBand, bandIdx, source }); 1051 List<TwoFacedObject> calList = null; 1052 try { 1053 Object dcObj = dataChoice.getId(); 1054 if (dcObj instanceof BandInfo) { 1055 bi = (BandInfo) dcObj; 1056 Integer bandInt = new Integer(bandInfos.indexOf(dcObj)+1); 1057 saveBand = bandInt.toString(); 1058 } else { 1059 msgFlag = true; 1060 bi = bandInfos.get(bandIdx); 1061 this.showPreview = false; 1062 } 1063 // pull out the list of cal units, we'll need for type check later... 1064 calList = bi.getCalibrationUnits(); 1065 1066 // TJJ Dec 2017 1067 // Kinda hacky (but then again so is this entire class) :-/ 1068 // Do our GEO speedup code for known GEO sensor IDs 1069 int sensorID = bi.getSensor(); 1070 if (sensorIsGEO(sensorID)) { 1071 doGeoSpeedup = true; 1072 } 1073 1074 logger.trace("replacing band: new={} from={}", bi.getBandNumber(), source); 1075// source = replaceKey(source, BAND_KEY, (Object) (bi.getBandNumber())); 1076 source = replaceKey(source, BAND_KEY, bi.getBandNumber()); 1077 // if we're replacing the band, replace cal type with preferred 1078 // type for that band 1079 logger.trace("replacing unit: new={} from={}", bi.getPreferredUnit(), source); 1080// source = replaceKey(source, UNIT_KEY, (Object) bi.getPreferredUnit()); 1081 source = replaceKey(source, UNIT_KEY, bi.getPreferredUnit()); 1082 } catch (Exception excp) { 1083 handlePreviewImageError(1, excp); 1084 } 1085 String name = dataChoice.getName(); 1086 int idx = name.lastIndexOf('_'); 1087 String unit = name.substring(idx + 1); 1088 1089 // if this is not a valid cal unit (e.g. could be set to a plugin formula name) 1090 // set it to something valid 1091 boolean validCal = false; 1092 for (TwoFacedObject tfo : calList) { 1093 if (unit.equals((String) tfo.getId())) { 1094 validCal = true; 1095 break; 1096 } 1097 } 1098 if (!validCal) { 1099 unit = bi.getPreferredUnit(); 1100 } 1101 1102 if (getKey(source, UNIT_KEY).length() == 0) { 1103 logger.trace("non-empty unit, replacing: new={} from={}", unit, source); 1104// source = replaceKey(source, UNIT_KEY, (Object)(unit)); 1105 source = replaceKey(source, UNIT_KEY, unit); 1106 } 1107 1108 AddeImageDescriptor aid = null; 1109 while (aid == null) { 1110 try { 1111 logger.trace("creating new AddeImageDescriptor from {}", this.source); 1112 aid = new AddeImageDescriptor(this.source); 1113 } catch (Exception excp) { 1114 msgFlag = true; 1115 if (bandIdx > (bandInfos.size() - 1)) { 1116 getIdv().showNormalCursor(); 1117 return false; 1118 } 1119 1120 bi = bandInfos.get(bandIdx); 1121 logger.trace("replacing band: new={} from={}", bi.getBandNumber(), source); 1122// source = replaceKey(source, BAND_KEY, (Object)(bi.getBandNumber())); 1123 source = replaceKey(source, BAND_KEY, bi.getBandNumber()); 1124 ++bandIdx; 1125 } 1126 } 1127// previewDir = getPreviewDirectory(aid); 1128 AddeImageDescriptor previewDescriptor = getPreviewDirectory(aid); 1129 previewDir = previewDescriptor.getDirectory(); 1130 logger.trace("using previewDir={}", previewDir); 1131// try { 1132// logger.trace("preview areadir: stlines={} stelements={} lines={} elements={}", new Object[] { previewDir.getValue(AreaFile.AD_STLINE), previewDir.getValue(AreaFile.AD_STELEM), previewDir.getLines(), previewDir.getElements() }); 1133// } catch (Exception e) { 1134// logger.error("error logging areadir preview", e); 1135// } 1136 int eMag = 1; 1137 int lMag = 1; 1138 int eSize = 1; 1139 int lSize = 1; 1140 try { 1141 int plMag = 1; 1142 int peMag = 1; 1143 Object magKey = (Object) "mag"; 1144 if (sourceProps.containsKey(magKey)) { 1145 String magVal = (String)(sourceProps.get(magKey)); 1146 String[] magVals = magVal.split(" "); 1147 peMag = new Integer(magVals[0]).intValue(); 1148 plMag = new Integer(magVals[1]).intValue(); 1149 } 1150 double feSize = (double) previewDir.getElements(); 1151 double flSize = (double) previewDir.getLines(); 1152 double feMag = (double) peMag; 1153 double flMag = (double) plMag; 1154 if (feSize > flSize) { 1155 feMag = feSize / 525.0; 1156 flMag = feMag * (double) plMag / (double) peMag; 1157 } else { 1158 flMag = flSize/500.0; 1159 feMag = flMag * (double) peMag / (double) plMag; 1160 } 1161 eMag = (int) Math.ceil(feMag); 1162 lMag = (int) Math.ceil(flMag); 1163 } catch(Exception excp) { 1164 handlePreviewImageError(3, excp); 1165 } 1166 if (eMag < 1) eMag = 1; 1167 if (lMag < 1) lMag = 1; 1168 1169 eSize = 525; 1170 lSize = 500; 1171 if ((baseSource == null) || msgFlag) { 1172 logger.trace("replacing\nbaseSource={}\nsource={}", baseSource, source); 1173 baseSource = source; 1174 } 1175 this.previewLineRes = lMag; 1176 this.previewEleRes = eMag; 1177 String uLStr = "0 0 F"; 1178 // MJH getting uLStr from previewDir here breaks Himawari-8, 1179 // and is apparently unnecessary in general, so just use "0 0 F" always. 1180 // try { 1181 // int startLine = previewDir.getValue(AreaFile.AD_STLINE); 1182 // int startEle = previewDir.getValue(AreaFile.AD_STELEM); 1183 // uLStr = startLine + " " + startEle + " I"; 1184 // } catch (Exception e) { 1185 // } 1186// String src = aid.getSource(); 1187 String src = previewDescriptor.getSource(); 1188 logger.trace("building preview request from src={}", src); 1189 1190 src = removeKey(src, LATLON_KEY); 1191 src = replaceKey(src, LINELE_KEY, uLStr); 1192 src = replaceKey(src, PLACE_KEY, "ULEFT"); 1193 src = replaceKey(src, SIZE_KEY,(lSize + " " + eSize)); 1194 src = replaceKey(src, MAG_KEY, (lMag + " " + eMag)); 1195 src = replaceKey(src, BAND_KEY, bi.getBandNumber()); 1196 src = replaceKey(src, UNIT_KEY, unit); 1197// if (aid.getIsRelative()) { 1198// logger.trace("injecting POS={}", aid.getRelativeIndex()); 1199// src = replaceKey(src, "POS", (Object)aid.getRelativeIndex()); 1200// } 1201// if (previewDescriptor.getIsRelative()) { 1202// logger.trace("inject POS={} into src={}", previewDescriptor.getRelativeIndex(), src); 1203// src = replaceKey(src, "POS", (Object)previewDescriptor.getRelativeIndex()); 1204// src = replaceKey(src, "POS", previewDescriptor.getRelativeIndex()); 1205// } 1206 1207 logger.trace("creating AddeImageDescriptor from src={}", src); 1208 try { 1209 aid = new AddeImageDescriptor(src); 1210 } catch (Exception excp) { 1211 handlePreviewImageError(4, excp); 1212 src = replaceKey(src, BAND_KEY, saveBand); 1213 aid = new AddeImageDescriptor(src); 1214 src = replaceKey(src, BAND_KEY, bi.getBandNumber()); 1215 } 1216 if (msgFlag && (!"ALL".equals(saveBand))) { 1217 src = replaceKey(src, BAND_KEY, saveBand); 1218 } 1219 logger.trace("overwriting\nbaseSource={}\nsrc={}", baseSource, src); 1220 baseSource = src; 1221 getIdv().showNormalCursor(); 1222 return true; 1223 } 1224 1225 /** 1226 * Return true if the Sensor is Geostationary 1227 * 1228 * @param McIDAS Sensor Source number. 1229 * See https://www.ssec.wisc.edu/mcidas/doc/users_guide/2017.2/app_c-1.html 1230 * @return true if ID matches a defined GEO sensor 1231 */ 1232 1233 private boolean sensorIsGEO(int sensorID) { 1234 boolean isGEO = false; 1235 1236 // early GEO through FY 1237 if ((sensorID >= 12) && (sensorID <= 40)) isGEO = true; 1238 1239 // Meteosat 1240 if ((sensorID >= 51) && (sensorID <= 58)) isGEO = true; 1241 if (sensorID == 354) isGEO = true; 1242 1243 // GOES 8 - 12 1244 if ((sensorID >= 70) && (sensorID <= 79)) isGEO = true; 1245 1246 // GMS, MTSAT (which is actually pre-8 Himawari), H-8/9 1247 if ((sensorID >= 82) && (sensorID <= 86)) isGEO = true; 1248 if ((sensorID >= 286) && (sensorID <= 288)) isGEO = true; 1249 1250 // Feng Yun 1251 if ((sensorID >= 95) && (sensorID <= 97)) isGEO = true; 1252 if ((sensorID >= 275) && (sensorID <= 277)) isGEO = true; 1253 1254 // GOES 13 - 17 1255 // NOTE: Assumes GOES-17 will take the 188 to 190 slots 1256 if ((sensorID >= 180) && (sensorID <= 190)) isGEO = true; 1257 1258 // Kalpana and INSAT 1259 if ((sensorID >= 230) && (sensorID <= 232)) isGEO = true; 1260 1261 // COMS 1262 if (sensorID == 250) isGEO = true; 1263 1264 return isGEO; 1265 } 1266 1267 /** 1268 * Show the given error to the user. 1269 * 1270 * @param excp The exception 1271 */ 1272 protected void handlePreviewImageError(int flag, Exception excp) { 1273 getIdv().showNormalCursor(); 1274 LogUtil.userErrorMessage("Error in makePreviewImage e=" + flag + " " + excp); 1275 } 1276 1277 public static String removeKey(String src, String key) { 1278 String returnString = src; 1279 key = key.toUpperCase() + '='; 1280 if (returnString.contains(key)) { 1281 String[] segs = returnString.split(key); 1282 String seg0 = segs[0]; 1283 String seg1 = segs[1]; 1284 int indx = seg1.indexOf('&'); 1285 if (indx >= 0) { 1286 seg1 = seg1.substring(indx + 1); 1287 } 1288 returnString = seg0 + seg1; 1289 } 1290 return returnString; 1291 } 1292 1293 public static String replaceKey(String sourceUrl, String key, Object value) { 1294 String returnString = sourceUrl; 1295 1296 // make sure we got valid key/value pair 1297 if ((key == null) || (value == null)) { 1298 return returnString; 1299 } 1300 1301 key = key.toUpperCase() + '='; 1302 String strValue = value.toString(); 1303 if (returnString.contains(key)) { 1304 String[] segs = returnString.split(key); 1305 String seg0 = segs[0]; 1306 String seg1 = segs[1]; 1307 int indx = seg1.indexOf('&'); 1308 if (indx < 0) { 1309 seg1 = ""; 1310 } else if (indx > 0) { 1311 seg1 = seg1.substring(indx); 1312 } 1313 returnString = seg0 + key + strValue + seg1; 1314 } else { 1315 returnString = returnString + '&' + key + strValue; 1316 } 1317 1318 // if key is for cal units, and it was changed to BRIT, 1319 // must change the spacing key too 1320 if ((key.equals(UNIT_KEY + '=')) && ("BRIT".equals(strValue))) { 1321 returnString = replaceKey(returnString, SPAC_KEY, SPAC_KEY, SPACING_BRIT); 1322 } else { 1323 returnString = replaceKey(returnString, SPAC_KEY, SPAC_KEY, SPACING_NON_BRIT); 1324 } 1325 return returnString; 1326 } 1327 1328 public static String replaceKey(String src, String oldKey, String newKey, Object value) { 1329 String returnString = src; 1330 oldKey = oldKey.toUpperCase() + '='; 1331 newKey = newKey.toUpperCase() + '='; 1332 if (returnString.contains(oldKey)) { 1333 String[] segs = returnString.split(oldKey); 1334 String seg0 = segs[0]; 1335 String seg1 = segs[1]; 1336 int indx = seg1.indexOf('&'); 1337 if (indx < 0) { 1338 seg1 = ""; 1339 } else if (indx > 0) { 1340 seg1 = seg1.substring(indx); 1341 } 1342 returnString = seg0 + newKey + value.toString() + seg1; 1343 } 1344 else { 1345 returnString = returnString + '&' + newKey + value.toString(); 1346 } 1347 return returnString; 1348 } 1349 1350 private <T> void replaceKey(String key, T value) { 1351 baseSource = replaceKey(baseSource, key, value); 1352 } 1353 1354 public static String getKey(String src, String key) { 1355 String returnString = ""; 1356 key = key.toUpperCase() + '='; 1357 if (src.contains(key)) { 1358 String[] segs = src.split(key); 1359 segs = segs[1].split("&"); 1360 returnString = segs[0]; 1361 } 1362 return returnString; 1363 } 1364 1365 1366 /** 1367 * Create the set of {@link ucar.unidata.data.DataChoice} that represent 1368 * the data held by this data source. We create one top-level 1369 * {@link ucar.unidata.data.CompositeDataChoice} that represents 1370 * all of the image time steps. We create a set of children 1371 * {@link ucar.unidata.data.DirectDataChoice}, one for each time step. 1372 */ 1373 1374 public void doMakeDataChoices() { 1375 super.doMakeDataChoices(); 1376 List<BandInfo> bandInfos = (List<BandInfo>) getProperty(PROP_BANDINFO, (Object) null); 1377 String name = ""; 1378 if (this.choiceName != null) { 1379 name = this.choiceName; 1380 } 1381 if (name.length() != 0) { 1382 logger.trace("already have a name={}", name); 1383 return; 1384 } 1385 if (!sourceProps.containsKey(UNIT_KEY)) { 1386 logger.trace("sourceProps has no unit key={}", sourceProps); 1387 return; 1388 } 1389 BandInfo bi = null; 1390 if (sourceProps.containsKey(BAND_KEY)) { 1391 int bandProp = new Integer((String)(sourceProps.get(BAND_KEY))).intValue(); 1392 int bandIndex = BandInfo.findIndexByNumber(bandProp, bandInfos); 1393 bi = (BandInfo)bandInfos.get(bandIndex); 1394 if (sourceProps.containsKey(UNIT_KEY)) { 1395 bi.setPreferredUnit((String)(sourceProps.get(UNIT_KEY))); 1396 } else { 1397 bi.setPreferredUnit(""); 1398 } 1399 name = makeBandParam(bi); 1400 } 1401 else if (sourceProps.containsKey(BANDINFO_KEY)) { 1402 ArrayList al = (ArrayList) sourceProps.get(BANDINFO_KEY); 1403 bi = (BandInfo) al.get(0); 1404 name = makeBandParam(bi); 1405 } 1406 if (stashedChoices != null) { 1407 int numChoices = stashedChoices.size(); 1408 for (int i = 0; i < numChoices; i++) { 1409 DataChoice choice = (DataChoice) stashedChoices.get(i); 1410 if (name.equals(choice.getName())) { 1411 setProperty(PROP_DATACHOICENAME, choice.getName()); 1412 } 1413 } 1414 } 1415 } 1416 1417 /** 1418 * Overridden so that McIDAS-V can <i>attempt</i> to return the correct 1419 * {@code DataSelection} for the current {@code DataChoice}. 1420 */ 1421 1422 @Override public DataSelection getDataSelection() { 1423 DataSelection tmp; 1424 1425 if (this.laLoSel != null) { 1426 logger.trace("* mcv getSelForChoice: choice='{}'", this.laLoSel.getDataChoice()); 1427 tmp = this.getSelForChoice(this.laLoSel.getDataChoice()); 1428 } else { 1429 logger.trace("* idvland getDataSelection laLoSel=null: {}; choiceToSel=null: {}", (this.laLoSel==null), (this.choiceToSel==null)); 1430 tmp = super.getDataSelection(); 1431 } 1432// if (this.laLoSel == null || this.choiceToSel == null || !this.choiceToSel.containsKey(this.laLoSel.getDataChoice())) { 1433// logger.trace("* idvland getDataSelection laLoSel=null: {}; choiceToSel=null: {}", (this.laLoSel==null), (this.choiceToSel==null)); 1434// tmp = super.getDataSelection(); 1435// } else if (this.laLoSel != null) { 1436// logger.trace("* mcv getSelForChoice"); 1437// tmp = this.getSelForChoice(this.laLoSel.getDataChoice()); 1438// } 1439 if (tmp != null) { 1440 logger.trace("return selection props={} geo={}", tmp.getProperties(), tmp.getGeoSelection()); 1441 } else { 1442 logger.trace("return selection props=null geo=null choiceToSel={} :(", this.choiceToSel); 1443 } 1444 return tmp; 1445 } 1446 1447 /** 1448 * Overridden so that McIDAS-V can associate this data source's current 1449 * {@code DataChoice} with the given {@code DataSelection}. 1450 */ 1451 1452 @Override public void setDataSelection(DataSelection s) { 1453 GeoSelection tmp = s.getGeoSelection(); 1454 if (tmp != null && this.laLoSel != null) { 1455 GeoLocationInfo bbox = tmp.getBoundingBox(); 1456 GeoLocationInfo laloBbox = this.laLoSel.getGeoLocationInfo(); 1457 tmp.setBoundingBox(laloBbox); 1458 logger.trace("incoming bbox={} laLo bbox={}", bbox, laloBbox); 1459 } 1460 1461 super.setDataSelection(s); 1462 1463 if (this.laLoSel != null) { 1464// logger.trace("putting selection for choice={} s={}", this.laLoSel.getDataChoice(), s); 1465 this.putSelForChoice(this.laLoSel.getDataChoice(), s); 1466 } else { 1467 logger.trace("laLoSel is null; s={}", s); 1468 } 1469 logger.trace("setting selection props={} geo={}", s.getProperties(), s.getGeoSelection()); 1470 } 1471 1472 /** 1473 * Insert the new DataChoice into the dataChoice list. 1474 * 1475 * @param choice new choice to add 1476 */ 1477 1478 protected void addDataChoice(DataChoice choice) { 1479 logger.trace("choice={}", choice); 1480 super.addDataChoice(choice); 1481 if (stashedChoices == null) { 1482 stashedChoices = new ArrayList(); 1483 } 1484 stashedChoices.add(choice); 1485 } 1486 1487 /** 1488 * Checks to see if a given {@code AddeImageDescriptor} is based upon a 1489 * local (or remote) file. 1490 * 1491 * <p>The check is pretty simple: is {@code descriptor.getSource()} a valid 1492 * path? 1493 * 1494 * @param descriptor {@code AddeImageDescriptor} of questionable origins. Shouldn't be {@code null}. 1495 * 1496 * @return {@code true} if {@code descriptor}'s source is a valid path. 1497 */ 1498 1499 public static boolean isFromFile(final AddeImageDescriptor descriptor) { 1500 return new File(descriptor.getSource()).exists(); 1501 } 1502 1503 /** 1504 * Create the actual data represented by the given 1505 * {@link ucar.unidata.data.DataChoice}. 1506 * 1507 * @param dataChoice Either the 1508 * {@link ucar.unidata.data.CompositeDataChoice} 1509 * representing all time steps or a 1510 * {@link ucar.unidata.data.DirectDataChoice} 1511 * representing a single time step. 1512 * @param category Not really used. 1513 * @param dataSelection Defines any time subsets. 1514 * @param requestProperties extra request properties 1515 * 1516 * @return The image or image sequence data. 1517 * 1518 * @throws RemoteException Java RMI problem 1519 * @throws VisADException VisAD problem 1520 */ 1521 1522 protected Data getDataInner(DataChoice dataChoice, DataCategory category, 1523 DataSelection dataSelection, 1524 Hashtable requestProperties) 1525 throws VisADException, RemoteException { 1526 Data img = null; 1527 iml = new ArrayList(); 1528 1529 if (dataSelection == null) { 1530 return null; 1531 } 1532 setDataSelection(dataSelection); 1533 1534 GeoSelection geoSelection = dataSelection.getGeoSelection(true); 1535 if (geoSelection == null) { 1536 return null; 1537 } 1538 1539 boolean validState = geoSelection.getHasValidState(); 1540 if (!validState) { 1541 return null; 1542 } 1543 1544 if (this.lastGeoSelection == null) { 1545 this.lastGeoSelection = geoSelection; 1546 } 1547 1548 this.selectionProps = dataSelection.getProperties(); 1549 Enumeration propEnum = this.selectionProps.keys(); 1550 while (propEnum.hasMoreElements()) { 1551 String key = propEnum.nextElement().toString(); 1552 if (key.compareToIgnoreCase(LATLON_KEY) == 0) { 1553 String val = (String)this.selectionProps.get(key); 1554 if (val.contains("NaN")) { 1555 return img; 1556 } 1557 } 1558 if (key.compareToIgnoreCase(LINELE_KEY) == 0) { 1559 String val = (String)this.selectionProps.get(key); 1560 if (val.contains("NaN")) { 1561 return img; 1562 } 1563 } 1564 } 1565 1566 if (this.selectionProps.containsKey("MAG")) { 1567 String str = (String)this.selectionProps.get("MAG"); 1568 String[] strs = StringUtil.split(str, " ", 2); 1569 this.lineMag = new Integer(strs[0]).intValue(); 1570 this.elementMag = new Integer(strs[1]).intValue(); 1571 } 1572 this.choiceName = dataChoice.getName(); 1573 if (this.choiceName != null) { 1574 setProperty(PROP_DATACHOICENAME, this.choiceName); 1575 } 1576 try { 1577 img = super.getDataInner(dataChoice, category, dataSelection, requestProperties); 1578 } catch (Exception e) { 1579 String displaySrc = getDisplaySource(); 1580 if (displaySrc != null) { 1581 AddeImageDescriptor aid = new AddeImageDescriptor(displaySrc); 1582 dataChoice.setId((Object)aid); 1583 img = super.getDataInner(dataChoice, category, dataSelection, requestProperties); 1584 } 1585 } 1586 return img; 1587 } 1588 1589 /** 1590 * Check if the DataChoice has a BandInfo for its ID 1591 * 1592 * @param dataChoice choice to check 1593 * 1594 * @return true if the choice ID is a BandInfo 1595 */ 1596 1597 private boolean hasBandInfo(DataChoice dataChoice) { 1598 Object id = dataChoice.getId(); 1599 return id instanceof BandInfo; 1600 } 1601 1602 /** _more_ */ 1603 AreaDirectory[][] currentDirs; 1604 1605 /** 1606 * Create the image sequence defined by the given dataChoice. 1607 * 1608 * @param dataChoice The choice. 1609 * @param subset any time subsets. 1610 * @return The image sequence. 1611 * 1612 * @throws RemoteException Java RMI problem 1613 * @throws VisADException VisAD problem 1614 */ 1615 1616 protected ImageSequence makeImageSequence(DataChoice dataChoice, DataSelection subset) 1617 throws VisADException, RemoteException { 1618 1619// if (dataChoice.getDataSelection() == null) { 1620// dataChoice.setDataSelection(subset); 1621// } 1622 Hashtable subsetProperties = subset.getProperties(); 1623 Enumeration propEnum = subsetProperties.keys(); 1624 int numLines = 0; 1625 int numEles = 0; 1626 while (propEnum.hasMoreElements()) { 1627 String key = propEnum.nextElement().toString(); 1628 if (key.compareToIgnoreCase(SIZE_KEY) == 0) { 1629 String sizeStr = (String)(subsetProperties.get(key)); 1630 String[] vals = StringUtil.split(sizeStr, " ", 2); 1631 Integer iVal = new Integer(vals[0]); 1632 numLines = iVal.intValue(); 1633 iVal = new Integer(vals[1]); 1634 numEles = iVal.intValue(); 1635 break; 1636 } 1637 } 1638 1639 if (sampleMapProjection == null) { 1640 String addeCmdBuff = baseSource; 1641 AreaFile af = null; 1642 try { 1643 af = new AreaFile(addeCmdBuff); 1644 } catch (Exception eOpen) { 1645 logger.error("could not open area file: {}", eOpen); 1646 setInError(true); 1647 throw new BadDataException("Opening area file: " + eOpen.getMessage(), eOpen); 1648 } 1649 try { 1650 McIDASAreaProjection map = new McIDASAreaProjection(af); 1651 AREACoordinateSystem acs = new AREACoordinateSystem(af); 1652 sampleMapProjection = (MapProjection)acs; 1653 sampleProjection = map; 1654 } catch (Exception e) { 1655 logger.error("making area projection: {}", e); 1656 setInError(true); 1657 throw new BadDataException("Making area projection: " + e.getMessage(), e); 1658 } 1659 } 1660 AREACoordinateSystem macs = (AREACoordinateSystem)sampleMapProjection; 1661 int[] dirBlk = macs.getDirBlock(); 1662 if (numLines == 0) { 1663 double elelin[][] = new double[2][2]; 1664 double latlon[][] = new double[2][2]; 1665 GeoSelection gs = subset.getGeoSelection(); 1666 GeoLocationInfo gli = gs.getBoundingBox(); 1667 if ((gli == null) && (lastGeoSelection != null)) { 1668 subset.setGeoSelection(lastGeoSelection); 1669 gs = lastGeoSelection; 1670 gli = gs.getBoundingBox(); 1671 } 1672 LatLonPoint llp = gli.getUpperLeft(); 1673 latlon[0][0] = llp.getLatitude(); 1674 latlon[1][0] = llp.getLongitude(); 1675 llp = gli.getLowerRight(); 1676 latlon[0][1] = llp.getLatitude(); 1677 latlon[1][1] = llp.getLongitude(); 1678 elelin = macs.fromReference(latlon); 1679 numLines = (int)(Math.abs(elelin[1][0] - elelin[1][1]))*dirBlk[11]; 1680 numEles = (int)(Math.abs(elelin[0][1] - elelin[0][0]))*dirBlk[12]; 1681 } 1682 1683 try { 1684 descriptorsToUse = new ArrayList(); 1685 if (hasBandInfo(dataChoice)) { 1686 descriptorsToUse = getDescriptors(dataChoice, subset); 1687 } else { 1688 List choices = (dataChoice instanceof CompositeDataChoice) 1689 ? getChoicesFromSubset( 1690 (CompositeDataChoice) dataChoice, subset) 1691 : Arrays.asList(new DataChoice[] { 1692 dataChoice }); 1693 for (Iterator iter = choices.iterator(); iter.hasNext(); ) { 1694 DataChoice subChoice = (DataChoice) iter.next(); 1695 AddeImageDescriptor aid = 1696 getDescriptor(subChoice.getId()); 1697 if (aid == null) { 1698 continue; 1699 } 1700 DateTime dttm = aid.getImageTime(); 1701 if ((subset != null) && (dttm != null)) { 1702 List times = getTimesFromDataSelection(subset, 1703 dataChoice); 1704 if ((times != null) && (times.indexOf(dttm) == -1)) { 1705 continue; 1706 } 1707 } 1708 descriptorsToUse.add(aid); 1709 } 1710 } 1711 1712 if (descriptorsToUse == null || descriptorsToUse.size() == 0) { 1713 return null; 1714 } 1715 AddeImageInfo biggestPosition = null; 1716 int pos = 0; 1717 boolean anyRelative = false; 1718 // Find the descriptor with the largest position 1719 for (Iterator iter = descriptorsToUse.iterator(); iter.hasNext(); ) { 1720 AddeImageDescriptor aid = (AddeImageDescriptor) iter.next(); 1721 if (aid.getIsRelative()) { 1722 anyRelative = true; 1723 } 1724 AddeImageInfo aii = aid.getImageInfo(); 1725 1726 // Are we dealing with area files here? 1727 if (aii == null) { 1728 break; 1729 } 1730 1731 // Check if this is absolute time 1732 if ((aii.getStartDate() != null) || (aii.getEndDate() != null)) { 1733 biggestPosition = null; 1734 break; 1735 } 1736 if ((biggestPosition == null) || (Math.abs(aii.getDatasetPosition()) > pos)) { 1737 pos = Math.abs(aii.getDatasetPosition()); 1738 biggestPosition = aii; 1739 } 1740 } 1741 1742 if (getCacheDataToDisk() && anyRelative && (biggestPosition != null)) { 1743 biggestPosition.setRequestType(AddeImageInfo.REQ_IMAGEDIR); 1744 AreaDirectoryList adl = new AreaDirectoryList(biggestPosition.getURLString()); 1745 biggestPosition.setRequestType(AddeImageInfo.REQ_IMAGEDATA); 1746 currentDirs = adl.getSortedDirs(); 1747 } else { 1748 currentDirs = null; 1749 } 1750 1751 int cnt = 1; 1752 DataChoice parent = dataChoice.getParent(); 1753 final List<SingleBandedImage> images = new ArrayList<SingleBandedImage>(); 1754 MathType rangeType = null; 1755 for (Iterator iter = descriptorsToUse.iterator(); iter.hasNext(); ) { 1756 final AddeImageDescriptor aid = (AddeImageDescriptor) iter.next(); 1757 if (currentDirs != null) { 1758 int idx = Math.abs(aid.getImageInfo().getDatasetPosition()); 1759 if (idx >= currentDirs.length) { 1760 continue; 1761 } 1762 } 1763 1764 String label = ""; 1765 if (parent != null) { 1766 label = label + parent.toString() + ' '; 1767 } else { 1768 DataCategory displayCategory = dataChoice.getDisplayCategory(); 1769 if (displayCategory != null) { 1770 label = label + displayCategory + ' '; 1771 } 1772 } 1773 label = label + dataChoice.toString(); 1774 final String readLabel = "Time: " + (cnt++) + '/' 1775 + descriptorsToUse.size() + ' ' 1776 + label; 1777 1778 String src = aid.getSource(); 1779 if (!isFromFile(aid)) { 1780 try { 1781 src = replaceKey(src, LINELE_KEY, (Object)("1 1")); 1782 String sizeString = "10 10"; 1783 src = replaceKey(src, SIZE_KEY, (Object)(sizeString)); 1784 String name = dataChoice.getName(); 1785 int idx = name.lastIndexOf('_'); 1786 String unit = name.substring(idx+1); 1787 if (getKey(src, UNIT_KEY).length() == 0) { 1788 src = replaceKey(src, UNIT_KEY, (Object)(unit)); 1789 } 1790 int lSize = numLines; 1791 int eSize = numEles; 1792 sizeString = lSize + " " + eSize; 1793 src = replaceKey(src, SIZE_KEY, (Object)(sizeString)); 1794 src = replaceKey(src, MAG_KEY, (Object)(this.lineMag + " " + this.elementMag)); 1795 aid.setSource(src); 1796 } catch (Exception exc) { 1797 logger.error("error trying to adjust AddeImageDescriptor: {}", exc); 1798 super.makeImageSequence(dataChoice, subset); 1799 } 1800 } 1801 1802 try { 1803 SingleBandedImage image = makeImage(aid, rangeType, true, readLabel, subset); 1804 if (image != null) { 1805 if(rangeType==null) { 1806 rangeType = ((FunctionType) image.getType()).getRange(); 1807 } 1808 synchronized (images) { 1809 images.add(image); 1810 } 1811 } 1812 } catch (VisADException e) { 1813 logger.error("avoiding visad exception: ",e); 1814 } catch (RemoteException e) { 1815 logger.error("avoiding remote exception: ", e); 1816 } 1817 } 1818 1819 TreeMap imageMap = new TreeMap(); 1820 for (SingleBandedImage image : images) { 1821 imageMap.put(image.getStartTime(), image); 1822 } 1823 List<SingleBandedImage> sortedImages = (List<SingleBandedImage>) new ArrayList(imageMap.values()); 1824 if ((sortedImages.size() > 0) && (sortedImages.get(0) instanceof AreaImageFlatField)) { 1825 DataRange[] sampleRanges = null; 1826 Set domainSet = null; 1827 for (SingleBandedImage sbi : sortedImages) { 1828 AreaImageFlatField aiff = (AreaImageFlatField) sbi; 1829 sampleRanges = aiff.getRanges(true); 1830 if (domainSet == null) { 1831 domainSet = aiff.getDomainSet(); 1832 } 1833 if ((sampleRanges != null) && (sampleRanges.length > 0)) { 1834 for (int rangeIdx = 0; rangeIdx < sampleRanges.length; rangeIdx++) { 1835 DataRange r = sampleRanges[rangeIdx]; 1836 if (Double.isInfinite(r.getMin()) || Double.isInfinite(r.getMax())) { 1837 sampleRanges = null; 1838 break; 1839 } 1840 } 1841 } 1842 if (sampleRanges != null) { 1843 break; 1844 } 1845 } 1846 1847 if (sampleRanges != null) { 1848 for (SingleBandedImage sbi : sortedImages) { 1849 AreaImageFlatField aiff = (AreaImageFlatField) sbi; 1850 aiff.setSampleRanges(sampleRanges); 1851 aiff.setDomainIfNeeded(domainSet); 1852 } 1853 } 1854 } 1855 1856 SingleBandedImage[] imageArray = 1857 (SingleBandedImage[]) sortedImages.toArray( 1858 new SingleBandedImage[sortedImages.size()]); 1859 FunctionType imageFunction = 1860 (FunctionType) imageArray[0].getType(); 1861 FunctionType ftype = new FunctionType(RealType.Time, 1862 imageFunction); 1863 return new ImageSequenceImpl(ftype, imageArray); 1864 } catch (Exception exc) { 1865 throw new ucar.unidata.util.WrapperException(exc); 1866 } 1867 } 1868 1869 /** 1870 * Create the single image defined by the given 1871 * {@link ucar.unidata.data.imagery.AddeImageDescriptor AddeImageDescriptor}. 1872 * 1873 * @param aid Holds image directory and location of the desired image. 1874 * @param rangeType {@literal "rangeType"} to use (if non-{@code null}). 1875 * @param fromSequence _more_ 1876 * @param readLabel 1877 * @param subset geographical subsetting info 1878 * 1879 * @return The data. 1880 * 1881 * @throws RemoteException Java RMI problem 1882 * @throws VisADException VisAD problem 1883 */ 1884 1885 private SingleBandedImage makeImage(AddeImageDescriptor aid, 1886 MathType rangeType, 1887 boolean fromSequence, 1888 String readLabel, DataSelection subset) 1889 throws VisADException, RemoteException { 1890 1891 if (aid == null) { 1892 return null; 1893 } 1894 1895 logger.trace("incoming src={} DateTime={} readLabel={}", new Object[] { aid.getSource(), aid.getImageTime(), readLabel }); 1896 String src = aid.getSource(); 1897 1898 Hashtable props = subset.getProperties(); 1899 1900// String areaDirectoryKey = getKey(src, "POS"); 1901 String areaDirectoryKey = null; 1902 if (aid.getIsRelative()) { 1903 areaDirectoryKey = getKey(src, "POS"); 1904 } else { 1905 areaDirectoryKey = aid.getImageTime().toString(); 1906// areaDirectoryKey = getKey(src, "TIME"); 1907 } 1908 AreaDirectory hacked = requestIdToDirectory.get(areaDirectoryKey); 1909 1910 // it only makes sense to set the following properties for things 1911 // coming from an ADDE server 1912 if (!isFromFile(aid)) { 1913 if (props.containsKey("PLACE")) { 1914 src = replaceKey(src, "PLACE", props.get("PLACE")); 1915 } 1916 if (props.containsKey("LATLON")) { 1917 src = replaceKey(src, "LINELE", "LATLON", props.get("LATLON")); 1918 } 1919 if (props.containsKey("LINELE")) { 1920 src = removeKey(src, "LATLON"); 1921 src = replaceKey(src, "LINELE", props.get("LINELE")); 1922 } 1923 if (props.containsKey("MAG")) { 1924 src = replaceKey(src, "MAG", props.get("MAG")); 1925 } 1926 } 1927 if (hacked != null) { 1928 logger.trace("adjusted src={} areaDirectoryKey='{}' hacked lat={} lon={}", new Object[] { src, areaDirectoryKey, hacked.getCenterLatitude(), hacked.getCenterLongitude() }); 1929 } 1930 aid.setSource(src); 1931 1932 SingleBandedImage result; 1933 result = (SingleBandedImage)getCache(src); 1934 if (result != null) { 1935 setDisplaySource(src, props); 1936 return result; 1937 } 1938 1939 // For now handle non ADDE URLs here 1940 try { 1941 AddeImageInfo aii = aid.getImageInfo(); 1942 AreaDirectory areaDir = null; 1943 try { 1944 if (aii != null) { 1945 logger.trace("imageinfo={}", aii.toString()); 1946 if (currentDirs != null) { 1947 int pos = Math.abs(aii.getDatasetPosition()); 1948 int band = 0; 1949 String bandString = aii.getBand(); 1950 if ((bandString != null) && !AddeURL.ALL.equals(bandString)) { 1951 band = new Integer(bandString).intValue(); 1952 } 1953 // TODO: even though the band is non-zero we might only 1954 // get back one band 1955 band = 0; 1956 areaDir = currentDirs[currentDirs.length - pos - 1][band]; 1957 } else { 1958 // If its absolute time then just use the AD from the descriptor 1959 if ((aii.getStartDate() != null) || (aii.getEndDate() != null)) { 1960 areaDir = aid.getDirectory(); 1961 } else { 1962 } 1963 } 1964 } else { 1965 logger.trace("uh oh"); 1966 } 1967 } catch (Exception exc) { 1968 LogUtil.printMessage("error looking up area dir"); 1969 logger.error("error looking up area dir", exc); 1970 return null; 1971 } 1972 1973 if (areaDir == null) { 1974 areaDir = aid.getDirectory(); 1975 } 1976 1977 if (!getCacheDataToDisk()) { 1978 areaDir = null; 1979 } 1980 1981 if (!fromSequence || (aid.getIsRelative() && (currentDirs == null))) { 1982 areaDir = null; 1983 } 1984 1985 if (areaDir != null) { 1986 if (isFromFile(aid)) { 1987 if (rangeType == null) { 1988 result = AreaImageFlatField.createImmediate(aid, readLabel); 1989 } else { 1990 // Else, pass in the already created range type 1991 result = AreaImageFlatField.create(aid, areaDir, rangeType, readLabel); 1992 } 1993 } 1994 1995 } else { 1996 src = aid.getSource(); 1997 try { 1998 savePlace = this.laLoSel.getPlace(); 1999 saveLat = this.laLoSel.getLatitude(); 2000 saveLon = this.laLoSel.getLongitude(); 2001 saveNumLine = this.laLoSel.getNumLines(); 2002 saveNumEle = this.laLoSel.getNumEles(); 2003 saveLineMag = this.laLoSel.getLineMag(); 2004 saveEleMag = this.laLoSel.getElementMag(); 2005 } catch (Exception e) { 2006 logger.error("error reading from laLoSel", e); 2007// savePlace = getSavePlace(); 2008// this.laLoSel.setPlace(savePlace); 2009// saveLat = getSaveLat(); 2010// this.laLoSel.setLatitude(saveLat); 2011// saveLon = getSaveLon(); 2012// this.laLoSel.setLongitude(saveLon); 2013// saveNumLine = getSaveNumLine(); 2014// this.laLoSel.setNumLines(saveNumLine); 2015// saveNumEle = getSaveNumEle(); 2016// this.laLoSel.setNumEles(saveNumEle); 2017// saveLineMag = getSaveLineMag(); 2018// this.laLoSel.setLineMag(saveLineMag); 2019// saveEleMag = getSaveEleMag(); 2020// this.laLoSel.setElementMag(saveEleMag); 2021 this.laLoSel.setPlace(savePlace); 2022 this.laLoSel.setLatitude(saveLat); 2023 this.laLoSel.setLongitude(saveLon); 2024 this.laLoSel.setNumLines(saveNumLine); 2025 this.laLoSel.setNumEles(saveNumEle); 2026 this.laLoSel.setLineMag(saveLineMag); 2027 this.laLoSel.setElementMag(saveEleMag); 2028 } 2029 2030 src = replaceKey(src, PLACE_KEY, savePlace); 2031 src = removeKey(src, LINELE_KEY); 2032 if (getKey(src, LATLON_KEY).length() != 0) { 2033 String latStr = Double.toString(saveLat); 2034 if (latStr.length() > 8) { 2035 latStr = latStr.substring(0,7); 2036 } 2037 String lonStr = Double.toString(saveLon); 2038 if (lonStr.length() > 9) { 2039 lonStr = lonStr.substring(0,8); 2040 } 2041 src = replaceKey(src, LATLON_KEY, latStr + ' ' + lonStr); 2042 } 2043 src = replaceKey(src, SIZE_KEY, saveNumLine + ' ' + saveNumEle); 2044 src = replaceKey(src, MAG_KEY, saveLineMag + ' ' + saveEleMag); 2045 } 2046 2047// try { 2048// AreaAdapter aa = new AreaAdapter(src, false); 2049// logger.trace("Getting a new aa={} for src=: {}", aa, src); 2050// areaDir = previewDir; 2051// result = aa.getImage(); 2052// } catch (VisADException e) { 2053// logger.error("attempting to swallow non-fatal visad exception: ", e); 2054// } catch (java.io.IOException e) { 2055// logger.error("attempting to swallow non-fatal I/O exception: ", e); 2056// } finally { 2057// putCache(src, result); 2058// aid.setSource(src); 2059// iml.add(aid); 2060// setImageList(iml); 2061// setDisplaySource(src, props); 2062// return result; 2063// } 2064 2065 AreaAdapter aa = new AreaAdapter(src, false); 2066 logger.trace("Getting a new aa={} for src=: {}", aa, src); 2067 areaDir = previewDir; 2068 result = aa.getImage(); 2069 2070 putCache(src, result); 2071 aid.setSource(src); 2072 iml.add(aid); 2073 setImageList(iml); 2074 setDisplaySource(src, props); 2075 return result; 2076 2077 } catch (java.io.IOException ioe) { 2078 throw new VisADException("Error creating AreaAdapter", ioe); 2079 } 2080 } 2081 2082 /** 2083 * Make a parameter name for the BandInfo 2084 * 2085 * @param bi the BandInfo in question 2086 * 2087 * @return a name for the parameter 2088 */ 2089 2090 private static String makeBandParam(BandInfo bi) { 2091 return new StringBuilder() 2092 .append(bi.getSensor()) 2093 .append("_Band") 2094 .append(bi.getBandNumber()) 2095 .append('_') 2096 .append(bi.getPreferredUnit()).toString(); 2097 } 2098 2099 private static String makeBandParam(AddeImageDescriptor descriptor) { 2100 AreaDirectory areaDir = descriptor.getDirectory(); 2101 if (areaDir == null) { 2102 throw new NullPointerException("No AREA directory!"); 2103 } 2104 return new StringBuilder() 2105 .append(areaDir.getSensorID()) 2106 .append("_Band") 2107 .append(areaDir.getBands()[0]) 2108 .append('_') 2109 .append(areaDir.getCalibrationType()).toString(); 2110 } 2111 2112 /** 2113 * Get a list of descriptors from the choice and subset 2114 * 2115 * @param dataChoice Data choice 2116 * @param subset subsetting info 2117 * 2118 * @return list of descriptors matching the selection 2119 */ 2120 2121 public List getDescriptors(DataChoice dataChoice, DataSelection subset) { 2122// logger.trace("choice={} subset props={} geo={}", new Object[] { dataChoice, subset.getProperties(), subset.getGeoSelection() }); 2123 int linRes = this.lineResolution; 2124 int eleRes = this.elementResolution; 2125 int newLinRes = linRes; 2126 int newEleRes = eleRes; 2127// List<TwoFacedObject> times = getTimesFromDataSelection(subset, dataChoice); 2128 List times = getTimesFromDataSelection(subset, dataChoice); 2129 boolean usingTimeDriver = ((subset != null) && (subset.getTimeDriverTimes() != null)); 2130 if (usingTimeDriver) { 2131 times = subset.getTimeDriverTimes(); 2132 } 2133 2134// if (dataChoice.getDataSelection() == null) { 2135// logger.trace("setting datasel!"); 2136// dataChoice.setDataSelection(subset); 2137// } 2138 if ((times == null) || times.isEmpty()) { 2139 times = imageTimes; 2140 } 2141// List<AddeImageDescriptor> descriptors = new ArrayList<AddeImageDescriptor>(times.size()); 2142 List descriptors = new ArrayList(); 2143 2144 if (usingTimeDriver) { 2145 if (imageList.isEmpty()) { 2146 return imageList; 2147 } 2148 AddeImageDescriptor aid = getDescriptor(imageList.get(0)); 2149 if (aid.getImageInfo() != null) { 2150 try { 2151 AddeImageInfo aii = 2152 (AddeImageInfo) aid.getImageInfo().clone(); 2153 // set the start and end dates 2154 Collections.sort(times); 2155 DateTime start = (DateTime) times.get(0); 2156 DateTime end = (DateTime) times.get(times.size() - 1); 2157 // In ADDE, you can't specify something like DAY=2011256 2011257 TIME=23:45:00 01:45:00 2158 // and expect that to be 2011256/23:45 to 2011257 01:45. Time ranges are on a per day 2159 // basis. So, we see if the starting time is a different day than the ending day and if so, 2160 // we set the start time to be 00Z on the first day an 23:59Z on the end day. 2161 // Even worse is that for archive datasets, you can't span multiple days. So make separate 2162 // requests for each day. 2163 String startDay = UtcDate.getYMD(start); 2164 String endDay = UtcDate.getYMD(end); 2165 List<String> days = new ArrayList<>(times.size()); 2166 if (!startDay.equals(endDay)) { 2167 days = getUniqueDayStrings(times); 2168 } else { 2169 days.add(startDay); 2170 } 2171 Map<DateTime, AreaDirectory> dateDir = new HashMap<>(days.size()); 2172 List<DateTime> dirTimes = new ArrayList<>(days.size() * 10); 2173 for (String day : days) { 2174 startDay = day + " 00:00:00"; 2175 endDay = day + " 23:59:59"; 2176 start = DateTime.createDateTime(startDay, 2177 DateTime.DEFAULT_TIME_FORMAT); 2178 end = UtcDate.createDateTime(endDay, 2179 DateTime.DEFAULT_TIME_FORMAT); 2180 aii.setStartDate(new Date((long) (start 2181 .getValue(CommonUnit.secondsSinceTheEpoch) * 1000))); 2182 aii.setEndDate(new Date((long) (end 2183 .getValue(CommonUnit.secondsSinceTheEpoch) * 1000))); 2184 // make the request for the times (AreaDirectoryList) 2185 aii.setRequestType(AddeURL.REQ_IMAGEDIR); 2186 AreaDirectoryList ad; 2187 try { // we may be asking for a date that doesn't exist 2188 ad = new AreaDirectoryList(aii.getURLString()); 2189 } catch (AreaFileException afe) { 2190 // If there's an error, we just ignore it. In the 2191 // end, the descriptor list will be empty if there is no 2192 // data for any of the days. 2193 continue; 2194 2195 // TODO: This is a hack because different servers return different 2196 // messages. AREA and GINI servers seem to have "no images" in the 2197 // exception message when there are no images. 2198 //String message = afe.getMessage().toLowerCase(); 2199 //if (message.indexOf("no images") >= 0 || 2200 // message.indexOf("error generating list of files") >= 0) { 2201 // continue; 2202 //} else { 2203 // throw afe; 2204 //} 2205 2206 } 2207 AreaDirectory[][] dirs = ad.getSortedDirs(); 2208 for (int d = 0; d < dirs.length; d++) { 2209 AreaDirectory dir = dirs[d][0]; 2210 DateTime dirTime = 2211 new DateTime(dir.getNominalTime()); 2212 dateDir.put(dirTime, dir); 2213 dirTimes.add(dirTime); 2214 } 2215 } 2216 List<DateTime> matchedTimes = selectTimesFromList(subset, 2217 dirTimes, times); 2218 for (DateTime dirTime : matchedTimes) { 2219 AreaDirectory dir = dateDir.get(dirTime); 2220 // shouldn't happen, but what the hey 2221 if (dir == null) { 2222 continue; 2223 } 2224 AddeImageInfo newaii = 2225 (AddeImageInfo) aid.getImageInfo().clone(); 2226 newaii.setRequestType(aii.REQ_IMAGEDATA); 2227 newaii.setStartDate(dir.getNominalTime()); 2228 newaii.setEndDate(dir.getNominalTime()); 2229 setBandInfo(dataChoice, newaii); 2230 AddeImageDescriptor newaid = 2231 new AddeImageDescriptor(dir, 2232 newaii.getURLString(), newaii); 2233 newaid.setIsRelative(false); 2234 descriptors.add(newaid); 2235 } 2236 } catch (CloneNotSupportedException cnse) { 2237 logger.error("Unable to clone AddeImageInfo (aii)", cnse); 2238 } catch (VisADException vader) { 2239 logger.error("Unable to get date values", vader); 2240 } catch (AreaFileException afe) { 2241 logger.error("Unable to make ADDE request", afe); 2242 } catch (Exception excp) { 2243 logger.error("Exception occurred while handling time driver", excp); 2244 } 2245 // we do this so save data local will work. However, if 2246 // this then gets set to be the time driver, it would not 2247 // necessarily be correct 2248 imageList = descriptors; 2249 return descriptors; 2250 } else if (imageList != null) { 2251 return imageList; 2252 } 2253 } 2254 2255 int choiceBandNum = ((BandInfo) dataChoice.getId()).getBandNumber(); 2256 int choiceSensorId = ((BandInfo) dataChoice.getId()).getSensor(); 2257 String choicePrefUnit = ((BandInfo) dataChoice.getId()).getPreferredUnit(); 2258 for (Iterator iter = times.iterator(); iter.hasNext(); ) { 2259 Object time = iter.next(); 2260 AddeImageDescriptor found = null; 2261 AddeImageDescriptor foundTimeMatch = null; 2262 if (saveImageList.isEmpty()) { 2263 saveImageList = getImageList(); 2264 } 2265 for (Iterator iter2 = saveImageList.iterator(); iter2.hasNext(); ) { 2266 AddeImageDescriptor aid = getDescriptor(iter2.next()); 2267 if (aid != null) { 2268 if (aid.getIsRelative()) { 2269 Object id; 2270 if (time instanceof TwoFacedObject) { 2271 id = ((TwoFacedObject)time).getId(); 2272 } else { 2273 id = time; 2274 } 2275 if ((id instanceof Integer) && ((Integer)id).intValue() == aid.getRelativeIndex()) { 2276 found = aid; 2277 break; 2278 } 2279 } else { 2280 int aidBand = aid.getDirectory().getBands()[0]; 2281 int aidSensorId = aid.getDirectory().getSensorID(); 2282 String calType = aid.getDirectory().getCalibrationType(); 2283 if (foundTimeMatch == null && aid.getImageTime().equals(time)) { 2284 logger.trace("found time match {}", time); 2285 foundTimeMatch = aid; 2286 } 2287 if (aid.getImageTime().equals(time) && choiceBandNum == aidBand && choiceSensorId == aidSensorId && choicePrefUnit.equals(calType)) { 2288 // the problem is here! 2289 logger.trace("found aid={} src={}", makeBandParam(aid), aid.getSource()); 2290 logger.trace("target info: param={}", dataChoice.getName()); 2291 found = aid; 2292 break; 2293 } 2294 } 2295 } 2296 } 2297 2298 if (found == null && foundTimeMatch != null) { 2299 logger.trace("good enough!?"); 2300 found = foundTimeMatch; 2301 } 2302 2303 if (found != null) { 2304 try { 2305 AddeImageDescriptor desc = new AddeImageDescriptor(found); 2306 // Sometimes we might have a null imageinfo 2307 if (desc.getImageInfo() != null) { 2308 AddeImageInfo aii = 2309 (AddeImageInfo) desc.getImageInfo().clone(); 2310 BandInfo bi = (BandInfo) dataChoice.getId(); 2311 List<BandInfo> bandInfos = 2312 (List<BandInfo>) getProperty(PROP_BANDINFO, (Object) null); 2313 boolean hasBand = true; 2314 // If this data source has been changed after we have create a display 2315 // then the possibility exists that the bandinfo contained by the incoming 2316 // data choice might not be valid. If it isn't then default to the first 2317 // one in the list 2318 if (bandInfos != null) { 2319 hasBand = bandInfos.contains(bi); 2320 if(!hasBand) { 2321 } 2322 if(!hasBand && bandInfos.size() > 0) { 2323 bi = bandInfos.get(0); 2324 } else { 2325 //Not sure what to do here. 2326 } 2327 } 2328 aii.setBand("" + bi.getBandNumber()); 2329 aii.setPlaceValue("ULEFT"); 2330 2331 try { 2332 AddeImageDescriptor newAid = new AddeImageDescriptor(aii.getURLString()); 2333 AreaDirectory newAd = newAid.getDirectory(); 2334 newLinRes = newAd.getValue(AreaFile.AD_LINERES); 2335 newEleRes = newAd.getValue(AreaFile.AD_ELEMRES); 2336 } catch (Exception e) { 2337 logger.error("resetting resolution", e); 2338 } 2339 2340 double[][] projCoords = new double[2][2]; 2341 try { 2342 AreaDirectory ad = desc.getDirectory(); 2343 double lin = (double) ad.getValue(AreaFile.AD_STLINE); 2344 double ele = (double) ad.getValue(AreaFile.AD_STELEM); 2345 aii.setLocateKey("LINELE"); 2346 aii.setLocateValue((int)lin + " " + (int)ele); 2347 projCoords[0][0] = lin; 2348 projCoords[1][0] = ele; 2349 lin += (double)ad.getValue(AreaFile.AD_NUMLINES); 2350 ele += (double)ad.getValue(AreaFile.AD_NUMELEMS); 2351 projCoords[0][1] = lin; 2352 projCoords[1][1] = ele; 2353 } catch (Exception e) { 2354 logger.error("problem with adjusting projCoords?", e); 2355 return descriptors; 2356 } 2357 int lins = Math.abs((int)(projCoords[1][1] - projCoords[1][0])); 2358 int eles = Math.abs((int)(projCoords[0][1] - projCoords[0][0])); 2359 lins = lins*linRes/newLinRes; 2360 if (this.lineMag > 0) { 2361 lins *= this.lineMag; 2362 } else { 2363 lins /= -this.lineMag; 2364 } 2365 2366 eles = eles*eleRes/newEleRes; 2367 2368 if (elementMag > 0) { 2369 eles *= elementMag; 2370 } else { 2371 eles /= -elementMag; 2372 } 2373 2374 aii.setLines(lins); 2375 aii.setElements(eles); 2376 desc.setImageInfo(aii); 2377 desc.setSource(aii.getURLString()); 2378 } 2379 descriptors.add(desc); 2380 } catch (CloneNotSupportedException cnse) {} 2381 } 2382 } 2383 return descriptors; 2384 } 2385 2386 /** 2387 * Get the subset of the composite based on the selection 2388 * 2389 * @param choice composite choice 2390 * @param subset time selection 2391 * 2392 * @return subset list 2393 */ 2394 2395 private List getChoicesFromSubset(CompositeDataChoice choice, 2396 DataSelection subset) { 2397 List choices = choice.getDataChoices(); 2398 if (subset == null) { 2399 return choices; 2400 } 2401 List times = subset.getTimes(); 2402 if (times == null) { 2403 return choices; 2404 } 2405 times = TwoFacedObject.getIdList(times); 2406 List subChoices = new ArrayList(); 2407 Object firstTime = times.get(0); 2408 if (firstTime instanceof Integer) { 2409 for (Iterator iter = times.iterator(); iter.hasNext(); ) { 2410 subChoices.add( 2411 choices.get(((Integer) iter.next()).intValue())); 2412 } 2413 } else { // TODO: what if they are DateTimes? 2414 subChoices.addAll(choices); 2415 } 2416 return subChoices; 2417 } 2418 2419 private List<AreaDirectory> getPreviewDirectories(final AddeImageDescriptor imageDescriptor) { 2420 List<AreaDirectory> directories = new ArrayList<AreaDirectory>(imageTimes.size()); 2421 2422 return directories; 2423 } 2424 2425// private AreaDirectory getPreviewDirectory(AddeImageDescriptor aid) { 2426// AreaDirectory directory = aid.getDirectory(); 2427// AddeImageDescriptor descriptor = null; 2428// int times = imageTimes.size(); 2429// if (times == 1) { 2430// logger.trace("only looking for a single time; returning AreaDirectory grabbed from incoming AddeImageDescriptor. directory={}", directory); 2431// return directory; 2432// } 2433// String src = aid.getSource(); 2434// logger.trace("URL for incoming AddeImageDescriptor: {}", src); 2435// src = removeKey(src, LATLON_KEY); 2436// src = removeKey(src, LINELE_KEY); 2437// src = removeKey(src, PLACE_KEY); 2438// src = removeKey(src, SIZE_KEY); 2439// src = removeKey(src, UNIT_KEY); 2440// src = removeKey(src, MAG_KEY); 2441// src = removeKey(src, SPAC_KEY); 2442// src = removeKey(src, NAV_KEY); 2443// src = removeKey(src, AUX_KEY); 2444// src = removeKey(src, DOC_KEY); 2445// 2446// int maxLine = 0; 2447// int maxEle = 0; 2448// int imageSize = 0; 2449// src = src.replace("imagedata", "imagedir"); 2450// boolean isRelative = aid.getIsRelative(); 2451// for (int i=0; i<times; i++) { 2452// if (isRelative) { 2453// src = replaceKey(src, "POS", new Integer(i).toString()); 2454// } else { 2455// DateTime dt = (DateTime)imageTimes.get(i); 2456// String timeStr = dt.timeString(); 2457// timeStr = timeStr.replace("Z", " "); 2458// src = removeKey(src, "POS"); 2459// src = replaceKey(src, "TIME", timeStr + timeStr + "I"); 2460// } 2461// try { 2462// logger.trace("attempting to create AreaDirectoryList using src={}", src); 2463// AreaDirectoryList dirList = new AreaDirectoryList(src); 2464// List ad = dirList.getDirs(); 2465// AreaDirectory areaDir = (AreaDirectory)ad.get(0); 2466// logger.trace("created AreaDirectory: {}", areaDir); 2467// int lines = areaDir.getLines(); 2468// int eles = areaDir.getElements(); 2469// if (imageSize < lines*eles) { 2470// imageSize = lines * eles; 2471// maxLine = lines; 2472// maxEle = eles; 2473// directory = areaDir; 2474// descriptor = new AddeImageDescriptor(src); 2475// } 2476// } catch (Exception e) { 2477// logger.error("problem when dealing with AREA directory", e); 2478// } 2479// } 2480// logger.trace("returning AreaDirectory: {}", directory); 2481// logger.trace("could return AddeImageDescriptor:\nisRelative={}\nrelativeIndex={}\ntime={}\ndirectory={}\n", new Object[] { descriptor.getIsRelative(), descriptor.getRelativeIndex(), descriptor.getImageTime(), descriptor.getDirectory()}); 2482// return directory; 2483// } 2484 2485 private AddeImageDescriptor getPreviewDirectory(AddeImageDescriptor aid) { 2486 AreaDirectory directory = aid.getDirectory(); 2487 AddeImageDescriptor descriptor = null; 2488 int times = imageTimes.size(); 2489 if (times == 1) { 2490 logger.trace("only looking for a single time; returning AreaDirectory grabbed from incoming AddeImageDescriptor. directory={}", directory); 2491// return directory; 2492 return aid; 2493 } 2494 2495 String src = aid.getSource(); 2496 logger.trace("URL for incoming AddeImageDescriptor: {}", src); 2497 2498 src = removeKey(src, LATLON_KEY); 2499 src = removeKey(src, LINELE_KEY); 2500 src = removeKey(src, PLACE_KEY); 2501 src = removeKey(src, SIZE_KEY); 2502 src = removeKey(src, UNIT_KEY); 2503 src = removeKey(src, MAG_KEY); 2504 src = removeKey(src, SPAC_KEY); 2505 src = removeKey(src, NAV_KEY); 2506 src = removeKey(src, AUX_KEY); 2507 src = removeKey(src, DOC_KEY); 2508 2509 int maxLine = 0; 2510 int maxEle = 0; 2511 int imageSize = 0; 2512 int prevSize = 0; 2513 src = src.replace("imagedata", "imagedir"); 2514 boolean isRelative = aid.getIsRelative(); 2515 2516 List<String> previewUrls = new ArrayList<String>(times); 2517 2518 if (isRelative) { 2519 2520 // TJJ Mar 2015 - (1891, R14) 2521 // Iterate through list to determine relative position different 2522 // if the objects are VisAD DateTime instead of TwoFacedObject 2523 2524 boolean isTwoFaced = false; 2525 List<?> tmpList = getAllDateTimes(); 2526 if ((tmpList != null) && (! tmpList.isEmpty())) { 2527 Object firstItem = tmpList.get(0); 2528 if (firstItem instanceof TwoFacedObject) isTwoFaced = true; 2529 } 2530 2531 int maxIndex; 2532 if (isTwoFaced) { 2533 maxIndex = Integer.MIN_VALUE; 2534 for (TwoFacedObject tfo : (List<TwoFacedObject>) getAllDateTimes()) { 2535 int relativeIndex = ((Integer) tfo.getId()).intValue(); 2536 if (relativeIndex > maxIndex) { 2537 maxIndex = relativeIndex; 2538 } 2539 } 2540 } else { 2541 maxIndex = Integer.MIN_VALUE; 2542 int relativeIndex = 0; 2543 double maxTime = Double.MIN_VALUE; 2544 for (DateTime dt : (List<DateTime>) getAllDateTimes()) { 2545 double d = dt.getValue(); 2546 if (d > maxTime) { 2547 maxIndex = relativeIndex; 2548 maxTime = d; 2549 } 2550 relativeIndex++; 2551 } 2552 } 2553 2554// TwoFacedObject tfo = (TwoFacedObject)this.getAllDateTimes().get(0); 2555 // negate maxIndex so we can get things like POS=0 or POS=-4 2556 maxIndex = 0 - maxIndex; 2557 logger.trace("using maxIndex={}", maxIndex); 2558 src = replaceKey(src, "POS", Integer.toString(maxIndex)); 2559 previewUrls.add(src); 2560 2561 } else { 2562 for (int i = 0; i < times; i++) { 2563 DateTime dt = (DateTime)imageTimes.get(i); 2564 String timeStr = dt.timeString(); 2565 timeStr = timeStr.replace("Z", " "); 2566 src = removeKey(src, "POS"); 2567 src = replaceKey(src, "TIME", timeStr + timeStr + 'I'); 2568 logger.trace("using time value: ", timeStr + timeStr + 'I'); 2569 logger.trace("added absolute time preview url: {}", src); 2570 previewUrls.add(src); 2571 } 2572 } 2573 2574 if (! isRelative && (previewUrls.size() == 1)) { 2575 logger.trace("only a single previewUrl; returning '{}'", previewUrls.get(0)); 2576 return new AddeImageDescriptor(previewUrls.get(0)); 2577 } else { 2578 logger.trace("preparing to examine previewUrls={}", previewUrls); 2579 } 2580 2581 try { 2582 2583 // TJJ Nov 2017 2584 // As an interim speedup, for Inq #2496, we are going to binary search the list 2585 // intstead of iterating through every single URL to make large loop times 2586 // (e.g. 50 GOES-16 MESO images) more tolerable. 2587 2588 if (doGeoSpeedup) { 2589 2590 int loIdx = 0; 2591 int hiIdx = previewUrls.size() - 1; 2592 boolean directionInc = true; 2593 boolean sizeMatch = false; 2594 int iterations = 0; 2595 2596 while (! sizeMatch) { 2597 2598 String previewUrl = null; 2599 if (directionInc) { 2600 previewUrl = previewUrls.get(loIdx); 2601 loIdx++; 2602 directionInc = false; 2603 } else { 2604 previewUrl = previewUrls.get(hiIdx); 2605 hiIdx--; 2606 directionInc = true; 2607 } 2608 2609 // Sanity check - if we get to the middle, we just quit and use what we found 2610 if ((loIdx > hiIdx) && (! isRelative)) break; 2611 2612 logger.trace("attempting to create AreaDirectoryList using previewUrl={}", previewUrl); 2613 AreaDirectoryList directoryList = new AreaDirectoryList(previewUrl); 2614 logger.trace("created directoryList! size={}\n{}", directoryList.getDirs().size(), directoryList); 2615 List<AreaDirectory> areaDirectories = (List<AreaDirectory>) directoryList.getDirs(); 2616 2617 for (int i = 0; i < areaDirectories.size(); i++) { 2618 iterations++; 2619 AreaDirectory areaDirectory = areaDirectories.get(i); 2620 String pos = Integer.toString(0 - i); 2621 int lines = areaDirectory.getLines(); 2622 int elements = areaDirectory.getElements(); 2623 int currentDimensions = lines * elements; 2624 logger.trace("image pos={} lines={} elements={} lat={} lon={} startTime='{}' nominalTime='{}' currentDimensions={} areaDirectory={}", new Object[] { pos, lines, elements, areaDirectory.getCenterLatitude(), areaDirectory.getCenterLongitude(), areaDirectory.getStartTime(), areaDirectory.getNominalTime(), currentDimensions, areaDirectory }); 2625 String key = null; 2626 if (isRelative) { 2627 key = pos; 2628 } else { 2629 try { 2630 DateTime reformatted = new DateTime(areaDirectory.getNominalTime()); 2631 key = reformatted.toString(); 2632 } catch (VisADException e) { 2633 logger.error("could not reformat time string='"+areaDirectory.getNominalTime().toString()+"'", e); 2634 key = areaDirectory.getNominalTime().toString(); 2635 } 2636 } 2637 requestIdToDirectory.put(key, areaDirectory); 2638 if (imageSize < currentDimensions) { 2639 2640 imageSize = currentDimensions; 2641 maxLine = lines; 2642 maxEle = elements; 2643 directory = areaDirectory; 2644 // TODO(jon): should be grabbing coord sys from chooser setting (HOW TO DO THAT!?) 2645 String latlonString = areaDirectory.getCenterLatitude() + " " + areaDirectory.getCenterLongitude() + " E"; 2646 String largestPreviewUrl = previewUrl.replace("imagedir", "imagedata"); 2647 largestPreviewUrl = replaceKey(largestPreviewUrl, "PLACE", "CENTER"); 2648 largestPreviewUrl = replaceKey(largestPreviewUrl, "LATLON", latlonString); 2649 Hashtable dataSourceProperties = this.getProperties(); 2650 if (dataSourceProperties.containsKey("navigation")) { 2651 largestPreviewUrl = replaceKey(largestPreviewUrl, "NAV", dataSourceProperties.get("navigation")); 2652 } 2653 2654 if (isRelative) { 2655 largestPreviewUrl = replaceKey(largestPreviewUrl, "POS", pos); 2656 } else { 2657 logger.trace("need to set DAY and TIME keywords for absolute times!"); 2658 } 2659 2660 logger.trace("found new max size! old={} new={} url={}", new Object[] { imageSize, currentDimensions, largestPreviewUrl }); 2661 descriptor = new AddeImageDescriptor(areaDirectory, largestPreviewUrl); 2662 2663 } 2664 2665 if (prevSize == currentDimensions) { 2666 logger.debug("Exiting Preview URL loop after " + iterations + " iterations..."); 2667 sizeMatch = true; 2668 } 2669 prevSize = currentDimensions; 2670 } 2671 } 2672 } else { 2673 2674 // Old way - go through all preview URLs looking for largest geographic coverage 2675 2676 for (String previewUrl : previewUrls) { 2677 2678 logger.trace("attempting to create AreaDirectoryList using previewUrl={}", previewUrl); 2679 AreaDirectoryList directoryList = new AreaDirectoryList(previewUrl); 2680 logger.trace("created directoryList! size={}\n{}", directoryList.getDirs().size(), directoryList); 2681 List<AreaDirectory> areaDirectories = (List<AreaDirectory>) directoryList.getDirs(); 2682 2683 for (int i = 0; i < areaDirectories.size(); i++) { 2684 2685 AreaDirectory areaDirectory = areaDirectories.get(i); 2686 String pos = Integer.toString(0 - i); 2687 int lines = areaDirectory.getLines(); 2688 int elements = areaDirectory.getElements(); 2689 int currentDimensions = lines * elements; 2690 logger.trace("image pos={} lines={} elements={} lat={} lon={} startTime='{}' nominalTime='{}' currentDimensions={} areaDirectory={}", new Object[] { pos, lines, elements, areaDirectory.getCenterLatitude(), areaDirectory.getCenterLongitude(), areaDirectory.getStartTime(), areaDirectory.getNominalTime(), currentDimensions, areaDirectory }); 2691 String key = null; 2692 if (isRelative) { 2693 key = pos; 2694 } else { 2695 try { 2696 DateTime reformatted = new DateTime(areaDirectory.getNominalTime()); 2697 key = reformatted.toString(); 2698 } catch (VisADException e) { 2699 logger.error("could not reformat time string='"+areaDirectory.getNominalTime().toString()+"'", e); 2700 key = areaDirectory.getNominalTime().toString(); 2701 } 2702 } 2703 requestIdToDirectory.put(key, areaDirectory); 2704 if (imageSize < currentDimensions) { 2705 2706 imageSize = currentDimensions; 2707 maxLine = lines; 2708 maxEle = elements; 2709 directory = areaDirectory; 2710 // TODO(jon): should be grabbing coord sys from chooser setting (HOW TO DO THAT!?) 2711 String latlonString = areaDirectory.getCenterLatitude() + " " + areaDirectory.getCenterLongitude() + " E"; 2712 String largestPreviewUrl = previewUrl.replace("imagedir", "imagedata"); 2713 largestPreviewUrl = replaceKey(largestPreviewUrl, "PLACE", "CENTER"); 2714 largestPreviewUrl = replaceKey(largestPreviewUrl, "LATLON", latlonString); 2715 Hashtable dataSourceProperties = this.getProperties(); 2716 if (dataSourceProperties.containsKey("navigation")) { 2717 largestPreviewUrl = replaceKey(largestPreviewUrl, "NAV", dataSourceProperties.get("navigation")); 2718 } 2719 2720 if (isRelative) { 2721 largestPreviewUrl = replaceKey(largestPreviewUrl, "POS", pos); 2722 } else { 2723 logger.trace("need to set DAY and TIME keywords for absolute times!"); 2724 } 2725 2726 logger.trace("found new max size! old={} new={} url={}", new Object[] { imageSize, currentDimensions, largestPreviewUrl }); 2727 descriptor = new AddeImageDescriptor(areaDirectory, largestPreviewUrl); 2728 2729 } 2730 } 2731 } 2732 } 2733 } catch (AreaFileException areaException) { 2734 logger.error("problem when dealing with AREA directory", areaException); 2735 } 2736// for (int i = 0; i < times; i++) { 2737// if (isRelative) { 2738// src = replaceKey(src, "POS", new Integer(i).toString()); 2739// } else { 2740// DateTime dt = (DateTime)imageTimes.get(i); 2741// String timeStr = dt.timeString(); 2742// timeStr = timeStr.replace("Z", " "); 2743// src = removeKey(src, "POS"); 2744// src = replaceKey(src, "TIME", timeStr + timeStr + "I"); 2745// } 2746// // don't forget to NOT negate POS=0 2747// try { 2748// logger.trace("attempting to create AreaDirectoryList using src={}", src); 2749// AreaDirectoryList dirList = new AreaDirectoryList(src); 2750// List ad = dirList.getDirs(); 2751// AreaDirectory areaDir = (AreaDirectory)ad.get(0); 2752// logger.trace("created AreaDirectory: {}", areaDir); 2753// int lines = areaDir.getLines(); 2754// int eles = areaDir.getElements(); 2755// logger.trace("image lines={} eles={} for src={}", new Object[] { lines, eles, src }); 2756// if (imageSize < lines*eles) { 2757// logger.trace("found new max size! old={} new={}", imageSize, lines*eles); 2758// imageSize = lines * eles; 2759// maxLine = lines; 2760// maxEle = eles; 2761// directory = areaDir; 2762// descriptor = new AddeImageDescriptor(src); 2763// } 2764// } catch (Exception e) { 2765// logger.error("problem when dealing with AREA directory", e); 2766// } 2767// } 2768// 2769 2770 logger.trace("returning AreaDirectory: {}", directory); 2771// logger.trace("could return AddeImageDescriptor:\nisRelative={}\nrelativeIndex={}\ntime={}\ndirectory={}\n", new Object[] { descriptor.getIsRelative(), descriptor.getRelativeIndex(), descriptor.getImageTime(), descriptor.getDirectory()}); 2772 return descriptor; 2773 } 2774 2775 private String getServer(String urlString) { 2776 int ix = urlString.indexOf("//") + 2; 2777 String temp = urlString.substring(ix); 2778 ix = temp.indexOf("/"); 2779 String retStr = temp.substring(0, ix); 2780 return retStr; 2781 } 2782 2783 public void setDisplaySource(String src, Hashtable props) { 2784 if (!props.isEmpty()) { 2785 Enumeration propEnum = props.keys(); 2786 for (int i=0; propEnum.hasMoreElements(); i++) { 2787 String key = propEnum.nextElement().toString(); 2788 Object val = props.get(key); 2789 if (getKey(src, key).length() != 0) { 2790 src = replaceKey(src, key, val); 2791 } 2792 } 2793 } 2794 this.displaySource = src; 2795 String unit = getKey(src, UNIT_KEY); 2796 if (unit.length() != 0) { 2797 sourceProps.put(UNIT_KEY.toUpperCase(), unit); 2798 } 2799 } 2800 2801 public String getDisplaySource() { 2802 return this.displaySource; 2803 } 2804 2805 2806 private float[] getLineEleResolution(AreaDirectory ad) { 2807 logger.trace("ad: {} sensor: {}", ad, ad.getSensorID()); 2808 float[] res = {(float)1.0, (float)1.0}; 2809 int sensor = ad.getSensorID(); 2810 List lines = null; 2811 try { 2812 String buff = getUrl(); 2813 2814 lines = readTextLines(buff); 2815 if (lines == null) { 2816 return res; 2817 } 2818 2819 int gotit = -1; 2820 String[] cards = StringUtil.listToStringArray(lines); 2821 logger.trace("cards: {}", cards); 2822 2823 for (int i = 0; i < cards.length; i++) { 2824 if ( ! cards[i].startsWith("Sat ")) continue; 2825 StringTokenizer st = new StringTokenizer(cards[i]," "); 2826 String temp = st.nextToken(); // throw away the key 2827 int m = st.countTokens(); 2828 for (int k = 0; k < m; k++) { 2829 int ss = Integer.parseInt(st.nextToken().trim()); 2830 if (ss == sensor) { 2831 gotit = i; 2832 break; 2833 } 2834 } 2835 2836 if (gotit != -1) { 2837 break; 2838 } 2839 } 2840 2841 if (gotit == -1) { 2842 return res; 2843 } 2844 2845 int gotSrc = -1; 2846 for (int i = gotit; i < cards.length; i++) { 2847 if (cards[i].startsWith("EndSat")) { 2848 return res; 2849 } 2850 if (!cards[i].startsWith("B") ) { 2851 continue; 2852 } 2853 StringTokenizer tok = new StringTokenizer(cards[i]); 2854 String str = tok.nextToken(); 2855 str = tok.nextToken(); 2856 Float flt = new Float(str); 2857 res[0] = flt.floatValue(); 2858 str = tok.nextToken(); 2859 flt = new Float(str); 2860 res[1] = flt.floatValue(); 2861 return res; 2862 } 2863 } catch (Exception e) { 2864 logger.error("problem getting the line+element rez", e); 2865 } 2866 return res; 2867 } 2868 2869 /** 2870 * Read the adde text url and return the lines of text. 2871 * If unsuccessful return null. 2872 * 2873 * @param url adde url to a text file 2874 * 2875 * @return List of lines or {@code null} if in error. 2876 */ 2877 2878 protected List readTextLines(String url) { 2879 AddeTextReader reader = new AddeTextReader(url); 2880 List lines = null; 2881 if ("OK".equals(reader.getStatus())) { 2882 lines = reader.getLinesOfText(); 2883 } 2884 return lines; 2885 } 2886 2887 /** 2888 * Create the first part of the ADDE request URL 2889 * 2890 * @return ADDE URL prefix 2891 */ 2892 2893 protected String getUrl() { 2894 String str = source; 2895 str = str.replaceFirst("imagedata", "text"); 2896 int indx = str.indexOf("VERSION"); 2897 str = str.substring(0, indx); 2898 str = str.concat("file=SATBAND"); 2899 return str; 2900 } 2901 2902 public Hashtable getSourceProps() { 2903 return this.sourceProps; 2904 } 2905 2906 public void setSourceProps(Hashtable sourceProps) { 2907 this.sourceProps = sourceProps; 2908 } 2909 2910 public String getChoiceName() { 2911 return this.choiceName; 2912 } 2913 2914 public void setChoiceName(String choiceName) { 2915 this.choiceName = choiceName; 2916 } 2917 2918 public String getSavePlace() { 2919 return this.savePlace; 2920 } 2921 2922 public void setSavePlace(String savePlace) { 2923 this.savePlace = savePlace; 2924 } 2925 2926 public double getSaveLat() { 2927 return this.saveLat; 2928 } 2929 2930 public void setSaveLat(double saveLat) { 2931 this.saveLat = saveLat; 2932 } 2933 2934 public double getSaveLon() { 2935 return this.saveLon; 2936 } 2937 2938 public void setSaveLon(double saveLon) { 2939 this.saveLon = saveLon; 2940 } 2941 2942 public int getSaveNumLine() { 2943 return this.saveNumLine; 2944 } 2945 2946 public void setSaveNumLine(int saveNumLine) { 2947 this.saveNumLine = saveNumLine; 2948 } 2949 2950 public int getSaveNumEle() { 2951 return this.saveNumEle; 2952 } 2953 2954 public void setSaveNumEle(int saveNumEle) { 2955 this.saveNumEle = saveNumEle; 2956 } 2957 2958 public int getSaveLineMag() { 2959 return this.saveLineMag; 2960 } 2961 2962 public void setSaveLineMag(int saveLineMag) { 2963 this.saveLineMag = saveLineMag; 2964 } 2965 2966 public int getSaveEleMag() { 2967 return this.saveEleMag; 2968 } 2969 2970 public void setSaveEleMag(int saveEleMag) { 2971 this.saveEleMag = saveEleMag; 2972 } 2973 2974 public String getSource() { 2975 return this.source; 2976 } 2977 2978 public void setSource(String source) { 2979 this.source = source; 2980 } 2981 2982 public boolean getShowPreview() { 2983 return this.showPreview; 2984 } 2985 2986 public void setShowPreview(boolean showPreview) { 2987 this.showPreview = showPreview; 2988 } 2989 2990 public boolean getSaveShowPreview() { 2991 return this.saveShowPreview; 2992 } 2993 2994 public void setSaveShowPreview(boolean saveShowPreview) { 2995 this.saveShowPreview = saveShowPreview; 2996 } 2997 2998 private void getSaveComponents() { 2999 saveCoordType = this.laLoSel.getCoordinateType(); 3000 savePlace = this.laLoSel.getPlace(); 3001 if (saveCoordType.equals(this.laLoSel.getLatLonType())) { 3002 saveLat = this.laLoSel.getLatitude(); 3003 saveLon = this.laLoSel.getLongitude(); 3004 } 3005 saveNumLine = this.laLoSel.getNumLines(); 3006 saveNumEle = this.laLoSel.getNumEles(); 3007 saveLineMag = this.laLoSel.getLineMag(); 3008 saveEleMag = this.laLoSel.getElementMag(); 3009 } 3010 3011 /** 3012 * Return the list of times held by the DataSelection member. 3013 * 3014 * @return DataSelection times 3015 */ 3016 3017 public List getDateTimeSelection() { 3018// return super.getDateTimeSelection(); 3019 DataSelection s = getDataSelection(); 3020 if (s == null) { 3021 logger.trace("oh no getDataSelection is null :("); 3022 return null; 3023 } else { 3024 return s.getTimes(); 3025 } 3026 } 3027 3028 /** 3029 * Set the list of selected times for this data source. This is used 3030 * for XML persistence. 3031 * 3032 * @param selectedTimes List of selected times 3033 */ 3034 3035 public void setDateTimeSelection(List selectedTimes) { 3036// //Check to see if we need to convert the absolute times into an index list. 3037// if (holdsDateTimes(selectedTimes) && (timesList != null)) { 3038// selectedTimes = Misc.getIndexList(selectedTimes, 3039// getAllDateTimes()); 3040// } 3041// getDataSelection().setTimes(selectedTimes); 3042 super.setDateTimeSelection(selectedTimes); 3043 List selected = getDateTimeSelection(); 3044 logger.trace("incoming: {} result: {}", selectedTimes, selected); 3045 } 3046 3047 protected boolean canDoProgressiveResolution() { 3048 return false; 3049 } 3050 3051 public boolean getIsProgressiveResolution() { 3052 return false; 3053 } 3054 3055 public void setIsProgressiveResolution(boolean isPG) { 3056 3057 } 3058 3059 public boolean getMatchDisplayRegion() { 3060 return false; 3061 } 3062 3063 public static class BundlePreviewSelection extends DataSelectionComponent { 3064 final String label; 3065 public BundlePreviewSelection(final String label) { 3066 super(label); 3067 this.label = label; 3068 } 3069 3070 @Override protected JComponent doMakeContents() { 3071 // TODO Auto-generated method stub 3072 JPanel panel = new JPanel(); 3073 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 3074 JLabel label1 = new JLabel("Area coverage has been defined by the data bundle;"); 3075 JLabel label2 = new JLabel("further subsetting is not currently supported."); 3076 label1.setAlignmentX(Component.CENTER_ALIGNMENT); 3077 label2.setAlignmentX(Container.CENTER_ALIGNMENT); 3078 panel.add(label1); 3079 panel.add(label2); 3080 return panel; 3081 } 3082 3083 @Override public void applyToDataSelection(DataSelection dataSelection) { 3084 } 3085 3086 /** 3087 * Overridden to disable these dummy tabs from showing up in properties 3088 * dialog. 3089 */ 3090 @Override public boolean getShowInControlProperties() { 3091 return false; 3092 } 3093 } 3094}