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