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