View Javadoc

1   /*
2    *  
3    *  Fosstrak LLRP Commander (www.fosstrak.org)
4    * 
5    *  Copyright (C) 2008 ETH Zurich
6    *
7    *  This program is free software: you can redistribute it and/or modify
8    *  it under the terms of the GNU General Public License as published by
9    *  the Free Software Foundation, either version 3 of the License, or
10   *  (at your option) any later version.
11   *
12   *  This program is distributed in the hope that it will be useful,
13   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   *  GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License
18   *  along with this program.  If not, see <http://www.gnu.org/licenses/> 
19   *
20   */
21  
22  package org.fosstrak.llrp.commander.views.roaccess;
23  
24  import java.text.SimpleDateFormat;
25  import java.util.Date;
26  import java.util.List;
27  
28  import org.apache.log4j.Logger;
29  import org.eclipse.jface.action.Action;
30  import org.eclipse.jface.action.IMenuManager;
31  import org.eclipse.jface.action.IToolBarManager;
32  import org.eclipse.jface.dialogs.MessageDialog;
33  import org.eclipse.jface.viewers.ColumnLayoutData;
34  import org.eclipse.jface.viewers.ColumnWeightData;
35  import org.eclipse.jface.viewers.DoubleClickEvent;
36  import org.eclipse.jface.viewers.IDoubleClickListener;
37  import org.eclipse.jface.viewers.IStructuredSelection;
38  import org.eclipse.jface.viewers.TableViewer;
39  import org.eclipse.jface.viewers.Viewer;
40  import org.eclipse.jface.viewers.ViewerComparator;
41  import org.eclipse.swt.widgets.Composite;
42  import org.eclipse.swt.widgets.Display;
43  import org.eclipse.swt.widgets.Table;
44  import org.eclipse.swt.widgets.TableItem;
45  import org.eclipse.ui.IActionBars;
46  import org.eclipse.ui.ISharedImages;
47  import org.eclipse.ui.PlatformUI;
48  import org.fosstrak.llrp.adaptor.AdaptorManagement;
49  import org.fosstrak.llrp.client.MessageHandler;
50  import org.fosstrak.llrp.client.ROAccessReportsRepository;
51  import org.fosstrak.llrp.client.Repository;
52  import org.fosstrak.llrp.client.repository.sql.roaccess.DerbyROAccessReportsRepository;
53  import org.fosstrak.llrp.client.repository.sql.roaccess.ROAccessItem;
54  import org.fosstrak.llrp.commander.ResourceCenter;
55  import org.fosstrak.llrp.commander.views.TableViewPart;
56  import org.llrp.ltk.generated.messages.RO_ACCESS_REPORT;
57  import org.llrp.ltk.types.LLRPMessage;
58  
59  /**
60   * View displaying the contents of RO_ACCESS_REPORT. The different fields of 
61   * the report get expanded into columns. The messages are sorted according 
62   * the arrival time.
63   * @author sawielan
64   *
65   */
66  public class ROAccessReportsView extends TableViewPart implements MessageHandler {
67  	
68  	// the column headers.
69  	private String columnHeaders[];
70  	
71  	// the layout for the columns
72  	private ColumnLayoutData columnLayouts[];
73  	
74  	// the display
75  	private Display display;
76  	
77  	// action to enable/disable logging.
78  	private Action actionEnable;
79  	
80  	// allow to load the entries from the database.
81  	private Action actionLoadFromDatabase;
82  	
83  	// clear the viewer from the messages.
84  	private Action actionClearViewer;
85  	
86  	// clear the database from the messages.
87  	private Action actionClearDB;
88  	
89  	// export the content to a CSV file.
90  	private Action actionExportAsCSV;
91  	
92  	// whether to log or not.
93  	private boolean enabled = false;
94  	
95  	// the log4j logger.
96  	private static Logger log = Logger.getLogger(ROAccessReportsView.class);
97  
98  	public ROAccessReportsView() {
99  		super();
100 		
101 		String[][] cnt = DerbyROAccessReportsRepository.COLUMN_NAMES_AND_TYPES;
102 		columnHeaders = new String[cnt.length];
103 		columnLayouts = new ColumnLayoutData[cnt.length];
104 		for (int i=0; i<cnt.length; i++) {
105 			columnHeaders[i] = cnt[i][0];
106 			columnLayouts[i] = new ColumnWeightData(20, true);
107 		}
108 		
109 		setColumnHeaders(columnHeaders);
110 		setColumnLayouts(columnLayouts);
111 	}
112 
113 	@Override
114 	public void createPartControl(Composite parent) {
115 		super.createPartControl(parent);
116 		
117 		display = parent.getDisplay();
118 		
119 		TableViewer viewer = getViewer();
120 		viewer.setLabelProvider(new ROAccessReportsLabelProvider());
121 		viewer.setComparator(new ROAccessItemComparator());
122 
123 		final MessageHandler h = this;
124 		
125 		actionEnable = new Action() {
126 			@Override
127 			public void run() {
128 				if (enabled) {
129 					// turn off logging.
130 					AdaptorManagement.getInstance().deregisterPartialHandler(
131 							h, RO_ACCESS_REPORT.class);
132 					enabled = false;
133 				} else {
134 					AdaptorManagement.getInstance().registerPartialHandler(
135 							h, RO_ACCESS_REPORT.class);
136 					enabled = true;
137 				}
138 			}
139 		};
140 		actionEnable.setText("Enable/Disable logging.");
141 		actionEnable.setToolTipText("Enable/Disable logging.");
142 		actionEnable.setImageDescriptor(
143 				ResourceCenter.getInstance().getImageDescriptor("filter.gif"));
144 		actionEnable.setChecked(false);
145 		
146 		actionClearViewer = new Action() {
147 			@Override
148 			public void run() {
149 				getViewer().getTable().removeAll();
150 			}
151 		};
152 		actionClearViewer.setText("Clear the table");
153 		actionClearViewer.setToolTipText("Remove all the messages from the " +
154 				"Viewer");
155 		
156 		actionLoadFromDatabase = new Action() {
157 			@Override
158 			public void run() {
159 				Repository repo = ResourceCenter.getInstance().getRepository();
160 				if (null == repo) return;
161 				ROAccessReportsRepository rorepo = repo.getROAccessRepository();
162 				if (null == rorepo) return;
163 				
164 				try {
165 					List<ROAccessItem> items = rorepo.getAll();
166 					for (ROAccessItem item : items) {
167 						getViewer().add(item);
168 					}
169 				} catch (Exception e) {
170 					log.error(
171 							String.format("could not load messages from db: %s",
172 									e.getMessage()));
173 				}
174 				
175 			}
176 		};
177 		Repository repo = ResourceCenter.getInstance().getRepository();
178 		if ((null != repo) && (null != repo.getROAccessRepository())) {
179 			actionLoadFromDatabase.setEnabled(true);
180 		} else {
181 			actionLoadFromDatabase.setEnabled(false);
182 		}
183 		actionLoadFromDatabase.setText("Load from DB");
184 		actionLoadFromDatabase.setToolTipText(
185 				"Loads the messages from the RO_ACCESS_REPORTS database in " +
186 				"the backend. This action is only available, if you have " +
187 				"a running instance of the backend.");
188 		
189 		actionClearDB = new Action() {
190 			@Override
191 			public void run() {
192 				Repository repo = ResourceCenter.getInstance().getRepository();
193 				if (null == repo) return;
194 				ROAccessReportsRepository rorepo = repo.getROAccessRepository();
195 				if (null == rorepo) return;
196 				
197 				try {
198 					rorepo.clear();
199 					getViewer().getTable().removeAll();
200 				} catch (Exception e) {
201 					log.error(
202 							String.format("could not clear db: %s",
203 									e.getMessage()));
204 				}
205 				
206 			}
207 		};
208 		if ((null != repo) && (null != repo.getROAccessRepository())) {
209 			actionClearDB.setEnabled(true);
210 		} else {
211 			actionClearDB.setEnabled(false);
212 		}
213 		actionClearDB.setText("Clear Database");
214 		actionClearDB.setToolTipText(
215 				"Delete all the messages from the database.");
216 		
217 		getViewer().addDoubleClickListener(new IDoubleClickListener() {
218 			public void doubleClick(DoubleClickEvent event) {
219 				
220 				IStructuredSelection sel = (IStructuredSelection) event.getSelection();
221 				if (sel.getFirstElement() instanceof ROAccessItem) {
222 					new DetailsDialog(
223 							getViewer().getControl().getShell(),
224 							(ROAccessItem) sel.getFirstElement()
225 							).open();
226 				}
227 			}
228 		});
229 		
230 		
231 		actionExportAsCSV = new Action() {
232 			@Override
233 			public void run() {
234 				try {
235 					String folder = "csv";
236 					String fileName = String.format(
237 							"%s.csv",
238 							new SimpleDateFormat(
239 							"yyyy-MMM-dd-HH-mm-ss-SSS").format(new Date()));
240 					ResourceCenter.getInstance().writeMessageToFile(
241 									folder, 
242 									fileName, 
243 									asCSV());
244 					
245 					MessageDialog.openInformation(
246 							getViewer().getControl().getShell(), 
247 							"CSV Export", String.format("Exported to file %s/%s", 
248 									folder, fileName));
249 				} catch (Exception e) {
250 					MessageDialog.openWarning(
251 							getViewer().getControl().getShell(),
252 							"CSV Export", "Could not write csv");
253 					e.printStackTrace();
254 				}
255 			}
256 		};
257 		actionExportAsCSV.setText("Save as CSV");
258 		actionExportAsCSV.setImageDescriptor(
259 				PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(
260 						ISharedImages.IMG_ETOOL_SAVE_EDIT));
261 		
262 		IActionBars bars = getViewSite().getActionBars();
263 		IToolBarManager man = bars.getToolBarManager();
264 		man.add(actionExportAsCSV);
265 		
266 		
267 		viewer.refresh();
268 	}
269 	
270 	/**
271 	 * @return the content of the table as a comma-separated-values string.
272 	 */
273 	public String asCSV() {
274 		StringBuffer str = new StringBuffer();
275 		String [][] clm = DerbyROAccessReportsRepository.COLUMN_NAMES_AND_TYPES;
276 		for (int i=0; i<clm.length; i++) {
277 			str.append(String.format("%s,", clm[i][0]));
278 		}
279 		str.append("\n");
280 		
281 		Table table = getViewer().getTable();
282 		for (TableItem item : table.getItems()) {
283 			if (item.getData() instanceof ROAccessItem) {
284 				ROAccessItem ro = (ROAccessItem) item.getData();
285 				str.append(ro.getAsCSV()); str.append("\n");
286 			}
287 		}
288 		return str.toString();
289 	}
290 
291 	public void handle(String adaptorName, String readerName,
292 			LLRPMessage message) {
293 		
294 		if (message instanceof RO_ACCESS_REPORT) {
295 			final List<ROAccessItem> items = ROAccessItem.parse(
296 					(RO_ACCESS_REPORT)message, adaptorName, 
297 					readerName, System.currentTimeMillis());
298 			
299 			// execute the update in the thread context of the 
300 			// window thread.
301 			synchronized (display) {
302 				display.syncExec(
303 						new Runnable() {
304 							public void run() {
305 								for (ROAccessItem item : items) {
306 									
307 									getViewer().add(item);
308 								}
309 							}
310 						}
311 					);
312 			}
313 		}
314 	}
315 
316 	/* (non-Javadoc)
317 	 * @see org.fosstrak.llrp.commander.views.TableViewPart#fillContextMenu(org.eclipse.jface.action.IMenuManager)
318 	 */
319 	@Override
320 	protected void fillContextMenu(IMenuManager manager) {
321 		super.fillContextMenu(manager);
322 		manager.add(actionEnable);
323 		manager.add(actionClearViewer);
324 		manager.add(actionLoadFromDatabase);
325 		manager.add(actionClearDB);
326 	}
327 	
328 	
329 	/**
330 	 * comparator to compare two llrp message item elements. if 
331 	 * the timestamp of the second element is smaller than the timestamp 
332 	 * of the first, then a negative number is returned. otherwise 
333 	 * a positive value.
334 	 * @author sawielan
335 	 *
336 	 */
337 	private class ROAccessItemComparator extends ViewerComparator {
338 		
339 		/**
340 		 * compares two elements and returns a negative number if element2 is 
341 		 * more recent than element1.
342 		 * @param viewer the viewer.
343 		 * @param element1 the first element to compare.
344 		 * @param element2 the second element to compare.
345 		 */
346 		public int compare(Viewer viewer, Object element1, Object element2) {
347 			if ((element1 instanceof ROAccessItem) && 
348 					(element2 instanceof ROAccessItem)) {
349 				
350 				ROAccessItem msg1 = (ROAccessItem) element1;
351 				ROAccessItem msg2 = (ROAccessItem) element2;
352 
353 				// compare the two timestamps...
354 				return (int)(msg2.getLogTime().getTime() - msg1.getLogTime().getTime());				
355 			}
356 			return 0;
357 		}
358 	}
359 }