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.slc.client.ui.views;
17  
18  import java.text.DateFormat;
19  import java.text.SimpleDateFormat;
20  import java.util.ArrayList;
21  import java.util.List;
22  
23  import javax.jcr.Node;
24  import javax.jcr.NodeIterator;
25  import javax.jcr.Repository;
26  import javax.jcr.RepositoryException;
27  import javax.jcr.Session;
28  import javax.jcr.observation.Event;
29  import javax.jcr.observation.EventListener;
30  import javax.jcr.observation.ObservationManager;
31  import javax.jcr.query.Query;
32  
33  import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
34  import org.argeo.eclipse.ui.jcr.NodeElementComparer;
35  import org.argeo.jcr.JcrUtils;
36  import org.argeo.slc.SlcException;
37  import org.argeo.slc.SlcNames;
38  import org.argeo.slc.SlcTypes;
39  import org.argeo.slc.client.ui.ClientUiPlugin;
40  import org.argeo.slc.client.ui.editors.ProcessEditor;
41  import org.argeo.slc.client.ui.editors.ProcessEditorInput;
42  import org.argeo.slc.jcr.SlcJcrResultUtils;
43  import org.eclipse.jface.viewers.ColumnLabelProvider;
44  import org.eclipse.jface.viewers.DoubleClickEvent;
45  import org.eclipse.jface.viewers.IBaseLabelProvider;
46  import org.eclipse.jface.viewers.IDoubleClickListener;
47  import org.eclipse.jface.viewers.IStructuredContentProvider;
48  import org.eclipse.jface.viewers.IStructuredSelection;
49  import org.eclipse.jface.viewers.ITableLabelProvider;
50  import org.eclipse.jface.viewers.TableViewer;
51  import org.eclipse.jface.viewers.Viewer;
52  import org.eclipse.swt.SWT;
53  import org.eclipse.swt.graphics.Image;
54  import org.eclipse.swt.widgets.Composite;
55  import org.eclipse.swt.widgets.Display;
56  import org.eclipse.swt.widgets.Table;
57  import org.eclipse.swt.widgets.TableColumn;
58  import org.eclipse.ui.IWorkbenchPage;
59  import org.eclipse.ui.PlatformUI;
60  import org.eclipse.ui.part.ViewPart;
61  
62  /** Displays results. */
63  public class JcrResultListView extends ViewPart implements SlcNames {
64  	public static final String ID = ClientUiPlugin.ID + ".jcrResultListView";
65  
66  	private TableViewer viewer;
67  
68  	private Repository repository;
69  	private Session session;
70  
71  	private EventListener resultsObserver;
72  
73  	private DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss");
74  	private Integer queryLimit = 2000;
75  
76  	public void createPartControl(Composite parent) {
77  		try {
78  			session = repository.login();
79  		} catch (RepositoryException e1) {
80  			throw new SlcException("Cannot log in to repository");
81  		}
82  
83  		Table table = createTable(parent);
84  		viewer = new TableViewer(table);
85  		viewer.setLabelProvider(createLabelProvider());
86  		viewer.setContentProvider(new ViewContentProvider());
87  		viewer.setInput(getViewSite());
88  		viewer.addDoubleClickListener(new ViewDoubleClickListener());
89  		viewer.setComparer(new NodeElementComparer());
90  
91  		getViewSite().setSelectionProvider(viewer);
92  
93  		resultsObserver = new ResultObserver(viewer.getTable().getDisplay());
94  		try {
95  			ObservationManager observationManager = session.getWorkspace().getObservationManager();
96  			String[] nodeTypes = { SlcTypes.SLC_TEST_RESULT };
97  			// FIXME Will not be notified if empty result is deleted
98  			observationManager.addEventListener(resultsObserver, Event.PROPERTY_ADDED | Event.NODE_REMOVED,
99  					SlcJcrResultUtils.getSlcResultsBasePath(session), true, null, nodeTypes, false);
100 		} catch (RepositoryException e) {
101 			throw new SlcException("Cannot register listeners", e);
102 		}
103 
104 	}
105 
106 	protected Table createTable(Composite parent) {
107 		int style = SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.MULTI;
108 		// does not work with RAP, commented for the time being
109 		// | SWT.HIDE_SELECTION;
110 
111 		Table table = new Table(parent, style);
112 
113 		table.setLinesVisible(true);
114 		table.setHeaderVisible(true);
115 
116 		TableColumn column = new TableColumn(table, SWT.LEFT, 0);
117 		column.setText("Date");
118 		column.setWidth(200);
119 
120 		column = new TableColumn(table, SWT.LEFT, 1);
121 		column.setText("Id");
122 		column.setWidth(300);
123 
124 		return table;
125 	}
126 
127 	// public void refresh() {
128 	// viewer.refresh();
129 	// }
130 
131 	/*
132 	 * METHODS TO BE OVERRIDDEN
133 	 */
134 	protected IBaseLabelProvider createLabelProvider() {
135 		return new ViewLabelProvider();
136 	}
137 
138 	protected void processDoubleClick(DoubleClickEvent evt) {
139 		Object obj = ((IStructuredSelection) evt.getSelection()).getFirstElement();
140 		try {
141 			if (obj instanceof Node) {
142 				Node node = (Node) obj;
143 				// FIXME: open a default result editor
144 				if (node.isNodeType(SlcTypes.SLC_PROCESS)) {
145 					IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
146 					activePage.openEditor(new ProcessEditorInput(node.getPath()), ProcessEditor.ID);
147 				}
148 			}
149 		} catch (Exception e) {
150 			throw new SlcException("Cannot open " + obj, e);
151 		}
152 	}
153 
154 	public void setFocus() {
155 		viewer.getControl().setFocus();
156 	}
157 
158 	class ViewContentProvider implements IStructuredContentProvider {
159 		private static final long serialVersionUID = -4719077015405546260L;
160 
161 		public Object[] getElements(Object inputElement) {
162 			try {
163 				// TODO filter, optimize with virtual table, ...
164 				String sql = "SELECT * from [" + SlcTypes.SLC_TEST_RESULT + "] ORDER BY [jcr:lastModified] DESC";
165 				Query query = session.getWorkspace().getQueryManager().createQuery(sql, Query.JCR_SQL2);
166 				// TODO paging
167 				query.setLimit(queryLimit);
168 				List<Node> nodes = new ArrayList<Node>();
169 				for (NodeIterator nit = query.execute().getNodes(); nit.hasNext();) {
170 					nodes.add(nit.nextNode());
171 				}
172 				return nodes.toArray();
173 			} catch (RepositoryException e) {
174 				throw new SlcException("Cannot retrieve processes", e);
175 			}
176 		}
177 
178 		public void dispose() {
179 		}
180 
181 		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
182 		}
183 
184 	}
185 
186 	class ViewLabelProvider extends ColumnLabelProvider implements ITableLabelProvider {
187 		private static final long serialVersionUID = -6323202576386795247L;
188 
189 		public Image getColumnImage(Object obj, int columnIndex) {
190 			if (columnIndex != 0)
191 				return null;
192 			try {
193 				Node node = (Node) obj;
194 				if (node.hasProperty(SLC_COMPLETED)) {
195 					// TODO
196 				}
197 				return null;
198 			} catch (RepositoryException e) {
199 				throw new SlcException("Cannot get column text", e);
200 			}
201 		}
202 
203 		public String getColumnText(Object obj, int index) {
204 			try {
205 				Node node = (Node) obj;
206 				switch (index) {
207 
208 				case 0:
209 					if (node.hasProperty(SLC_COMPLETED)) {
210 						return dateFormat.format(node.getProperty(SLC_COMPLETED).getDate().getTime());
211 					} else {
212 						return "OPEN";
213 					}
214 				case 1:
215 					return node.getProperty(SlcNames.SLC_UUID).getString();
216 				}
217 				return getText(obj);
218 			} catch (RepositoryException e) {
219 				throw new SlcException("Cannot get column text", e);
220 			}
221 		}
222 
223 	}
224 
225 	class ViewDoubleClickListener implements IDoubleClickListener {
226 		public void doubleClick(DoubleClickEvent evt) {
227 			processDoubleClick(evt);
228 		}
229 
230 	}
231 
232 	class ResultObserver extends AsyncUiEventListener {
233 
234 		public ResultObserver(Display display) {
235 			super(display);
236 		}
237 
238 		@Override
239 		protected Boolean willProcessInUiThread(List<Event> events) throws RepositoryException {
240 			for (Event event : events) {
241 				// getLog().debug("Received event " + event);
242 				int eventType = event.getType();
243 				if (eventType == Event.NODE_REMOVED)
244 					return true;
245 				String path = event.getPath();
246 				int index = path.lastIndexOf('/');
247 				String propertyName = path.substring(index + 1);
248 				if (propertyName.equals(SLC_COMPLETED) || propertyName.equals(SLC_UUID)) {
249 					return true;
250 				}
251 			}
252 			return false;
253 		}
254 
255 		protected void onEventInUiThread(List<Event> events) throws RepositoryException {
256 			if (getLog().isTraceEnabled())
257 				getLog().trace("Refresh result list");
258 			viewer.refresh();
259 		}
260 	}
261 
262 	public void dispose() {
263 		JcrUtils.unregisterQuietly(session.getWorkspace(), resultsObserver);
264 		JcrUtils.logoutQuietly(session);
265 		super.dispose();
266 	}
267 
268 	public void setRepository(Repository repository) {
269 		this.repository = repository;
270 	}
271 }