View Javadoc
1   /*
2    * Copyright (C) 2007-2012 Argeo GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.argeo.cms.ui.workbench.internal.jcr.parts;
17  
18  import java.util.ArrayList;
19  import java.util.List;
20  
21  import javax.jcr.RepositoryException;
22  import javax.jcr.Session;
23  import javax.jcr.query.QueryResult;
24  import javax.jcr.query.Row;
25  import javax.jcr.query.RowIterator;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.argeo.eclipse.ui.EclipseUiException;
30  import org.argeo.eclipse.ui.GenericTableComparator;
31  import org.eclipse.core.runtime.IProgressMonitor;
32  import org.eclipse.core.runtime.IStatus;
33  import org.eclipse.core.runtime.Status;
34  import org.eclipse.jface.dialogs.ErrorDialog;
35  import org.eclipse.jface.viewers.ColumnLabelProvider;
36  import org.eclipse.jface.viewers.IDoubleClickListener;
37  import org.eclipse.jface.viewers.IStructuredContentProvider;
38  import org.eclipse.jface.viewers.TableViewer;
39  import org.eclipse.jface.viewers.TableViewerColumn;
40  import org.eclipse.jface.viewers.Viewer;
41  import org.eclipse.swt.SWT;
42  import org.eclipse.swt.custom.SashForm;
43  import org.eclipse.swt.events.SelectionAdapter;
44  import org.eclipse.swt.events.SelectionEvent;
45  import org.eclipse.swt.graphics.Image;
46  import org.eclipse.swt.layout.FillLayout;
47  import org.eclipse.swt.layout.GridData;
48  import org.eclipse.swt.layout.GridLayout;
49  import org.eclipse.swt.widgets.Composite;
50  import org.eclipse.swt.widgets.TableColumn;
51  import org.eclipse.ui.IEditorInput;
52  import org.eclipse.ui.IEditorSite;
53  import org.eclipse.ui.PartInitException;
54  import org.eclipse.ui.part.EditorPart;
55  
56  /** Executes any JCR query. */
57  public abstract class AbstractJcrQueryEditor extends EditorPart {
58  	private final static Log log = LogFactory.getLog(AbstractJcrQueryEditor.class);
59  
60  	protected String initialQuery;
61  	protected String initialQueryType;
62  
63  	/* DEPENDENCY INJECTION */
64  	private Session session;
65  
66  	// Widgets
67  	private TableViewer viewer;
68  	private List<TableViewerColumn> tableViewerColumns = new ArrayList<TableViewerColumn>();
69  	private GenericTableComparator comparator;
70  
71  	/** Override to layout a form enabling the end user to build his query */
72  	protected abstract void createQueryForm(Composite parent);
73  
74  	@Override
75  	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
76  		JcrQueryEditorInput editorInput = (JcrQueryEditorInput) input;
77  		initialQuery = editorInput.getQuery();
78  		initialQueryType = editorInput.getQueryType();
79  		setSite(site);
80  		setInput(editorInput);
81  	}
82  
83  	@Override
84  	public final void createPartControl(final Composite parent) {
85  		parent.setLayout(new FillLayout());
86  
87  		SashForm sashForm = new SashForm(parent, SWT.VERTICAL);
88  		sashForm.setSashWidth(4);
89  		sashForm.setLayout(new FillLayout());
90  
91  		Composite top = new Composite(sashForm, SWT.NONE);
92  		GridLayout gl = new GridLayout(1, false);
93  		top.setLayout(gl);
94  
95  		createQueryForm(top);
96  
97  		Composite bottom = new Composite(sashForm, SWT.NONE);
98  		bottom.setLayout(new GridLayout(1, false));
99  		sashForm.setWeights(getWeights());
100 
101 		viewer = new TableViewer(bottom);
102 		viewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
103 		viewer.getTable().setHeaderVisible(true);
104 		viewer.setContentProvider(getQueryResultContentProvider());
105 		viewer.setInput(getEditorSite());
106 
107 		if (getComparator() != null) {
108 			comparator = getComparator();
109 			viewer.setComparator(comparator);
110 		}
111 		if (getTableDoubleClickListener() != null)
112 			viewer.addDoubleClickListener(getTableDoubleClickListener());
113 
114 	}
115 
116 	protected void executeQuery(String statement) {
117 		try {
118 			if (log.isDebugEnabled())
119 				log.debug("Query : " + statement);
120 
121 			QueryResult qr = session.getWorkspace().getQueryManager().createQuery(statement, initialQueryType)
122 					.execute();
123 
124 			// remove previous columns
125 			for (TableViewerColumn tvc : tableViewerColumns)
126 				tvc.getColumn().dispose();
127 
128 			int i = 0;
129 			for (final String columnName : qr.getColumnNames()) {
130 				TableViewerColumn tvc = new TableViewerColumn(viewer, SWT.NONE);
131 				configureColumn(columnName, tvc, i);
132 				tvc.setLabelProvider(getLabelProvider(columnName));
133 				tableViewerColumns.add(tvc);
134 				i++;
135 			}
136 
137 			// Must create a local list: QueryResults can only be read once.
138 			try {
139 				List<Row> rows = new ArrayList<Row>();
140 				RowIterator rit = qr.getRows();
141 				while (rit.hasNext()) {
142 					rows.add(rit.nextRow());
143 				}
144 				viewer.setInput(rows);
145 			} catch (RepositoryException e) {
146 				throw new EclipseUiException("Cannot read query result", e);
147 			}
148 
149 		} catch (RepositoryException e) {
150 			ErrorDialog.openError(null, "Error", "Cannot execute JCR query: " + statement,
151 					new Status(IStatus.ERROR, "org.argeo.eclipse.ui.jcr", e.getMessage()));
152 		}
153 	}
154 
155 	/**
156 	 * To be overidden to adapt size of form and result frames.
157 	 * 
158 	 * @return
159 	 */
160 	protected int[] getWeights() {
161 		return new int[] { 30, 70 };
162 	}
163 
164 	/**
165 	 * To be overidden to implement a doubleclick Listener on one of the rows of
166 	 * the table.
167 	 * 
168 	 * @return
169 	 */
170 	protected IDoubleClickListener getTableDoubleClickListener() {
171 		return null;
172 	}
173 
174 	/**
175 	 * To be overiden in order to implement a specific
176 	 * QueryResultContentProvider
177 	 */
178 	protected IStructuredContentProvider getQueryResultContentProvider() {
179 		return new QueryResultContentProvider();
180 	}
181 
182 	/**
183 	 * Enable specific implementation for columns
184 	 */
185 	protected List<TableViewerColumn> getTableViewerColumns() {
186 		return tableViewerColumns;
187 	}
188 
189 	/**
190 	 * Enable specific implementation for columns
191 	 */
192 	protected TableViewer getTableViewer() {
193 		return viewer;
194 	}
195 
196 	/**
197 	 * To be overridden in order to configure column label providers .
198 	 */
199 	protected ColumnLabelProvider getLabelProvider(final String columnName) {
200 		return new ColumnLabelProvider() {
201 			private static final long serialVersionUID = -3539689333250152606L;
202 
203 			public String getText(Object element) {
204 				Row row = (Row) element;
205 				try {
206 					return row.getValue(columnName).getString();
207 				} catch (RepositoryException e) {
208 					throw new EclipseUiException("Cannot display row " + row, e);
209 				}
210 			}
211 
212 			public Image getImage(Object element) {
213 				return null;
214 			}
215 		};
216 	}
217 
218 	/**
219 	 * To be overridden in order to configure the columns.
220 	 * 
221 	 * @deprecated use
222 	 *             {@link AbstractJcrQueryEditor#configureColumn(String, TableViewerColumn , int )}
223 	 *             instead
224 	 */
225 	protected void configureColumn(String jcrColumnName, TableViewerColumn column) {
226 		column.getColumn().setWidth(50);
227 		column.getColumn().setText(jcrColumnName);
228 	}
229 
230 	/** To be overridden in order to configure the columns. */
231 	protected void configureColumn(String jcrColumnName, TableViewerColumn column, int columnIndex) {
232 		column.getColumn().setWidth(50);
233 		column.getColumn().setText(jcrColumnName);
234 	}
235 
236 	private class QueryResultContentProvider implements IStructuredContentProvider {
237 		private static final long serialVersionUID = -5421095459600554741L;
238 
239 		public void dispose() {
240 		}
241 
242 		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
243 		}
244 
245 		public Object[] getElements(Object inputElement) {
246 
247 			if (inputElement instanceof List)
248 				return ((List<?>) inputElement).toArray();
249 
250 			// Never reached might be deleted in future release
251 			if (!(inputElement instanceof QueryResult))
252 				return new String[] {};
253 
254 			try {
255 				QueryResult queryResult = (QueryResult) inputElement;
256 				List<Row> rows = new ArrayList<Row>();
257 				RowIterator rit = queryResult.getRows();
258 				while (rit.hasNext()) {
259 					rows.add(rit.nextRow());
260 				}
261 
262 				// List<Node> elems = new ArrayList<Node>();
263 				// NodeIterator nit = queryResult.getNodes();
264 				// while (nit.hasNext()) {
265 				// elems.add(nit.nextNode());
266 				// }
267 				return rows.toArray();
268 			} catch (RepositoryException e) {
269 				throw new EclipseUiException("Cannot read query result", e);
270 			}
271 		}
272 
273 	}
274 
275 	/**
276 	 * Might be used by children classes to sort columns.
277 	 * 
278 	 * @param column
279 	 * @param index
280 	 * @return
281 	 */
282 	protected SelectionAdapter getSelectionAdapter(final TableColumn column, final int index) {
283 
284 		// A comparator must be define
285 		if (comparator == null)
286 			return null;
287 
288 		SelectionAdapter selectionAdapter = new SelectionAdapter() {
289 			private static final long serialVersionUID = 239829307927778349L;
290 
291 			@Override
292 			public void widgetSelected(SelectionEvent e) {
293 
294 				try {
295 
296 					comparator.setColumn(index);
297 					int dir = viewer.getTable().getSortDirection();
298 					if (viewer.getTable().getSortColumn() == column) {
299 						dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
300 					} else {
301 
302 						dir = SWT.DOWN;
303 					}
304 					viewer.getTable().setSortDirection(dir);
305 					viewer.getTable().setSortColumn(column);
306 					viewer.refresh();
307 				} catch (Exception exc) {
308 					exc.printStackTrace();
309 				}
310 			}
311 		};
312 		return selectionAdapter;
313 	}
314 
315 	/**
316 	 * To be overridden to enable sorting.
317 	 */
318 	protected GenericTableComparator getComparator() {
319 		return null;
320 	}
321 
322 	@Override
323 	public boolean isDirty() {
324 		return false;
325 	}
326 
327 	@Override
328 	public void doSave(IProgressMonitor monitor) {
329 		// TODO save the query in JCR?
330 	}
331 
332 	@Override
333 	public void doSaveAs() {
334 	}
335 
336 	@Override
337 	public boolean isSaveAsAllowed() {
338 		return false;
339 	}
340 
341 	/** Returns the injected current session */
342 	protected Session getSession() {
343 		return session;
344 	}
345 
346 	/* DEPENDENCY INJECTION */
347 	public void setSession(Session session) {
348 		this.session = session;
349 	}
350 }