This project has retired. For details please refer to its Attic page.
QueryFrame xref

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.chemistry.opencmis.workbench;
20  
21  import java.awt.Cursor;
22  import java.awt.Dimension;
23  import java.awt.GridBagConstraints;
24  import java.awt.GridBagLayout;
25  import java.awt.event.ActionEvent;
26  import java.awt.event.ActionListener;
27  import java.awt.event.MouseAdapter;
28  import java.awt.event.MouseEvent;
29  import java.awt.event.MouseMotionListener;
30  import java.util.GregorianCalendar;
31  import java.util.HashMap;
32  import java.util.Map;
33  
34  import javax.swing.BoxLayout;
35  import javax.swing.JButton;
36  import javax.swing.JCheckBox;
37  import javax.swing.JFormattedTextField;
38  import javax.swing.JFrame;
39  import javax.swing.JLabel;
40  import javax.swing.JMenuItem;
41  import javax.swing.JPanel;
42  import javax.swing.JPopupMenu;
43  import javax.swing.JScrollPane;
44  import javax.swing.JSplitPane;
45  import javax.swing.JTable;
46  import javax.swing.JTextArea;
47  import javax.swing.table.AbstractTableModel;
48  import javax.swing.text.NumberFormatter;
49  
50  import org.apache.chemistry.opencmis.client.api.ItemIterable;
51  import org.apache.chemistry.opencmis.client.api.ObjectId;
52  import org.apache.chemistry.opencmis.client.api.QueryResult;
53  import org.apache.chemistry.opencmis.client.runtime.ObjectIdImpl;
54  import org.apache.chemistry.opencmis.commons.PropertyIds;
55  import org.apache.chemistry.opencmis.commons.data.PropertyData;
56  import org.apache.chemistry.opencmis.workbench.model.ClientModel;
57  import org.apache.chemistry.opencmis.workbench.swing.IdRenderer;
58  
59  public class QueryFrame extends JFrame {
60  
61      private static final long serialVersionUID = 1L;
62  
63      private static final Cursor HAND_CURSOR = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
64      private static final Cursor DEFAULT_CURSOR = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
65  
66      private static final String WINDOW_TITLE = "CMIS Query";
67      private static final String DEFAULT_QUERY = "SELECT * FROM cmis:document";
68  
69      private final ClientModel model;
70  
71      private JTextArea queryText;
72      private JFormattedTextField maxHitsField;
73      private JCheckBox searchAllVersionsCheckBox;
74      private JTable resultsTable;
75      private JLabel queryTimeLabel;
76  
77      public QueryFrame(ClientModel model) {
78          super();
79  
80          this.model = model;
81          createGUI();
82      }
83  
84      private void createGUI() {
85          setTitle(WINDOW_TITLE + " - " + model.getRepositoryName());
86          setPreferredSize(new Dimension(800, 700));
87          setMinimumSize(new Dimension(200, 60));
88  
89          setLayout(new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS));
90  
91          // input
92          JPanel inputPanel = new JPanel();
93          inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.LINE_AXIS));
94  
95          queryText = new JTextArea(DEFAULT_QUERY, 5, 60);
96          inputPanel.add(queryText);
97  
98          JPanel inputPanel2 = new JPanel();
99          inputPanel2.setPreferredSize(new Dimension(160, 100));
100         inputPanel2.setMaximumSize(inputPanel.getPreferredSize());
101         inputPanel2.setLayout(new GridBagLayout());
102 
103         GridBagConstraints c = new GridBagConstraints();
104         c.fill = GridBagConstraints.HORIZONTAL;
105 
106         JButton queryButton = new JButton("Query");
107         queryButton.addActionListener(new ActionListener() {
108             public void actionPerformed(ActionEvent e) {
109                 doQuery();
110             }
111         });
112 
113         c.gridx = 0;
114         c.gridy = 0;
115         c.gridwidth = 2;
116         inputPanel2.add(queryButton, c);
117 
118         maxHitsField = new JFormattedTextField(new NumberFormatter());
119         maxHitsField.setValue(Integer.valueOf(100));
120         maxHitsField.setColumns(5);
121 
122         JLabel maxHitsLabel = new JLabel("Max hits:");
123         maxHitsLabel.setLabelFor(maxHitsField);
124 
125         c.gridx = 0;
126         c.gridy = 1;
127         c.gridwidth = 1;
128         inputPanel2.add(maxHitsLabel, c);
129         c.gridx = 1;
130         c.gridy = 1;
131         c.gridwidth = 1;
132         inputPanel2.add(maxHitsField, c);
133 
134         searchAllVersionsCheckBox = new JCheckBox("search all versions", false);
135         c.gridx = 0;
136         c.gridy = 2;
137         c.gridwidth = 2;
138         inputPanel2.add(searchAllVersionsCheckBox, c);
139 
140         queryTimeLabel = new JLabel("(-- hits in -- seconds)");
141         c.gridx = 0;
142         c.gridy = 3;
143         c.gridwidth = 2;
144         inputPanel2.add(queryTimeLabel, c);
145 
146         inputPanel.add(inputPanel2);
147 
148         // table
149         resultsTable = new JTable();
150         resultsTable.setDefaultRenderer(ObjectIdImpl.class, new IdRenderer());
151         resultsTable.setFillsViewportHeight(true);
152         resultsTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
153 
154         final JPopupMenu popup = new JPopupMenu();
155         JMenuItem menuItem = new JMenuItem("Copy to clipboard");
156         popup.add(menuItem);
157 
158         menuItem.addActionListener(new ActionListener() {
159             public void actionPerformed(ActionEvent e) {
160                 ClientHelper.copyTableToClipboard(resultsTable);
161             }
162         });
163 
164         resultsTable.addMouseListener(new MouseAdapter() {
165             public void mouseClicked(MouseEvent e) {
166                 int row = resultsTable.rowAtPoint(e.getPoint());
167                 int column = resultsTable.columnAtPoint(e.getPoint());
168                 if (row > -1 && resultsTable.getColumnClass(column) == ObjectIdImpl.class) {
169                     try {
170                         model.loadObject(((ObjectId) resultsTable.getValueAt(row, column)).getId());
171                     } catch (Exception ex) {
172                         ClientHelper.showError(QueryFrame.this, ex);
173                     }
174                 }
175             }
176 
177             public void mousePressed(MouseEvent e) {
178                 maybeShowPopup(e);
179             }
180 
181             public void mouseReleased(MouseEvent e) {
182                 maybeShowPopup(e);
183             }
184 
185             private void maybeShowPopup(MouseEvent e) {
186                 if (e.isPopupTrigger()) {
187                     popup.show(e.getComponent(), e.getX(), e.getY());
188                 }
189             }
190         });
191 
192         resultsTable.addMouseMotionListener(new MouseMotionListener() {
193             public void mouseMoved(MouseEvent e) {
194                 int row = resultsTable.rowAtPoint(e.getPoint());
195                 int column = resultsTable.columnAtPoint(e.getPoint());
196                 if (row > -1 && resultsTable.getColumnClass(column) == ObjectIdImpl.class) {
197                     resultsTable.setCursor(HAND_CURSOR);
198                 } else {
199                     resultsTable.setCursor(DEFAULT_CURSOR);
200                 }
201             }
202 
203             public void mouseDragged(MouseEvent e) {
204             }
205         });
206 
207         add(new JSplitPane(JSplitPane.VERTICAL_SPLIT, inputPanel, new JScrollPane(resultsTable)));
208 
209         getRootPane().setDefaultButton(queryButton);
210         
211         ClientHelper.installEscapeBinding(this, getRootPane(), true);
212         
213         setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
214         pack();
215 
216         setLocationRelativeTo(null);
217         setVisible(true);
218     }
219 
220     private synchronized void doQuery() {
221         String text = queryText.getText();
222         text = text.replace('\n', ' ');
223 
224         ItemIterable<QueryResult> results = null;
225 
226         try {
227             setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
228 
229             int maxHits = 1000;
230             try {
231                 maxHitsField.commitEdit();
232                 maxHits = ((Number) maxHitsField.getValue()).intValue();
233             } catch (Exception e) {
234             }
235 
236             results = model.query(text, searchAllVersionsCheckBox.isSelected(), maxHits);
237 
238             ResultTableModel rtm = new ResultTableModel();
239 
240             long startTime = System.currentTimeMillis();
241 
242             int row = 0;
243             for (QueryResult qr : results.getPage(maxHits)) {
244                 rtm.setColumnCount(Math.max(rtm.getColumnCount(), qr.getProperties().size()));
245 
246                 for (PropertyData<?> prop : qr.getProperties()) {
247                     if (PropertyIds.OBJECT_ID.equals(prop.getId()) && (prop.getFirstValue() != null)) {
248                         rtm.setValue(row, prop.getQueryName(), new ObjectIdImpl(prop.getFirstValue().toString()));
249                     } else {
250                         rtm.setValue(row, prop.getQueryName(), prop.getFirstValue());
251                     }
252                 }
253 
254                 row++;
255             }
256             rtm.setRowCount(row);
257 
258             long stopTime = System.currentTimeMillis();
259             float time = ((float) (stopTime - startTime)) / 1000f;
260             queryTimeLabel.setText("(" + row + " hits in " + time + " seconds)");
261 
262             resultsTable.setModel(rtm);
263         } catch (Exception ex) {
264             ClientHelper.showError(null, ex);
265             return;
266         } finally {
267             setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
268         }
269     }
270 
271     static class ResultTableModel extends AbstractTableModel {
272 
273         private static final long serialVersionUID = 1L;
274 
275         private int columnCount = 0;
276         private int rowCount = 0;
277         private final Map<String, Integer> columnMapping = new HashMap<String, Integer>();
278         private final Map<Integer, Map<Integer, Object>> data = new HashMap<Integer, Map<Integer, Object>>();
279         private final Map<Integer, Class<?>> columnClass = new HashMap<Integer, Class<?>>();
280 
281         public ResultTableModel() {
282         }
283 
284         public void setColumnCount(int columnCount) {
285             this.columnCount = columnCount;
286         }
287 
288         public int getColumnCount() {
289             return columnCount;
290         }
291 
292         public void setRowCount(int rowCount) {
293             this.rowCount = rowCount;
294         }
295 
296         public int getRowCount() {
297             return rowCount;
298         }
299 
300         public void setValue(int rowIndex, String queryName, Object value) {
301             Integer col = columnMapping.get(queryName);
302             if (col == null) {
303                 col = columnMapping.size();
304                 columnMapping.put(queryName, columnMapping.size());
305             }
306 
307             if (value == null) {
308                 return;
309             }
310 
311             if (value instanceof GregorianCalendar) {
312                 value = ClientHelper.getDateString((GregorianCalendar) value);
313             }
314 
315             columnClass.put(col, value.getClass());
316 
317             Map<Integer, Object> row = data.get(rowIndex);
318             if (row == null) {
319                 row = new HashMap<Integer, Object>();
320                 data.put(rowIndex, row);
321             }
322 
323             row.put(col, value);
324         }
325 
326         public Object getValueAt(int rowIndex, int columnIndex) {
327             Map<Integer, Object> row = data.get(rowIndex);
328             if (row == null) {
329                 return null;
330             }
331 
332             return row.get(columnIndex);
333         }
334 
335         @Override
336         public String getColumnName(int column) {
337             for (Map.Entry<String, Integer> e : columnMapping.entrySet()) {
338                 if (e.getValue().equals(column)) {
339                     return e.getKey();
340                 }
341             }
342 
343             return "?";
344         }
345 
346         @Override
347         public Class<?> getColumnClass(int columnIndex) {
348             Class<?> clazz = columnClass.get(columnIndex);
349             if (clazz != null) {
350                 return clazz;
351             }
352 
353             return String.class;
354         }
355     }
356 }