< Indietro | Avanti >

Esecuzione di una query e visualizzazione della serie di risultati

Il seguente esempio di codice è un'applicazione Swing che esegue le seguenti operazioni: La selezione e l'esecuzione della query si verifica nel metodo run. La visualizzazione della serie di risultati ha luogo nel metodo showResults. Di seguito, viene mostrato l'esempio completo:
static void run(String title, CqProvider provider, Viewer viewer)
    throws WvcmException
    {
        ResourceList<CqUserDb> databases =
            setUserFriendlyLocation(Utilities
                .getUserDbList(provider,
                               new PropertyRequest(CqUserDb.USER_FRIENDLY_LOCATION)));
        CqUserDb userDb = (CqUserDb)JOptionPane.showInputDialog
            (null, "Choose a Database to Explore", title, 
             JOptionPane.INFORMATION_MESSAGE, 
             null, databases.toArray(), databases.get(0));
    
        if (userDb == null) System.exit(0);
        
        userDb = (CqUserDb)userDb.doReadProperties
            (new PropertyRequest(CqUserDb.ALL_QUERIES.nest(CqQuery.USER_FRIENDLY_LOCATION)));
    
        // Convertire l'elenco in un array ordinato per l'utilizzo nella finestra di dialogo di selezione
        CqQuery[] queries = 
            setUserFriendlyLocation(userDb.getAllQueries()).toArray(new CqQuery[]{});
    
        Arrays.sort(queries, new Comparator<CqQuery>(){
                public int compare(CqQuery arg0, CqQuery arg1)
                { return arg0.toString().compareTo(arg1.toString()); }});
    
        // Presentare l'elenco di query all'utente e consentire all'utente di selezionarne una
        CqQuery query = (CqQuery)JOptionPane.showInputDialog
                    (null, "Choose a Query to Execute", 
                     "All Queries in " + userDb.location().string(), 
                     JOptionPane.INFORMATION_MESSAGE, null, 
                     queries, queries[0]);
        
        if (query == null) System.exit(0);
        
        CqResultSet results = 
            query.doExecute(1, Long.MAX_VALUE, CqQuery.COUNT_ROWS);
        
        // Se la query è stata eseguita correttamente, salvare i dati e prepararli per la visualizzazione
        if (results.hasNext()) {
            // Informazioni sulla colonna a cui si accede dal programma di visualizzazione
            g_columns = results.getColumnLabels();
            g_cell = new CqRowData[(int)results.getRowCount()];
    
            for (CqRowData row: results)
                (g_cell[(int)row.getRowNumber()-1] = row).getValues();
            
            // Visualizzare i dati sui risultati della query
            showResults(query.location().string(), viewer);
        }
    }
    
    /** La serie di risultati a cui i componenti della GUI possono accedere per la visualizzazione */
    static CqRowData[] g_cell;
    /** Le intestazioni colonna a cui i componenti della GUI possono accedere per la visualizzazione */
    static String[] g_columns;
    
    /**
     * Visualizza la serie di risultati (in g_cell) in una tabella.
     * 
     * @param title La stringa del titolo per la finestra della serie di risultati
     * @param viewer Un'istanza del programma di visualizzazione da utilizzare per una visualizzazione dettagliata di una
     *            singola risorsa della serie di risultati. È possibile che sia nulla, in tal caso
     *            l'opzione per visualizzare una singola risorsa non viene presentata.
     */
    static void showResults(String title, final Viewer viewer) {
        // Definire il modello tabella per la finestra JTable; una colonna per ciascun
        // campo di visualizzazione query e una riga per ciascuna riga della serie di risultati della query.
        TableModel dataModel = new AbstractTableModel() {
    		 		 private static final long serialVersionUID = -3764643269044024406L;
    		 		 public int getColumnCount() { return g_columns.length; }
            public int getRowCount() { return g_cell.length;}
            public Object getValueAt(int row, int col) 
                { return g_cell[row].getValues()[col]; }
            public String getColumnName(int col)
                { return g_columns[col]; }
        };
        
        // Creare la finestra di risultati della query con un pulsante facoltativo per la
        // visualizzazione del record in una riga selezionata (utilizzata negli esempi View Record e
        // Modify Record)
        final JFrame frame = new JFrame(title);
        final JTable table = new JTable(dataModel);
        JPanel panel = new JPanel(new BorderLayout());
        
        if (viewer != null) {
            JButton button = new JButton("Open");
    
            panel.add(button, BorderLayout.SOUTH);
            button.addActionListener(new ActionListener(){
                    public void actionPerformed(ActionEvent arg0)
                    {
                        int[] selected = table.getSelectedRows();
                        
                        for (int i = 0; i < selected.length; ++i)
                            try {
                                viewer.view((CqRecord) g_cell[selected[i]]
                                    .getRecord());
                            } catch (WvcmException e) {
                                Utilities.exception(frame, "View Record", e);
                            }
                    }
                });
        }
        
        panel.add(new JScrollPane(table), BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(panel);
        frame.setBounds(300, 300, 600, 300);
        frame.setVisible(true);
    }
    
    static <U extends=""> ResourceList<U> 
    setUserFriendlyLocation(ResourceList<U> list)
    throws WvcmException
    {
        for (U res: list)
            res.modifyLocation(res.getUserFriendlyLocation());
    
        return list;
    }
    
    /**
     * Una semplice interfaccia per un oggetto che visualizzerà una risorsa Record.
     * (Utilizzata dalle estensioni per l'esempio ExecuteQuery.)
     */
    static interface Viewer {
        /**
         * Visualizza una risorsa Record
         * @param resource Il proxy Record per il record da visualizzare.
         * @return TODO
         */
        JFrame view(CqRecord resource);
    }
    
    /**
     * Il programma principale per l'esempio ExecuteQuery.
     * @param args Non utilizzato.
     * @throws Exception Se non è possibile creare un'istanza di un provider.
     */
    public static void main(String[] args) throws Exception
    {
        try {
            run("Execute Query", Utilities.getProvider().cqProvider(), null);
        } catch(Throwable ex) {
            Utilities.exception(null, "Execute Query", ex);
            System.exit(0);
        }
    }

In questo esempio, l'elenco dei database disponibili viene creato come nella lezione precedente. Inoltre, l'elenco viene presentato all'utente per la selezione di un singolo database al quale eseguire l'accesso.

Dopo che l'utente seleziona un database utente, la proprietà ALL_QUERIES di tale database viene letta nell'applicazione. Il valore di questa proprietà è un ResourceList dei proxy CqQuery. Questo elenco viene ordinato in base all'ubicazione della query e presentato all'utente per la selezione di una singola query da eseguire.

Per la selezione del database e della query, viene utilizzato lo stesso metodo Swing generico, JOptionPane.showInputDialog. L'input è l'array dei proxy da cui eseguire la scelta e il risultato è il proxy selezionato. Il metodo toString() del proxy viene utilizzato per generare l'elenco visualizzato all'utente. Il metodo toString() di un proxy genera una immagine del campo ubicazione del proxy, ad es. Resource.location().string().

Poiché l'ubicazione del proxy viene visualizzata, è necessario assicurarsi che l'ubicazione del proxy sia semplice (user-friendly), ossia, composta da nomi percorso segmentati invece che da id database. I server possono utilizzare qualsiasi formato di percorso nei proxy restituiti e, in generale, verrà selezionato il formato elaborato nel modo più efficace se il proxy viene utilizzato per tornare al server. Il formato più efficace è raramente semplice. In ogni modo, un client non dovrebbe presumere il formato del percorso utilizzato. In questo modo, quando viene richiesto l'elenco di database e l'elenco di query, viene richiesta anche la proprietà USER_FRIENDLY_LOCATION di ciascun elemento presente nell'elenco. Quindi, nel metodo setUserFriendlyLocation, viene modificata l'ubicazione di ciascun proxy con la versione semplice.

Questa applicazione ignora la possibilità che la query selezionata definisca i filtri dinamici (anche chiamati parametri della query) e funzionerà in maniera insolita o probabilmente avrà esito negativo se la query selezionata dispone di filtri dinamici. Una implementazione più stabile dovrebbe richiedere la proprietà DYNAMIC_FILTERS della query dal server e ottenere i dati mancanti dall'utente prima di eseguire la query. Questo sarà un esercizio per il lettore.

Notare che CqRowData.getValues() viene richiamato su ciascuna riga quando l'oggetto CqRowData viene inserito nell'array per la visualizzazione. Questo è necessario poiché le informazioni necessarie per calcolare i valori dei dati della riga come oggetti Java™ non sono disponibili dopo il rilascio dell'iteratore CqResultSet, che si verifica automaticamente quando viene raggiunta la fine.

Il secondo parametro per ExecuteQuery.showResults (denominato programma di visualizzazione) non viene utilizzato in questo esempio, ma in quello successivo per consentire all'utente di selezionare una riga della serie di risultati e di visualizzare il record associato.

Punto di controllo della lezione

Ora che sono state fornite informazioni su come utilizzare Rational CM API per eseguire una query, è possibile esaminare le interfacce Rational CM API disponibili e analizzare in che modo scrivere o modificare le query esistenti.
In questa lezione, sono state fornite informazioni su come utilizzare Rational CM API per eseguire una query. Sono state acquisite le seguenti informazioni:
  • Informazioni sugli oggetti Rational CM API necessari per l'esecuzione di una query Rational ClearQuest.
  • Come iterare una serie di risultati.
  • Come creare un'applicazione client che esegue una query.
< Indietro | Avanti >

Feedback