001    /*
002     * file ExecuteQuery.java
003     *
004     * Licensed Materials - Property of IBM
005     * Restricted Materials of IBM - you are allowed to copy, modify and 
006     * redistribute this file as part of any program that interfaces with 
007     * IBM Rational CM API.
008     *
009     * com.ibm.rational.stp.client.samples.ExecuteQuery
010     *
011     * © Copyright IBM Corporation 2005, 2008.  All Rights Reserved.
012     * Note to U.S. Government Users Restricted Rights:  Use, duplication or 
013     * disclosure restricted by GSA ADP  Schedule Contract with IBM Corp.
014     */
015    package com.ibm.rational.stp.client.samples;
016    
017    import java.awt.BorderLayout;
018    import java.awt.event.ActionEvent;
019    import java.awt.event.ActionListener;
020    import java.util.Arrays;
021    import java.util.Comparator;
022    
023    import javax.swing.JButton;
024    import javax.swing.JFrame;
025    import javax.swing.JOptionPane;
026    import javax.swing.JPanel;
027    import javax.swing.JScrollPane;
028    import javax.swing.JTable;
029    import javax.swing.table.AbstractTableModel;
030    import javax.swing.table.TableModel;
031    import javax.wvcm.ResourceList;
032    import javax.wvcm.WvcmException;
033    import javax.wvcm.PropertyRequestItem.PropertyRequest;
034    
035    import com.ibm.rational.wvcm.stp.StpResource;
036    import com.ibm.rational.wvcm.stp.cq.CqProvider;
037    import com.ibm.rational.wvcm.stp.cq.CqQuery;
038    import com.ibm.rational.wvcm.stp.cq.CqRecord;
039    import com.ibm.rational.wvcm.stp.cq.CqResultSet;
040    import com.ibm.rational.wvcm.stp.cq.CqRowData;
041    import com.ibm.rational.wvcm.stp.cq.CqUserDb;
042    
043    /**
044     * Pick a query from a list of those available in a database and execute it.
045     * Display the result in a table.
046     */
047    public class ExecuteQuery {
048    
049        /**
050         * Asks the user to select a database and a query in that database and then
051         * executes the query, displaying the results in a table.
052         * @param title The title string used in the initial dialog
053         * @param provider A javax.wvcm provider for accessing ClearQuest
054         * @param viewer A Viewer instance for displaying an individual row of the
055         * results set. May be null.
056         * @throws WvcmException
057         */
058        static void run(String title, CqProvider provider, Viewer viewer)
059        throws WvcmException
060        {
061            ResourceList<CqUserDb> databases =
062                setUserFriendlyLocation(Utilities
063                    .getUserDbList(provider,
064                                   new PropertyRequest(CqUserDb.USER_FRIENDLY_LOCATION)));
065            CqUserDb userDb = (CqUserDb)JOptionPane.showInputDialog
066                (null, "Choose a Database to Explore", title, 
067                 JOptionPane.INFORMATION_MESSAGE, 
068                 null, databases.toArray(), databases.get(0));
069        
070            if (userDb == null) System.exit(0);
071            
072            userDb = (CqUserDb)userDb.doReadProperties
073                (new PropertyRequest(CqUserDb.ALL_QUERIES.nest(CqQuery.USER_FRIENDLY_LOCATION)));
074        
075            // Convert the list to a sorted array for use in the selection dialog
076            CqQuery[] queries = 
077                setUserFriendlyLocation(userDb.getAllQueries()).toArray(new CqQuery[]{});
078        
079            Arrays.sort(queries, new Comparator<CqQuery>(){
080                    public int compare(CqQuery arg0, CqQuery arg1)
081                    { return arg0.toString().compareTo(arg1.toString()); }});
082        
083            // Present the list of queries to the user and allow the user to select one
084            CqQuery query = (CqQuery)JOptionPane.showInputDialog
085                        (null, "Choose a Query to Execute", 
086                         "All Queries in " + userDb.location().string(), 
087                         JOptionPane.INFORMATION_MESSAGE, null, 
088                         queries, queries[0]);
089            
090            if (query == null) System.exit(0);
091            
092            CqResultSet results = 
093                query.doExecute(1, Long.MAX_VALUE, CqQuery.COUNT_ROWS);
094            
095            // If the query executed properly, internalize the data and prepare it for display
096            if (results.hasNext()) {
097                // Column information accessed from the viewer
098                g_columns = results.getColumnLabels();
099                g_cell = new CqRowData[(int)results.getRowCount()];
100        
101                for (CqRowData row: results)
102                    (g_cell[(int)row.getRowNumber()-1] = row).getValues();
103                
104                // Display the query result data
105                showResults(query.location().string(), viewer);
106            }
107        }
108        
109        /** The result set made accessible to the GUI components for display */
110        static CqRowData[] g_cell;
111        /** The column headings made accessible to the GUI components for display */
112        static String[] g_columns;
113        
114        /**
115         * Displays the result set (in g_cell) in a table.
116         * 
117         * @param title The title string for the result set window
118         * @param viewer A Viewer instance to be used for a detailed display of a
119         *            single resource of the result set. May be null, in which case
120         *            the option to display a single resource is not presented.
121         */
122        static void showResults(String title, final Viewer viewer) {
123            // Define the table model for the JTable window; one column for each
124            // query display field and one row for each row of the query result set.
125            TableModel dataModel = new AbstractTableModel() {
126                    private static final long serialVersionUID = -3764643269044024406L;
127                    public int getColumnCount() { return g_columns.length; }
128                public int getRowCount() { return g_cell.length;}
129                public Object getValueAt(int row, int col) 
130                    { return g_cell[row].getValues()[col]; }
131                public String getColumnName(int col)
132                    { return g_columns[col]; }
133            };
134            
135            // Construct the query result window with an optional button for
136            // displaying the record in a selected row (used in the View Record and
137            // Modify Record examples)
138            final JFrame frame = new JFrame(title);
139            final JTable table = new JTable(dataModel);
140            JPanel panel = new JPanel(new BorderLayout());
141            
142            if (viewer != null) {
143                JButton button = new JButton("Open");
144        
145                panel.add(button, BorderLayout.SOUTH);
146                button.addActionListener(new ActionListener(){
147                        public void actionPerformed(ActionEvent arg0)
148                        {
149                            int[] selected = table.getSelectedRows();
150                            
151                            for (int i = 0; i < selected.length; ++i)
152                                try {
153                                    viewer.view((CqRecord) g_cell[selected[i]]
154                                        .getRecord());
155                                } catch (WvcmException e) {
156                                    Utilities.exception(frame, "View Record", e);
157                                }
158                        }
159                    });
160            }
161            
162            panel.add(new JScrollPane(table), BorderLayout.CENTER);
163            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
164            frame.setContentPane(panel);
165            frame.setBounds(300, 300, 600, 300);
166            frame.setVisible(true);
167        }
168        
169        static <U extends StpResource> ResourceList<U> 
170        setUserFriendlyLocation(ResourceList<U> list)
171        throws WvcmException
172        {
173            for (U res: list)
174                res.modifyLocation(res.getUserFriendlyLocation());
175        
176            return list;
177        }
178        
179        /**
180         * A simple interface for an object that will display a Record resource.
181         * (Used by extensions to the ExecuteQuery example.)
182         */
183        static interface Viewer {
184            /**
185             * Displays a Record resource
186             * @param resource The Record proxy for the record to be displayed.
187             * @return TODO
188             */
189            JFrame view(CqRecord resource);
190        }
191        
192        /**
193         * The main program for the ExecuteQuery example.
194         * @param args Not used.
195         * @throws Exception If a provider cannot be instantiated.
196         */
197        public static void main(String[] args) throws Exception
198        {
199            try {
200                run("Execute Query", Utilities.getProvider().cqProvider(), null);
201            } catch(Throwable ex) {
202                Utilities.exception(null, "Execute Query", ex);
203                System.exit(0);
204            }
205        }
206    }