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))); // Convert the list to a sorted array for use in the selection dialog 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()); }}); // Present the list of queries to the user and allow the user to select one 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); // If the query executed properly, save the data and prepare it for display if (results.hasNext()) { // Column information accessed from the viewer g_columns = results.getColumnLabels(); g_cell = new CqRowData[(int)results.getRowCount()]; for (CqRowData row: results) (g_cell[(int)row.getRowNumber()-1] = row).getValues(); // Display the query result data showResults(query.location().string(), viewer); } } /** The result set made accessible to the GUI components for display */ static CqRowData[] g_cell; /** The column headings made accessible to the GUI components for display */ static String[] g_columns; /** * Displays the result set (in g_cell) in a table. * * @param title The title string for the result set window * @param viewer A Viewer instance to be used for a detailed display of a * single resource of the result set. May be null, in which case * the option to display a single resource is not presented. */ static void showResults(String title, final Viewer viewer) { // Define the table model for the JTable window; one column for each // query display field and one row for each row of the query result set. 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]; } }; // Construct the query result window with an optional button for // displaying the record in a selected row (used in the View Record and // Modify Record examples) 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; } /** * A simple interface for an object that will display a Record resource. * (Used by extensions to the ExecuteQuery example.) */ static interface Viewer { /** * Displays a Record resource * @param resource The Record proxy for the record to be displayed. * @return TODO */ JFrame view(CqRecord resource); } /** * The main program for the ExecuteQuery example. * @param args Not used. * @throws Exception If a provider cannot be instantiated. */ 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); } }
En el ejemplo, la lista de bases de datos disponibles se crea del mismo modo que en la lección anterior. Y la lista se muestra al usuario para que seleccione una única base de datos en la que iniciará la sesión.
Después de que el usuario seleccione una base de datos de usuarios, la propiedad ALL_QUERIES de dicha base de datos se lee en la aplicación. El valor de esta propiedad es un ResourceList de proxies CqQuery. Esta lista se almacena en la ubicación de la consulta y se muestra al usuario para que seleccione una única consulta para ejecutar.
Para la selección de la base de datos y la selección de la consulta, se utiliza el mismo método Swing de ámbito general, JOptionPane.showInputDialog. Los datos de entrada son la matriz de los proxies entre los que se realiza una selección y el resultado es el proxy seleccionado. El método toString() del proxy se utiliza para generar la lista visualiza ante el usuario. El método toString() de un proxy genera una imagen del campo de ubicación del proxy; es decir, Resource.location().string().
Como se visualiza la ubicación del proxy, hemos de cerciorarnos de que la ubicación del proxy es fácil; es decir, que está compuesta de nombres de vías de acceso segmentadas y no de ID de base de datos. Los servidores pueden utilizar cualquier formato de ubicación en los proxies que devuelven y, en general, seleccionarán el formato que se procese del modo más eficaz si el proxy se utiliza para volver al servidor. El formato más eficaz raras veces es el más sencillo. En cualquier caso, un cliente no debe dar por supuesto qué formato de ubicación se utiliza. Por lo tanto, cuando solicitamos la lista de bases de datos y la lista de consultas, también solicitamos la propiedad USER_FRIENDLY_LOCATION de cada elemento de la lista. A continuación, en el método setUserFriendlyLocation, modificamos la ubicación de cada proxy con la versión de fácil de usar.
Esta aplicación hace caso omiso de la posibilidad de que la consulta seleccionada defina filtros dinámicos (también denominados parámetros de consulta) y mostrará un comportamiento extraño o quizás no se ejecutará correctamente si la consulta seleccionada tiene filtros dinámicos. Una implementación más potente solicitaría la propiedad DYNAMIC_FILTERS de la consulta del servidor y obtendría los datos que faltan del usuario antes de ejecutar la consulta. Esta implementación se deja como ejercicio para el lector.
Recuerde que CqRowData.getValues() se invoca en cada fila a medida que el objeto CqRowData se coloca en la matriz para visualizarse. Es necesario, dado que la información necesaria para calcular los valores de datos de filas como objetos Java no está disponible después de que se libere el repetidor CqResultSet, lo que sucede automáticamente cuando alcanza el final.
El segundo parámetro de ExecuteQuery.showResults (visor especificado) no se utiliza en este ejemplo, sino que se utilizará en el siguiente ejemplo para permitir al usuario seleccionar una fila del conjunto de resultados y visualizar el registro asociado.