001/* 002 * This file is part of McIDAS-V 003 * 004 * Copyright 2007-2017 005 * Space Science and Engineering Center (SSEC) 006 * University of Wisconsin - Madison 007 * 1225 W. Dayton Street, Madison, WI 53706, USA 008 * https://www.ssec.wisc.edu/mcidas 009 * 010 * All Rights Reserved 011 * 012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 013 * some McIDAS-V source code is based on IDV and VisAD source code. 014 * 015 * McIDAS-V is free software; you can redistribute it and/or modify 016 * it under the terms of the GNU Lesser Public License as published by 017 * the Free Software Foundation; either version 3 of the License, or 018 * (at your option) any later version. 019 * 020 * McIDAS-V is distributed in the hope that it will be useful, 021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 023 * GNU Lesser Public License for more details. 024 * 025 * You should have received a copy of the GNU Lesser Public License 026 * along with this program. If not, see http://www.gnu.org/licenses. 027 */ 028 029package edu.wisc.ssec.mcidasv.chooser.adde; 030 031import static edu.wisc.ssec.mcidasv.servermanager.EntryTransforms.strToEntryType; 032import static edu.wisc.ssec.mcidasv.servermanager.AddeEntry.DEFAULT_ACCOUNT; 033import static edu.wisc.ssec.mcidasv.util.CollectionHelpers.arrList; 034import static edu.wisc.ssec.mcidasv.McIDASV.isLoopback; 035 036import static javax.swing.GroupLayout.DEFAULT_SIZE; 037import static javax.swing.GroupLayout.Alignment.BASELINE; 038import static javax.swing.GroupLayout.Alignment.LEADING; 039import static javax.swing.GroupLayout.Alignment.TRAILING; 040import static javax.swing.LayoutStyle.ComponentPlacement.RELATED; 041import static javax.swing.LayoutStyle.ComponentPlacement.UNRELATED; 042 043import java.awt.Component; 044import java.awt.Dimension; 045import java.awt.event.ActionEvent; 046import java.awt.event.ActionListener; 047import java.awt.event.ItemEvent; 048import java.awt.event.ItemListener; 049import java.awt.event.KeyEvent; 050import java.awt.event.KeyListener; 051import java.awt.event.MouseAdapter; 052import java.awt.event.MouseEvent; 053import java.io.EOFException; 054import java.io.InputStream; 055import java.net.ConnectException; 056import java.net.URL; 057import java.net.URLConnection; 058import java.util.ArrayList; 059import java.util.Arrays; 060import java.util.Collections; 061import java.util.Comparator; 062import java.util.Enumeration; 063import java.util.HashMap; 064import java.util.Hashtable; 065import java.util.LinkedHashMap; 066import java.util.List; 067import java.util.Map; 068import java.util.Objects; 069import java.util.Vector; 070import java.util.regex.Pattern; 071 072import javax.swing.GroupLayout; 073import javax.swing.JButton; 074import javax.swing.JCheckBox; 075import javax.swing.JComboBox; 076import javax.swing.JComponent; 077import javax.swing.JLabel; 078import javax.swing.JMenu; 079import javax.swing.JMenuItem; 080import javax.swing.JPanel; 081import javax.swing.JPopupMenu; 082import javax.swing.JScrollPane; 083import javax.swing.JTabbedPane; 084import javax.swing.JTextField; 085import javax.swing.SwingUtilities; 086import javax.swing.event.DocumentEvent; 087import javax.swing.event.DocumentListener; 088import javax.swing.text.BadLocationException; 089 090import edu.wisc.ssec.mcidasv.ui.MenuScroller; 091import edu.wisc.ssec.mcidasv.util.McVTextField; 092import org.bushe.swing.event.annotation.AnnotationProcessor; 093import org.bushe.swing.event.annotation.EventSubscriber; 094import org.slf4j.Logger; 095import org.slf4j.LoggerFactory; 096import org.w3c.dom.Element; 097 098import edu.wisc.ssec.mcidas.adde.AddeURLException; 099import edu.wisc.ssec.mcidas.adde.DataSetInfo; 100 101import ucar.unidata.util.IOUtil; 102import visad.DateTime; 103 104import ucar.unidata.idv.chooser.IdvChooser; 105import ucar.unidata.idv.chooser.IdvChooserManager; 106import ucar.unidata.idv.chooser.adde.AddeServer; 107import ucar.unidata.idv.chooser.adde.AddeServer.Group; 108import ucar.unidata.util.DatedThing; 109import ucar.unidata.util.GuiUtils; 110import ucar.unidata.util.LogUtil; 111import ucar.unidata.util.Misc; 112import ucar.unidata.util.PreferenceList; 113import ucar.unidata.util.StringUtil; 114import ucar.unidata.xml.XmlObjectStore; 115 116import edu.wisc.ssec.mcidasv.Constants; 117import edu.wisc.ssec.mcidasv.McIDASV; 118import edu.wisc.ssec.mcidasv.ParameterSet; 119import edu.wisc.ssec.mcidasv.PersistenceManager; 120import edu.wisc.ssec.mcidasv.servermanager.AddeAccount; 121import edu.wisc.ssec.mcidasv.servermanager.AddeEntry; 122import edu.wisc.ssec.mcidasv.servermanager.AddeEntry.EditorAction; 123import edu.wisc.ssec.mcidasv.servermanager.AddeEntry.EntrySource; 124import edu.wisc.ssec.mcidasv.servermanager.AddeEntry.EntryType; 125import edu.wisc.ssec.mcidasv.servermanager.AddeEntry.EntryValidity; 126import edu.wisc.ssec.mcidasv.servermanager.EntryStore; 127import edu.wisc.ssec.mcidasv.servermanager.EntryTransforms; 128import edu.wisc.ssec.mcidasv.servermanager.LocalEntryEditor; 129import edu.wisc.ssec.mcidasv.servermanager.RemoteAddeEntry; 130import edu.wisc.ssec.mcidasv.servermanager.RemoteEntryEditor; 131import edu.wisc.ssec.mcidasv.servermanager.TabbedAddeManager; 132import edu.wisc.ssec.mcidasv.ui.ParameterTree; 133import edu.wisc.ssec.mcidasv.ui.UIManager; 134import edu.wisc.ssec.mcidasv.util.CollectionHelpers; 135import edu.wisc.ssec.mcidasv.util.McVGuiUtils; 136import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Position; 137import edu.wisc.ssec.mcidasv.util.McVGuiUtils.TextColor; 138import edu.wisc.ssec.mcidasv.util.McVGuiUtils.Width; 139 140/** 141 * 142 * @version $Revision$ 143 */ 144public class AddeChooser extends ucar.unidata.idv.chooser.adde.AddeChooser implements Constants { 145 146 private static final Logger logger = LoggerFactory.getLogger(AddeChooser.class); 147 148 /** Label to use with the relative times {@link JTextField}. */ 149 public static final String RELATIVE_TIMES_LABEL = "Number of times: "; 150 151 /** Tooltip for the relative times {@link JTextField}. */ 152 public static final String RELATIVE_TIMES_TOOLTIP = 153 "<html>Load the N most recent images.<br/><br/>" + 154 "Values must be integers greater than zero.</html>"; 155 156 private JComboBox serverSelector; 157 158 /** List of descriptors */ 159 private PreferenceList descList; 160 161 /** Descriptor/name hashtable */ 162 protected Hashtable descriptorTable; 163 164 /** List of available descriptors. */ 165 protected List<String> descriptorList; 166 167 /** List of comments associated with list of descriptors. */ 168 protected List<String> commentList; 169 170 /** Property for the descriptor table */ 171 public static final String DESCRIPTOR_TABLE = "DESCRIPTOR_TABLE"; 172 173 /** Connect button--we need to be able to disable this */ 174 JButton connectButton = McVGuiUtils.makeImageTextButton(ICON_CONNECT_SMALL, "Connect"); 175 176 /** Parameter button--we need to be able to disable this */ 177 JButton parameterButton = 178 McVGuiUtils.makeImageButton("/edu/wisc/ssec/mcidasv/resources/icons/toolbar/document-open22.png", 179 this, "doParameters", null, "Load parameter set"); 180 181 /** Manage button */ 182 JButton manageButton = 183 McVGuiUtils.makeImageButton("/edu/wisc/ssec/mcidasv/resources/icons/toolbar/preferences-system22.png", 184 this, "doManager", null, "Manage servers"); 185 186 /** Public button--we need to draw a menu from this */ 187 JButton publicButton = 188 McVGuiUtils.makeImageButton("/edu/wisc/ssec/mcidasv/resources/icons/toolbar/show-layer-controls22.png", 189 this, "showGroups", null, "List public datasets"); 190 191 /** descriptor label */ 192 protected JLabel descriptorLabel = new JLabel(getDescriptorLabel()+":"); 193 194 /** A widget for the list of dataset descriptors */ 195 protected JComboBox descriptorComboBox = new JComboBox(); 196 197 /** The descriptor names */ 198 protected String[] descriptorNames; 199 200 /** Flag to keep from infinite looping */ 201 protected boolean ignoreDescriptorChange = false; 202 203 /** 204 * List of JComponent-s that depend on a descriptor being selected 205 * to be enabled 206 */ 207 protected ArrayList compsThatNeedDescriptor = new ArrayList(); 208 209 /** Selection label text */ 210 protected String LABEL_SELECT = " -- Select -- "; 211 212 /** Separator string */ 213 protected static String separator = "----------------"; 214 215 /** Name separator string */ 216 protected static String nameSeparator = " - "; 217 218 /** Reference back to the server manager */ 219 protected EntryStore serverManager; 220 221 public boolean allServersFlag; 222 223 /** Command for opening up the server manager */ 224 protected static final String CMD_MANAGER = "cmd.manager"; 225 226 private String lastBadServer = ""; 227 private String lastBadGroup = ""; 228 229 private String lastServerName = ""; 230 private String lastServerGroup = ""; 231 private String lastServerUser = ""; 232 private String lastServerProj = ""; 233 private AddeServer lastServer = new AddeServer(""); 234 235 private List<AddeServer> addeServers; 236 237 /** Used for parameter set restore */ 238 private static final String TAG_FOLDER = "folder"; 239 private static final String TAG_DEFAULT = "default"; 240 private static final String ATTR_NAME = "name"; 241 private static final String ATTR_SERVER = "server"; 242 private static final String ATTR_GROUP = "GROUP"; 243 private static final String ATTR_DESCRIPTOR = "DESCRIPTOR"; 244 private static final String ATTR_POS = "POS"; 245 private static final String ATTR_DAY = "DAY"; 246 private static final String ATTR_TIME = "TIME"; 247 private List restoreTimes = new ArrayList(); 248 public Element restoreElement; 249 private boolean shouldAddSource = false; 250 final JCheckBox cb = new JCheckBox("Add source",shouldAddSource); 251 252 /** Maps favorite type to the BundleTree that shows the Manage window for the type */ 253 private Hashtable parameterTrees = new Hashtable(); 254 255 /** Number of relative time steps to load */ 256 private int relativeTimes = 5; 257 258 /** 259 * Create an AddeChooser associated with an IdvChooser 260 * 261 * @param mgr The chooser manager 262 * @param root The chooser.xml node 263 */ 264 public AddeChooser(IdvChooserManager mgr, Element root) { 265 super(mgr, root); 266 AnnotationProcessor.process(this); 267 descriptorList = new ArrayList<String>(); 268 commentList = new ArrayList<String>(); 269 270 simpleMode = !getProperty(IdvChooser.ATTR_SHOWDETAILS, true); 271 272 loadButton = McVGuiUtils.makeImageTextButton(ICON_ACCEPT_SMALL, getLoadCommandName()); 273 loadButton.setActionCommand(getLoadCommandName()); 274 loadButton.addActionListener(this); 275 276 cancelButton = McVGuiUtils.makeImageButton(ICON_CANCEL, "Cancel"); 277 cancelButton.setActionCommand(GuiUtils.CMD_CANCEL); 278 cancelButton.addActionListener(this); 279 cancelButton.setEnabled(false); 280 281 serverSelector = getServerSelector(); 282 283 serverSelector.setToolTipText("Right click to manage servers"); 284 serverSelector.getEditor().getEditorComponent().addMouseListener( 285 new MouseAdapter() { 286 public void mouseReleased(MouseEvent e) { 287 if (!SwingUtilities.isRightMouseButton(e)) { 288 return; 289 } 290 291 AddeServer server = getAddeServer(); 292 if (server == null) { 293 return; 294 } 295 List<JMenuItem> items = new ArrayList<JMenuItem>(); 296 297 // Set the right-click behavior 298 if (isLocalServer()) { 299 items.add(GuiUtils.makeMenuItem("Manage local ADDE data", 300 AddeChooser.this, 301 "doManager", null)); 302 } 303 else { 304 items.add(GuiUtils.makeMenuItem("Manage ADDE servers", 305 AddeChooser.this, 306 "doManager", null)); 307 } 308 JPopupMenu popup = GuiUtils.makePopupMenu(items); 309 popup.show(serverSelector, e.getX(), e.getY()); 310 } 311 }); 312 serverSelector.setMaximumRowCount(16); 313 314 groupSelector.setToolTipText("Right click to manage servers"); 315 groupSelector.getEditor().getEditorComponent().addMouseListener( 316 new MouseAdapter() { 317 public void mouseReleased(MouseEvent e) { 318 if (!SwingUtilities.isRightMouseButton(e)) { 319 return; 320 } 321 322 AddeServer server = getAddeServer(); 323 if (server == null) { 324 return; 325 } 326 List<JMenuItem> items = new ArrayList<JMenuItem>(); 327 328 // Set the right-click behavior 329 if (isLocalServer()) { 330 items.add(GuiUtils.makeMenuItem("Manage local ADDE data", 331 AddeChooser.this, "doManager", null)); 332 } 333 else { 334 items.add(GuiUtils.makeMenuItem("Manage ADDE servers", 335 AddeChooser.this, "doManager", null)); 336 } 337 JPopupMenu popup = GuiUtils.makePopupMenu(items); 338 popup.show(groupSelector, e.getX(), e.getY()); 339 } 340 }); 341 groupSelector.setMaximumRowCount(16); 342 343 // serverManager = ((McIDASV)getIdv()).getServerManager(); 344 // serverManager.addManagedChooser(this); 345 addServerComp(descriptorLabel); 346 // addServerComp(descriptorComboBox); 347 348 descriptorComboBox.addItemListener(new ItemListener() { 349 public void itemStateChanged(ItemEvent e) { 350 if ( !ignoreDescriptorChange 351 && (e.getStateChange() == e.SELECTED)) { 352 descriptorChanged(); 353 } 354 } 355 }); 356 357 // Update the server list and load the saved state 358 updateServerList(); 359 loadServerState(); 360 361 // Default to no parameter button unless the overriding class wants one 362 hideParameterButton(); 363 } 364 365 /** 366 * Force a reload of the available servers and groups. 367 */ 368 public void updateServerList() { 369 updateServers(); 370 updateGroups(); 371 } 372 373 /** 374 * Returns a {@link java.util.Map Map} containing {@code user} and {@code proj} 375 * keys for the given {@code server/group} combination. 376 * 377 * <p>The values are either the specific ADDE account details for 378 * {@code server/group} or {@link edu.wisc.ssec.mcidasv.servermanager.AddeEntry#DEFAULT_ACCOUNT DEFAULT_ACCOUNT} 379 * values. 380 * 381 * @param server Server name. Should not be {@code null}. 382 * @param group Group name on {@code name}. Should not be {@code null}. 383 * 384 * @return {@code Map} containing the accounting details for {@code server/group}. 385 */ 386 protected Map<String, String> getAccounting(final String server, final String group) { 387 Map<String, String> acctInfo = new HashMap<String, String>(); 388 EntryStore entryStore = ((McIDASV)getIdv()).getServerManager(); 389 String strType = this.getDataType(); 390 EntryType type = strToEntryType(strType); 391 AddeAccount acct = entryStore.getAccountingFor(server, group, type); 392 acctInfo.put("user", acct.getUsername()); 393 acctInfo.put("proj", acct.getProject()); 394 return acctInfo; 395 } 396 397 /** 398 * Returns a {@link java.util.Map Map} containing {@code user} and {@code proj} 399 * keys for the given {@code server/group} combination. 400 * 401 * <p>The values are either the specific ADDE account details for 402 * {@code server/group} or {@link edu.wisc.ssec.mcidasv.servermanager.AddeEntry#DEFAULT_ACCOUNT DEFAULT_ACCOUNT} 403 * values. 404 * 405 * @param server Server name. Should not be {@code null}. 406 * @param group Group name on {@code name}. Should not be {@code null}. 407 * 408 * @return {@code Map} containing the accounting details for {@code server/group}. 409 */ 410 protected Map<String, String> getAccounting(final AddeServer server, final String group) { 411 return getAccounting(server.getName(), group); 412 } 413 414 private List<AddeServer> getManagedServers(final String type) { 415 EntryStore entryStore = ((McIDASV)getIdv()).getServerManager(); 416 return arrList(entryStore.getIdvStyleEntries(type)); 417 } 418 419 public void updateServers() { 420 Object selected = serverSelector.getSelectedItem(); 421 422 String type = getGroupType(); 423 List<AddeServer> managedServers = getManagedServers(type); 424 List<AddeServer> localList = arrList(); 425 List<AddeServer> remoteList = arrList(); 426 addeServers = CollectionHelpers.arrList(); 427 for (AddeServer server : managedServers) { 428 if (server.getIsLocal()) 429 localList.add(server); 430 else 431 remoteList.add(server); 432 } 433 434// logger.debug("{}: updateServers: local size={} contents={}", new Object[] { getDataType(), localList.size(), localList }); 435// logger.debug("{}: updateServers: remote size={} contents={}", new Object[] { getDataType(), remoteList.size(), remoteList }); 436 437 // server list doesn't need a separator if there's only remote servers 438 if (!localList.isEmpty()) { 439 addeServers.addAll(localList); 440 addeServers.add(new AddeServer(separator)); 441 } 442 Comparator<AddeServer> byServer = new ServerComparator(); 443 Collections.sort(remoteList, byServer); 444 addeServers.addAll(remoteList); 445 446 // always making this call helps to ensure the chooser stays up to date 447 // with the server manager. 448 GuiUtils.setListData(serverSelector, addeServers); 449 if (!addeServers.isEmpty()) { 450 if (selected == null || !containsServerName(addeServers, selected)) { 451 selected = serverSelector.getItemAt(0); 452// logger.debug("updateServers: selecting item at idx=0, item={} chooser={}", selected, this.getDataType()); 453 } 454 455 int index = getSelectorIndex(selected, serverSelector); 456 serverSelector.setSelectedIndex(index); 457 } 458 } 459 460 /** 461 * Searches the given {@link java.util.List List} of {@link ucar.unidata.idv.chooser.adde.AddeServer AddeServers} 462 * for {@code server}. 463 * 464 * @param servers Servers to search. {@code null} is permitted. 465 * @param server Server to search for within {@code servers}. {@code null} is permitted. 466 * 467 * @return {@code true} if {@code servers} contains {@code server} or {@code false} otherwise. 468 */ 469 protected static boolean containsServerName(final List<AddeServer> servers, final Object server) { 470 if (servers == null || server == null) { 471 return false; 472 } 473 String serverName = (server instanceof AddeServer) ? ((AddeServer)server).getName() : server.toString(); 474 for (AddeServer tmp : servers) { 475 if (tmp.getName().equals(serverName)) { 476 return true; 477 } 478 } 479 return false; 480 } 481 482 /** 483 * Searches the given {@link java.util.List List} of {@link ucar.unidata.idv.chooser.adde.AddeServer.Group Groups} 484 * for {@code group}. 485 * 486 * @param groups Groups to search. {@code null} is permitted. 487 * @param group Group to search for within {@code group}. {@code null} is permitted. 488 * 489 * @return {@code true} if {@code groups} contains {@code group} or {@code false} otherwise. 490 */ 491 protected static boolean containsGroupName(final List<Group> groups, final Object group) { 492 if (groups == null || group == null) { 493 return false; 494 } 495 String groupName = (group instanceof Group) ? ((Group)group).getName() : group.toString(); 496 for (Group tmp : groups) { 497 if (tmp.getName().equals(groupName)) { 498 return true; 499 } 500 } 501 return false; 502 } 503 504 /** 505 * Sort the groups alphabetically 506 */ 507 public void updateGroups() { 508 if (addingServer || groupSelector == null || getAddeServer() == null) 509 return; 510 511 Object selected = groupSelector.getSelectedItem(); 512 513 EntryStore servManager = ((McIDASV)getIdv()).getServerManager(); 514 515 List<Group> groups = CollectionHelpers.arrList(); 516 if (isLocalServer()) { 517 groups.addAll(servManager.getIdvStyleLocalGroups()); 518 } else { 519 String sel = null; 520 Object obj = serverSelector.getSelectedItem(); 521 if (obj instanceof String) { 522 sel = (String)obj; 523// logger.debug("updateGroups: string={} chooser={}", sel, this.getDataType()); 524 } else if (obj instanceof AddeServer) { 525 sel = ((AddeServer)obj).getName(); 526// logger.debug("updateGroups: server selection={} chooser={}", sel, this.getDataType()); 527 } else { 528 sel = obj.toString(); 529// logger.debug("updateGroups: unknown type={}; toString={}", sel.getClass().getName(), sel); 530 } 531 532 EntryType selType = strToEntryType(getGroupType()); 533 groups.addAll(servManager.getIdvStyleRemoteGroups(sel, selType)); 534 } 535// logger.trace("updateGroups: selected={} (type={}) chooser={} contents={}", new Object[] { serverSelector.getSelectedItem(), serverSelector.getSelectedItem().getClass().getName(), this.getDataType(), groups}); 536 Comparator<Group> byGroup = new GroupComparator(); 537 Collections.sort(groups, byGroup); 538 GuiUtils.setListData(groupSelector, groups); 539 if (!groups.isEmpty()) { 540 if (selected == null || !containsGroupName(groups, selected)) { 541 selected = groupSelector.getItemAt(0); 542 } 543 groupSelector.setSelectedItem(selected); 544 } 545 } 546 547 /** 548 * Load any saved server state 549 */ 550 //TODO: Make loadServerState protected in IDV, remove from here 551 private void loadServerState() { 552 if (addeServers == null) { 553// logger.debug("loadServerState: addeServers == null chooser={}", this.getDataType()); 554 return; 555 } 556 String id = getId(); 557 String[] serverState = 558 (String[]) getIdv().getStore().get(Constants.PREF_SERVERSTATE + '.' + id); 559 if (serverState == null) { 560// serverState = Constants.DEFAULT_SERVERSTATE; 561// logger.debug("loadServerState: serverState == null chooser={}",this.getDataType()); 562 return; 563 } 564 AddeServer server = AddeServer.findServer(addeServers, serverState[0]); 565 if (server == null) { 566// logger.debug("loadServerState: server == null chooser={}",this.getDataType()); 567 return; 568 } 569// logger.debug("loadServerState: selecting server={} chooser={}", server, this.getDataType()); 570 serverSelector.setSelectedItem(server); 571 setGroups(); 572 updateGroups(); 573 if (serverState[1] != null) { 574 Group group = new Group(getDataType(), serverState[1], serverState[1]); 575 int index = getSelectorIndex(group, groupSelector); 576 if (index >= 0) { 577// logger.debug("loadServerState: selecting index={} group={} chooser={}", new Object[] { index, group, this.getDataType() }); 578 groupSelector.setSelectedIndex(index); 579 } else { 580// logger.debug("loadServerState: group == null chooser={}", this.getDataType()); 581 } 582 } else { 583// logger.debug("loadServerState: serverState[1] == null chooser={}", this.getDataType()); 584 } 585 } 586 587 /** 588 * Decide if the server you're asking about is actually a separator 589 */ 590 protected static boolean isSeparator(AddeServer checkServer) { 591 if (checkServer != null) { 592 if (checkServer.getName().equals(separator)) { 593 return true; 594 } 595 } 596 return false; 597 } 598 599 /** 600 * Decide if the server you're asking about is local 601 */ 602 protected boolean isLocalServer() { 603 return isLocalServer(getAddeServer()); 604 } 605 606 protected static boolean isLocalServer(AddeServer checkServer) { 607 if (checkServer != null) { 608 return checkServer.getIsLocal(); 609 } 610 return false; 611 } 612 613 private void setBadServer(String name, String group) { 614 if (name == null) { 615 name = ""; 616 } 617 if (group == null) { 618 group = ""; 619 } 620 621 lastBadServer = name; 622 lastBadGroup = group; 623 } 624 625 private boolean isBadServer(String name, String group) { 626 assert lastBadServer != null; 627 assert lastBadGroup != null; 628 return lastBadServer.equals(name) && lastBadGroup.equals(group); 629 } 630 631 private void setLastServer(String name, String group, AddeServer server) { 632// logger.trace("name='{}' group='{}' server='{}' old: name='{}' group='{}' server='{}'", new Object[] { name, group, server, lastServerName, lastServerGroup, lastServer }); 633 if (name == null) { 634 name = ""; 635 } 636 if (group == null) { 637 group = ""; 638 } 639 if (server == null) { 640 server = new AddeServer(name); 641 Group addeGroup = new Group(getDataType(), group, group); 642 server.addGroup(addeGroup); 643 } 644 lastServerName = name; 645 lastServerGroup = group; 646 lastServer = server; 647 } 648 649 private boolean isLastServer(String name, String group) { 650 assert lastServer != null; 651 assert lastServerName != null; 652 assert lastServerGroup != null; 653 return lastServerName.equals(name) && lastServerGroup.equals(group); 654 } 655 656 @EventSubscriber(eventClass=EntryStore.Event.class) 657 public void onServerManagerDataEvent(EntryStore.Event evt) { 658 EntryStore servManager = ((McIDASV)getIdv()).getServerManager(); 659// logger.debug("onServerManagerDataEvent: evt={} server={}", evt, servManager.getLastAdded()); 660 this.updateServerList(); 661 } 662 663 @EventSubscriber(eventClass=TabbedAddeManager.Event.class) 664 public void onServerManagerWindowEvent(TabbedAddeManager.Event evt) { 665// logger.debug("onServerManagerWindowEvent: caught event bus obj"); 666 } 667 668 private boolean addingServer = false; 669 670 /** 671 * Search a given {@link JComboBox} for the index of a given object. Mostly 672 * useful for searching {@link #serverSelector} or {@link #groupSelector}. 673 * 674 * @param needle An object. {@code null} values are permitted. 675 * @param haystack {@code JComboBox} to search. {@code null} values are 676 * permitted, but return {@code -1}. 677 * 678 * @return Either the index of {@code needle} within {@code haystack}, or 679 * {@code -1} if {@code needle} could not be found (or {@code haystack} is 680 * {@code null}). 681 */ 682 protected static int getSelectorIndex(final Object needle, 683 final JComboBox haystack) 684 { 685 if (haystack == null) { 686 return -1; 687 } 688 689 String name = null; 690 if (needle instanceof AddeServer) { 691 name = ((AddeServer)needle).getName(); 692 } else if (needle instanceof Group) { 693 name = ((Group)needle).getName(); 694 } else if (needle instanceof AddeEntry) { 695 name = ((AddeEntry)needle).getAddress(); 696 } else { 697 name = needle.toString(); 698 } 699 700 if (isLoopback(name)) { 701 return 0; 702 } 703 704 for (int i = 0; i < haystack.getItemCount(); i++) { 705 Object item = haystack.getItemAt(i); 706 String tmpName; 707 if (item instanceof AddeServer) { 708 tmpName = ((AddeServer)item).getName(); 709 } else { 710 tmpName = item.toString(); 711 } 712 713 if (name.equals(tmpName)) { 714 return i; 715 } 716 } 717 return -1; 718 } 719 720 /** 721 * Get the selected AddeServer 722 * 723 * @return the server or null 724 */ 725 protected AddeServer getAddeServer() { 726 if (lastServerName != null && lastServerName.equals("unset")) { 727 return null; 728 } 729 730 Object selected = serverSelector.getSelectedItem(); 731 if ((selected != null) && (selected instanceof AddeServer)) { 732 AddeServer server = (AddeServer)selected; 733 String group = getGroup(true); 734 Map<String, String> accounting = getAccounting(server, group); 735// logger.trace("accounting: new: u='{}' p='{}' old: u='{}' p='{}'", new Object[] { accounting.get("user"), accounting.get("proj"), lastServerUser, lastServerProj }); 736 lastServerUser = accounting.get("user"); 737 lastServerProj = accounting.get("proj"); 738 setLastServer(server.getName(), group, server); 739 return (AddeServer)selected; 740 } else if ((selected != null) && (selected instanceof String)) { 741 742 EntryStore servManager = ((McIDASV)getIdv()).getServerManager(); 743 String server = (String)selected; 744 String group = getGroup(true); 745 746 if (isBadServer(server, group)) { 747// logger.trace("getAddeServer: returning null; known bad server; server={} group={}", server, group); 748 return null; 749 } 750 751 if (isLastServer(server, group)) { 752// logger.trace("getAddeServer: returning last server name; server={} group={}", server, group); 753 return lastServer; 754 } 755 756 EditorAction editorAction = EditorAction.INVALID; 757 if (!isLoopback(server)) { 758 RemoteEntryEditor editor = new RemoteEntryEditor(servManager, server, ""); 759 editor.setVisible(true); 760 editorAction = editor.getEditorAction(); 761 } else { 762 LocalEntryEditor editor = new LocalEntryEditor(servManager, group); 763 editor.setVisible(true); 764 editorAction = editor.getEditorAction(); 765 } 766 767 int servIndex = 0; 768 int groupIndex = 0; 769 770 if (editorAction != EditorAction.CANCELLED && editorAction != EditorAction.INVALID) { 771 772 List<AddeServer> added = arrList(EntryTransforms.convertMcvServers(servManager.getLastAddedByType(strToEntryType(getDataType())))); 773 AddeServer first = null; 774 if (!added.isEmpty()) { 775 first = added.get(0); 776 servIndex = getSelectorIndex(first, serverSelector); 777 setLastServer(server, group, first); 778 } 779 780 serverSelector.setSelectedIndex(servIndex); 781 groupSelector.setSelectedIndex(groupIndex); 782// logger.trace("getAddeServer: serverIdx={} groupIdx={}", servIndex, groupIndex); 783 784 return first; 785 } else { 786// logger.trace("getAddeServer: returning null due to cancel request"); 787 setBadServer(server, group); 788 return null; 789 } 790 791 792 793 } else if (selected == null) { 794// logger.trace("getAddeServer: null object in selector; returning null"); 795 } else { 796// logger.debug("getAddeServer: unknown obj type={}; toString={}", selected.getClass().getName(), selected.toString()); 797 } 798 return null; 799 } 800 801 /** 802 * A utility to add a component to the list of components that 803 * need the descriptor 804 * 805 * @param comp The component 806 * @return The component 807 */ 808 protected JComponent addDescComp(JComponent comp) { 809 compsThatNeedDescriptor.add(comp); 810 return comp; 811 } 812 813 /** 814 * Set LABEL_SELECT from elsewhere 815 */ 816 protected void setSelectString(String string) { 817 LABEL_SELECT = string; 818 } 819 820 /** 821 * Reset the descriptor stuff 822 */ 823 protected void resetDescriptorBox() { 824 ignoreDescriptorChange = true; 825 descriptorComboBox.setSelectedItem(LABEL_SELECT); 826 ignoreDescriptorChange = false; 827 } 828 829 /** 830 * Handle when the user presses the connect button 831 * 832 * @throws Exception On badness 833 */ 834 public void handleConnect() throws Exception { 835 AddeServer server = getAddeServer(); 836 if (server == null) { 837 return; 838 } 839 setState(STATE_CONNECTING); 840 connectToServer(); 841 handleUpdate(); 842 } 843 844 /** 845 * Show the user a descriptive error message in a dialog (if in foreground 846 * mode) depending on the state of {@code e}. 847 * 848 * @param e Exception to handle. Cannot be {@code null}. 849 * 850 * @throws NullPointerException if {@code e} is {@code null}. 851 * 852 * @see #handleConnectionError(String, Exception) 853 */ 854 @Override protected void handleConnectionError(Exception e) { 855 handleConnectionError("", e); 856 } 857 858 /** 859 * Show the user a descriptive error message (with optional details) in a 860 * dialog. 861 * 862 * @param details Details about the context of {@code e}. {@code null} will 863 * be treated as an empty {@code String}. 864 * @param e Exception to handle. Cannot be {@code null}. 865 * 866 * @throws NullPointerException if {@code e} is {@code null}. 867 */ 868 protected void handleConnectionError(String details, Exception e) { 869 Objects.requireNonNull(e, "Cannot handle null exception"); 870 logger.error("attempting to handle connection error", e); 871 872 if ((details != null) && !details.isEmpty()) { 873 details = details+":\n"; 874 } else { 875 details = ""; 876 } 877 878 boolean isError = true; 879 if (e.getMessage() != null) { 880 String msg = e.getMessage(); 881 int msgPos = msg.indexOf("AddeURLException:"); 882 if ((msgPos >= 0) && (msg.length() > 18)) { 883 msg = msg.substring(msgPos + 18); 884 GuiUtils.showDialog("ADDE Error", new JLabel(details+msg)); 885 } else if (msg.indexOf("Connecting to server:localhost:") >= 0) { 886 GuiUtils.showDialog("ADDE Error", new JLabel("Local server is not responding.")); 887 } else if (msg.toLowerCase().contains("unknownhostexception")) { 888 LogUtil.userErrorMessage("Could not access server: " + getServer()); 889 } else if ((e instanceof AddeURLException) || msg.toLowerCase().contains("server unable to resolve this dataset")) { 890 handleUnknownDataSetError(); 891 } else if ((msg.toLowerCase().contains("no images satisfy")) 892 || (msg.toLowerCase().contains("error generating list of files"))) 893 { 894 LogUtil.userErrorMessage("No data available for the selection"); 895 isError = false; 896 } else { 897 LogUtil.logException("Encountered a problem (server: '" + getServer()+"'):\n"+details, e); 898 } 899 } else { 900 LogUtil.userErrorMessage("Encountered a problem (server: '" + getServer() + "'):\n" + details +e); 901 } 902 903 if (isError && (getState() == STATE_CONNECTED)) { 904 setHaveData(false); 905 resetDescriptorBox(); 906 updateStatus(); 907 setState(STATE_UNCONNECTED); 908 } 909 } 910 911 /** 912 * Handle unknown data set error 913 */ 914 @Override protected void handleUnknownDataSetError() { 915 String server = getServer(); 916 String group = getGroup(); 917 Map<String, String> acct = getAccounting(server, group); 918 String user = acct.get("user"); 919 String proj = acct.get("proj"); 920 921 StringBuilder msg = new StringBuilder("Could not connect to dataset \""); 922 msg.append(getGroup()).append("\" on server \"").append(getServer()).append("\"."); 923 if (DEFAULT_ACCOUNT.getUsername().equals(user) && DEFAULT_ACCOUNT.getProject().equals(proj)) { 924 msg.append("\n\nDataset may require ADDE accounting information."); 925 } else { 926 msg.append("\n\nAccounting information:\nusername: \"") 927 .append(user).append("\"\nproject: \"").append(proj).append('"'); 928 } 929 LogUtil.userErrorMessage(msg.toString()); 930 setState(STATE_UNCONNECTED); 931 } 932 933 /** 934 * Handle the event 935 * 936 * @param ae The event 937 */ 938 public void actionPerformed(ActionEvent ae) { 939 String cmd = ae.getActionCommand(); 940 if (cmd.equals(CMD_MANAGER)) { 941 doManager(); 942 } 943 else { 944 super.actionPerformed(ae); 945 } 946 } 947 948 /** 949 * Go directly to the Server Manager 950 */ 951 public void doManager() { 952// if (isLocalServer()) { 953// ((McIDASV)getIdv()).showAddeManager(); 954// return; 955// } 956 getIdv().getPreferenceManager().showTab(Constants.PREF_LIST_ADDE_SERVERS); 957 } 958 959 /** 960 * Show the parameter restore tree 961 */ 962 public void doParameters() { 963 JPopupMenu popup = new JPopupMenu(); 964 JMenuItem mi = new JMenuItem("Manage..."); 965 mi.addActionListener(new ActionListener() { 966 public void actionPerformed(ActionEvent ae) { 967 System.out.println(ae); 968 showParameterSetDialog(getParameterSetType()); 969 } 970 }); 971 popup.add(mi); 972 973 // Add the checkbox to automatically create a data source 974 cb.addActionListener(new ActionListener() { 975 public void actionPerformed(ActionEvent ae) { 976 shouldAddSource = cb.isSelected(); 977 } 978 }); 979 popup.addSeparator(); 980 popup.add(cb); 981 982 final PersistenceManager pm = (PersistenceManager)getIdv().getPersistenceManager(); 983 List<ParameterSet> parameterSets = pm.getAllParameterSets(getParameterSetType()); 984 985 for (int i=0; i<parameterSets.size(); i++) { 986 if (i==0) popup.addSeparator(); 987 final ParameterSet ps = parameterSets.get(i); 988 989 // Parameter set at root 990 if (ps.getCategories().size() == 0) { 991 mi = new JMenuItem(ps.getName()); 992 mi.addActionListener(new ActionListener() { 993 public void actionPerformed(ActionEvent ae) { 994 restoreParameterSet(ps.getElement()); 995 } 996 }); 997 popup.add(mi); 998 } 999 1000 // Recurse into folders 1001 else { 1002 // Find or make the menu for the given parameter set 1003 JMenu m = getPopupSubMenuForParameterSet(popup, ps); 1004 // Create parameter set entry 1005 mi = new JMenuItem(ps.getName()); 1006 mi.addActionListener(new ActionListener() { 1007 public void actionPerformed(ActionEvent ae) { 1008 restoreParameterSet(ps.getElement()); 1009 } 1010 }); 1011 m.add(mi); 1012 } 1013 1014 } 1015 1016 popup.show(parameterButton, 0, (int) parameterButton.getBounds().getHeight()); 1017 } 1018 1019 private JMenu getPopupSubMenuForParameterSet(JPopupMenu popup, final ParameterSet ps) { 1020 List<String> menuNames = ps.getCategories(); 1021 if (menuNames.size() < 1) return null; 1022 1023 // Build the complete menu 1024 String menuName = menuNames.get(0); 1025 menuNames.remove(0); 1026 JMenu theMenu = new JMenu(); 1027 1028 // Look for the menu in popup 1029 boolean found = false; 1030 for (int i=0; i<popup.getComponentCount(); i++) { 1031 Component thisComponent = popup.getComponent(i); 1032 if (thisComponent instanceof JMenu && ((JMenu)thisComponent).getText().equals(menuName)) { 1033 theMenu = mergeMenuNames((JMenu)thisComponent, menuNames); 1034 found = true; 1035 } 1036 } 1037 1038 // Make a new menu, add the root, return the leaf 1039 if (!found) { 1040 JMenu theRoot = new JMenu(menuName); 1041 theMenu = makeMenuRecursive(theRoot, menuNames); 1042 popup.add(theRoot); 1043 } 1044 1045 return theMenu; 1046 } 1047 1048 /** 1049 * Make a new recursive menu 1050 * 1051 * @param rootMenu The root menu to add items to 1052 * @param menuNames List of string names for submenus 1053 * @return A new JMenu representing the leaf 1054 */ 1055 private JMenu makeMenuRecursive(JMenu rootMenu, List<String> menuNames) { 1056 if (menuNames.size() < 1) return rootMenu; 1057 JMenu newMenu = new JMenu(menuNames.get(0)); 1058 rootMenu.add(newMenu); 1059 menuNames.remove(0); 1060 return makeMenuRecursive(newMenu, menuNames); 1061 } 1062 1063 /** 1064 * Recurse into a menu, returning either a pointer to the designated names path 1065 * or a pointer to the leaf menu added by merging new names 1066 * 1067 * @param thisMenu The root menu to merge 1068 * @param menuNames List of string names to look for 1069 * @return A new JMenu representing the leaf matched by menuNames 1070 */ 1071 private JMenu mergeMenuNames(JMenu thisMenu, List<String> menuNames) { 1072 if (menuNames.size() < 1) return thisMenu; 1073 boolean found = false; 1074 String menuName = menuNames.get(0); 1075 for (int i=0; i<thisMenu.getItemCount(); i++) { 1076 JMenuItem mi = thisMenu.getItem(i); 1077 if (!(mi instanceof JMenu)) continue; 1078 if (mi.getText().equals(menuName)) { 1079 menuNames.remove(0); 1080 thisMenu = mergeMenuNames((JMenu)mi, menuNames); 1081 found = true; 1082 } 1083 } 1084 if (!found) { 1085 thisMenu = makeMenuRecursive(thisMenu, menuNames); 1086 } 1087 return thisMenu; 1088 } 1089 1090 /** 1091 * Return the parameter type associated with this chooser. Override! 1092 */ 1093 protected String getParameterSetType() { 1094 return "adde"; 1095 } 1096 1097 /** 1098 * Show the parameter set manager. 1099 */ 1100 private void showParameterSetDialog(final String parameterSetType) { 1101 ParameterTree tree = (ParameterTree) parameterTrees.get(parameterSetType); 1102 if (tree == null) { 1103 tree = new ParameterTree((UIManager)getIdv().getIdvUIManager() , parameterSetType); 1104 parameterTrees.put(parameterSetType, tree); 1105 } 1106 else { 1107 //DAVEP 1108 System.out.println("Should refresh the parameter tree here"); 1109 } 1110 tree.setVisible(true); 1111 } 1112 1113 /** 1114 * Clear the selected parameter set. 1115 */ 1116 protected void clearParameterSet() { 1117 restoreElement = null; 1118 restoreTimes = new ArrayList(); 1119 shouldAddSource = false; 1120 } 1121 1122 /** 1123 * Restore the selected parameter set using element attributes. 1124 * 1125 * @param restoreElement {@code Element} with the desired attributes. 1126 * {@code null} values are permitted. 1127 * 1128 * @return {@code true} if the parameter set was restored, {@code false} 1129 * otherwise. 1130 */ 1131 protected boolean restoreParameterSet(Element restoreElement) { 1132 if (restoreElement == null) return false; 1133 if (!restoreElement.getTagName().equals("default")) return false; 1134 1135 this.restoreElement = restoreElement; 1136 1137 boolean oldISCE = ignoreStateChangedEvents; 1138 ignoreStateChangedEvents = true; 1139 1140 // Restore server 1141 String server = restoreElement.getAttribute(ATTR_SERVER); 1142 if (server != null) serverSelector.setSelectedItem(new AddeServer(server)); 1143 1144 // Restore group 1145 String group = restoreElement.getAttribute(ATTR_GROUP); 1146 if (group != null) groupSelector.setSelectedItem(group); 1147 1148 // Act as though the user hit "connect" 1149 readFromServer(); 1150 1151 // Restore descriptor 1152 String descriptor = restoreElement.getAttribute(ATTR_DESCRIPTOR); 1153 if (descriptor != null) { 1154 Enumeration enumeration = descriptorTable.keys(); 1155 for (int i = 0; enumeration.hasMoreElements(); i++) { 1156 String key = enumeration.nextElement().toString(); 1157 Object val = descriptorTable.get(key); 1158 if (descriptor.equals(val)) { 1159 descriptorComboBox.setSelectedItem(val + nameSeparator + key); 1160 descriptorChanged(); 1161 break; 1162 } 1163 } 1164 } 1165 1166 // Restore date/time 1167 if (restoreElement.hasAttribute(ATTR_POS)) { 1168 setDoAbsoluteTimes(false); 1169 Integer pos = new Integer(restoreElement.getAttribute(ATTR_POS)); 1170 if (pos.intValue() >= 0) { 1171 getRelativeTimesList().setSelectedIndex(pos); 1172 } 1173 restoreTimes = new ArrayList(); 1174 } 1175 else if ((restoreElement.hasAttribute(ATTR_DAY)) && (restoreElement.hasAttribute(ATTR_TIME))) { 1176 setDoAbsoluteTimes(true); 1177 String dateStr = restoreElement.getAttribute(ATTR_DAY); 1178 String timeStr = restoreElement.getAttribute(ATTR_TIME); 1179 List dateS = StringUtil.split(dateStr, ","); 1180 List timeS = StringUtil.split(timeStr, ","); 1181 int numImages = timeS.size(); 1182 restoreTimes = new ArrayList(); 1183 try { 1184 DateTime dt = new DateTime(); 1185 dt.resetFormat(); 1186 String dtformat = dt.getFormatPattern(); 1187 for (int ix=0; ix<numImages; ix++) { 1188 DateTime restoreTime = dt.createDateTime((String)dateS.get(ix) + " " + (String)timeS.get(ix)); 1189 restoreTimes.add(restoreTime); 1190 } 1191 } catch (Exception e) { 1192 System.out.println("Exception e=" + e); 1193 return false; 1194 } 1195 } 1196 1197 System.out.println("Returning from AddeChooser.restoreParameterSet()"); 1198 1199 ignoreStateChangedEvents = oldISCE; 1200 return true; 1201 } 1202 1203 /** 1204 * Set the absolute times list. The times list can contain any of the object types 1205 * that makeDatedObjects knows how to handle, i.e., Date, visad.DateTime, DatedThing, AddeImageDescriptor, etc. 1206 * 1207 * @param times List of thinggs to put into absolute times list 1208 */ 1209 protected void setAbsoluteTimes(List times) { 1210 super.setAbsoluteTimes(times); 1211 restoreAbsoluteTimes(); 1212 } 1213 1214 protected void restoreAbsoluteTimes() { 1215 List allTimes = makeDatedObjects(super.getAbsoluteTimes()); 1216 if (restoreTimes.size() > 0 && allTimes.size() > 0) { 1217 int[] indices = new int[restoreTimes.size()]; 1218 try { 1219 DateTime rtdt; 1220 DateTime atdt; 1221 DatedThing at; 1222 for (int i = 0; i < restoreTimes.size(); i++) { 1223 rtdt = (DateTime)restoreTimes.get(i); 1224 for (int j = 0; j < allTimes.size(); j++) { 1225 at = (DatedThing)allTimes.get(j); 1226 atdt = new DateTime(at.getDate()); 1227 if (atdt.equals(rtdt)) { 1228 indices[i] = j; 1229 } 1230 } 1231 } 1232 } catch (Exception e) { 1233 System.out.println("Exception e=" + e); 1234 } 1235 setSelectedAbsoluteTimes(indices); 1236 } 1237 } 1238 1239 /** 1240 * show/hide the parameter restore button 1241 */ 1242 public void showParameterButton() { 1243 parameterButton.setVisible(true); 1244 } 1245 1246 public void hideParameterButton() { 1247 parameterButton.setVisible(false); 1248 } 1249 1250 /** 1251 * Override and simulate clicking Add Source if requested 1252 */ 1253 public void setHaveData(boolean have) { 1254 super.setHaveData(have); 1255 if (have && shouldAddSource) { 1256 // Even though setHaveData should mean we can go, we can't... wait a few jiffies 1257 Misc.runInABit(100, AddeChooser.this, "doClickLoad", null); 1258 } 1259 } 1260 1261 public void doClickLoad() { 1262 loadButton.doClick(); 1263 } 1264 1265 public void showServers() { 1266 allServersFlag = !allServersFlag; 1267 XmlObjectStore store = getIdv().getStore(); 1268 store.put(Constants.PREF_SYSTEMSERVERSIMG, allServersFlag); 1269 store.save(); 1270 updateServers(); 1271 updateGroups(); 1272 } 1273 1274 protected String getStateString() { 1275 int state = getState(); 1276 switch (state) { 1277 case STATE_CONNECTED: return "Connected to server"; 1278 case STATE_UNCONNECTED: return "Not connected to server"; 1279 case STATE_CONNECTING: return "Connecting to server"; 1280 default: return "Unknown state: " + state; 1281 } 1282 } 1283 1284 /** 1285 * Disable/enable any components that depend on the server. 1286 * Try to update the status label with what we know here. 1287 */ 1288 protected void updateStatus() { 1289 super.updateStatus(); 1290 if (getState() == STATE_CONNECTED) { 1291 lastServer = new AddeServer(""); 1292 lastServerGroup = ""; 1293 lastServerName = ""; 1294 lastServerProj = ""; 1295 lastServerUser = ""; 1296 1297 if (!haveDescriptorSelected()) { 1298 if (!usingStations() || haveStationSelected()) { 1299 // String name = getDataName().toLowerCase(); 1300 String name = getDescriptorLabel().toLowerCase(); 1301 if (StringUtil.startsWithVowel(name)) { 1302 setStatus("Please select an " + name); 1303 } else { 1304 setStatus("Please select a " + name); 1305 } 1306 } 1307 } 1308 } 1309 1310 GuiUtils.enableTree(connectButton, getState() != STATE_CONNECTING); 1311 } 1312 1313 /** 1314 * Get the data type ID 1315 * 1316 * @return the data type 1317 */ 1318 public String getDataType() { 1319 return "ANY"; 1320 } 1321 1322 /** 1323 * Check if the server is ok 1324 * 1325 * @return status code 1326 */ 1327 protected int checkIfServerIsOk() { 1328 EntryStore servManager = ((McIDASV)getIdv()).getServerManager(); 1329 if (isLocalServer() && !servManager.checkLocalServer()) { 1330 LogUtil.userErrorMessage("Local servers are stopped.\n\nLocal servers can be restarted from the 'Tools' menu:\n Tools > Manage ADDE Datasets >\nLocal Servers > Start Local Servers"); 1331 logger.info("Local servers are stopped"); 1332 return STATUS_ERROR; 1333 } 1334 try { 1335 StringBuffer buff = getUrl(REQ_TEXT); 1336 appendKeyValue(buff, PROP_FILE, FILE_PUBLICSRV); 1337// URL url = new URL(buff.toString()); 1338 URLConnection urlc = IOUtil.getUrlConnection(buff.toString()); 1339 InputStream is = urlc.getInputStream(); 1340 is.close(); 1341 return STATUS_OK; 1342 } catch (AddeURLException ae) { 1343 String aes = ae.toString(); 1344 if (aes.indexOf("Invalid project number") >= 0 || 1345 aes.indexOf("Invalid user id") >= 0 || 1346 aes.indexOf("Accounting data") >= 0) { 1347 LogUtil.userErrorMessage("Invalid login.\n\nPlease verify your username and password."); 1348 logger.info("Invalid login"); 1349 setState(STATE_UNCONNECTED); 1350 setHaveData(false); 1351 resetDescriptorBox(); 1352 return STATUS_NEEDSLOGIN; 1353 } 1354 if (aes.indexOf("cannot run server 'txtgserv'") >= 0) { 1355 return STATUS_OK; 1356 } 1357 LogUtil.userErrorMessage("Error connecting to server " + getServer() + ":\n" + ae.getMessage()); 1358 logger.info("Error connecting to server"); 1359 setState(STATE_UNCONNECTED); 1360 setHaveData(false); 1361 resetDescriptorBox(); 1362 return STATUS_ERROR; 1363 } catch (ConnectException exc) { 1364 setState(STATE_UNCONNECTED); 1365 setHaveData(false); 1366 resetDescriptorBox(); 1367 String message = "Error connecting to server " + getServer(); 1368 String info = "Error connecting to server"; 1369 if (isLocalServer()) { 1370 if (!servManager.checkLocalServer()) { 1371 message += "\n\nLocal servers can be restarted from the 'Tools' menu:\n Tools > Manage ADDE Datasets >\n Local Servers > Start Local Servers"; 1372 info += " (Local servers are stopped)"; 1373 } 1374 else { 1375 message += "\n\nLocal servers appear to be running.\nYour firewall may be preventing access."; 1376 info += " (Local servers are running)"; 1377 } 1378 } 1379 LogUtil.userErrorMessage(message); 1380 logger.info(info); 1381 return STATUS_ERROR; 1382 } catch (EOFException exc) { 1383 setState(STATE_UNCONNECTED); 1384 setHaveData(false); 1385 resetDescriptorBox(); 1386 LogUtil.userErrorMessage("Server " + getServer() + " is not responding"); 1387 logger.info("Server is not responding"); 1388 return STATUS_ERROR; 1389 } catch (Exception exc) { 1390 setState(STATE_UNCONNECTED); 1391 setHaveData(false); 1392 resetDescriptorBox(); 1393 logException("Connecting to server: " + getServer(), exc); 1394 logger.info("Error connecting to server"); 1395 return STATUS_ERROR; 1396 } 1397 } 1398 1399 public boolean canAccessServer() { 1400 return (checkIfServerIsOk() == STATUS_OK); 1401 } 1402 1403 public Map<String, String> getAccountingInfo() { 1404 AddeServer server = getAddeServer(); 1405 Map<String, String> map = new LinkedHashMap<String, String>(); 1406 if (server != null) { 1407 List<AddeServer.Group> groups = server.getGroups(); 1408 Map<String, String>acctInfo = getAccounting(server, groups.get(0).toString()); 1409 map.put("user", acctInfo.get("user")); 1410 map.put("proj", acctInfo.get("proj")); 1411 map.put("server", server.getName()); 1412 map.put("group", getGroup()); 1413 } else { 1414 map.put("user", RemoteAddeEntry.DEFAULT_ACCOUNT.getUsername()); 1415 map.put("proj", RemoteAddeEntry.DEFAULT_ACCOUNT.getUsername()); 1416 map.put("server", ""); 1417 map.put("group", ""); 1418 } 1419 return map; 1420 } 1421 1422 /** 1423 * Saves the currently selected server and group to a chooser-specific 1424 * preference. Preference ID is {@code PREF_SERVERSTATE+'.'+getId()}. 1425 */ 1426 @Override public void saveServerState() { 1427 String[] serverState = { getServer(), getGroup() }; 1428 getIdv().getStore().put(PREF_SERVERSTATE+'.'+getId(), serverState); 1429 getIdv().getStore().save(); 1430 } 1431 1432 /** 1433 * Connect to the server. 1434 */ 1435 protected void connectToServer() { 1436 clearParameterSet(); 1437 setDescriptors(null); 1438 setDoAbsoluteTimes(false); 1439 if (!canAccessServer()) { 1440 return; 1441 } 1442 readFromServer(); 1443 saveServerState(); 1444 ignoreStateChangedEvents = true; 1445 if (descList != null) { 1446 descList.saveState(groupSelector); 1447 } 1448 ignoreStateChangedEvents = false; 1449 } 1450 1451 /** 1452 * Do server connection stuff... override this with type-specific methods 1453 */ 1454 protected void readFromServer() { 1455 readDescriptors(); 1456 readTimes(); 1457 } 1458 1459// what the request needs to look like: 1460// adde://localhost:8112/imagedata?&PORT=112&COMPRES S=gzip&USER=idv&PROJ=0 1461// &VERSION=1&DEBUG=false&TRAC E=0&GROUP=MYDATA&DESCRIPTOR=ENTRY4&BAND=1 1462// &LATLON= 30.37139 71.74912&PLACE=CENTER&SIZE=1000 1000&UNI T=BRIT 1463// &MAG=1 1&SPAC=1&NAV=X&AUX=YES&DOC=X&POS=0 1464 1465 /** 1466 * Generate a list of image descriptors for the descriptor list. 1467 */ 1468 protected void readDescriptors() { 1469 try { 1470 StringBuffer buff = getGroupUrl(REQ_DATASETINFO, getGroup()); 1471 buff.append("&type=").append(getDataType()); 1472 logger.debug("readDesc: buff={}", buff.toString()); 1473 DataSetInfo dsinfo = new DataSetInfo(buff.toString()); 1474 1475 descriptorTable = dsinfo.getDescriptionTable(); 1476 descriptorList.clear(); 1477 commentList.clear(); 1478 descriptorList.addAll(dsinfo.getDescriptorList()); 1479 commentList.addAll(dsinfo.getCommentList()); 1480 int count = commentList.size(); 1481 String[] names = new String[count]; 1482 for (int i = 0; i < count; i++) { 1483 if (!isLocalServer()) { 1484 names[i] = descriptorList.get(i) + nameSeparator + commentList.get(i); 1485 } else { 1486 names[i] = commentList.get(i); 1487 } 1488 } 1489 logger.debug("readDesc: names={}", names); 1490 Arrays.sort(names); 1491 setDescriptors(names); 1492 setState(STATE_CONNECTED); 1493 } catch (Exception e) { 1494 handleConnectionError(e); 1495 } 1496 } 1497 1498 /** 1499 * Initialize the descriptor list from a list of names 1500 * 1501 * @param names list of names 1502 */ 1503 protected void setDescriptors(String[] names) { 1504 synchronized (WIDGET_MUTEX) { 1505 ignoreDescriptorChange = true; 1506 descriptorComboBox.removeAllItems(); 1507 descriptorNames = names; 1508 if ((names == null) || (names.length == 0)) { 1509 return; 1510 } 1511 descriptorComboBox.addItem(LABEL_SELECT); 1512 for (int j = 0; j < names.length; j++) { 1513 logger.trace("adding names[{}]='{}' to combo box", j, names[j]); 1514 descriptorComboBox.addItem(names[j]); 1515 } 1516 ignoreDescriptorChange = false; 1517 } 1518 } 1519 1520 /** 1521 * Respond to a change in the descriptor list. 1522 */ 1523 protected void descriptorChanged() { 1524 readTimes(); 1525 updateStatus(); 1526 } 1527 1528 /** 1529 * Check if a descriptor (image type) has been chosen 1530 * 1531 * @return true if an image type has been chosen 1532 */ 1533 protected boolean haveDescriptorSelected() { 1534 if (!GuiUtils.anySelected(descriptorComboBox)) { 1535 return false; 1536 } 1537 return getDescriptor() != null; 1538 } 1539 1540 /** 1541 * Get the selected descriptor. 1542 * 1543 * @return the currently selected descriptor. 1544 */ 1545 protected String getDescriptor() { 1546 return getDescriptorFromSelection(getSelectedDescriptor()); 1547 } 1548 1549 /** 1550 * Get the descriptor relating to the selection. 1551 * 1552 * @param selection String name from the widget. Can be {@code null}. 1553 * 1554 * @return Either the descriptor associated with {@code selection} or {@code null} if {@link #descriptorTable} or 1555 * {@code selection} is {@code null}. 1556 */ 1557 protected String getDescriptorFromSelection(String selection) { 1558 if (descriptorTable == null) { 1559 return null; 1560 } 1561 if (selection == null) { 1562 return null; 1563 } 1564 1565 String descriptor = null; 1566 if (!selection.contains(nameSeparator)) { 1567 descriptor = (String)descriptorTable.get(selection); 1568 } else { 1569 String[] toks = selection.split(nameSeparator, 2); 1570 String firstToken = toks[0].trim(); 1571 if (descriptorList.contains(firstToken)) { 1572 descriptor = firstToken; 1573 } else { 1574 String key = toks[1].trim(); 1575 descriptor = (String)descriptorTable.get(key); 1576 } 1577 } 1578 return descriptor; 1579 } 1580 1581 /** 1582 * Get the selected descriptor. 1583 * 1584 * @return the selected descriptor 1585 */ 1586 public String getSelectedDescriptor() { 1587 String selection = (String)descriptorComboBox.getSelectedItem(); 1588 if (selection == null) { 1589 return null; 1590 } 1591 if (selection.equals(LABEL_SELECT)) { 1592 return null; 1593 } 1594 return selection; 1595 } 1596 1597 /** 1598 * Get the descriptor table for this chooser 1599 * 1600 * @return a Hashtable of descriptors and names 1601 */ 1602 public Hashtable getDescriptorTable() { 1603 return descriptorTable; 1604 } 1605 1606 /** 1607 * Get any extra key=value pairs that are appended to all requests. 1608 * 1609 * @param buff The buffer to append onto 1610 */ 1611 protected void appendMiscKeyValues(StringBuffer buff) { 1612 appendKeyValue(buff, PROP_COMPRESS, DEFAULT_COMPRESS); 1613 appendKeyValue(buff, PROP_PORT, DEFAULT_PORT); 1614 // appendKeyValue(buff, PROP_DEBUG, DEFAULT_DEBUG); 1615 appendKeyValue(buff, PROP_DEBUG, Boolean.toString(EntryStore.isAddeDebugEnabled(false))); 1616 appendKeyValue(buff, PROP_VERSION, DEFAULT_VERSION); 1617 appendKeyValue(buff, PROP_USER, getLastAddedUser()); 1618 appendKeyValue(buff, PROP_PROJ, getLastAddedProj()); 1619 } 1620 1621 public String getLastAddedUser() { 1622 if ((lastServerUser != null) && !lastServerUser.isEmpty()) { 1623 logger.debug("getLastAddedUser: using non-default {}", lastServerUser); 1624 return lastServerUser; 1625 } else { 1626 logger.debug("getLastAddedUser: using default {}", DEFAULT_USER); 1627 return DEFAULT_USER; 1628 } 1629 } 1630 1631 public String getLastAddedProj() { 1632 if ((lastServerProj != null) && !lastServerProj.isEmpty()) { 1633 logger.debug("getLastAddedProj: using non-default {}", lastServerProj); 1634 return lastServerProj; 1635 } else { 1636 logger.debug("getLastAddedProj: using default {}", DEFAULT_PROJ); 1637 return DEFAULT_PROJ; 1638 } 1639 } 1640 1641 /** 1642 * Show the groups dialog. This method is not meant to be called 1643 * but is public by reason of implementation (or insanity). 1644 */ 1645 public void showGroups() { 1646 JPopupMenu popup = new JPopupMenu(); 1647 popup.add(new JMenuItem("Reading public datasets...")); 1648 1649 1650 List groups = readGroups(); 1651 popup.removeAll(); 1652 if ((groups == null) || (groups.isEmpty())) { 1653 popup.add(new JMenuItem("The list of public datasets is not available")); 1654 popup.show(publicButton, 0, (int) publicButton.getBounds().getHeight()); 1655 return; 1656 } 1657 1658 JMenuItem mi; 1659 for (int i = 0; i < groups.size(); i++) { 1660 final String group = groups.get(i).toString(); 1661 mi = new JMenuItem(group); 1662 mi.addActionListener(ae -> { 1663 EntryStore servManager = ((McIDASV)getIdv()).getServerManager(); 1664 1665 servManager.addEntry( 1666 new RemoteAddeEntry.Builder(lastServerName, group) 1667 .account(lastServerUser, lastServerProj) 1668 .type(strToEntryType(getDataType())) 1669 .source(EntrySource.USER) 1670 .validity(EntryValidity.VERIFIED) 1671 .build()); 1672 1673 groupSelector.setSelectedItem(group); 1674 doConnect(); 1675 }); 1676 popup.add(mi); 1677 } 1678 MenuScroller foo = new MenuScroller(popup, 125); 1679 foo.setParent(publicButton); 1680 popup.show(publicButton, 0, (int) publicButton.getBounds().getHeight()); 1681 } 1682 1683 /** 1684 * return the String id of the chosen server name 1685 * 1686 * @return the server name 1687 */ 1688 public String getServer() { 1689 AddeServer server = getAddeServer(); 1690 if (server != null) { 1691 return server.getName(); 1692 } else { 1693 return ""; 1694 } 1695 } 1696 1697 protected String getGroup() { 1698 return getGroup(false); 1699 } 1700 1701 /** 1702 * Is the group selector editable? 1703 * 1704 * @return Always returns {@code true}. 1705 */ 1706 protected boolean isGroupEditable() { 1707 return true; 1708 } 1709 1710 /** 1711 * Get the image group from the GUI. 1712 * 1713 * @return The image group. 1714 */ 1715 protected String getGroup(final boolean fromGetServer) { 1716 Object selected = groupSelector.getSelectedItem(); 1717 if (selected == null) { 1718 return null; 1719 } 1720 1721 if (selected instanceof AddeServer.Group) { 1722 AddeServer.Group group = (AddeServer.Group) selected; 1723 return group.getName(); 1724 } 1725 1726 if (selected instanceof String) { 1727 return (String)selected; 1728 } 1729 1730 String groupName = selected.toString().trim(); 1731 if (!fromGetServer && (!groupName.isEmpty())) { 1732 //Force the get in case they typed a server name 1733 getServer(); 1734 1735 AddeServer server = getAddeServer(); 1736 if (server != null) { 1737 AddeServer.Group group = 1738 getIdv().getIdvChooserManager().addAddeServerGroup( 1739 server, groupName, getGroupType()); 1740 if (!group.getActive()) { 1741 getIdv().getIdvChooserManager().activateAddeServerGroup( 1742 server, group); 1743 } 1744 //Now put the list of groups back in to the selector 1745 setGroups(); 1746 groupSelector.setSelectedItem(group); 1747 } 1748 } 1749 return groupName; 1750 } 1751 1752 /** 1753 * Get the server selector 1754 * @return The server selector 1755 */ 1756 public JComboBox getServerSelector() { 1757 if (serverSelector == null) 1758 serverSelector = super.getServerSelector(); 1759 1760 ItemListener[] ell = serverSelector.getItemListeners(); 1761 for (int i=0; i < ell.length; i++) { 1762 serverSelector.removeItemListener((ItemListener)ell[i]); 1763 } 1764 updateServers(); 1765 updateGroups(); 1766 serverSelector.addItemListener(new ItemListener() { 1767 public void itemStateChanged(ItemEvent e) { 1768 if (!ignoreStateChangedEvents) { 1769 Object selected = serverSelector.getSelectedItem(); 1770 if (selected instanceof AddeServer) { 1771 AddeServer selectedServer = (AddeServer)selected; 1772 if (selectedServer != null) { 1773 if (isSeparator(selectedServer)) { 1774 connectButton.setEnabled(false); 1775 return; 1776 } 1777 } 1778 } 1779 setState(STATE_UNCONNECTED); 1780 connectButton.setEnabled(true); 1781// setGroups(); 1782 resetDescriptorBox(); 1783 updateGroups(); 1784// System.err.println("itemStateChanged"); 1785 } 1786// else { 1787// System.out.println("Ignoring state change here..."); 1788// } 1789 } 1790 }); 1791 1792 serverSelector.getEditor().getEditorComponent().addKeyListener(new KeyListener() { 1793 public void keyTyped(final KeyEvent e) {} 1794 public void keyPressed(final KeyEvent e) {} 1795 public void keyReleased(final KeyEvent e) { 1796 JTextField field = (JTextField)serverSelector.getEditor().getEditorComponent(); 1797 boolean partialMatch = false; 1798 for (int i = 0; i < serverSelector.getItemCount(); i++) { 1799 String entry = serverSelector.getItemAt(i).toString(); 1800 if (entry.toLowerCase().startsWith(field.getText().toLowerCase())) 1801 partialMatch = true; 1802 } 1803 1804 if (!partialMatch && groupSelector != null) { 1805 logger.debug("aha! chooser=", getDataType()); 1806 ((JTextField)groupSelector.getEditor().getEditorComponent()).setText(""); 1807 } 1808 } 1809 }); 1810 1811 return serverSelector; 1812 } 1813 1814 /** 1815 * Enable or disable the GUI widgets based on what has been 1816 * selected. 1817 */ 1818 protected void enableWidgets() { 1819 synchronized (WIDGET_MUTEX) { 1820 boolean newEnabledState = (getState() == STATE_CONNECTED); 1821 for (int i = 0; i < compsThatNeedDescriptor.size(); i++) { 1822 JComponent comp = (JComponent) compsThatNeedDescriptor.get(i); 1823 if (comp.isEnabled() != newEnabledState) { 1824 GuiUtils.enableTree(comp, newEnabledState); 1825 } 1826 } 1827 if (drivercbx != null) { 1828 boolean descriptorState = newEnabledState && haveDescriptorSelected(); 1829// logger.trace("hrm set drivercbx={}", anyTimeDrivers() && descriptorState); 1830 drivercbx.setEnabled(anyTimeDrivers() && descriptorState); 1831 } 1832 } 1833 } 1834 1835 /** 1836 * Add a listener to the given combobox that will set the 1837 * state to unconnected 1838 * 1839 * @param box The box to listen to. 1840 */ 1841 protected void clearOnChange(final JComboBox box) { 1842 box.addItemListener(new ItemListener() { 1843 public void itemStateChanged(ItemEvent e) { 1844 if ( !ignoreStateChangedEvents) { 1845 setState(STATE_UNCONNECTED); 1846 GuiUtils.setListData(descriptorComboBox, new Vector()); 1847// System.err.println("clearOnChange"); 1848 } 1849// else { 1850// System.out.println("Ignoring state change in clearOnChange for: " + box.toString()); 1851// } 1852 } 1853 }); 1854 } 1855 1856 /** 1857 * Get the descriptor widget label 1858 * 1859 * @return label for the descriptor widget 1860 */ 1861 public String getDescriptorLabel() { 1862 return "Descriptor"; 1863 } 1864 1865 protected int getNumTimesToSelect() { 1866 return 5; 1867 } 1868 1869 /** 1870 * Get the default selected index for the relative times list. 1871 * 1872 * @return default index 1873 */ 1874 protected int getDefaultRelativeTimeIndex() { 1875 return 4; 1876 } 1877 1878 /** 1879 * Check the times lists 1880 */ 1881 protected void checkTimesLists() { 1882 super.checkTimesLists(); 1883 if (timesCardPanelExtra == null) { 1884 return; 1885 } 1886 if (getDoAbsoluteTimes()) { 1887 timesCardPanelExtra.show("absolute"); 1888 } else { 1889 timesCardPanelExtra.show("relative"); 1890 } 1891 } 1892 1893 /** Card panel to hold extra relative and absolute time components */ 1894 protected GuiUtils.CardLayoutPanel timesCardPanelExtra; 1895 1896 /** 1897 * Set the relative and absolute extra components. 1898 */ 1899 protected JPanel makeTimesPanel(JComponent relativeCard, JComponent absoluteCard) { 1900// JPanel timesPanel = super.makeTimesPanel(false, true); 1901 JPanel timesPanel = super.makeTimesPanel(false, true, getIdv().getUseTimeDriver()); 1902 1903 // Make a new timesPanel that has extra components tacked on the bottom, inside the tabs 1904 Component[] comps = timesPanel.getComponents(); 1905 1906// if (drivercbx != null) { 1907// drivercbx.setEnabled(anyTimeDrivers()); 1908// } 1909 1910 if ((comps.length == 1) && (comps[0] instanceof JTabbedPane)) { 1911 timesCardPanelExtra = new GuiUtils.CardLayoutPanel(); 1912 if (relativeCard == null) { 1913 relativeCard = new JPanel(); 1914 } 1915 if (absoluteCard == null) { 1916 absoluteCard = new JPanel(); 1917 } 1918 timesCardPanelExtra.add(relativeCard, "relative"); 1919 timesCardPanelExtra.add(absoluteCard, "absolute"); 1920 timesPanel = GuiUtils.centerBottom(comps[0], timesCardPanelExtra); 1921 } 1922 1923 return timesPanel; 1924 } 1925 1926 private JPanel innerPanel = new JPanel(); 1927 1928 private JLabel statusLabel = new JLabel("Status"); 1929 1930 /** 1931 * Super setStatus() takes a second string to enable "simple" mode 1932 * which highlights the required component. We don't really care 1933 * about that feature, and we don't want getStatusLabel() to 1934 * change the label background color. 1935 */ 1936 @Override 1937 public void setStatus(String statusString, String foo) { 1938 if (statusString == null) { 1939 statusString = ""; 1940 } 1941 statusLabel.setText(statusString); 1942 } 1943 1944 protected void setInnerPanel(JPanel newInnerPanel) { 1945 innerPanel = newInnerPanel; 1946 } 1947 1948 /** 1949 * Create the widget responsible for handling relative time selection. 1950 * 1951 * @return GUI widget. 1952 */ 1953 @Override public JComponent getRelativeTimesChooser() { 1954 McVTextField relativeTimesField = 1955 McVGuiUtils.makeTextFieldAllow(String.valueOf(relativeTimes), 1956 4, 1957 false, 1958 '0', '1', '2', '3', '4', '5', 1959 '6', '7','8','9'); 1960 1961 // need to keep *both* the ActionListener and DocumentListener around. 1962 // removing the ActionListener results in strange behavior when you've 1963 // accidentally cleared out the text field. 1964 relativeTimesField.setAllow(Pattern.compile("^[1-9][0-9]*$"), true); 1965// relativeTimesField.setDeny(Pattern.compile("^0$"), true); 1966 relativeTimesField.setColumns(4); 1967 relativeTimesField.addActionListener(e -> { 1968 String text = ((JTextField)e.getSource()).getText(); 1969 validateRelativeTimeInput(text); 1970 }); 1971 relativeTimesField.getDocument().addDocumentListener(new DocumentListener() { 1972 @Override public void insertUpdate(DocumentEvent e) { 1973 handleRelativeTimeChange(e); 1974 } 1975 1976 @Override public void removeUpdate(DocumentEvent e) { 1977 handleRelativeTimeChange(e); 1978 } 1979 1980 @Override public void changedUpdate(DocumentEvent e) { 1981 handleRelativeTimeChange(e); 1982 } 1983 }); 1984 relativeTimesField.setToolTipText(RELATIVE_TIMES_TOOLTIP); 1985 1986 JPanel panel = 1987 GuiUtils.topLeft(GuiUtils.label(RELATIVE_TIMES_LABEL, 1988 relativeTimesField)); 1989 JScrollPane scrollPane = new JScrollPane(panel); 1990 scrollPane.setPreferredSize(new Dimension(150, 100)); 1991 return scrollPane; 1992 } 1993 1994 /** 1995 * Validate the contents of the relative times text field. 1996 * 1997 * <p>This method overwrites {@link #relativeTimes} if {@code text} is an 1998 * integer greater than zero.</p> 1999 * 2000 * @param text Contents of the text field. 2001 */ 2002 private void validateRelativeTimeInput(String text) { 2003 try { 2004 int value = Integer.valueOf(text); 2005 if (value > 0) { 2006 relativeTimes = value; 2007 setHaveData(true); 2008 setState(STATE_CONNECTED); 2009 updateStatus(); 2010 } 2011 } catch (NumberFormatException e) { 2012 setState(STATUS_ERROR); 2013 setHaveData(false); 2014 setStatus("Please provide an integer value greater than zero."); 2015 } 2016 } 2017 2018 /** 2019 * Handle {@link DocumentListener} events for the {@link JTextField} 2020 * created by {@link #getRelativeTimesChooser()}. 2021 * 2022 * @param event Event to handle. Cannot be {@code null}. 2023 */ 2024 private void handleRelativeTimeChange(DocumentEvent event) { 2025 int len = event.getDocument().getLength(); 2026 try { 2027 String text = event.getDocument().getText(0, len); 2028 validateRelativeTimeInput(text); 2029 } catch (BadLocationException ex) { 2030 logger.warn("Could not get contents of text field!", ex); 2031 } 2032 } 2033 2034 /** 2035 * Get the relative time indices 2036 * 2037 * @return an array of indices 2038 */ 2039 @Override public int[] getRelativeTimeIndices() { 2040 int[] indices = new int[relativeTimes]; 2041 for (int i = 0; i < indices.length; i++) { 2042 indices[i] = i; 2043 } 2044 return indices; 2045 } 2046 2047 /** 2048 * Make the UI for this selector. 2049 * 2050 * Thank you NetBeans for helping with the layout! 2051 * 2052 * @return The GUI. 2053 */ 2054 protected JComponent doMakeContents() { 2055 JPanel outerPanel = new JPanel(); 2056 2057 JLabel serverLabelInner = new JLabel("Server:"); 2058 McVGuiUtils.setLabelPosition(serverLabelInner, Position.RIGHT); 2059 JPanel serverLabel = GuiUtils.leftRight(parameterButton, serverLabelInner); 2060 McVGuiUtils.setComponentWidth(serverLabel); 2061 2062 clearOnChange(serverSelector); 2063 McVGuiUtils.setComponentWidth(serverSelector, Width.DOUBLE); 2064 2065 JLabel groupLabel = McVGuiUtils.makeLabelRight("Dataset:"); 2066 2067 groupSelector.setEditable(isGroupEditable()); 2068 clearOnChange(groupSelector); 2069 McVGuiUtils.setComponentWidth(groupSelector, Width.DOUBLE); 2070 2071 McVGuiUtils.setComponentWidth(connectButton, Width.DOUBLE); 2072 connectButton.setActionCommand(CMD_CONNECT); 2073 connectButton.addActionListener(this); 2074 2075 /* Set the attributes for the descriptor label and combo box, even though 2076 * they are not used here. Extending classes can add them to the panel if 2077 * necessary. 2078 */ 2079 McVGuiUtils.setComponentWidth(descriptorLabel); 2080 McVGuiUtils.setLabelPosition(descriptorLabel, Position.RIGHT); 2081 2082 McVGuiUtils.setComponentWidth(descriptorComboBox, Width.DOUBLEDOUBLE); 2083 2084 if (descriptorComboBox.getMinimumSize().getWidth() < ELEMENT_DOUBLE_WIDTH) { 2085 McVGuiUtils.setComponentWidth(descriptorComboBox, Width.DOUBLE); 2086 } 2087 2088 JLabel statusLabelLabel = McVGuiUtils.makeLabelRight(""); 2089 2090 statusLabel.setText("Status"); 2091 McVGuiUtils.setLabelPosition(statusLabel, Position.RIGHT); 2092 McVGuiUtils.setComponentColor(statusLabel, TextColor.STATUS); 2093 2094 JButton helpButton = McVGuiUtils.makeImageButton(ICON_HELP, "Show help"); 2095 helpButton.setActionCommand(GuiUtils.CMD_HELP); 2096 helpButton.addActionListener(this); 2097 2098 JButton refreshButton = McVGuiUtils.makeImageButton(ICON_REFRESH, "Refresh"); 2099 refreshButton.setActionCommand(GuiUtils.CMD_UPDATE); 2100 refreshButton.addActionListener(this); 2101 2102 McVGuiUtils.setComponentWidth(loadButton, Width.DOUBLE); 2103 2104 GroupLayout layout = new GroupLayout(outerPanel); 2105 outerPanel.setLayout(layout); 2106 layout.setHorizontalGroup( 2107 layout.createParallelGroup(LEADING) 2108 .addGroup(TRAILING, layout.createSequentialGroup() 2109 .addGroup(layout.createParallelGroup(TRAILING) 2110 .addGroup(layout.createSequentialGroup() 2111 .addContainerGap() 2112 .addComponent(helpButton) 2113 .addGap(GAP_RELATED) 2114 .addComponent(refreshButton) 2115 .addGap(GAP_RELATED) 2116 .addComponent(cancelButton) 2117 .addPreferredGap(RELATED) 2118 .addComponent(loadButton)) 2119 .addGroup(LEADING, layout.createSequentialGroup() 2120 .addContainerGap() 2121 .addGroup(layout.createParallelGroup(LEADING) 2122 .addComponent(innerPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 2123 .addGroup(layout.createSequentialGroup() 2124 .addComponent(serverLabel) 2125 .addGap(GAP_RELATED) 2126 .addComponent(serverSelector) 2127 .addGap(GAP_RELATED) 2128 .addComponent(manageButton) 2129 .addGap(GAP_RELATED) 2130 .addComponent(groupLabel) 2131 .addGap(GAP_RELATED) 2132 .addComponent(groupSelector) 2133 .addGap(GAP_RELATED) 2134 .addComponent(publicButton) 2135 .addPreferredGap(RELATED, DEFAULT_SIZE, Short.MAX_VALUE) 2136 .addComponent(connectButton)) 2137 .addGroup(layout.createSequentialGroup() 2138 .addComponent(statusLabelLabel) 2139 .addGap(GAP_RELATED) 2140 .addComponent(statusLabel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))))) 2141 .addContainerGap()) 2142 ); 2143 layout.setVerticalGroup( 2144 layout.createParallelGroup(LEADING) 2145 .addGroup(layout.createSequentialGroup() 2146 .addContainerGap() 2147 .addGroup(layout.createParallelGroup(BASELINE) 2148 .addComponent(serverLabel) 2149 .addComponent(serverSelector) 2150 .addComponent(manageButton) 2151 .addComponent(groupLabel) 2152 .addComponent(groupSelector) 2153 .addComponent(publicButton) 2154 .addComponent(connectButton)) 2155 .addPreferredGap(UNRELATED) 2156 .addComponent(innerPanel, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE) 2157 .addPreferredGap(UNRELATED) 2158 .addGroup(layout.createParallelGroup(BASELINE) 2159 .addComponent(statusLabelLabel) 2160 .addComponent(statusLabel)) 2161 .addPreferredGap(UNRELATED) 2162 .addGroup(layout.createParallelGroup(BASELINE) 2163 .addComponent(loadButton) 2164 .addComponent(cancelButton) 2165 .addComponent(refreshButton) 2166 .addComponent(helpButton)) 2167 .addContainerGap()) 2168 ); 2169 2170 return outerPanel; 2171 2172 } 2173 2174 public class ServerComparator implements Comparator<AddeServer> { 2175 public int compare(AddeServer server1, AddeServer server2) { 2176 return server1.getName().compareTo(server2.getName()); 2177 } 2178 } 2179 2180 public class GroupComparator implements Comparator<Group> { 2181 public int compare(Group group1, Group group2) { 2182 return group1.getName().compareTo(group2.getName()); 2183 } 2184 } 2185} 2186