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 * (C) 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 */
015package com.ibm.rational.stp.client.samples;
016
017import java.awt.BorderLayout;
018import java.awt.event.ActionEvent;
019import java.awt.event.ActionListener;
020import java.util.Arrays;
021import java.util.Comparator;
022
023import javax.swing.JButton;
024import javax.swing.JFrame;
025import javax.swing.JOptionPane;
026import javax.swing.JPanel;
027import javax.swing.JScrollPane;
028import javax.swing.JTable;
029import javax.swing.table.AbstractTableModel;
030import javax.swing.table.TableModel;
031import javax.wvcm.ResourceList;
032import javax.wvcm.WvcmException;
033import javax.wvcm.PropertyRequestItem.PropertyRequest;
034
035import com.ibm.rational.wvcm.stp.StpResource;
036import com.ibm.rational.wvcm.stp.cq.CqProvider;
037import com.ibm.rational.wvcm.stp.cq.CqQuery;
038import com.ibm.rational.wvcm.stp.cq.CqRecord;
039import com.ibm.rational.wvcm.stp.cq.CqResultSet;
040import com.ibm.rational.wvcm.stp.cq.CqRowData;
041import 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 */
047public 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}