001/* 002 * $Id: AddePointDataChooser.java,v 1.30 2011/03/24 16:06:32 davep Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2011 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 031package edu.wisc.ssec.mcidasv.chooser.adde; 032 033 034import static javax.swing.GroupLayout.DEFAULT_SIZE; 035import static javax.swing.GroupLayout.PREFERRED_SIZE; 036import static javax.swing.GroupLayout.Alignment.BASELINE; 037import static javax.swing.GroupLayout.Alignment.LEADING; 038import static javax.swing.LayoutStyle.ComponentPlacement.RELATED; 039 040import java.awt.IllegalComponentStateException; 041import java.awt.Point; 042import java.awt.event.ActionEvent; 043import java.awt.event.ActionListener; 044import java.text.SimpleDateFormat; 045import java.util.ArrayList; 046import java.util.Arrays; 047import java.util.Collections; 048import java.util.Date; 049import java.util.Enumeration; 050import java.util.Hashtable; 051import java.util.List; 052import java.util.SortedSet; 053import java.util.TreeSet; 054 055import javax.swing.GroupLayout; 056import javax.swing.JButton; 057import javax.swing.JComboBox; 058import javax.swing.JComponent; 059import javax.swing.JDialog; 060import javax.swing.JLabel; 061import javax.swing.JPanel; 062import javax.swing.ListSelectionModel; 063 064import org.w3c.dom.Element; 065 066import edu.wisc.ssec.mcidas.McIDASUtil; 067import edu.wisc.ssec.mcidas.adde.AddePointDataReader; 068import edu.wisc.ssec.mcidas.adde.DataSetInfo; 069 070import visad.DateTime; 071import visad.VisADException; 072 073import ucar.unidata.data.AddeUtil; 074import ucar.unidata.data.point.AddePointDataSource; 075import ucar.unidata.idv.chooser.IdvChooserManager; 076import ucar.unidata.idv.chooser.adde.AddeServer; 077import ucar.unidata.ui.DateTimePicker; 078import ucar.unidata.ui.symbol.StationModel; 079import ucar.unidata.ui.symbol.StationModelManager; 080import ucar.unidata.util.GuiUtils; 081import ucar.unidata.util.Misc; 082import ucar.unidata.util.TwoFacedObject; 083import ucar.visad.UtcDate; 084 085import edu.wisc.ssec.mcidasv.util.McVGuiUtils; 086import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Width; 087 088 089/** 090 * Selection widget for ADDE point data 091 * 092 * @author MetApps Development Team 093 * @version $Revision: 1.30 $ $Date: 2011/03/24 16:06:32 $ 094 */ 095public class AddePointDataChooser extends AddeChooser { 096 097 /** 098 * Property for the dataset name key. 099 * @see #getDatasetName() 100 */ 101 public static String DATASET_NAME_KEY = "name"; 102 103 /** Property for the data type. */ 104 public static String DATA_TYPE = "ADDE.POINT.V"; 105 106 /** Are we currently reading times */ 107 private Object readTimesTask; 108 109 /** box and label for the relative time */ 110 protected JLabel relTimeIncLabel; 111 protected JComboBox relTimeIncBox; 112 113 /** the relative time increment */ 114 private float relativeTimeIncrement = 1; 115 116 /** archive date */ 117 protected String archiveDay = null; 118 119 /** archive day button and label */ 120 protected JLabel archiveDayLabel; 121 protected JButton archiveDayBtn; 122 123 /** archive date formatter */ 124 private SimpleDateFormat archiveDayFormatter; 125 126 /** station model manager */ 127 private StationModelManager stationModelManager; 128 129 /** allowed descriptor prefix */ 130 protected String descriptorsAllowPrefix = ""; 131 132 protected boolean firstTime = true; 133 protected boolean retry = true; 134 135 /** Possibly ask for times a second time if the first sampling doesn't get any */ 136 private boolean gotObs = false; 137 protected boolean tryWithoutSampling = false; 138 139 /** 140 * Create a chooser for Adde POINT data 141 * 142 * @param mgr The chooser manager 143 * @param root The chooser.xml node 144 */ 145 public AddePointDataChooser(IdvChooserManager mgr, Element root) { 146 super(mgr, root); 147 148 this.stationModelManager = getIdv().getStationModelManager(); 149 150 relTimeIncLabel = new JLabel(" Interval:"); 151 relTimeIncBox = new JComboBox(); 152 relTimeIncBox.setToolTipText("Set the increment between relative times"); 153 relTimeIncBox.addActionListener(new ActionListener() { 154 public void actionPerformed(ActionEvent ae) { 155 JComboBox box = (JComboBox) ae.getSource(); 156 if (GuiUtils.anySelected(box)) { 157 setRelativeTimeIncrement(getRelBoxValue()); 158 } 159 } 160 }); 161 McVGuiUtils.setComponentWidth(relTimeIncBox, Width.ONEHALF); 162 163 descriptorsAllowPrefix = ""; 164 165 archiveDayBtn = GuiUtils.makeImageButton( 166 "/auxdata/ui/icons/calendar_edit.png", this, "getArchiveDay", null, 167 true); 168 archiveDayBtn.setToolTipText("Select a day for archive datasets"); 169 archiveDayLabel = new JLabel("Select day:"); 170 archiveDayFormatter = new SimpleDateFormat(UtcDate.YMD_FORMAT); 171 } 172 173 /** 174 * Do server connection stuff... override this with type-specific methods 175 */ 176 protected void readFromServer() { 177 archiveDay = null; 178 if (archiveDayLabel != null) { 179 archiveDayLabel.setText("Select day:"); 180 } 181 super.readFromServer(); 182 } 183 184 /** 185 * Generate a list of image descriptors for the descriptor list. 186 */ 187 protected void readDescriptors() { 188 try { 189 StringBuffer buff = getGroupUrl(REQ_DATASETINFO, getGroup()); 190 buff.append("&type=" + getDataType()); 191 DataSetInfo dsinfo = new DataSetInfo(buff.toString()); 192 descriptorTable = dsinfo.getDescriptionTable(); 193 194 // Only show descriptorsAllowPrefix if set 195 for (Enumeration e = descriptorTable.keys(); e.hasMoreElements();) { 196 Object key = e.nextElement(); 197 String str = (String) descriptorTable.get(key); 198 if (!descriptorsAllowPrefix.equals("") && str.indexOf(descriptorsAllowPrefix) != 0) 199 descriptorTable.remove(key); 200 } 201 202 String[] names = new String[descriptorTable.size()]; 203 Enumeration enumeration = descriptorTable.keys(); 204 for (int i = 0; enumeration.hasMoreElements(); i++) { 205 Object thisElement = enumeration.nextElement(); 206 names[i] = descriptorTable.get(thisElement).toString() + " - " + thisElement.toString(); 207 } 208 Arrays.sort(names); 209 setDescriptors(names); 210 setState(STATE_CONNECTED); 211 } catch (Exception e) { 212 handleConnectionError(e); 213 } 214 } 215 216 /** 217 * Load in an ADDE point data set based on the 218 * <code>PropertyChangeEvent<code>. 219 * 220 */ 221 public void doLoadInThread() { 222 showWaitCursor(); 223 try { 224 StationModel selectedStationModel = getSelectedStationModel(); 225 String source = getRequestUrl(); 226 227 // make properties Hashtable to hand the station name 228 // to the AddeProfilerDataSource 229 Hashtable ht = new Hashtable(); 230 getDataSourceProperties(ht); 231 ht.put(AddePointDataSource.PROP_STATIONMODELNAME, 232 selectedStationModel.getName()); 233 ht.put(DATASET_NAME_KEY, getDescriptor()); 234 ht.put(DATA_NAME_KEY, getDataName()); 235 if (source.indexOf(AddeUtil.RELATIVE_TIME) >= 0) { 236 ht.put(AddeUtil.NUM_RELATIVE_TIMES, getRelativeTimeIndices()); 237 ht.put(AddeUtil.RELATIVE_TIME_INCREMENT, 238 new Float(getRelativeTimeIncrement())); 239 } 240 241// System.out.println("makeDataSource: source=" + source); 242// System.out.println(" DATA_TYPE=" + DATA_TYPE); 243// System.out.println(" ht=" + ht); 244 makeDataSource(source, DATA_TYPE, ht); 245 saveServerState(); 246 } catch (Exception excp) { 247 logException("Unable to open ADDE point dataset", excp); 248 } 249 showNormalCursor(); 250 } 251 252 /** 253 * Show the archive dialog. This method is not meant to be called but is 254 * public by reason of implementation (or insanity). 255 */ 256 public void getArchiveDay() { 257 final JDialog dialog = GuiUtils.createDialog("Set Archive Day", true); 258 final DateTimePicker dtp = new DateTimePicker((Date) null, false); 259 if (archiveDay != null) { 260 if (archiveDayFormatter == null) { 261 archiveDayFormatter = new SimpleDateFormat(UtcDate.YMD_FORMAT); 262 } 263 Date d = null; 264 try { 265 d = archiveDayFormatter.parse(archiveDay); 266 dtp.setDate(d); 267 } catch (Exception e) { 268 logException("parsing archive day " + archiveDay, e); 269 } 270 } 271 272 ActionListener listener = new ActionListener() { 273 public void actionPerformed(ActionEvent ae) { 274 String cmd = ae.getActionCommand(); 275 if (cmd.equals(GuiUtils.CMD_REMOVE)) { 276 archiveDay = null; 277 archiveDayLabel.setText("Select day:"); 278 setDoAbsoluteTimes(true); 279 descriptorChanged(); 280 } else if (cmd.equals(GuiUtils.CMD_OK)) { 281 try { 282 DateTime dt = new DateTime(dtp.getDate()); 283 String myDay = UtcDate.getYMD(dt); 284 // archiveDayLabel.setText(UtcDate.formatUtcDate(dt, 285 // "MMM dd, yyyy")); 286 archiveDayLabel.setText(myDay); 287 } catch (Exception e) { 288 } 289 // System.out.println("archiveDay = " + archiveDay); 290 setDoAbsoluteTimes(true); 291 descriptorChanged(); 292 } 293 dialog.dispose(); 294 } 295 }; 296 297 JPanel buttons = GuiUtils.makeButtons(listener, new String[] { 298 GuiUtils.CMD_OK, GuiUtils.CMD_REMOVE, GuiUtils.CMD_CANCEL }); 299 300 JComponent contents = GuiUtils.topCenterBottom(GuiUtils.inset(GuiUtils 301 .lLabel("Please select a day for this dataset:"), 10), GuiUtils 302 .inset(dtp, 10), buttons); 303 Point p = new Point(200, 200); 304 if (archiveDayBtn != null) { 305 try { 306 p = archiveDayBtn.getLocationOnScreen(); 307 } catch (IllegalComponentStateException ice) { 308 } 309 } 310 dialog.setLocation(p); 311 dialog.getContentPane().add(contents); 312 dialog.pack(); 313 dialog.setVisible(true); 314 } 315 316 /** 317 * Get the selected station model. 318 * 319 * @return StationModel to use: defined by defaultModels list in ctor 320 */ 321 public StationModel getSelectedStationModel() { 322 StationModel returnModel = null; 323 if (isUpperAir()) 324 returnModel = this.stationModelManager.getStationModel("Observations>Upper Air"); 325 else if (isSynoptic()) 326 returnModel = this.stationModelManager.getStationModel("Observations>SYNOP"); 327 else 328 returnModel = this.stationModelManager.getStationModel("Observations>METAR"); 329 return returnModel; 330 } 331 332 /** 333 * Add the interval selector to the component. 334 * @return superclass component with extra stuff 335 */ 336 protected JPanel makeTimesPanel() { 337 JComponent extra1 = getExtraTimeComponentRelative(); 338 GuiUtils.enableTree(extra1, false); 339 JComponent extra2 = getExtraTimeComponentAbsolute(); 340 JPanel timesPanel = super.makeTimesPanel(extra1, extra2); 341 return timesPanel; 342 } 343 344 /** 345 * Get the extra time widget, but built in a different way. 346 * Designed to be put into a GroupLayout 347 */ 348 protected JComponent getExtraTimeComponentRelative() { 349 TwoFacedObject[] intervals = { 350 new TwoFacedObject("30 minute", .5f), 351 new TwoFacedObject("Hourly", 1f), 352 new TwoFacedObject("Three hourly", 3f), 353 new TwoFacedObject("Six hourly", 6f), 354 new TwoFacedObject("12 hourly", 12f), 355 new TwoFacedObject("24 hourly", 24f) 356 }; 357 358 GuiUtils.setListData(relTimeIncBox, intervals); 359 if (relTimeIncBox.getItemCount()>=2) relTimeIncBox.setSelectedIndex(1); 360 361 return McVGuiUtils.makeLabeledComponent(relTimeIncLabel, relTimeIncBox, McVGuiUtils.Position.LEFT); 362 } 363 364 /** 365 * Get the time popup widget 366 * 367 * @return a widget for selecing the day 368 */ 369 protected JComponent getExtraTimeComponentAbsolute() { 370 return null; 371// return McVGuiUtils.makeLabeledComponent(archiveDayLabel, archiveDayBtn); 372 } 373 374 /** 375 * Get the value from the relative increment box 376 * 377 * @return the selected value or a default 378 */ 379 protected float getRelBoxValue() { 380 float value = relativeTimeIncrement; 381 if (relTimeIncBox != null) { 382 Object o = relTimeIncBox.getSelectedItem(); 383 if (o != null) { 384 String val = TwoFacedObject.getIdString(o); 385 value = (float) Misc.parseNumber(val); 386 } 387 } 388 return value; 389 } 390 391 /** 392 * Get the string from the relative increment box 393 * 394 * @return the selected string or a default 395 */ 396 public String getRelBoxString() { 397 String value = ""; 398 if (relTimeIncBox != null) { 399 Object o = relTimeIncBox.getSelectedItem(); 400 if (o != null) { 401 value = TwoFacedObject.getIdString(o); 402 } 403 } 404 return value; 405 } 406 407 /** 408 * Get the request URL 409 * 410 * @return the request URL 411 */ 412 public String getRequestUrl() { 413 StringBuffer request = getGroupUrl(REQ_POINTDATA, getGroup()); 414 appendKeyValue(request, PROP_USER, getLastAddedUser()); 415 appendKeyValue(request, PROP_PROJ, getLastAddedProj()); 416 appendKeyValue(request, PROP_DESCR, getDescriptor()); 417 appendRequestSelectClause(request); 418 appendKeyValue(request, PROP_NUM, "ALL"); 419 appendKeyValue(request, PROP_POS, getDoRelativeTimes() ? "ALL" : "0"); 420 return request.toString(); 421 } 422 423 /** 424 * Get the select clause for the adde request specific to this 425 * type of data. 426 * 427 * @param buf The buffer to append to 428 */ 429 protected void appendRequestSelectClause(StringBuffer buf) { 430 StringBuffer selectValue = new StringBuffer(); 431 selectValue.append("'"); 432 selectValue.append(getDayTimeSelectString()); 433 //TODO: why is SFCHOURLY explicit here? better way to do it? 434 if (getDescriptor().equalsIgnoreCase("SFCHOURLY")) { 435 selectValue.append(";type 0"); 436 } 437 selectValue.append(";"); 438 if (isUpperAir()){ 439 selectValue.append(AddeUtil.LEVEL); 440 selectValue.append(";"); 441 } 442 selectValue.append(AddeUtil.LATLON_BOX); 443 selectValue.append("'"); 444 appendKeyValue(buf, PROP_SELECT, selectValue.toString()); 445 } 446 447 /** 448 * Check if we are ready to read times 449 * 450 * @return true if times can be read 451 */ 452 protected boolean canReadTimes() { 453 return haveDescriptorSelected(); 454 } 455 456 /** 457 * Enable or disable the GUI widgets based on what has been 458 * selected. 459 */ 460 protected void enableWidgets() { 461 boolean descriptorState = ((getState() == STATE_CONNECTED) 462 && canReadTimes()); 463 464 for (int i = 0; i < compsThatNeedDescriptor.size(); i++) { 465 JComponent comp = (JComponent) compsThatNeedDescriptor.get(i); 466 GuiUtils.enableTree(comp, descriptorState); 467 } 468 469 boolean timesOk = timesOk(); 470 471 // Require times to be selected 472 GuiUtils.enableTree(loadButton, descriptorState && timesOk); 473 474 checkTimesLists(); 475 476 enableAbsoluteTimesList(getDoAbsoluteTimes() && descriptorState); 477 478 getRelativeTimesChooser().setEnabled( !getDoAbsoluteTimes() 479 && descriptorState); 480 481 revalidate(); 482 } 483 484 /** 485 * Do we have times selected. Either we are doing absolute 486 * times and there are some selected in the list. Or we 487 * are doing relative times and we have done a connect to the 488 * server 489 * 490 * @return Do we have times 491 */ 492 public boolean timesOk() { 493 if (getDoAbsoluteTimes() && !haveTimeSelected()) { 494 return false; 495 } 496 return true; 497 } 498 499 /** 500 * Return true if selected descriptor is for SYNOPTIC data 501 */ 502 protected boolean isSynoptic() { 503 if (getDescriptor().indexOf("SYNOP") == 0) return true; 504 return false; 505 } 506 507 /** 508 * Return true if selected descriptor is for upper air 509 */ 510 protected boolean isUpperAir() { 511 if (getDescriptor().indexOf("UPPER") == 0) return true; 512 return false; 513 } 514 515 /** 516 * Return true if selected descriptor is for profiler 517 */ 518 protected boolean isProfiler() { 519 if (getDescriptor().indexOf("PROF") == 0) return true; 520 return false; 521 } 522 523 /** 524 * Update the widget with the latest data. 525 * 526 * @throws Exception On badness 527 */ 528 public void handleUpdate() throws Exception { 529 if (getState() != STATE_CONNECTED) { 530 //If not connected then update the server list 531 updateServerList(); 532 } else { 533 //If we are already connected then update the rest of the chooser 534 descriptorChanged(); 535 } 536 updateStatus(); 537 } 538 539 /** 540 * Get the request string for times particular to this chooser 541 * 542 * @return request string 543 */ 544 protected String getTimesRequest() { 545 StringBuffer buf = getGroupUrl(REQ_POINTDATA, getGroup()); 546 appendKeyValue(buf, PROP_USER, getLastAddedUser()); 547 appendKeyValue(buf, PROP_PROJ, getLastAddedProj()); 548 appendKeyValue(buf, PROP_DESCR, getDescriptor()); 549 if (!isUpperAir() && !tryWithoutSampling) { 550// appendKeyValue(buf, PROP_POS, "0"); 551 appendKeyValue(buf, PROP_POS, "ALL"); 552 appendKeyValue(buf, PROP_SELECT, "'DAY "+getJulianDay()+";LAT 38 42;LON 70 75'"); 553 } 554 else { 555 appendKeyValue(buf, PROP_SELECT, "'DAY "+getJulianDay()+"'"); 556 appendKeyValue(buf, PROP_POS, "ALL"); 557 } 558 if (getDoAbsoluteTimes()) { 559 appendKeyValue(buf, PROP_NUM, "ALL"); 560 } 561 appendKeyValue(buf, PROP_PARAM, "DAY TIME"); 562 return buf.toString(); 563 } 564 565 /** 566 * Get the current Julian day as a String 567 * 568 * @return the current day as a string (yyyyDDD) 569 */ 570 // TODO: This should really be more accessible 571 private String getJulianDay() { 572 String retString = ""; 573 try { 574 DateTime dt = new DateTime(); 575 retString = UtcDate.formatUtcDate(dt, "yyyyDDD"); 576 } catch (VisADException ve) {} 577 return retString; 578 579 } 580 581 /** 582 * This allows derived classes to provide their own name for labeling, etc. 583 * 584 * @return the dataset name 585 */ 586 public String getDataName() { 587 return "Point Data"; 588 } 589 590 /** 591 * _more_ 592 */ 593 public void doCancel() { 594 readTimesTask = null; 595 setState(STATE_UNCONNECTED); 596 super.doCancel(); 597 } 598 599 /** locking mutex */ 600 private Object MUTEX = new Object(); 601 602 /** 603 * Read the set of image times available for the current server/group/type 604 * This method is a wrapper, setting the wait cursor and wrapping the 605 * call to {@link #readTimesInner()}; in a try/catch block 606 */ 607 public void readTimes() { 608 clearTimesList(); 609 if ( !canReadTimes()) { 610 return; 611 } 612 Misc.run(new Runnable() { 613 public void run() { 614 updateStatus(); 615 showWaitCursor(); 616 try { 617 gotObs = false; 618 tryWithoutSampling = false; 619 readTimesInner(); 620 // Try again, this time not sampling by LAT/LON 621 if (!gotObs) { 622 tryWithoutSampling = true; 623 readTimesInner(); 624 } 625 } catch (Exception e) { 626 handleConnectionError(e); 627 } 628 showNormalCursor(); 629 updateStatus(); 630 } 631 }); 632 } 633 634 /** 635 * Set the list of dates/times based on the image selection 636 * 637 */ 638 protected void readTimesInner() { 639 SortedSet uniqueTimes = Collections.synchronizedSortedSet(new TreeSet()); 640 641 readTimesTask = startTask(); 642 updateStatus(); 643 Object task = readTimesTask; 644 try { 645 AddePointDataReader apr = new AddePointDataReader(getTimesRequest()); 646 //Make sure no other loads are occurred 647 boolean ok = stopTaskAndIsOk(task); 648 if ( !Misc.equals(readTimesTask, task) || !ok) { 649 return; 650 } 651 readTimesTask = null; 652 653 synchronized (MUTEX) { 654 int[][] data = apr.getData(); 655 String[] units = apr.getUnits(); 656 if ( !units[0].equals("CYD") || !units[1].equals("HMS")) { 657 throw new Exception("can't handle date/time units"); 658 } 659 int numObs = data[0].length; 660 //System.out.println("found " + numObs + " obs"); 661 // loop through and find all the unique times 662 for (int i = 0; i < numObs; i++) { 663 try { 664 DateTime dt = 665 new DateTime(McIDASUtil.mcDayTimeToSecs(data[0][i], 666 data[1][i])); 667 uniqueTimes.add(dt); 668 } catch (Exception e) {} 669 } 670 //System.out.println( 671 // "found " + uniqueTimes.size() + " unique times"); 672 if (getDoAbsoluteTimes()) { 673 if ( !uniqueTimes.isEmpty()) { 674 setAbsoluteTimes(new ArrayList(uniqueTimes)); 675 getTimesList().setSelectionMode( 676 ListSelectionModel.SINGLE_INTERVAL_SELECTION); 677 } 678 679 // Select the last n hours 680 int selectedIndex = getAbsoluteTimes().size() - 1; 681 int firstIndex = Math.max(0, selectedIndex 682 - getDefaultRelativeTimeIndex()); 683 if (selectedIndex >= 0) 684 setSelectedAbsoluteTime(selectedIndex, firstIndex); 685 } 686 if (numObs>0) gotObs=true; 687 } 688 setState(STATE_CONNECTED); 689 } catch (Exception excp) { 690 stopTask(task); 691 readTimesTask = null; 692 handleConnectionError(excp); 693 if (retry == false) return; 694 try { 695 handleUpdate(); 696 } catch (Exception e) {} 697 698 } 699 } 700 701 /** 702 * Show the given error to the user. If it was an Adde exception 703 * that was a bad server error then print out a nice message. 704 * 705 * @param excp The exception 706 */ 707 protected void handleConnectionError(Exception e) { 708 retry = false; 709 super.handleConnectionError(e); 710 } 711 712 /** 713 * Are there any times selected. 714 * 715 * @return Any times selected. 716 */ 717 protected boolean haveTimeSelected() { 718 return !getDoAbsoluteTimes() || getHaveAbsoluteTimesSelected(); 719 } 720 721 /** 722 * Create the date time selection string for the "select" clause 723 * of the ADDE URL. 724 * 725 * @return the select day and time strings 726 */ 727 protected String getDayTimeSelectString() { 728 StringBuffer buf = new StringBuffer(); 729 if (getDoAbsoluteTimes()) { 730 List times = getSelectedAbsoluteTimes(); 731 732 // no time selection is permitted as a valid choice - 733 // will then use all times today by default. 734 if (times.size() == 0) { 735 return ""; 736 } 737 738 //check for the "no times available" message 739 if (times.get(0) instanceof String) { 740 return ""; 741 } 742 743 if (archiveDay!=null) { 744 System.out.println("archiveDay: " + archiveDay); 745 try { 746 Date d = archiveDayFormatter.parse(archiveDay); 747 DateTime dt = new DateTime(d); 748 System.out.println("parsed to: " + dt.toString()); 749 buf.append("day " + UtcDate.getIYD(dt) + ";"); 750 } catch (Exception e) { 751 System.out.println("archiveDay parse error"); 752 } 753 } 754 else { System.out.println("archiveDay is null!"); } 755 756 buf.append("time "); 757 for (int i = 0; i < times.size(); i++) { 758 DateTime dt = (DateTime) times.get(i); 759 buf.append(UtcDate.getHMS(dt)); 760 if (i != times.size() - 1) { 761 buf.append(","); 762 } 763 } 764 } else { 765 buf.append(AddeUtil.RELATIVE_TIME); 766 } 767 return buf.toString(); 768 } 769 770// /** 771// * Get the name of the dataset. 772// * 773// * @return descriptive name of the dataset. 774// */ 775// public String getDatasetName() { 776// return dataTypes.getSelectedItem().toString(); 777// } 778 779 /** 780 * Get the data type for this chooser 781 * 782 * @return the type 783 */ 784 public String getDataType() { 785 return "POINT"; 786 } 787 788 /** 789 * Get the increment between times for relative time requests 790 * 791 * @return time increment (hours) 792 */ 793 public float getRelativeTimeIncrement() { 794 return relativeTimeIncrement; 795 } 796 797 /** 798 * Set the increment between times for relative time requests 799 * 800 * @param increment time increment (hours) 801 */ 802 public void setRelativeTimeIncrement(float increment) { 803 relativeTimeIncrement = increment; 804 if (relTimeIncBox != null) { 805 relTimeIncBox.setSelectedItem(new Float(relativeTimeIncrement)); 806 } 807 } 808 809 /** 810 * Update labels, enable widgets, etc. 811 */ 812 protected void updateStatus() { 813 super.updateStatus(); 814 if (readTimesTask != null) { 815 if (taskOk(readTimesTask)) { 816 setStatus("Reading available times from server"); 817 } 818 } else if (getDoAbsoluteTimes() && !haveTimeSelected()) { 819 setStatus(MSG_TIMES); 820 } 821 enableWidgets(); 822 } 823 824 825 /** 826 * Get the descriptor widget label. 827 * 828 * @return label for the descriptor widget 829 */ 830 public String getDescriptorLabel() { 831 return "Point Type"; 832 } 833 834 /** 835 * get the adde server grup type to use 836 * 837 * @return group type 838 */ 839 @Override 840 protected String getGroupType() { 841 return AddeServer.TYPE_POINT; 842 } 843 844 /** 845 * Make the UI for this selector. 846 * 847 * @return The gui 848 */ 849 public JComponent doMakeContents() { 850 JPanel myPanel = new JPanel(); 851 852 McVGuiUtils.setComponentWidth(descriptorComboBox, Width.DOUBLEDOUBLE); 853 854 JLabel stationLabel = McVGuiUtils.makeLabelRight("Station:"); 855 addServerComp(stationLabel); 856 857 JLabel timesLabel = McVGuiUtils.makeLabelRight("Times:"); 858 addDescComp(timesLabel); 859 860 JPanel timesPanel = makeTimesPanel(); 861 timesPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder()); 862 addDescComp(timesPanel); 863 864 GroupLayout layout = new GroupLayout(myPanel); 865 myPanel.setLayout(layout); 866 layout.setHorizontalGroup( 867 layout.createParallelGroup(LEADING) 868 .addGroup(layout.createSequentialGroup() 869 .addGroup(layout.createParallelGroup(LEADING) 870 .addGroup(layout.createSequentialGroup() 871 .addComponent(descriptorLabel) 872 .addGap(GAP_RELATED) 873 .addComponent(descriptorComboBox)) 874 .addGroup(layout.createSequentialGroup() 875 .addComponent(timesLabel) 876 .addGap(GAP_RELATED) 877 .addComponent(timesPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)))) 878 ); 879 layout.setVerticalGroup( 880 layout.createParallelGroup(LEADING) 881 .addGroup(layout.createSequentialGroup() 882 .addGroup(layout.createParallelGroup(BASELINE) 883 .addComponent(descriptorLabel) 884 .addComponent(descriptorComboBox)) 885 .addPreferredGap(RELATED) 886 .addGroup(layout.createParallelGroup(LEADING) 887 .addComponent(timesLabel) 888 .addComponent(timesPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))) 889 ); 890 891 setInnerPanel(myPanel); 892 return super.doMakeContents(); 893 } 894 895 public JComponent doMakeContents(boolean doesOverride) { 896 if (doesOverride) 897 return super.doMakeContents(); 898 else 899 return doMakeContents(); 900 } 901 902}