View Javadoc

1   /*
2    * Copyright (C) 2007 ETH Zurich
3    *
4    * This file is part of Fosstrak (www.fosstrak.org).
5    *
6    * Fosstrak is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License version 2.1, as published by the Free Software Foundation.
9    *
10   * Fosstrak is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13   * Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public
16   * License along with Fosstrak; if not, write to the Free
17   * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18   * Boston, MA  02110-1301  USA
19   */
20  
21  package org.fosstrak.epcis.queryclient;
22  
23  import java.awt.BorderLayout;
24  import java.awt.GridBagConstraints;
25  import java.awt.GridBagLayout;
26  import java.awt.Insets;
27  import java.awt.event.ActionEvent;
28  import java.awt.event.ActionListener;
29  import java.awt.event.WindowAdapter;
30  import java.awt.event.WindowEvent;
31  import java.io.PrintWriter;
32  import java.io.StringWriter;
33  import java.net.MalformedURLException;
34  import java.net.URL;
35  import java.text.ParseException;
36  import java.util.ArrayList;
37  import java.util.Calendar;
38  import java.util.Iterator;
39  import java.util.LinkedHashMap;
40  import java.util.LinkedList;
41  import java.util.List;
42  import java.util.Map;
43  
44  import javax.swing.BorderFactory;
45  import javax.swing.Box;
46  import javax.swing.BoxLayout;
47  import javax.swing.JButton;
48  import javax.swing.JCheckBox;
49  import javax.swing.JComboBox;
50  import javax.swing.JFrame;
51  import javax.swing.JLabel;
52  import javax.swing.JList;
53  import javax.swing.JOptionPane;
54  import javax.swing.JPanel;
55  import javax.swing.JScrollPane;
56  import javax.swing.JTable;
57  import javax.swing.JTextArea;
58  import javax.swing.JTextField;
59  import javax.swing.ListSelectionModel;
60  import javax.swing.UIManager;
61  import javax.swing.event.DocumentEvent;
62  import javax.swing.event.DocumentListener;
63  import javax.xml.bind.JAXBElement;
64  import javax.xml.datatype.DatatypeFactory;
65  
66  import org.fosstrak.epcis.gui.AuthenticationOptionsChangeEvent;
67  import org.fosstrak.epcis.gui.AuthenticationOptionsChangeListener;
68  import org.fosstrak.epcis.gui.AuthenticationOptionsPanel;
69  import org.fosstrak.epcis.model.AggregationEventType;
70  import org.fosstrak.epcis.model.ArrayOfString;
71  import org.fosstrak.epcis.model.BusinessTransactionType;
72  import org.fosstrak.epcis.model.EPC;
73  import org.fosstrak.epcis.model.EPCISEventType;
74  import org.fosstrak.epcis.model.ObjectEventType;
75  import org.fosstrak.epcis.model.Poll;
76  import org.fosstrak.epcis.model.QuantityEventType;
77  import org.fosstrak.epcis.model.QueryParam;
78  import org.fosstrak.epcis.model.QueryParams;
79  import org.fosstrak.epcis.model.QueryResults;
80  import org.fosstrak.epcis.model.QuerySchedule;
81  import org.fosstrak.epcis.model.Subscribe;
82  import org.fosstrak.epcis.model.SubscriptionControls;
83  import org.fosstrak.epcis.model.TransactionEventType;
84  import org.fosstrak.epcis.queryclient.QueryClientHelper.ExampleQueries;
85  import org.fosstrak.epcis.utils.TimeParser;
86  
87  /**
88   * Implements the GUI part of the EPCIS Query Interface client.
89   * 
90   * @author David Gubler
91   */
92  public class QueryClientGui extends WindowAdapter implements ActionListener, AuthenticationOptionsChangeListener {
93  
94      /**
95       * The enumeration of all possible query parameter types.
96       */
97      public enum ParameterType {
98          ListOfString, Boolean, Int, Float, String, Time, noType
99      };
100 
101     /**
102      * The Map which holds all possible query parameters. Key is the user text.
103      */
104     private Map<String, QueryItem> queryParamsUserText;
105 
106     /**
107      * The Map which holds all possible query parameters. Key is the query text.
108      */
109     private Map<String, QueryItem> queryParamsQueryText;
110 
111     /**
112      * Contains the column names for the result table.
113      */
114     private final String[] columnNames = {
115             "Event", "occurred", "recorded", "Parent ID", "Quantity", "EPCs", "Action", "Business step", "Disposition",
116             "Readpoint ID", "Business location", "Business transaction" };
117 
118     /**
119      * Contains the various choices for the query parameters in a human readable
120      * form.
121      */
122     private String[] queryParameterUsertext;
123 
124     /**
125      * Contains the data for the result table.
126      */
127     private Object[][] data = {};
128 
129     /**
130      * The query client instance. Has methods to actually execute a query.
131      */
132     private QueryControlClient client = null;
133 
134     private boolean configurationChanged;
135 
136     /**
137      * Holds the query parameters.
138      */
139     private List<QueryParam> internalQueryParams = new ArrayList<QueryParam>();
140 
141     /* main window */
142     private JFrame mainWindow;
143     private JPanel mwMainPanel;
144     private JPanel mwConfigPanel;
145     private JPanel mwSubscribeManagementPanel;
146     private JPanel mwEventTypeSelectPanel;
147     private JPanel mwQueryPanel;
148     private AuthenticationOptionsPanel mwAuthOptions;
149     private JPanel mwSubscriptionPanel;
150     private JPanel mwQueryArgsPanel;
151     private JPanel mwQueryExamplesPanel;
152     private JPanel mwButtonPanel;
153     private JLabel mwServiceUrlLabel;
154 
155     private JTextField mwServiceUrlTextField = new JTextField("", 40);
156     private JButton mwServiceInfoButton;
157     private JLabel mwUnsubscribeQueryLabel;
158     private JTextField mwUnsubscribeQueryTextField;
159     private JButton mwUnsubscribeQueryButton;
160     private JButton mwSubscriptionIdButton;
161     private JCheckBox mwShowDebugWindowCheckBox;
162     private JCheckBox mwObjectEventsCheckBox;
163     private JCheckBox mwAggregationEventsCheckBox;
164     private JCheckBox mwQuantityEventsCheckBox;
165     private JCheckBox mwTransactionEventsCheckBox;
166 
167     /*
168      * These lists hold the input fields for the query arguments. The lists are
169      * modified by the user to allow for as many arguments as the user wants
170      * Objects may be deleted from these lists by selecting "ignore" from the
171      * drop-down box
172      */
173     private LinkedList<JComboBox> mwQuerySelectComboBoxes;
174     private LinkedList<JTextFieldEnhanced> mwQueryArgumentTextFields;
175 
176     private int mwQueryArgumentTextFieldsExtraWidth = 550;
177 
178     private JButton mwRunQueryButton;
179     private JButton mwFillInExampleButton;
180 
181     /* subscribe Query */
182     private JCheckBox isSubscribed;
183     private JTextField mwScheduleMinuteField;
184     private JTextField mwScheduleSecField;
185     private JTextField mwScheduleHourField;
186     private JTextField mwScheduleWeekField;
187     private JTextField mwScheduleMonthField;
188     private JTextField mwScheduleDayField;
189     private JTextField mwSubIdField;
190     private JTextField mwInitRecTimeField;
191     private JTextField mwDestUriTextField;
192     private JCheckBox reportIf;
193     private JCheckBox triggerIf;
194 
195     /* results window */
196     private JFrame resultsWindow;
197     private JPanel rwResultsPanel;
198     private JTable rwResultsTable;
199     private JScrollPane rwResultsScrollPane;
200 
201     /* example selection window */
202     private JFrame exampleWindow;
203     private JPanel ewMainPanel;
204     private JPanel ewListPanel;
205     private JPanel ewButtonPanel;
206     private JList ewExampleList;
207     private JScrollPane ewExampleScrollPane;
208     private JButton ewOkButton;
209 
210     /* debug window */
211     private JFrame debugWindow;
212     private JTextArea dwOutputTextArea;
213     private JScrollPane dwOutputScrollPane;
214     private JPanel dwButtonPanel;
215     private JButton dwClearButton;
216 
217     /**
218      * The constructor. Starts a new thread which draws the main window.
219      */
220     public QueryClientGui() {
221         try {
222             initGui(null);
223         } catch (MalformedURLException e) {
224             // shouldn't happen because url is loaded from properties 
225         }
226     }
227 
228     /**
229      * Constructs a new QueryClientGui which sends its queries to the given
230      * endpoint address. If no such address is provided, the properties file is
231      * checked; if there is an error with reading the properties, a default url
232      * will be provided.
233      * 
234      * @param address
235      *            The address to send the queries to.
236      */
237     public QueryClientGui(final String address) throws MalformedURLException {
238         initGui(address);
239     }
240     
241     private void initGui(String url) throws MalformedURLException {
242         generateParamHashMap();
243         drawDebugWindow();
244         client = new QueryControlClient(url);
245         mwServiceUrlTextField.setText(client.getQueryUrl());
246         javax.swing.SwingUtilities.invokeLater(new Runnable() {
247             public void run() {
248                 drawMainWindow(client.getQueryUrl());
249             }
250         });
251     }
252 
253     /**
254      * Initialized all the possible Query Parameters.
255      */
256     private void generateParamHashMap() {
257         QueryItem newEntry = new QueryItem();
258         queryParamsUserText = new LinkedHashMap<String, QueryItem>();
259         queryParamsQueryText = new LinkedHashMap<String, QueryItem>();
260 
261         newEntry.setDescription("Choose a query parameter " + "from the drop-down menu");
262         newEntry.setParamType(ParameterType.noType);
263         newEntry.setQueryText("");
264         newEntry.setRequired(false);
265         newEntry.setUserText("ignore");
266         queryParamsUserText.put(newEntry.getUserText(), newEntry);
267         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
268 
269         newEntry = new QueryItem();
270         newEntry.setDescription("Format is ISO 8601, i.e. YYYY-MM-DDThh:mm:ss.sssZ");
271         newEntry.setParamType(ParameterType.Time);
272         newEntry.setQueryText("GE_eventTime");
273         newEntry.setRequired(false);
274         newEntry.setUserText("event time >= ");
275         queryParamsUserText.put(newEntry.getUserText(), newEntry);
276         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
277 
278         newEntry = new QueryItem();
279         newEntry.setDescription("Format is ISO 8601, i.e. YYYY-MM-DDThh:mm:ss.sssZ");
280         newEntry.setParamType(ParameterType.Time);
281         newEntry.setQueryText("LT_eventTime");
282         newEntry.setRequired(false);
283         newEntry.setUserText("event time < ");
284         queryParamsUserText.put(newEntry.getUserText(), newEntry);
285         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
286 
287         newEntry = new QueryItem();
288         newEntry.setDescription("Format is ISO 8601, i.e. YYYY-MM-DDThh:mm:ss.sssZ");
289         newEntry.setParamType(ParameterType.Time);
290         newEntry.setQueryText("GE_recordTime");
291         newEntry.setRequired(false);
292         newEntry.setUserText("record time >= ");
293         queryParamsUserText.put(newEntry.getUserText(), newEntry);
294         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
295 
296         newEntry = new QueryItem();
297         newEntry.setDescription("Format is ISO 8601, i.e. YYYY-MM-DDThh:mm:ss.sssZ");
298         newEntry.setParamType(ParameterType.Time);
299         newEntry.setQueryText("LT_recordTime");
300         newEntry.setRequired(false);
301         newEntry.setUserText("record time < ");
302         queryParamsUserText.put(newEntry.getUserText(), newEntry);
303         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
304 
305         newEntry = new QueryItem();
306         newEntry.setDescription("Space-separated list of ADD, DELETE, OBSERVE");
307         newEntry.setParamType(ParameterType.ListOfString);
308         newEntry.setQueryText("EQ_action");
309         newEntry.setRequired(false);
310         newEntry.setUserText("action = ");
311         queryParamsUserText.put(newEntry.getUserText(), newEntry);
312         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
313 
314         newEntry = new QueryItem();
315         newEntry.setDescription("Space-separated list " + "of URIs with OR semantics");
316         newEntry.setParamType(ParameterType.ListOfString);
317         newEntry.setQueryText("EQ_bizStep");
318         newEntry.setRequired(false);
319         newEntry.setUserText("business step = ");
320         queryParamsUserText.put(newEntry.getUserText(), newEntry);
321         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
322 
323         newEntry = new QueryItem();
324         newEntry.setDescription("Space-separated list " + "of URIs with OR semantics");
325         newEntry.setParamType(ParameterType.ListOfString);
326         newEntry.setQueryText("EQ_disposition");
327         newEntry.setRequired(false);
328         newEntry.setUserText("disposition = ");
329         queryParamsUserText.put(newEntry.getUserText(), newEntry);
330         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
331 
332         newEntry = new QueryItem();
333         newEntry.setDescription("Space-separated list " + "of URIs with OR semantics");
334         newEntry.setParamType(ParameterType.ListOfString);
335         newEntry.setQueryText("EQ_readPoint");
336         newEntry.setRequired(false);
337         newEntry.setUserText("readpoint = ");
338         queryParamsUserText.put(newEntry.getUserText(), newEntry);
339         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
340 
341         newEntry = new QueryItem();
342         newEntry.setDescription("Space-separated list " + "of URIs with OR semantics");
343         newEntry.setParamType(ParameterType.ListOfString);
344         newEntry.setQueryText("WD_readPoint");
345         newEntry.setRequired(false);
346         newEntry.setUserText("readpoint descendant of ");
347         queryParamsUserText.put(newEntry.getUserText(), newEntry);
348         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
349 
350         newEntry = new QueryItem();
351         newEntry.setDescription("Space-separated list " + "of URIs with OR semantics");
352         newEntry.setParamType(ParameterType.ListOfString);
353         newEntry.setQueryText("EQ_bizLocation");
354         newEntry.setRequired(false);
355         newEntry.setUserText("business location = ");
356         queryParamsUserText.put(newEntry.getUserText(), newEntry);
357         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
358 
359         newEntry = new QueryItem();
360         newEntry.setDescription("Space-separated list " + "of URIs with OR semantics");
361         newEntry.setParamType(ParameterType.ListOfString);
362         newEntry.setQueryText("WD_bizLocation");
363         newEntry.setRequired(false);
364         newEntry.setUserText("business location descendant of ");
365         queryParamsUserText.put(newEntry.getUserText(), newEntry);
366         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
367 
368         // "EQ_bizTransaction_type", "business transaction type with ID's= ",
369         // we do not support this in the GUI (List of String)
370 
371         newEntry = new QueryItem();
372         newEntry.setDescription("Space-separated list " + "of URIs with OR semantics");
373         newEntry.setParamType(ParameterType.ListOfString);
374         newEntry.setQueryText("MATCH_epc");
375         newEntry.setRequired(false);
376         newEntry.setUserText("EPC = ");
377         queryParamsUserText.put(newEntry.getUserText(), newEntry);
378         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
379 
380         newEntry = new QueryItem();
381         newEntry.setDescription("Space-separated list " + "of URIs with OR semantics");
382         newEntry.setParamType(ParameterType.ListOfString);
383         newEntry.setQueryText("MATCH_parentID");
384         newEntry.setRequired(false);
385         newEntry.setUserText("parent ID = ");
386         queryParamsUserText.put(newEntry.getUserText(), newEntry);
387         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
388 
389         newEntry = new QueryItem();
390         newEntry.setDescription("Space-separated list " + "of URIs with OR semantics");
391         newEntry.setParamType(ParameterType.ListOfString);
392         newEntry.setQueryText("MATCH_epcClass");
393         newEntry.setRequired(false);
394         newEntry.setUserText("EPC class = ");
395         queryParamsUserText.put(newEntry.getUserText(), newEntry);
396         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
397 
398         newEntry = new QueryItem();
399         newEntry.setDescription("Integer number");
400         newEntry.setParamType(ParameterType.Int);
401         newEntry.setQueryText("EQ_quantity");
402         newEntry.setRequired(false);
403         newEntry.setUserText("quantity = ");
404         queryParamsUserText.put(newEntry.getUserText(), newEntry);
405         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
406 
407         newEntry = new QueryItem();
408         newEntry.setDescription("Integer number");
409         newEntry.setParamType(ParameterType.Int);
410         newEntry.setQueryText("GT_quantity");
411         newEntry.setRequired(false);
412         newEntry.setUserText("quantity > ");
413         queryParamsUserText.put(newEntry.getUserText(), newEntry);
414         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
415 
416         newEntry = new QueryItem();
417         newEntry.setDescription("Integer number");
418         newEntry.setParamType(ParameterType.Int);
419         newEntry.setQueryText("GE_quantity");
420         newEntry.setRequired(false);
421         newEntry.setUserText("quantity >= ");
422         queryParamsUserText.put(newEntry.getUserText(), newEntry);
423         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
424 
425         newEntry = new QueryItem();
426         newEntry.setDescription("Integer number");
427         newEntry.setParamType(ParameterType.Int);
428         newEntry.setQueryText("LT_quantity");
429         newEntry.setRequired(false);
430         newEntry.setUserText("quantity < ");
431         queryParamsUserText.put(newEntry.getUserText(), newEntry);
432         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
433 
434         newEntry = new QueryItem();
435         newEntry.setDescription("Integer number");
436         newEntry.setParamType(ParameterType.Int);
437         newEntry.setQueryText("LE_quantity");
438         newEntry.setRequired(false);
439         newEntry.setUserText("quantity <= ");
440         queryParamsUserText.put(newEntry.getUserText(), newEntry);
441         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
442 
443         // "EQ_fieldname", "Fieldname with values = "
444         // we do not support this in the GUI (List of String)
445         // "EQ_fieldname", "Fieldname with values = "
446         // we do not support this in the GUI (Int, Float, Time)
447         // "GT_fieldname", "Fieldname with values > "
448         // we do not support this in the GUI (Int, Float, Time)
449         // "GE_fieldname", "Fieldname with values >= "
450         // we do not support this in the GUI (Int, Float, Time)
451         // "LT_fieldname", "Fieldname with values < "
452         // we do not support this in the GUI (Int, Float, Time)
453         // "LE_fieldname", "Fieldname with values <= "
454         // we do not support this in the GUI (Int, Float, Time)
455         // "EXISTS_fieldname", "exists field: "
456         // we do not support this in the GUI (Void)
457         // "HASATTR_fieldname", "Has fieldname attributes: "
458         // we do not support this in the GUI (List of String)
459         // "EQATTR_fieldname_attrname", "Equals fieldname attributname: "
460         // we do not support this in the GUI (List of String)
461 
462         newEntry = new QueryItem();
463         newEntry.setDescription("A single fieldname written in");
464         newEntry.setParamType(ParameterType.String);
465         newEntry.setQueryText("orderBy");
466         newEntry.setRequired(false);
467         newEntry.setUserText("Order by field: ");
468         queryParamsUserText.put(newEntry.getUserText(), newEntry);
469         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
470 
471         newEntry = new QueryItem();
472         newEntry.setDescription("ASC or DESC. Default is DESC.");
473         newEntry.setParamType(ParameterType.String);
474         newEntry.setQueryText("orderDirection");
475         newEntry.setRequired(false);
476         newEntry.setUserText("direction of order: ");
477         queryParamsUserText.put(newEntry.getUserText(), newEntry);
478         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
479 
480         newEntry = new QueryItem();
481         newEntry.setDescription("Integer number");
482         newEntry.setParamType(ParameterType.Int);
483         newEntry.setQueryText("eventCountLimit");
484         newEntry.setRequired(false);
485         newEntry.setUserText("only the first n: ");
486         queryParamsUserText.put(newEntry.getUserText(), newEntry);
487         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
488 
489         newEntry = new QueryItem();
490         newEntry.setDescription("Integer number");
491         newEntry.setParamType(ParameterType.Int);
492         newEntry.setQueryText("maxEventCount");
493         newEntry.setRequired(false);
494         newEntry.setUserText("has not more then n Events ");
495         queryParamsUserText.put(newEntry.getUserText(), newEntry);
496         queryParamsQueryText.put(newEntry.getQueryText(), newEntry);
497 
498         queryParameterUsertext = new String[queryParamsUserText.size()];
499         int i = 0;
500         for (Iterator<String> it = queryParamsUserText.keySet().iterator(); it.hasNext();) {
501             queryParameterUsertext[i] = (String) it.next();
502             i++;
503         }
504     }
505 
506     /**
507      * Sets up the main window. To be called only once per program run
508      */
509     private void drawMainWindow(String queryUrl) {
510         JFrame.setDefaultLookAndFeelDecorated(true);
511 
512         mainWindow = new JFrame("EPCIS query interface client");
513         mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
514         mainWindow.setResizable(false);
515 
516         mwMainPanel = new JPanel();
517         mwMainPanel.setLayout(new BoxLayout(mwMainPanel, BoxLayout.PAGE_AXIS));
518         mwMainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
519 
520         mwConfigPanel = new JPanel(new GridBagLayout());
521         mwMainPanel.add(mwConfigPanel);
522 
523         mwSubscribeManagementPanel = new JPanel(new GridBagLayout());
524         mwMainPanel.add(mwSubscribeManagementPanel);
525 
526         mwEventTypeSelectPanel = new JPanel();
527         mwMainPanel.add(mwEventTypeSelectPanel);
528 
529         mwQueryPanel = new JPanel();
530         mwSubscriptionPanel = new JPanel();
531         mwQueryPanel.setLayout(new BoxLayout(mwQueryPanel, BoxLayout.PAGE_AXIS));
532         mwSubscriptionPanel.setLayout(new GridBagLayout());
533         mwMainPanel.add(mwQueryPanel);
534 
535         isSubscribed = new JCheckBox("Subscribe this query");
536         mwMainPanel.add(isSubscribed);
537         isSubscribed.addActionListener(new ActionListener() {
538             public void actionPerformed(final ActionEvent e) {
539                 if (mwSubscriptionPanel.isVisible()) {
540                     mwSubscriptionPanel.setVisible(false);
541                     mwRunQueryButton.setText("Run Query");
542                     mainWindow.pack();
543                 } else {
544                     mwSubscriptionPanel.setVisible(true);
545                     mwRunQueryButton.setText("Subscribe Query");
546                     mainWindow.pack();
547                 }
548             }
549         });
550         mwSubscriptionPanel.setVisible(false);
551         mwMainPanel.add(mwSubscriptionPanel);
552 
553         mwButtonPanel = new JPanel();
554         mwMainPanel.add(mwButtonPanel);
555 
556         mwConfigPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Configuration"),
557                 BorderFactory.createEmptyBorder(5, 5, 5, 5)));
558 
559         mwSubscribeManagementPanel.setBorder(BorderFactory.createCompoundBorder(
560                 BorderFactory.createTitledBorder("Subscribe Management"), BorderFactory.createEmptyBorder(5, 5, 5, 5)));
561 
562         mwEventTypeSelectPanel.setBorder(BorderFactory.createCompoundBorder(
563                 BorderFactory.createTitledBorder("Events to be returned"), BorderFactory.createEmptyBorder(5, 5, 5, 5)));
564 
565         mwQueryPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder("Query arguments"),
566                 BorderFactory.createEmptyBorder(5, 5, 5, 5)));
567 
568         mwSubscriptionPanel.setBorder(BorderFactory.createCompoundBorder(
569                 BorderFactory.createTitledBorder("Subscription Arguments"), BorderFactory.createEmptyBorder(5, 5, 5, 5)));
570 
571         mwServiceUrlLabel = new JLabel("Query interface URL: ");
572         mwServiceInfoButton = new JButton("Info");
573         mwServiceInfoButton.addActionListener(this);
574         mwAuthOptions = new AuthenticationOptionsPanel(this);
575 
576         mwUnsubscribeQueryLabel = new JLabel("Unsubscribe ID: ");
577         mwUnsubscribeQueryTextField = new JTextField("", 40);
578         mwUnsubscribeQueryTextField.setToolTipText("Only one Subscription ID");
579         mwUnsubscribeQueryButton = new JButton("Unsubscribe");
580         mwUnsubscribeQueryButton.addActionListener(this);
581         mwSubscriptionIdButton = new JButton("Show SubscriptionIDs");
582         mwSubscriptionIdButton.addActionListener(this);
583 
584         mwShowDebugWindowCheckBox = new JCheckBox("Show debug window", false);
585         mwShowDebugWindowCheckBox.addActionListener(this);
586 
587         mwServiceUrlTextField.getDocument().addDocumentListener(new DocumentListener() {
588 
589             public void changedUpdate(DocumentEvent e) {
590                 configurationChanged(new AuthenticationOptionsChangeEvent(this, isComplete()));
591             }
592 
593             public void insertUpdate(DocumentEvent e) {
594                 configurationChanged(new AuthenticationOptionsChangeEvent(this, isComplete()));
595             }
596 
597             public void removeUpdate(DocumentEvent e) {
598                 configurationChanged(new AuthenticationOptionsChangeEvent(this, isComplete()));
599             }
600 
601             public boolean isComplete() {
602                 String url = mwServiceUrlTextField.getText();
603                 return url != null && url.length() > 0;
604             }
605 
606         });
607 
608         GridBagConstraints c = new GridBagConstraints();
609         c.fill = GridBagConstraints.HORIZONTAL;
610         c.insets = new Insets(5, 5, 5, 0);
611         c.weightx = 0;
612         c.gridx = 0;
613         c.gridy = 0;
614         mwConfigPanel.add(mwServiceUrlLabel, c);
615         c.weightx = 1;
616         c.gridx = 1;
617         c.gridy = 0;
618         mwConfigPanel.add(mwServiceUrlTextField, c);
619         c.weightx = 0;
620         c.gridx = 3;
621         c.gridy = 0;
622         mwConfigPanel.add(mwServiceInfoButton, c);
623         c.weightx = 0;
624         c.gridx = 0;
625         c.gridy = 1;
626         c.gridwidth = 2;
627         mwConfigPanel.add(mwAuthOptions, c);
628         c.weightx = 0;
629         c.gridx = 0;
630         c.gridy = 2;
631         c.gridwidth = 2;
632         mwConfigPanel.add(mwShowDebugWindowCheckBox, c);
633 
634         c.weightx = 0;
635         c.gridx = 0;
636         c.gridy = 0;
637         c.gridwidth = 1;
638         mwSubscribeManagementPanel.add(mwUnsubscribeQueryLabel, c);
639         c.weightx = 1;
640         c.gridx = 1;
641         c.gridy = 0;
642         mwSubscribeManagementPanel.add(mwUnsubscribeQueryTextField, c);
643         c.weightx = 0;
644         c.gridx = 2;
645         c.gridy = 0;
646         mwSubscribeManagementPanel.add(mwUnsubscribeQueryButton, c);
647         c.weightx = 0;
648         c.gridx = 3;
649         c.gridy = 0;
650         mwSubscribeManagementPanel.add(mwSubscriptionIdButton, c);
651 
652         mwObjectEventsCheckBox = new JCheckBox("ObjectEvents");
653         mwEventTypeSelectPanel.add(mwObjectEventsCheckBox);
654         mwAggregationEventsCheckBox = new JCheckBox("AggregationEvents");
655         mwEventTypeSelectPanel.add(mwAggregationEventsCheckBox);
656         mwQuantityEventsCheckBox = new JCheckBox("QuantityEvents");
657         mwEventTypeSelectPanel.add(mwQuantityEventsCheckBox);
658         mwTransactionEventsCheckBox = new JCheckBox("TransactionEvents");
659         mwEventTypeSelectPanel.add(mwTransactionEventsCheckBox);
660 
661         mwQuerySelectComboBoxes = new LinkedList<JComboBox>();
662         mwQueryArgumentTextFields = new LinkedList<JTextFieldEnhanced>();
663 
664         mwQuerySelectComboBoxes.add(new JComboBox(queryParameterUsertext));
665         ((JComboBox) mwQuerySelectComboBoxes.getFirst()).addActionListener(this);
666         queryParamsUserText.get("ignore");
667         mwQueryArgumentTextFields.add(new JTextFieldEnhanced(15, queryParamsUserText.get("ignore")));
668 
669         mwQueryArgsPanel = new JPanel(new GridBagLayout());
670         mwQueryExamplesPanel = new JPanel(new BorderLayout());
671         mwQueryPanel.add(mwQueryArgsPanel);
672         mwQueryPanel.add(mwQueryExamplesPanel);
673 
674         c = new GridBagConstraints();
675         c.fill = GridBagConstraints.HORIZONTAL;
676         c.insets = new Insets(10, 5, 5, 0);
677         c.weightx = 0;
678         c.gridx = 0;
679         c.gridy = 0;
680         mwQueryArgsPanel.add((JComboBox) mwQuerySelectComboBoxes.getFirst(), c);
681         c.weightx = 1;
682         c.gridx = 1;
683         c.ipadx = mwQueryArgumentTextFieldsExtraWidth;
684         mwQueryArgsPanel.add((JTextField) mwQueryArgumentTextFields.getFirst(), c);
685 
686         c = new GridBagConstraints();
687         c.fill = GridBagConstraints.HORIZONTAL;
688         c.insets = new Insets(10, 5, 5, 0);
689         c.weightx = 0;
690         c.gridx = 0;
691         c.gridy = 0;
692         reportIf = new JCheckBox("Report if empty?");
693         reportIf.setSelected(true);
694         mwSubscriptionPanel.add(reportIf);
695 
696         c = new GridBagConstraints();
697         c.fill = GridBagConstraints.HORIZONTAL;
698         c.insets = new Insets(10, 5, 5, 0);
699         c.weightx = 0;
700         c.gridx = 1;
701         c.gridy = 0;
702         triggerIf = new JCheckBox("Use trigger instead of schedule?");
703         triggerIf.setSelected(false);
704         mwSubscriptionPanel.add(triggerIf);
705         triggerIf.addActionListener(new ActionListener() {
706             public void actionPerformed(final ActionEvent e) {
707                 if (mwScheduleMonthField.isEnabled()) {
708                     mwScheduleMonthField.setEnabled(false);
709                     mwScheduleWeekField.setEnabled(false);
710                     mwScheduleDayField.setEnabled(false);
711                     mwScheduleHourField.setEnabled(false);
712                     mwScheduleMinuteField.setEnabled(false);
713                     mwScheduleSecField.setEnabled(false);
714                 } else {
715                     mwScheduleMonthField.setEnabled(true);
716                     mwScheduleWeekField.setEnabled(true);
717                     mwScheduleDayField.setEnabled(true);
718                     mwScheduleHourField.setEnabled(true);
719                     mwScheduleMinuteField.setEnabled(true);
720                     mwScheduleSecField.setEnabled(true);
721                 }
722             }
723         });
724 
725         c.weightx = 0;
726         c.gridx = 0;
727         c.gridy = 1;
728         JLabel mwDestUri = new JLabel("Destination URI: ");
729         mwSubscriptionPanel.add(mwDestUri, c);
730         c.weightx = 1;
731         c.gridx = 1;
732         c.gridy = 1;
733         c.gridwidth = 6;
734         mwDestUriTextField = new JTextField("http://localhost:8888", 40);
735         mwSubscriptionPanel.add(mwDestUriTextField, c);
736 
737         c.weightx = 0;
738         c.gridx = 0;
739         c.gridy = 2;
740         c.gridwidth = 1;
741         JLabel mwInitRecTime = new JLabel("Initial Record Time: ");
742         mwSubscriptionPanel.add(mwInitRecTime, c);
743         c.weightx = 1;
744         c.gridx = 1;
745         c.gridy = 2;
746         c.gridwidth = 6;
747         Calendar cal = Calendar.getInstance();
748         mwInitRecTimeField = new JTextField(TimeParser.format(cal), 40);
749         mwSubscriptionPanel.add(mwInitRecTimeField, c);
750 
751         c.weightx = 0;
752         c.gridx = 0;
753         c.gridy = 3;
754         c.gridwidth = 1;
755         JLabel mwSubId = new JLabel("Subscription ID: ");
756         mwSubscriptionPanel.add(mwSubId, c);
757         c.weightx = 1;
758         c.gridx = 1;
759         c.gridy = 3;
760         c.gridwidth = 6;
761         mwSubIdField = new JTextField("", 40);
762         mwSubscriptionPanel.add(mwSubIdField, c);
763 
764         c.weightx = 0;
765         c.gridx = 0;
766         c.gridy = 4;
767         c.gridwidth = 1;
768         JLabel mwSchedule = new JLabel("Schedule: ");
769         mwSubscriptionPanel.add(mwSchedule, c);
770 
771         c.fill = GridBagConstraints.NONE;
772         c.anchor = GridBagConstraints.WEST;
773         c.gridx = 1;
774         JLabel mwScheduleDay = new JLabel("Day of Month: ");
775         mwSubscriptionPanel.add(mwScheduleDay, c);
776 
777         c.gridx = 2;
778         c.insets = new Insets(10, 5, 5, 30);
779         mwScheduleDayField = new JTextField("", 10);
780         mwSubscriptionPanel.add(mwScheduleDayField, c);
781 
782         c.gridx = 3;
783         c.insets = new Insets(10, 5, 5, 0);
784         JLabel mwScheduleMonth = new JLabel("Month: ");
785         mwSubscriptionPanel.add(mwScheduleMonth, c);
786 
787         c.gridx = 4;
788         c.insets = new Insets(10, 5, 5, 30);
789         mwScheduleMonthField = new JTextField("", 10);
790         mwSubscriptionPanel.add(mwScheduleMonthField, c);
791 
792         c.gridx = 5;
793         c.insets = new Insets(10, 5, 5, 0);
794         JLabel mwScheduleWeek = new JLabel("Day of Week: ");
795         mwSubscriptionPanel.add(mwScheduleWeek, c);
796 
797         c.gridx = 6;
798         mwScheduleWeekField = new JTextField("", 10);
799         mwSubscriptionPanel.add(mwScheduleWeekField, c);
800 
801         c.gridy = 5;
802         c.gridx = 1;
803         c.insets = new Insets(10, 5, 5, 0);
804         JLabel mwScheduleHour = new JLabel("Hour: ");
805         mwSubscriptionPanel.add(mwScheduleHour, c);
806 
807         c.gridx = 2;
808         c.insets = new Insets(10, 5, 5, 30);
809         mwScheduleHourField = new JTextField("", 10);
810         mwSubscriptionPanel.add(mwScheduleHourField, c);
811 
812         c.gridx = 3;
813         c.insets = new Insets(10, 5, 5, 0);
814         JLabel mwScheduleMinute = new JLabel("Minute: ");
815         mwSubscriptionPanel.add(mwScheduleMinute, c);
816 
817         c.gridx = 4;
818         c.insets = new Insets(10, 5, 5, 30);
819         mwScheduleMinuteField = new JTextField("", 10);
820         mwSubscriptionPanel.add(mwScheduleMinuteField, c);
821 
822         c.gridx = 5;
823         c.insets = new Insets(10, 5, 5, 0);
824         JLabel mwScheduleSec = new JLabel("Sec: ");
825         mwSubscriptionPanel.add(mwScheduleSec, c);
826 
827         c.gridx = 6;
828         mwScheduleSecField = new JTextField("", 10);
829         mwSubscriptionPanel.add(mwScheduleSecField, c);
830 
831         mwFillInExampleButton = new JButton("Fill in example");
832         mwFillInExampleButton.addActionListener(this);
833         mwQueryExamplesPanel.add(mwFillInExampleButton, BorderLayout.EAST);
834 
835         mwRunQueryButton = new JButton("Run query");
836         mwRunQueryButton.addActionListener(this);
837         mwButtonPanel.add(mwRunQueryButton);
838 
839         mainWindow.getContentPane().add(mwMainPanel);
840         mainWindow.pack();
841         mainWindow.setVisible(true);
842 
843         // /*
844         // * Find out how much the window has to be scaled whenever new
845         // components
846         // * are added. This must be done after rendering the GUI, otherwise the
847         // * sizes will be wrong!
848         // */
849         // if (((JComboBox) mwQuerySelectComboBoxes.getFirst()).getSize().height
850         // > ((JTextField)
851         // mwQueryArgumentTextFields.getFirst()).getSize().height) {
852         // mwHeightDifference = ((JComboBox)
853         // mwQuerySelectComboBoxes.getFirst()).getPreferredSize().height
854         // + c.insets.top + c.insets.bottom;
855         // } else {
856         // mwHeightDifference = ((JTextField)
857         // mwQueryArgumentTextFields.getFirst()).getPreferredSize().height
858         // + c.insets.top + c.insets.bottom;
859         // }
860     }
861 
862     /**
863      * Sets up the window used for results display. Does not destroy the old
864      * window.
865      */
866     private void createResultsWindow() {
867         resultsWindow = new JFrame("Query results");
868         resultsWindow.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
869 
870         rwResultsPanel = new JPanel();
871         rwResultsPanel.setLayout(new BoxLayout(rwResultsPanel, BoxLayout.Y_AXIS));
872 
873         rwResultsTable = new JTable(data, columnNames);
874         rwResultsScrollPane = new JScrollPane(rwResultsTable);
875         rwResultsPanel.add(rwResultsTable.getTableHeader());
876         rwResultsPanel.add(rwResultsScrollPane);
877 
878         resultsWindow.getContentPane().add(rwResultsPanel);
879         resultsWindow.pack();
880         resultsWindow.setVisible(true);
881     }
882 
883     /**
884      * Sets up the window used to show the list of examples. Can only be open
885      * once.
886      */
887     private void drawExampleWindow() {
888         if (exampleWindow != null) {
889             exampleWindow.setVisible(true);
890             return;
891         }
892         exampleWindow = new JFrame("Choose example");
893         exampleWindow.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
894 
895         ewMainPanel = new JPanel();
896         ewMainPanel.setLayout(new BoxLayout(ewMainPanel, BoxLayout.PAGE_AXIS));
897         exampleWindow.add(ewMainPanel);
898 
899         ewListPanel = new JPanel();
900         ewListPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 5));
901         ewListPanel.setLayout(new BoxLayout(ewListPanel, BoxLayout.PAGE_AXIS));
902 
903         ewButtonPanel = new JPanel();
904         ewButtonPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 10, 10));
905         ewButtonPanel.setLayout(new BoxLayout(ewButtonPanel, BoxLayout.LINE_AXIS));
906 
907         ewMainPanel.add(ewListPanel);
908         ewMainPanel.add(ewButtonPanel);
909 
910         ewExampleList = new JList();
911         ewExampleScrollPane = new JScrollPane(ewExampleList);
912         ewListPanel.add(ewExampleScrollPane);
913         ewExampleList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
914 
915         String[] exampleList = new String[ExampleQueries.getExamples().size()];
916         for (int i = 0; i < ExampleQueries.getExamples().size(); i++) {
917             exampleList[i] = ((Query) ExampleQueries.getExamples().get(i)).getDescription();
918         }
919         ewExampleList.setListData(exampleList);
920 
921         ewOkButton = new JButton("Fill in");
922         ewOkButton.addActionListener(this);
923         ewButtonPanel.add(Box.createHorizontalGlue());
924         ewButtonPanel.add(ewOkButton);
925         ewButtonPanel.add(Box.createHorizontalGlue());
926 
927         exampleWindow.pack();
928         exampleWindow.setVisible(true);
929     }
930 
931     /**
932      * Sets up the window used to show the debug output.
933      */
934     private void drawDebugWindow() {
935         debugWindow = new JFrame("Debug output");
936         debugWindow.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
937         debugWindow.addWindowListener(this);
938         debugWindow.setLocation(500, 100);
939         debugWindow.setSize(500, 300);
940 
941         dwOutputTextArea = new JTextArea();
942         dwOutputScrollPane = new JScrollPane(dwOutputTextArea);
943         debugWindow.add(dwOutputScrollPane);
944 
945         dwButtonPanel = new JPanel();
946         debugWindow.add(dwButtonPanel, BorderLayout.AFTER_LAST_LINE);
947 
948         dwClearButton = new JButton("Clear");
949         dwClearButton.addActionListener(this);
950         dwButtonPanel.add(dwClearButton);
951     }
952 
953     public final void actionPerformed(final ActionEvent e) {
954         int i;
955         if (e.getSource() == mwRunQueryButton) {
956             mwQueryButtonPressed();
957         } else if (e.getSource() == mwServiceInfoButton) {
958             mwInfoButtonPressed();
959         } else if (e.getSource() == mwSubscriptionIdButton) {
960             mwSubscriptionIdButtonPressed();
961         } else if (e.getSource() == mwFillInExampleButton) {
962             drawExampleWindow();
963         } else if (e.getSource() == dwClearButton) {
964             dwOutputTextArea.setText("");
965         } else if (e.getSource() == mwUnsubscribeQueryButton) {
966             mwUnsubscribeQueryButtonPressed(mwUnsubscribeQueryTextField.getText());
967         } else if (e.getSource() == ewOkButton) {
968             examplesChanged();
969         } else if (e.getSource() == mwShowDebugWindowCheckBox) {
970             debugWindow.setVisible(mwShowDebugWindowCheckBox.isSelected());
971         } else if ((i = mwQuerySelectComboBoxes.indexOf(e.getSource())) >= 0) {
972             mwQuerySelectComboBoxesChanged(i);
973         }
974     }
975 
976     private void mwSubscriptionIdButtonPressed() {
977         try {
978             String title = "Service is responding";
979             StringBuilder msg = new StringBuilder();
980             List<String> subscriptionIDs = client.getSubscriptionIds("SimpleEventQuery");
981             if (subscriptionIDs != null && !subscriptionIDs.isEmpty()) {
982                 msg.append("The following subscription IDs were found in the repository:\n");
983                 for (String s : subscriptionIDs) {
984                     msg.append("- ").append(s).append("\n");
985                 }
986             } else {
987                 msg.append("There are no subscribed queries.");
988             }
989             JFrame frame = new JFrame();
990             JOptionPane.showMessageDialog(frame, msg.toString(), title, JOptionPane.INFORMATION_MESSAGE);
991         } catch (Exception ex) {
992             dwOutputTextArea.append("Could not fetch subscription IDs from repository.");
993             StringWriter detailed = new StringWriter();
994             PrintWriter pw = new PrintWriter(detailed);
995             ex.printStackTrace(pw);
996             dwOutputTextArea.append(detailed.toString());
997             showErrorFrame();
998         }
999     }
1000 
1001     private void mwUnsubscribeQueryButtonPressed(String subscriptionID) {
1002         try {
1003             JFrame frame = new JFrame();
1004             if (subscriptionID.equals("")) {
1005                 JOptionPane.showMessageDialog(frame, "Please specify a SubscriptionID", "Service is responding",
1006                         JOptionPane.ERROR_MESSAGE);
1007                 return;
1008             }
1009             client.unsubscribe(subscriptionID);
1010             JOptionPane.showMessageDialog(frame, "Successfully unsubscribed.", "Service is responding",
1011                     JOptionPane.INFORMATION_MESSAGE);
1012         } catch (Exception ex) {
1013             dwOutputTextArea.append("Could not unsubscribe query.");
1014             StringWriter detailed = new StringWriter();
1015             PrintWriter pw = new PrintWriter(detailed);
1016             ex.printStackTrace(pw);
1017             dwOutputTextArea.append(detailed.toString());
1018             showErrorFrame();
1019         }
1020     }
1021 
1022     /**
1023      * Handler for pressed "Run query" button.
1024      */
1025     private void mwQueryButtonPressed() {
1026         dwOutputTextArea.setText("");
1027         if (resultsWindow != null) {
1028             resultsWindow.dispose();
1029         }
1030         try {
1031             // checkQueryUrl(mwServiceUrlTextField.getText());
1032             clearParameters();
1033 
1034             /* get event type selection from GUI */
1035             ArrayOfString events = new ArrayOfString();
1036             if (mwObjectEventsCheckBox.isSelected()) {
1037                 events.getString().add("ObjectEvent");
1038             }
1039             if (mwAggregationEventsCheckBox.isSelected()) {
1040                 events.getString().add("AggregationEvent");
1041             }
1042             if (mwQuantityEventsCheckBox.isSelected()) {
1043                 events.getString().add("QuantityEvent");
1044             }
1045             if (mwTransactionEventsCheckBox.isSelected()) {
1046                 events.getString().add("TransactionEvent");
1047             }
1048             if (!events.getString().isEmpty()) {
1049                 QueryParam queryParam = new QueryParam();
1050                 queryParam.setName("eventType");
1051                 queryParam.setValue(events);
1052                 addParameter(queryParam);
1053             }
1054 
1055             String name;
1056             for (int i = 0; i < mwQueryArgumentTextFields.size() - 1; i++) {
1057                 name = ((JTextFieldEnhanced) mwQueryArgumentTextFields.get(i)).queryItem.getQueryText();
1058                 QueryParam param = new QueryParam();
1059                 param.setName(name);
1060                 switch (((JTextFieldEnhanced) mwQueryArgumentTextFields.get(i)).queryItem.getParamType()) {
1061                 case ListOfString:
1062                     ArrayOfString valueArray = QueryClientHelper.stringListToArray(((JTextField) mwQueryArgumentTextFields.get(i)).getText());
1063                     param.setValue(valueArray);
1064                     addParameter(param);
1065                     break;
1066                 case Int:
1067                     Integer valueInteger = Integer.decode(((JTextField) mwQueryArgumentTextFields.get(i)).getText());
1068                     param.setValue(valueInteger);
1069                     addParameter(param);
1070                     break;
1071                 case Time:
1072                     // parse given ISO8601 date string into a calendar
1073                     String dateStr = ((JTextField) mwQueryArgumentTextFields.get(i)).getText();
1074                     Calendar cal = TimeParser.parseAsCalendar(dateStr);
1075                     param.setValue(cal);
1076                     addParameter(param);
1077                     break;
1078                 default:
1079                     String value = ((JTextField) mwQueryArgumentTextFields.get(i)).getText();
1080                     param.setValue(value);
1081                     addParameter(param);
1082                     break;
1083                 }
1084             }
1085 
1086             configureServiceIfNecessary();
1087             if (isSubscribed.isSelected()) {
1088                 if (mwSubIdField.getText().equals("")) {
1089                     JFrame frame = new JFrame();
1090                     JOptionPane.showMessageDialog(frame, "Please specify a SubscriptionID", "Missing input",
1091                             JOptionPane.PLAIN_MESSAGE);
1092                     return;
1093                 }
1094                 Subscribe subcr = new Subscribe();
1095                 subcr.setDest(mwDestUriTextField.getText());
1096                 subcr.setQueryName("SimpleEventQuery");
1097                 subcr.setSubscriptionID(mwSubIdField.getText());
1098                 SubscriptionControls controls = new SubscriptionControls();
1099                 String dateStr = mwInitRecTimeField.getText();
1100                 DatatypeFactory factory = DatatypeFactory.newInstance();
1101                 controls.setInitialRecordTime(factory.newXMLGregorianCalendar(dateStr));
1102                 controls.setReportIfEmpty(reportIf.isSelected());
1103                 QuerySchedule sched = new QuerySchedule();
1104 
1105                 if (!triggerIf.isSelected()) {
1106                     sched.setSecond(mwScheduleSecField.getText());
1107                     sched.setMinute(mwScheduleMinuteField.getText());
1108                     sched.setHour(mwScheduleHourField.getText());
1109                     sched.setDayOfMonth(mwScheduleDayField.getText());
1110                     sched.setMonth(mwScheduleMonthField.getText());
1111                     sched.setDayOfWeek(mwScheduleWeekField.getText());
1112                     controls.setSchedule(sched);
1113                 } else {
1114                     controls.setTrigger(mwDestUriTextField.getText());
1115                 }
1116                 subcr.setControls(controls);
1117                 QueryParams queryParams = new QueryParams();
1118                 queryParams.getParam().addAll(internalQueryParams);
1119                 debug("Number of query parameters: " + queryParams.getParam().size() + "\n");
1120                 for (QueryParam queryParam : internalQueryParams) {
1121                     debug(queryParam.getName() + " " + queryParam.getValue() + "\n");
1122                 }
1123                 subcr.setParams(queryParams);
1124                 client.subscribe(subcr);
1125                 JFrame frame = new JFrame();
1126                 JOptionPane.showMessageDialog(frame, "Query subscription successful.", "Service invocation successful",
1127                         JOptionPane.INFORMATION_MESSAGE);
1128             } else {
1129                 data = runQuery();
1130                 createResultsWindow();
1131             }
1132         } catch (ParseException e) {
1133             String msg = "Unable to parse a Time value.";
1134             dwOutputTextArea.append("\n" + msg + "\n");
1135             StringWriter sw = new StringWriter();
1136             PrintWriter pw = new PrintWriter(sw);
1137             e.printStackTrace(pw);
1138             dwOutputTextArea.append(sw.toString());
1139             JFrame frame = new JFrame();
1140             JOptionPane.showMessageDialog(frame, msg + "\n" + e.getMessage(), "Service invocation error",
1141                     JOptionPane.ERROR_MESSAGE);
1142         } catch (Exception e) {
1143             String msg = "Unexpected error while invoking EPCIS Query Interface.";
1144             dwOutputTextArea.append("\n" + msg + "\n");
1145             dwOutputTextArea.append(e.toString());
1146             StringWriter sw = new StringWriter();
1147             PrintWriter pw = new PrintWriter(sw);
1148             e.printStackTrace(pw);
1149             dwOutputTextArea.append(sw.toString());
1150             showErrorFrame();
1151         }
1152     }
1153 
1154     /**
1155      * Shows a new JFrame with a specific invocation error message.
1156      */
1157     private void showErrorFrame() {
1158         JFrame frame = new JFrame();
1159         String msg = "Unexpected error while invoking EPCIS Query Interface.\n"
1160                 + "See the Debug output window for more details.";
1161         JOptionPane.showMessageDialog(frame, msg, "Service invocation failed", JOptionPane.ERROR_MESSAGE);
1162     }
1163 
1164     /**
1165      * Handles the event of a changed JComboBox in the query arguments section
1166      * Will add or remove JComboBoxes as necessary and resize the window.
1167      * 
1168      * @param i
1169      *            The index of the combo box.
1170      */
1171     private void mwQuerySelectComboBoxesChanged(final int i) {
1172         JComboBox cb = (JComboBox) mwQuerySelectComboBoxes.get(i);
1173 
1174         if ((cb.getSelectedIndex() == 0) && (cb != mwQuerySelectComboBoxes.getLast())) {
1175             /*
1176              * the user selected "ignore" and this is not the last row, so
1177              * remove it
1178              */
1179             removeArgumentRow(i);
1180         } else if ((cb.getSelectedIndex() != 0) && (cb == mwQuerySelectComboBoxes.getLast())) {
1181             /* the user changed the value of the last row, so add a new row */
1182             addArgumentRow(i);
1183         } else {
1184             /* the user changed an existing row, so just update description */
1185             ((JTextFieldEnhanced) mwQueryArgumentTextFields.get(i)).setQueryItem(queryParamsUserText.get(queryParameterUsertext[cb.getSelectedIndex()]));
1186         }
1187     }
1188 
1189     /**
1190      * Handles the event of a pressed "info" button. Queries the server for
1191      * information about it's version and the implemented standard. If this
1192      * succeeds, one can assume that the connection to the service works fine;
1193      * if this fails, an error message will be shown to the user with the cause
1194      * and a stack trace will be printed to the console
1195      */
1196     private void mwInfoButtonPressed() {
1197         dwOutputTextArea.setText("");
1198         try {
1199             configureServiceIfNecessary();
1200             String standardVersion = client.getStandardVersion();
1201             String vendorVersion = client.getVendorVersion();
1202             List<String> queryNames = client.getQueryNames();
1203             String text = "EPCIS Query Service responding:\n" + "Standard version: " + standardVersion + "\n"
1204                     + "Service version: " + vendorVersion + "\n" + "Supported query names: ";
1205             for (String elem : queryNames) {
1206                 text += elem + "\n";
1207             }
1208             JFrame frame = new JFrame();
1209             JOptionPane.showMessageDialog(frame, text, "Service invocation successful", JOptionPane.INFORMATION_MESSAGE);
1210 
1211         } catch (Exception e) {
1212             dwOutputTextArea.append("Could not execute query:");
1213             StringWriter detailed = new StringWriter();
1214             PrintWriter pw = new PrintWriter(detailed);
1215             e.printStackTrace(pw);
1216             dwOutputTextArea.append(detailed.toString());
1217             showErrorFrame();
1218         }
1219     }
1220 
1221     /**
1222      * Handler for the case that the user chooses an example. Updates the GUI
1223      * with the example
1224      */
1225     private void examplesChanged() {
1226         int selected = ewExampleList.getSelectedIndex();
1227         if (selected >= 0) {
1228             Query ex = (Query) ExampleQueries.getExamples().get(selected);
1229             mwObjectEventsCheckBox.setSelected(ex.getReturnObjectEvents());
1230             mwAggregationEventsCheckBox.setSelected(ex.getReturnAggregationEvents());
1231             mwQuantityEventsCheckBox.setSelected(ex.getReturnQuantityEvents());
1232             mwTransactionEventsCheckBox.setSelected(ex.getReturnTransactionEvents());
1233 
1234             QueryItem toAddItem = null;
1235             int i = 0;
1236             for (QueryParam item : ex.getQueryParameters()) {
1237                 toAddItem = null;
1238                 toAddItem = queryParamsQueryText.get(item.getName());
1239                 if (toAddItem == null) {
1240                     dwOutputTextArea.append("bugbug: Query example " + "uses unknown queryParam");
1241                 } else {
1242                     ((JComboBox) mwQuerySelectComboBoxes.get(i)).setSelectedItem(toAddItem.getUserText());
1243                     ((JTextFieldEnhanced) mwQueryArgumentTextFields.get(i)).setText((String) item.getValue());
1244                 }
1245                 i++;
1246             }
1247 
1248             /* set the not necessary rows to "ignore" which will delete them */
1249             int tobedeleted = mwQuerySelectComboBoxes.size() - 1 - i;
1250             for (int j = 0; j < tobedeleted; j++) {
1251                 ((JComboBox) mwQuerySelectComboBoxes.get(i)).setSelectedIndex(0);
1252             }
1253 
1254             exampleWindow.setVisible(false);
1255         }
1256     }
1257 
1258     /**
1259      * Removes the row ith row of the query parameters list and updates
1260      * constraints of the others. Only used by queryselect_changed()
1261      * 
1262      * @param i
1263      *            The index of the row to be removed.
1264      */
1265     private void removeArgumentRow(final int i) {
1266         mwQueryArgsPanel.remove((JComboBox) mwQuerySelectComboBoxes.get(i));
1267         mwQueryArgsPanel.remove((JTextField) mwQueryArgumentTextFields.get(i));
1268 
1269         mwQuerySelectComboBoxes.remove(i);
1270         mwQueryArgumentTextFields.remove(i);
1271 
1272         /* Update constraints */
1273         GridBagLayout layout = (GridBagLayout) mwQueryArgsPanel.getLayout();
1274         GridBagConstraints c = new GridBagConstraints();
1275         c.fill = GridBagConstraints.HORIZONTAL;
1276         c.insets = new Insets(10, 5, 5, 0);
1277         for (int j = i; j < mwQuerySelectComboBoxes.size(); j++) {
1278             c.weightx = 0;
1279             c.gridx = 0;
1280             c.gridy = j;
1281             c.ipadx = 0;
1282             layout.setConstraints((JComboBox) mwQuerySelectComboBoxes.get(j), c);
1283             c.weightx = 1;
1284             c.gridx = 1;
1285             c.ipadx = mwQueryArgumentTextFieldsExtraWidth;
1286             layout.setConstraints((JTextField) mwQueryArgumentTextFields.get(j), c);
1287         }
1288         /* update graphics */
1289         mainWindow.pack();
1290     }
1291 
1292     /**
1293      * Adds another row at the end of the query parameters list. Only used by
1294      * queryselect_changed()
1295      * 
1296      * @param i
1297      *            The index of the row to be added.
1298      */
1299     private void addArgumentRow(final int i) {
1300 
1301         mwQuerySelectComboBoxes.add(new JComboBox(queryParameterUsertext));
1302         ((JComboBox) mwQuerySelectComboBoxes.getLast()).addActionListener(this);
1303         mwQueryArgumentTextFields.add(new JTextFieldEnhanced(15, queryParamsUserText.get("ignore")));
1304 
1305         GridBagConstraints c = new GridBagConstraints();
1306         c.fill = GridBagConstraints.HORIZONTAL;
1307         c.insets = new Insets(10, 5, 5, 0);
1308         c.weightx = 0;
1309         c.gridx = 0;
1310         c.gridy = i + 1;
1311         mwQueryArgsPanel.add((JComboBox) mwQuerySelectComboBoxes.getLast(), c);
1312         c.weightx = 1;
1313         c.gridx = 1;
1314         c.ipadx = mwQueryArgumentTextFieldsExtraWidth;
1315         mwQueryArgsPanel.add((JTextFieldEnhanced) mwQueryArgumentTextFields.getLast(), c);
1316 
1317         /* update tooltip of TextField */
1318         JComboBox cb = (JComboBox) mwQuerySelectComboBoxes.get(i);
1319         ((JTextFieldEnhanced) mwQueryArgumentTextFields.get(i)).setQueryItem(queryParamsUserText.get(queryParameterUsertext[cb.getSelectedIndex()]));
1320 
1321         /* update graphics */
1322         mainWindow.pack();
1323     }
1324 
1325     @Override
1326     public void windowClosing(final WindowEvent e) {
1327         if (e.getSource() == debugWindow) {
1328             mwShowDebugWindowCheckBox.setSelected(false);
1329             return;
1330         }
1331     }
1332 
1333     /**
1334      * A extended JTextField which allows us to store the corresponding
1335      * QueryItem.
1336      */
1337     public class JTextFieldEnhanced extends JTextField {
1338 
1339         private static final long serialVersionUID = -8874871130001273285L;
1340 
1341         /**
1342          * The stored QueryItem.
1343          */
1344         private QueryItem queryItem;
1345 
1346         /**
1347          * Constructor which assigns a QueryItem.
1348          * 
1349          * @param columns
1350          *            for the length of the JTextField
1351          * @param item
1352          *            which should be stored
1353          */
1354         public JTextFieldEnhanced(final int columns, final QueryItem item) {
1355             super(columns);
1356             setQueryItem(item);
1357         }
1358 
1359         /**
1360          * Default Constructor.
1361          * 
1362          * @param columns
1363          *            for the length of the JTextField
1364          */
1365         public JTextFieldEnhanced(final int columns) {
1366             super(columns);
1367         }
1368 
1369         /**
1370          * Default Constructor.
1371          */
1372         public JTextFieldEnhanced() {
1373             super();
1374         }
1375 
1376         /**
1377          * Sets another QueryItem an does the update of the tool-tip.
1378          * 
1379          * @param item
1380          *            the new QueryItem
1381          */
1382         public void setQueryItem(final QueryItem item) {
1383             this.queryItem = item;
1384             this.setToolTipText(queryItem.getDescription());
1385         }
1386     }
1387 
1388     /**
1389      * A new class for a QueryItem which can store all its specific features.
1390      */
1391     public class QueryItem {
1392 
1393         private boolean required;
1394 
1395         private String userText;
1396 
1397         private String queryText;
1398 
1399         private String description;
1400 
1401         private ParameterType paramType;
1402 
1403         /**
1404          * @return the description
1405          */
1406         public String getDescription() {
1407             return description;
1408         }
1409 
1410         /**
1411          * @param description
1412          *            the description to set
1413          */
1414         public void setDescription(final String description) {
1415             this.description = description;
1416         }
1417 
1418         /**
1419          * @return the paramType
1420          */
1421         public ParameterType getParamType() {
1422             return paramType;
1423         }
1424 
1425         /**
1426          * @param paramType
1427          *            the paramType to set
1428          */
1429         public void setParamType(final ParameterType paramType) {
1430             this.paramType = paramType;
1431         }
1432 
1433         /**
1434          * @return the queryText
1435          */
1436         public String getQueryText() {
1437             return queryText;
1438         }
1439 
1440         /**
1441          * @param queryText
1442          *            the queryText to set
1443          */
1444         public void setQueryText(final String queryText) {
1445             this.queryText = queryText;
1446         }
1447 
1448         /**
1449          * @return the required
1450          */
1451         public boolean getRequired() {
1452             return required;
1453         }
1454 
1455         /**
1456          * @param required
1457          *            the required to set
1458          */
1459         public void setRequired(final boolean required) {
1460             this.required = required;
1461         }
1462 
1463         /**
1464          * @return the userText
1465          */
1466         public String getUserText() {
1467             return userText;
1468         }
1469 
1470         /**
1471          * @param userText
1472          *            the userText to set
1473          */
1474         public void setUserText(final String userText) {
1475             this.userText = userText;
1476         }
1477     }
1478 
1479     void debug(String debugMessage) {
1480         if (!debugMessage.endsWith("\n")) {
1481             debugMessage += "\n";
1482         }
1483         dwOutputTextArea.append(debugMessage);
1484     }
1485 
1486     String getAddress() {
1487         return mwServiceUrlTextField.getText();
1488     }
1489 
1490     Object[] getAuthenticationOptions() {
1491         return mwAuthOptions.getAuthenticationOptions();
1492     }
1493 
1494     void setButtonsEnabled(boolean buttonsEnabled) {
1495         JButton[] buttons = { mwRunQueryButton, mwServiceInfoButton, mwUnsubscribeQueryButton, mwSubscriptionIdButton };
1496         for (JButton button : buttons) {
1497             button.setEnabled(buttonsEnabled);
1498         }
1499     }
1500 
1501     public void configurationChanged(AuthenticationOptionsChangeEvent ace) {
1502         this.configurationChanged = true;
1503         setButtonsEnabled(ace.isComplete());
1504     }
1505 
1506     /**
1507      * Prints the results from a query invocation to the debug window and
1508      * returns a two-dimensional array in a format suitable for a JTable object.
1509      * 
1510      * @param eventList
1511      *            The result list containing the matching events.
1512      * @return A two-dimensional array containing the matching events in a
1513      *         format suitable for displaying in a JTable object.
1514      */
1515     private Object[][] processEvents(final List<Object> eventList) {
1516         int nofEvents = eventList.size();
1517         Object[][] table = new Object[nofEvents][12];
1518         int row = 0;
1519 
1520         debug("\n\n" + nofEvents + " events returned by the server:\n\n");
1521         for (Object o : eventList) {
1522             if (o instanceof JAXBElement<?>) {
1523                 o = ((JAXBElement<?>) o).getValue();
1524             }
1525             EPCISEventType event = (EPCISEventType) o;
1526             debug("[ EPCISEvent ]\n");
1527             String eventTime = QueryClientHelper.printCalendar(event.getEventTime().toGregorianCalendar());
1528             debug("eventTime:\t" + eventTime + "\n");
1529             table[row][1] = eventTime;
1530             String recordTime = QueryClientHelper.printCalendar(event.getRecordTime().toGregorianCalendar());
1531             debug("recordTime:\t" + recordTime + "\n");
1532             table[row][2] = recordTime;
1533             debug("timeZoneOffset:\t" + event.getEventTimeZoneOffset() + "\n");
1534 
1535             if (event instanceof ObjectEventType) {
1536                 debug("[ ObjectEvent ]\n");
1537                 ObjectEventType e = (ObjectEventType) event;
1538                 table[row][0] = "Object";
1539                 debug("epcList:\t");
1540                 table[row][5] = "";
1541                 for (EPC epc : e.getEpcList().getEpc()) {
1542                     debug(" '" + epc.getValue() + "'");
1543                     table[row][5] = table[row][5] + "'" + epc.getValue() + "' ";
1544                 }
1545                 debug("\n");
1546                 debug("action:\t\t" + e.getAction().toString() + "\n");
1547                 table[row][6] = e.getAction().toString();
1548                 debug("bizStep:\t" + e.getBizStep() + "\n");
1549                 table[row][7] = e.getBizStep();
1550                 debug("disposition:\t" + e.getDisposition() + "\n");
1551                 table[row][8] = e.getDisposition();
1552                 if (e.getReadPoint() != null) {
1553                     debug("readPoint:\t" + e.getReadPoint().getId() + "\n");
1554                     table[row][9] = e.getReadPoint().getId();
1555                 } else {
1556                     debug("readPoint:\tnull\n");
1557                 }
1558                 if (e.getBizLocation() != null) {
1559                     debug("bizLocation:\t" + e.getBizLocation().getId() + "\n");
1560                     table[row][10] = e.getBizLocation().getId();
1561                 } else {
1562                     debug("bizLocation:\tnull\n");
1563                 }
1564                 if (e.getBizTransactionList() != null) {
1565                     debug("bizTrans:\tType, ID\n");
1566                     table[row][11] = "";
1567                     for (BusinessTransactionType bizTrans : e.getBizTransactionList().getBizTransaction()) {
1568                         debug("\t'" + bizTrans.getType() + "', '" + bizTrans.getValue() + "'\n");
1569                         table[row][11] = table[row][11] + "'" + bizTrans.getType() + ", " + bizTrans.getValue()
1570                                 + "' ; ";
1571                     }
1572                     if (!"".equals(table[row][11])) {
1573                         // remove last "; "
1574                         table[row][11] = ((String) table[row][11]).substring(0, ((String) table[row][11]).length() - 2);
1575                     }
1576                 } else {
1577                     debug("bizTrans:\tnull\n");
1578                 }
1579                 debug("\n");
1580 
1581             } else if (event instanceof TransactionEventType) {
1582                 debug("[ TransactionEvent ]\n");
1583                 TransactionEventType e = (TransactionEventType) event;
1584                 table[row][0] = "Transaction";
1585                 debug("parentID:\t" + e.getParentID() + "\n");
1586                 table[row][3] = e.getParentID();
1587                 debug("epcList:\t");
1588                 table[row][5] = "";
1589                 for (EPC epc : e.getEpcList().getEpc()) {
1590                     debug(" '" + epc.getValue() + "'");
1591                     table[row][5] = table[row][5] + "'" + epc.getValue() + "' ";
1592                 }
1593                 debug("\n");
1594                 debug("action:\t\t" + e.getAction().toString() + "\n");
1595                 table[row][6] = e.getAction().toString();
1596                 debug("bizStep:\t" + e.getBizStep() + "\n");
1597                 table[row][7] = e.getBizStep();
1598                 debug("disposition:\t" + e.getDisposition() + "\n");
1599                 table[row][8] = e.getDisposition();
1600                 if (e.getReadPoint() != null) {
1601                     debug("readPoint:\t" + e.getReadPoint().getId() + "\n");
1602                     table[row][9] = e.getReadPoint().getId();
1603                 } else {
1604                     debug("readPoint:\tnull\n");
1605                 }
1606                 if (e.getBizLocation() != null) {
1607                     debug("bizLocation:\t" + e.getBizLocation().getId() + "\n");
1608                     table[row][10] = e.getBizLocation().getId();
1609                 } else {
1610                     debug("bizLocation:\tnull\n");
1611                 }
1612                 if (e.getBizTransactionList() != null) {
1613                     debug("bizTrans:\tType, ID\n");
1614                     table[row][11] = "";
1615                     for (BusinessTransactionType bizTrans : e.getBizTransactionList().getBizTransaction()) {
1616                         debug("\t'" + bizTrans.getType() + "', '" + bizTrans.getValue() + "'\n");
1617                         table[row][11] = table[row][11] + "'" + bizTrans.getType() + ", " + bizTrans.getValue()
1618                                 + "' ; ";
1619                     }
1620                     if (!"".equals(table[row][11])) {
1621                         // remove last "; "
1622                         table[row][11] = ((String) table[row][11]).substring(0, ((String) table[row][11]).length() - 2);
1623                     }
1624                 } else {
1625                     debug("bizTrans:\tnull\n");
1626                 }
1627                 debug("\n");
1628 
1629             } else if (event instanceof AggregationEventType) {
1630                 debug("[ AggregationEvent ]\n");
1631                 AggregationEventType e = (AggregationEventType) event;
1632                 table[row][0] = "Aggregation";
1633                 debug("parentID:\t" + e.getParentID() + "\n");
1634                 table[row][3] = e.getParentID();
1635                 debug("childEPCs:\t");
1636                 table[row][5] = "";
1637                 for (EPC epc : e.getChildEPCs().getEpc()) {
1638                     debug(" '" + epc.getValue() + "'");
1639                     table[row][5] = table[row][5] + "'" + epc.getValue() + "' ";
1640                 }
1641                 debug("\n");
1642                 debug("action:\t\t" + e.getAction().toString() + "\n");
1643                 table[row][6] = e.getAction().toString();
1644                 debug("bizStep:\t" + e.getBizStep() + "\n");
1645                 table[row][7] = e.getBizStep();
1646                 debug("disposition:\t" + e.getDisposition() + "\n");
1647                 table[row][8] = e.getDisposition();
1648                 if (e.getReadPoint() != null) {
1649                     debug("readPoint:\t" + e.getReadPoint().getId() + "\n");
1650                     table[row][9] = e.getReadPoint().getId();
1651                 } else {
1652                     debug("readPoint:\tnull\n");
1653                 }
1654                 if (e.getBizLocation() != null) {
1655                     debug("bizLocation:\t" + e.getBizLocation().getId() + "\n");
1656                     table[row][10] = e.getBizLocation().getId();
1657                 } else {
1658                     debug("bizLocation:\tnull\n");
1659                 }
1660                 if (e.getBizTransactionList() != null) {
1661                     debug("bizTrans:\tType, ID\n");
1662                     table[row][11] = "";
1663                     for (BusinessTransactionType bizTrans : e.getBizTransactionList().getBizTransaction()) {
1664                         debug("\t'" + bizTrans.getType() + "', '" + bizTrans.getValue() + "'\n");
1665                         table[row][11] = table[row][11] + "'" + bizTrans.getType() + ", " + bizTrans.getValue()
1666                                 + "' ; ";
1667                     }
1668                     if (!"".equals(table[row][11])) {
1669                         // remove last "; "
1670                         table[row][11] = ((String) table[row][11]).substring(0, ((String) table[row][11]).length() - 2);
1671                     }
1672                 } else {
1673                     debug("bizTrans:\tnull\n");
1674                 }
1675                 debug("\n");
1676 
1677             } else if (event instanceof QuantityEventType) {
1678                 debug("[ QuantityEvent ]\n");
1679                 QuantityEventType e = (QuantityEventType) event;
1680                 table[row][0] = "Quantity";
1681                 debug("quantity:\t" + e.getQuantity() + "\n");
1682                 table[row][4] = Integer.valueOf(e.getQuantity());
1683                 debug("ecpClass:\t" + e.getEpcClass() + "\n");
1684                 table[row][5] = e.getEpcClass();
1685                 debug("bizStep:\t" + e.getBizStep() + "\n");
1686                 table[row][7] = e.getBizStep();
1687                 debug("disposition:\t" + e.getDisposition() + "\n");
1688                 table[row][8] = e.getDisposition();
1689                 if (e.getReadPoint() != null) {
1690                     debug("readPoint:\t" + e.getReadPoint().getId() + "\n");
1691                     table[row][9] = e.getReadPoint().getId();
1692                 } else {
1693                     debug("readPoint:\tnull\n");
1694                 }
1695                 if (e.getBizLocation() != null) {
1696                     debug("bizLocation:\t" + e.getBizLocation().getId() + "\n");
1697                     table[row][10] = e.getBizLocation().getId();
1698                 } else {
1699                     debug("bizLocation:\tnull\n");
1700                 }
1701                 if (e.getBizTransactionList() != null) {
1702                     debug("bizTrans:\tType, ID\n");
1703                     table[row][11] = "";
1704                     for (BusinessTransactionType bizTrans : e.getBizTransactionList().getBizTransaction()) {
1705                         debug("\t'" + bizTrans.getType() + "', '" + bizTrans.getValue() + "'\n");
1706                         table[row][11] = table[row][11] + "'" + bizTrans.getType() + ", " + bizTrans.getValue()
1707                                 + "' ; ";
1708                     }
1709                     if (!"".equals(table[row][11])) {
1710                         // remove last "; "
1711                         table[row][11] = ((String) table[row][11]).substring(0, ((String) table[row][11]).length() - 2);
1712                     }
1713                 } else {
1714                     debug("bizTrans:\tnull\n");
1715                 }
1716                 debug("\n");
1717             }
1718             row++;
1719         }
1720         return table;
1721     }
1722 
1723     /**
1724      * Reset the query arguments.
1725      */
1726     public void clearParameters() {
1727         internalQueryParams.clear();
1728     }
1729 
1730     /**
1731      * Add a new query parameter.
1732      * 
1733      * @param param
1734      *            The query parameter to add.
1735      */
1736     public void addParameter(final QueryParam param) {
1737         internalQueryParams.add(param);
1738     }
1739 
1740     /**
1741      * Forces the client to reconfigure the service if the any of its parameters
1742      * (authentication, endpoint address) have been changed.
1743      * 
1744      * @throws Exception
1745      */
1746     private void configureServiceIfNecessary() throws Exception {
1747         if (!client.isServiceConfigured() || configurationChanged) {
1748             // validate the URL and get auth options from the main window
1749             client.configureService(new URL(getAddress()), getAuthenticationOptions());
1750             configurationChanged = false;
1751         }
1752     }
1753 
1754     /**
1755      * Run the query with the currently set query arguments Returns the results
1756      * in a format that is suitable for JTable.
1757      * 
1758      * @return The pretty-printed query results.
1759      * @throws Exception
1760      *             If any Exception occurred while invoking the query service.
1761      */
1762     private Object[][] runQuery() throws Exception {
1763         QueryParams queryParams = new QueryParams();
1764         queryParams.getParam().addAll(internalQueryParams);
1765         debug("Number of query parameters: " + queryParams.getParam().size() + "\n");
1766         for (QueryParam queryParam : internalQueryParams) {
1767             if (queryParam.getValue() instanceof ArrayOfString) {
1768                 debug(queryParam.getName() + " " + ((ArrayOfString) queryParam.getValue()).getString() + "\n");
1769             } else {
1770                 debug(queryParam.getName() + " " + queryParam.getValue() + "\n");
1771             }
1772         }
1773 
1774         Poll poll = new Poll();
1775         poll.setQueryName("SimpleEventQuery");
1776         poll.setParams(queryParams);
1777 
1778         debug("running query...\n");
1779         QueryResults results = client.poll(poll);
1780         debug("done\n");
1781 
1782         // print to debug window and return result
1783         if (results != null && results.getResultsBody() != null && results.getResultsBody().getEventList() != null) {
1784             return processEvents(results.getResultsBody().getEventList().getObjectEventOrAggregationEventOrQuantityEvent());
1785         } else {
1786             return null;
1787         }
1788     }
1789 
1790     /**
1791      * Instantiates a new QueryClientGui and sets its look-and-feel to the one
1792      * matching the current operating system.
1793      * 
1794      * @param args
1795      *            The address to which the QueryClient should send the queries
1796      *            to. If omitted, a default address will be provided.
1797      */
1798     public static void main(final String[] args) {
1799         try {
1800             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
1801         } catch (Exception e) {
1802             e.printStackTrace();
1803         }
1804         if (args != null && args.length > 0) {
1805             try {
1806                 new QueryClientGui(args[0]);
1807             } catch (MalformedURLException e) {
1808                 e.printStackTrace();
1809             }
1810         } else {
1811             new QueryClientGui();
1812         }
1813     }
1814 }