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