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