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