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;
23  
24  import java.rmi.NotBoundException;
25  import java.rmi.RemoteException;
26  
27  import org.apache.log4j.Logger;
28  import org.eclipse.jface.action.Action;
29  import org.eclipse.jface.action.IMenuListener;
30  import org.eclipse.jface.action.IMenuManager;
31  import org.eclipse.jface.action.IToolBarManager;
32  import org.eclipse.jface.action.MenuManager;
33  import org.eclipse.jface.action.Separator;
34  import org.eclipse.jface.dialogs.IInputValidator;
35  import org.eclipse.jface.dialogs.InputDialog;
36  import org.eclipse.jface.dialogs.MessageDialog;
37  import org.eclipse.jface.viewers.DoubleClickEvent;
38  import org.eclipse.jface.viewers.IDoubleClickListener;
39  import org.eclipse.jface.viewers.ISelectionChangedListener;
40  import org.eclipse.jface.viewers.IStructuredSelection;
41  import org.eclipse.jface.viewers.SelectionChangedEvent;
42  import org.eclipse.jface.viewers.TreeViewer;
43  import org.eclipse.jface.window.Window;
44  import org.eclipse.swt.SWT;
45  import org.eclipse.swt.widgets.Composite;
46  import org.eclipse.swt.widgets.Menu;
47  import org.eclipse.ui.IActionBars;
48  import org.eclipse.ui.ISharedImages;
49  import org.eclipse.ui.PlatformUI;
50  import org.eclipse.ui.part.DrillDownAdapter;
51  import org.eclipse.ui.part.ViewPart;
52  import org.fosstrak.llrp.adaptor.Adaptor;
53  import org.fosstrak.llrp.adaptor.AdaptorManagement;
54  import org.fosstrak.llrp.adaptor.Reader;
55  import org.fosstrak.llrp.adaptor.exception.LLRPRuntimeException;
56  import org.fosstrak.llrp.commander.ExceptionHandler;
57  import org.fosstrak.llrp.commander.ResourceCenter;
58  import org.fosstrak.llrp.commander.dialogs.AddFCDialog;
59  import org.fosstrak.llrp.commander.dialogs.AddReaderDialog;
60  import org.fosstrak.llrp.commander.dialogs.ReaderSettingsDialog;
61  import org.fosstrak.llrp.commander.util.LLRPConstraints;
62  import org.fosstrak.llrp.commander.util.LLRPFactory;
63  import org.fosstrak.llrp.commander.util.LLRPRangeConstraint;
64  import org.llrp.ltk.generated.messages.DELETE_ACCESSSPEC;
65  import org.llrp.ltk.generated.messages.DELETE_ROSPEC;
66  import org.llrp.ltk.generated.messages.DISABLE_ACCESSSPEC;
67  import org.llrp.ltk.generated.messages.DISABLE_ROSPEC;
68  import org.llrp.ltk.generated.messages.ENABLE_ACCESSSPEC;
69  import org.llrp.ltk.generated.messages.ENABLE_ROSPEC;
70  import org.llrp.ltk.generated.messages.START_ROSPEC;
71  import org.llrp.ltk.generated.messages.STOP_ROSPEC;
72  import org.llrp.ltk.types.LLRPMessage;
73  import org.llrp.ltk.types.UnsignedInteger;
74  
75  /**
76   * The Reader Management View. It embeds one <code>TreeViewer</code>, and
77   * illustrates the Adapter/Reader relationship in tree-like hierarchy.
78   * 
79   * Only two partitions are defined, XML tag and XML comment.
80   * 
81   * @author Haoning Zhang
82   * @author Ulrich Etter
83   * @author sawielan
84   * @version 1.0
85   */
86  public class ReaderExplorerView extends ViewPart {
87  
88  	/**
89  	 * Log4j instance.
90  	 */
91  	private static Logger log = Logger.getLogger(ReaderExplorerView.class);
92  
93  	/**
94  	 * JFace Tree control for Reader hierarchy.
95  	 */
96  	private TreeViewer viewer;
97  	private DrillDownAdapter drillDownAdapter;
98  	private ReaderTreeObject currentSelectedReader;
99  	private boolean isFocusOnReaderTreeObject;
100 
101 	private ExceptionHandler exceptionHandler;
102 
103 	/**
104 	 * Add Reader Action
105 	 */
106 	private Action actionAddReader;
107 
108 	/**
109 	 * Remove Reader Action.
110 	 */
111 	private Action actionRemoveReader;
112 
113 	/**
114 	 * Add Adapter Action
115 	 */
116 	private Action actionAddAdapter;
117 
118 	/**
119 	 * Remove Adaptor Action
120 	 */
121 	private Action actionRemoveAdaptor;
122 
123 	/**
124 	 * Action triggered when user click the Connect menu item.
125 	 */
126 	private Action actionConnect;
127 	private Action actionDisconnect;
128 	private Action actionRefresh;
129 
130 	private Action actionGetReaderCapabilities;
131 	private Action actionGetReaderConfig;
132 
133 	private Action actionGetRospecs;
134 	private Action actionEnableRospec;
135 	private Action actionDisableRospec;
136 	private Action actionStartRospec;
137 	private Action actionStopRospec;
138 	private Action actionDeleteRospec;
139 
140 	private Action actionGetAccessspecs;
141 	private Action actionEnableAccessspec;
142 	private Action actionDisableAccessspec;
143 	private Action actionDeleteAccessspec;
144 
145 	private Action actionReaderSettings;
146 
147 	/**
148 	 * Default Constructor.
149 	 */
150 	public ReaderExplorerView() {
151 		isFocusOnReaderTreeObject = false;
152 	}
153 
154 	/**
155 	 * This is a callback that will allow us to create the viewer and initialize
156 	 * it.
157 	 */
158 	public void createPartControl(Composite parent) {
159 		viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
160 		drillDownAdapter = new DrillDownAdapter(viewer);
161 		viewer.setContentProvider(new ReaderExplorerViewContentProvider());
162 		viewer.setLabelProvider(new ReaderExplorerViewLabelProvider());
163 		viewer.setInput(getViewSite());
164 		viewer.addSelectionChangedListener(new ReaderChangeListenser());
165 
166 		makeActions();
167 		hookContextMenu();
168 		hookDoubleClickAction();
169 		contributeToActionBars();
170 
171 		// Publish the Reader selection to MessageboxView, then the
172 		// MessageboxView can refresh the window
173 		getSite().setSelectionProvider(viewer);
174 
175 		exceptionHandler = new ExceptionHandler(viewer.getControl().getShell());
176 		ResourceCenter.getInstance().setExceptionHandler(exceptionHandler);
177 
178 		viewer.expandAll();
179 		ResourceCenter.getInstance().setReaderExplorerView(this);
180 	}
181 
182 	class ReaderChangeListenser implements ISelectionChangedListener {
183 		public void selectionChanged(SelectionChangedEvent event) {
184 
185 			// if the selection is empty then quit
186 			if (event.getSelection().isEmpty()) {
187 				return;
188 			}
189 
190 			if (event.getSelection() instanceof IStructuredSelection) {
191 				IStructuredSelection selection = (IStructuredSelection) event
192 						.getSelection();
193 
194 				Object selectedObj = selection.getFirstElement();
195 				if (selectedObj instanceof ReaderTreeObject) {
196 					ReaderTreeObject reader = (ReaderTreeObject) selectedObj;
197 					currentSelectedReader = reader;
198 					isFocusOnReaderTreeObject = true;
199 				} else if (selectedObj instanceof MessageBoxTreeObject) {
200 					MessageBoxTreeObject msgBox = (MessageBoxTreeObject) selectedObj;
201 					currentSelectedReader = msgBox.getParent();
202 					isFocusOnReaderTreeObject = false;
203 				}
204 			}
205 		}
206 	}
207 
208 	private void hookContextMenu() {
209 		MenuManager menuMgr = new MenuManager("#PopupMenu");
210 		menuMgr.setRemoveAllWhenShown(true);
211 		menuMgr.addMenuListener(new IMenuListener() {
212 			public void menuAboutToShow(IMenuManager manager) {
213 				ReaderExplorerView.this.fillContextMenu(manager);
214 			}
215 		});
216 		Menu menu = menuMgr.createContextMenu(viewer.getControl());
217 		viewer.getControl().setMenu(menu);
218 		getSite().registerContextMenu(menuMgr, viewer);
219 	}
220 
221 	private void contributeToActionBars() {
222 		IActionBars bars = getViewSite().getActionBars();
223 		fillLocalPullDown(bars.getMenuManager());
224 		fillLocalToolBar(bars.getToolBarManager());
225 	}
226 
227 	private void fillLocalPullDown(IMenuManager manager) {
228 		manager.add(actionAddReader);
229 		manager.add(new Separator());
230 		manager.add(actionRemoveReader);
231 	}
232 
233 	/**
234 	 * Construct the context menu.
235 	 * 
236 	 * @param manager
237 	 *            IMenuManager instance
238 	 */
239 	private void fillContextMenu(IMenuManager manager) {
240 		if (null != currentSelectedReader) {
241 			if (isFocusOnReaderTreeObject && currentSelectedReader.isReader()) {
242 				if (currentSelectedReader.isConnected()) {
243 					actionConnect.setEnabled(false);
244 					actionDisconnect.setEnabled(true);
245 					actionRemoveReader.setEnabled(false);
246 
247 					actionGetReaderCapabilities.setEnabled(true);
248 					actionGetReaderConfig.setEnabled(true);
249 
250 					actionGetRospecs.setEnabled(true);
251 					actionEnableRospec.setEnabled(true);
252 					actionDisableRospec.setEnabled(true);
253 					actionStartRospec.setEnabled(true);
254 					actionStopRospec.setEnabled(true);
255 					actionDeleteRospec.setEnabled(true);
256 
257 					actionGetAccessspecs.setEnabled(true);
258 					actionEnableAccessspec.setEnabled(true);
259 					actionDisableAccessspec.setEnabled(true);
260 					actionDeleteAccessspec.setEnabled(true);
261 
262 				} else {
263 					actionConnect.setEnabled(true);
264 					actionDisconnect.setEnabled(false);
265 					actionRemoveReader.setEnabled(true);
266 
267 					actionGetReaderCapabilities.setEnabled(false);
268 					actionGetReaderConfig.setEnabled(false);
269 
270 					actionGetRospecs.setEnabled(false);
271 					actionEnableRospec.setEnabled(false);
272 					actionDisableRospec.setEnabled(false);
273 					actionStartRospec.setEnabled(false);
274 					actionStopRospec.setEnabled(false);
275 					actionDeleteRospec.setEnabled(false);
276 
277 					actionGetAccessspecs.setEnabled(false);
278 					actionEnableAccessspec.setEnabled(false);
279 					actionDisableAccessspec.setEnabled(false);
280 					actionDeleteAccessspec.setEnabled(false);
281 
282 				}
283 
284 				actionReaderSettings.setEnabled(true);
285 
286 				manager.add(actionConnect);
287 				manager.add(actionDisconnect);
288 				manager.add(actionRemoveReader);
289 
290 				MenuManager sendMessageMenuManager = new MenuManager(
291 						"Send Message", "sendMessage");
292 
293 				sendMessageMenuManager.add(actionGetReaderCapabilities);
294 				sendMessageMenuManager.add(actionGetReaderConfig);
295 				sendMessageMenuManager.add(new Separator());
296 				sendMessageMenuManager.add(actionGetRospecs);
297 				sendMessageMenuManager.add(actionEnableRospec);
298 				sendMessageMenuManager.add(actionDisableRospec);
299 				sendMessageMenuManager.add(actionStartRospec);
300 				sendMessageMenuManager.add(actionStopRospec);
301 				sendMessageMenuManager.add(actionDeleteRospec);
302 				sendMessageMenuManager.add(new Separator());
303 				sendMessageMenuManager.add(actionGetAccessspecs);
304 				sendMessageMenuManager.add(actionEnableAccessspec);
305 				sendMessageMenuManager.add(actionDisableAccessspec);
306 				sendMessageMenuManager.add(actionDeleteAccessspec);
307 
308 				manager.add(sendMessageMenuManager);
309 
310 				sendMessageMenuManager.add(new Separator());
311 				manager.add(actionReaderSettings);
312 			} else if (isFocusOnReaderTreeObject) {
313 				// get the name of the currently selected adaptor item
314 				String adaptorName = currentSelectedReader.getName();
315 				try {
316 					// by default do not show the remove adaptor item
317 					actionRemoveAdaptor.setEnabled(false);
318 					actionAddAdapter.setEnabled(false);
319 					actionAddReader.setEnabled(false);
320 
321 					// check whether the requested adaptor is registered in the
322 					// mgmt
323 					if (AdaptorManagement.getInstance().containsAdaptor(
324 							adaptorName)) {
325 						Adaptor adaptor = (Adaptor) AdaptorManagement
326 								.getInstance().getAdaptor(adaptorName);
327 
328 						// default adaptor cannot be deleted therefore showing
329 						// the
330 						// delete action only when the selected adaptor is not
331 						// the
332 						// default adaptor.
333 						if (!adaptor.getAdaptorName().equalsIgnoreCase(
334 								AdaptorManagement.DEFAULT_ADAPTOR_NAME)) {
335 
336 							actionRemoveAdaptor.setEnabled(true);
337 
338 							// if the adapter is local, we allow to add readers
339 							if (AdaptorManagement.getInstance().isLocalAdapter(
340 									adaptor.getAdaptorName())) {
341 								actionAddReader.setEnabled(true);
342 							}
343 						} else {
344 							actionAddReader.setEnabled(true);
345 						}
346 					} else {
347 						actionAddAdapter.setEnabled(true);
348 					}
349 				} catch (Exception e) {
350 					log
351 							.error("caught exception when adding undefine adaptor menu");
352 					e.printStackTrace();
353 				}
354 
355 				manager.add(actionRemoveAdaptor);
356 				manager.add(actionAddAdapter);
357 				manager.add(actionAddReader);
358 			}
359 		}
360 		// drillDownAdapter.addNavigationActions(manager);
361 		// Other plug-ins can contribute there actions here
362 		// manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
363 	}
364 
365 	private void fillLocalToolBar(IToolBarManager manager) {
366 		manager.add(actionAddAdapter);
367 		manager.add(actionAddReader);
368 		manager.add(actionRefresh);
369 		manager.add(new Separator());
370 		drillDownAdapter.addNavigationActions(manager);
371 	}
372 
373 	private void makeActions() {
374 
375 		actionAddAdapter = new Action() {
376 			public void run() {
377 
378 				// Open the Dialog
379 				AddFCDialog dlg = new AddFCDialog(viewer.getControl()
380 						.getShell());
381 				if (dlg.open() == Window.CANCEL) {
382 					return;
383 				}
384 
385 				String message = null;
386 				try {
387 					// Define the Adapter in Adapter Management module.
388 					if (dlg.isLocalAdapter()) {
389 						AdaptorManagement.getInstance().define(dlg.getName(),
390 								null);
391 					} else {
392 						AdaptorManagement.getInstance().define(dlg.getName(),
393 								dlg.getIP());
394 					}
395 				} catch (LLRPRuntimeException llrpe) {
396 					log.info(llrpe.getMessage());
397 					message = llrpe.getMessage();
398 				} catch (NotBoundException nbe) {
399 					log.info(nbe.getMessage());
400 					message = nbe.getMessage();
401 				} catch (RemoteException re) {
402 					log.info(re.getMessage());
403 					message = re.getMessage();
404 				}
405 				if (null != message) {
406 					MessageDialog.openWarning(viewer.getControl().getShell(),
407 							"Could not create Adapter", message);
408 				}
409 
410 				refresh();
411 			}
412 		};
413 
414 		actionAddAdapter.setText("Add Adapter Instance");
415 		actionAddAdapter.setToolTipText("Manually Add Adapter Instance");
416 		actionAddAdapter.setImageDescriptor(ResourceCenter.getInstance()
417 				.getImageDescriptor("adapter.gif"));
418 
419 		actionAddReader = new Action() {
420 			public void run() {
421 
422 				// Open the Dialog
423 				AddReaderDialog dlg = new AddReaderDialog(viewer.getControl()
424 						.getShell());
425 				if (dlg.open() == Window.CANCEL) {
426 					return;
427 				}
428 
429 				String message = null;
430 				try {
431 					// Define the Adapter in Adapter Management module.
432 					String adapterName = getSelectedAdapter();
433 					Adaptor adapter = null;
434 					if (AdaptorManagement.getInstance().containsAdaptor(adapterName)) {
435 						adapter = AdaptorManagement.getInstance().getAdaptor(adapterName);
436 					} else {
437 						adapter = AdaptorManagement.getInstance().getDefaultAdaptor();
438 					}
439 					
440 					adapter.define(dlg.getName(), dlg.getIP(), dlg
441 							.getPort(), dlg.isClientInitiated(), dlg
442 							.isConnectImmediately());
443 					
444 				} catch (LLRPRuntimeException llrpe) {
445 					log.info(llrpe.getMessage());
446 					message = llrpe.getMessage();
447 				} catch (RemoteException re) {
448 					log.info(re.getMessage());
449 					message = re.getMessage();
450 				}
451 				if (null != message) {
452 					MessageDialog.openWarning(viewer.getControl().getShell(),
453 							"Could not create Reader", message);
454 				}
455 
456 				log.debug("Refreshing the Reader Tree...");
457 				viewer.refresh(true);
458 				viewer.expandAll();
459 			}
460 		};
461 
462 		actionAddReader.setText("Add RFID Reader");
463 		actionAddReader.setToolTipText("Manually Add Local RFID Reader");
464 		actionAddReader.setImageDescriptor(ResourceCenter.getInstance()
465 				.getImageDescriptor("reader.gif"));
466 
467 		actionRemoveReader = new Action() {
468 			public void run() {
469 				if ((null != currentSelectedReader)
470 						&& (currentSelectedReader.isReader())) {
471 
472 					try {
473 						Adaptor adapter = null;
474 						if (AdaptorManagement.getInstance().containsAdaptor(
475 								getSelectedAdapter())) {
476 							adapter = AdaptorManagement.getInstance().
477 								getAdaptor(getSelectedAdapter());
478 						} else {
479 							adapter = AdaptorManagement.getInstance().
480 								getDefaultAdaptor();
481 						}
482 						adapter.undefine(currentSelectedReader.getName());
483 					} catch (LLRPRuntimeException llrpe) {
484 						llrpe.printStackTrace();
485 					} catch (RemoteException re) {
486 						re.printStackTrace();
487 					}
488 
489 					log.debug("Refreshing the Reader Tree...");
490 					viewer.refresh(true);
491 					viewer.expandAll();
492 				}
493 			}
494 		};
495 		actionRemoveReader.setText("Remove RFID Reader");
496 		actionRemoveReader.setToolTipText("Manually Remove RFID Reader");
497 		actionRemoveReader.setImageDescriptor(PlatformUI.getWorkbench()
498 				.getSharedImages().getImageDescriptor(
499 						ISharedImages.IMG_TOOL_DELETE));
500 
501 		actionRefresh = new Action() {
502 			public void run() {
503 				log.debug("Refreshing the Reader Tree...");
504 				viewer.refresh(true);
505 				viewer.expandAll();
506 			}
507 		};
508 		actionRefresh.setText("Refresh");
509 		actionRefresh.setToolTipText("Refresh");
510 		actionRefresh.setImageDescriptor(ResourceCenter.getInstance()
511 				.getImageDescriptor("refresh.gif"));
512 
513 		/**
514 		 * doubleClickAction = new Action() { public void run() { ISelection
515 		 * selection = viewer.getSelection(); Object obj =
516 		 * ((IStructuredSelection)selection).getFirstElement();
517 		 * showMessage("Double-click detected on "+obj.toString()); } };
518 		 */
519 
520 		actionConnect = new Action() {
521 			public void run() {
522 				if ((null != currentSelectedReader)
523 						&& (currentSelectedReader.isReader())) {
524 					ReaderTreeObject adapterNode = currentSelectedReader
525 							.getParent();
526 
527 					try {
528 						Adaptor adaptor = AdaptorManagement.getInstance()
529 								.getAdaptor(adapterNode.getName());
530 						adaptor.getReader(currentSelectedReader.getName())
531 								.connect(true);
532 					} catch (LLRPRuntimeException llrpe) {
533 						llrpe.printStackTrace();
534 					} catch (RemoteException re) {
535 						re.printStackTrace();
536 					}
537 				}
538 
539 				viewer.refresh(true);
540 				viewer.expandAll();
541 			}
542 		};
543 		actionConnect.setText("Connect");
544 		actionConnect.setToolTipText("Connect to RFID Reader");
545 		actionConnect.setImageDescriptor(PlatformUI.getWorkbench()
546 				.getSharedImages().getImageDescriptor(
547 						ISharedImages.IMG_TOOL_FORWARD));
548 
549 		actionDisconnect = new Action() {
550 			public void run() {
551 				log.debug("Disconnecting...");
552 				if ((null != currentSelectedReader)
553 						&& (currentSelectedReader.isReader())) {
554 
555 					log.debug("Disconnecting "
556 							+ currentSelectedReader.getName());
557 
558 					ReaderTreeObject adapterNode = currentSelectedReader
559 							.getParent();
560 
561 					try {
562 						Adaptor adaptor = AdaptorManagement.getInstance()
563 								.getAdaptor(adapterNode.getName());
564 						log.debug("Geting adapter " + adaptor.getAdaptorName());
565 						adaptor.getReader(currentSelectedReader.getName())
566 								.disconnect();
567 						log.debug("Disconnecting from Adapter "
568 								+ currentSelectedReader.getName());
569 					} catch (LLRPRuntimeException llrpe) {
570 						llrpe.printStackTrace();
571 					} catch (RemoteException re) {
572 						re.printStackTrace();
573 					}
574 				}
575 				viewer.refresh(true);
576 				viewer.expandAll();
577 			}
578 		};
579 		actionDisconnect.setText("Disconnect");
580 		actionDisconnect.setToolTipText("Disconnect from local adapter");
581 		actionDisconnect.setImageDescriptor(PlatformUI.getWorkbench()
582 				.getSharedImages().getImageDescriptor(
583 						ISharedImages.IMG_TOOL_BACK));
584 
585 		actionReaderSettings = new Action() {
586 			public void run() {
587 				if ((null != currentSelectedReader)
588 						&& (currentSelectedReader.isReader())) {
589 
590 					String adapter = currentSelectedReader.getParent()
591 							.getName();
592 					String reader = currentSelectedReader.getName();
593 					new ReaderSettingsDialog(viewer.getControl().getShell(),
594 							adapter, reader).open();
595 				}
596 			}
597 		};
598 		actionReaderSettings.setText("Settings");
599 		actionReaderSettings.setToolTipText("Settings for the reader");
600 
601 		actionGetReaderCapabilities = createSendMessageAction("GET_READER_CAPABILITIES");
602 		actionGetReaderConfig = createSendMessageAction("GET_READER_CONFIG");
603 
604 		actionGetRospecs = createSendMessageAction("GET_ROSPECS");
605 		actionEnableRospec = createSendMessageAction("ENABLE_ROSPEC");
606 		actionDisableRospec = createSendMessageAction("DISABLE_ROSPEC");
607 		actionStartRospec = createSendMessageAction("START_ROSPEC");
608 		actionStopRospec = createSendMessageAction("STOP_ROSPEC");
609 		actionDeleteRospec = createSendMessageAction("DELETE_ROSPEC");
610 
611 		actionGetAccessspecs = createSendMessageAction("GET_ACCESSSPECS");
612 		actionEnableAccessspec = createSendMessageAction("ENABLE_ACCESSSPEC");
613 		actionDisableAccessspec = createSendMessageAction("DISABLE_ACCESSSPEC");
614 		actionDeleteAccessspec = createSendMessageAction("DELETE_ACCESSSPEC");
615 
616 		// action to remove a remote instance of an adaptor
617 		actionRemoveAdaptor = new Action() {
618 			public void run() {
619 				if ((currentSelectedReader != null)
620 						&& (!currentSelectedReader.isReader())) {
621 					// get the name of the currently selected adaptor item
622 					String adaptorName = currentSelectedReader.getName();
623 					try {
624 
625 						// only call delete method if adaptor is present in the
626 						// mgmt
627 						if (AdaptorManagement.getInstance().containsAdaptor(
628 								adaptorName)) {
629 							Adaptor adaptor = (Adaptor) AdaptorManagement
630 									.getInstance().getAdaptor(adaptorName);
631 
632 							// default adaptor cannot be deleted.
633 							if (!adaptor.getAdaptorName().equalsIgnoreCase(
634 									AdaptorManagement.DEFAULT_ADAPTOR_NAME)) {
635 
636 								// delete the adaptor
637 								AdaptorManagement.getInstance().undefine(
638 										adaptorName);
639 							}
640 						}
641 
642 						viewer.refresh(true);
643 						viewer.expandAll();
644 					} catch (Exception e) {
645 						log
646 								.error("caught exception when undefining adaptor instance");
647 						e.printStackTrace();
648 					}
649 
650 				}
651 			}
652 		};
653 		actionRemoveAdaptor.setText("Delete Adaptor");
654 		actionRemoveAdaptor.setToolTipText("Delete a remote adaptor");
655 		actionRemoveAdaptor.setImageDescriptor(PlatformUI.getWorkbench()
656 				.getSharedImages().getImageDescriptor(
657 						ISharedImages.IMG_OBJ_FILE));
658 	}
659 
660 	private Action createSendMessageAction(final String messageName) {
661 		Action result = new Action() {
662 			public void run() {
663 				if ((null != currentSelectedReader)
664 						&& (currentSelectedReader.isReader())) {
665 					LLRPMessage message;
666 					if (messageName.equals("DELETE_ROSPEC")) {
667 						InputDialog dlg = new InputDialog(viewer.getControl()
668 								.getShell(), messageName, "ROSpecID:", "1",
669 								new IDValidator("ROSpecID", "DELETE_ROSPEC"));
670 						if (dlg.open() == Window.OK) {
671 							try {
672 								message = (DELETE_ROSPEC) LLRPFactory
673 										.createLLRPMessage("DELETE_ROSPEC");
674 								UnsignedInteger rOSpecID = new UnsignedInteger(
675 										dlg.getValue());
676 								((DELETE_ROSPEC) message).setROSpecID(rOSpecID);
677 							} catch (Exception e) {
678 								e.printStackTrace();
679 								return;
680 							}
681 						} else {
682 							return;
683 						}
684 					} else if (messageName.equals("START_ROSPEC")) {
685 						InputDialog dlg = new InputDialog(viewer.getControl()
686 								.getShell(), messageName, "ROSpecID:", "1",
687 								new IDValidator("ROSpecID", "START_ROSPEC"));
688 						if (dlg.open() == Window.OK) {
689 							try {
690 								message = (START_ROSPEC) LLRPFactory
691 										.createLLRPMessage("START_ROSPEC");
692 								UnsignedInteger rOSpecID = new UnsignedInteger(
693 										dlg.getValue());
694 								((START_ROSPEC) message).setROSpecID(rOSpecID);
695 							} catch (Exception e) {
696 								e.printStackTrace();
697 								return;
698 							}
699 						} else {
700 							return;
701 						}
702 					} else if (messageName.equals("STOP_ROSPEC")) {
703 						InputDialog dlg = new InputDialog(viewer.getControl()
704 								.getShell(), messageName, "ROSpecID:", "1",
705 								new IDValidator("ROSpecID", "STOP_ROSPEC"));
706 						if (dlg.open() == Window.OK) {
707 							try {
708 								message = (STOP_ROSPEC) LLRPFactory
709 										.createLLRPMessage("STOP_ROSPEC");
710 								UnsignedInteger rOSpecID = new UnsignedInteger(
711 										dlg.getValue());
712 								((STOP_ROSPEC) message).setROSpecID(rOSpecID);
713 							} catch (Exception e) {
714 								e.printStackTrace();
715 								return;
716 							}
717 						} else {
718 							return;
719 						}
720 					} else if (messageName.equals("ENABLE_ROSPEC")) {
721 						InputDialog dlg = new InputDialog(viewer.getControl()
722 								.getShell(), messageName, "ROSpecID:", "1",
723 								new IDValidator("ROSpecID", "ENABLE_ROSPEC"));
724 						if (dlg.open() == Window.OK) {
725 							try {
726 								message = (ENABLE_ROSPEC) LLRPFactory
727 										.createLLRPMessage("ENABLE_ROSPEC");
728 								UnsignedInteger rOSpecID = new UnsignedInteger(
729 										dlg.getValue());
730 								((ENABLE_ROSPEC) message).setROSpecID(rOSpecID);
731 							} catch (Exception e) {
732 								e.printStackTrace();
733 								return;
734 							}
735 						} else {
736 							return;
737 						}
738 					} else if (messageName.equals("DISABLE_ROSPEC")) {
739 						InputDialog dlg = new InputDialog(viewer.getControl()
740 								.getShell(), messageName, "ROSpecID:", "1",
741 								new IDValidator("ROSpecID", "DISABLE_ROSPEC"));
742 						if (dlg.open() == Window.OK) {
743 							try {
744 								message = (DISABLE_ROSPEC) LLRPFactory
745 										.createLLRPMessage("DISABLE_ROSPEC");
746 								UnsignedInteger rOSpecID = new UnsignedInteger(
747 										dlg.getValue());
748 								((DISABLE_ROSPEC) message)
749 										.setROSpecID(rOSpecID);
750 							} catch (Exception e) {
751 								e.printStackTrace();
752 								return;
753 							}
754 						} else {
755 							return;
756 						}
757 					} else if (messageName.equals("DELETE_ACCESSSPEC")) {
758 						InputDialog dlg = new InputDialog(viewer.getControl()
759 								.getShell(), messageName, "AccessSpecID:", "1",
760 								new IDValidator("AccessSpecID",
761 										"DELETE_ACCESSSPEC"));
762 						if (dlg.open() == Window.OK) {
763 							try {
764 								message = (DELETE_ACCESSSPEC) LLRPFactory
765 										.createLLRPMessage("DELETE_ACCESSSPEC");
766 								UnsignedInteger accessSpecID = new UnsignedInteger(
767 										dlg.getValue());
768 								((DELETE_ACCESSSPEC) message)
769 										.setAccessSpecID(accessSpecID);
770 							} catch (Exception e) {
771 								e.printStackTrace();
772 								return;
773 							}
774 						} else {
775 							return;
776 						}
777 					} else if (messageName.equals("ENABLE_ACCESSSPEC")) {
778 						InputDialog dlg = new InputDialog(viewer.getControl()
779 								.getShell(), messageName, "AccessSpecID:", "1",
780 								new IDValidator("AccessSpecID",
781 										"ENABLE_ACCESSSPEC"));
782 						if (dlg.open() == Window.OK) {
783 							try {
784 								message = (ENABLE_ACCESSSPEC) LLRPFactory
785 										.createLLRPMessage("ENABLE_ACCESSSPEC");
786 								UnsignedInteger accessSpecID = new UnsignedInteger(
787 										dlg.getValue());
788 								((ENABLE_ACCESSSPEC) message)
789 										.setAccessSpecID(accessSpecID);
790 							} catch (Exception e) {
791 								e.printStackTrace();
792 								return;
793 							}
794 						} else {
795 							return;
796 						}
797 					} else if (messageName.equals("DISABLE_ACCESSSPEC")) {
798 						InputDialog dlg = new InputDialog(viewer.getControl()
799 								.getShell(), messageName, "AccessSpecID:", "1",
800 								new IDValidator("AccessSpecID",
801 										"DISABLE_ACCESSSPEC"));
802 						if (dlg.open() == Window.OK) {
803 							try {
804 								message = (DISABLE_ACCESSSPEC) LLRPFactory
805 										.createLLRPMessage("DISABLE_ACCESSSPEC");
806 								UnsignedInteger accessSpecID = new UnsignedInteger(
807 										dlg.getValue());
808 								((DISABLE_ACCESSSPEC) message)
809 										.setAccessSpecID(accessSpecID);
810 							} catch (Exception e) {
811 								e.printStackTrace();
812 								return;
813 							}
814 						} else {
815 							return;
816 						}
817 					} else {
818 						message = LLRPFactory.createLLRPMessage(messageName);
819 					}
820 					ReaderTreeObject adapterNode = currentSelectedReader
821 							.getParent();
822 					ResourceCenter.getInstance().sendMessage(
823 							adapterNode.getName(),
824 							currentSelectedReader.getName(), message, "");
825 				}
826 			}
827 		};
828 		if (messageName.equals("ENABLE_ROSPEC")
829 				|| messageName.equals("DISABLE_ROSPEC")
830 				|| messageName.equals("START_ROSPEC")
831 				|| messageName.equals("STOP_ROSPEC")
832 				|| messageName.equals("DELETE_ROSPEC")
833 				|| messageName.equals("ENABLE_ACCESSSPEC")
834 				|| messageName.equals("DISABLE_ACCESSSPEC")
835 				|| messageName.equals("DELETE_ACCESSSPEC")) {
836 			result.setText(messageName + "...");
837 		} else {
838 			result.setText(messageName);
839 		}
840 		result.setToolTipText("Send a " + messageName
841 				+ " message to this reader");
842 		result.setImageDescriptor(ResourceCenter.getInstance()
843 				.getImageDescriptor("Message.gif"));
844 		return result;
845 	}
846 
847 	private void hookDoubleClickAction() {
848 		viewer.addDoubleClickListener(new IDoubleClickListener() {
849 			public void doubleClick(DoubleClickEvent event) {
850 				try {
851 					String adapterName = currentSelectedReader.getParent()
852 							.getName();
853 					String readerName = currentSelectedReader.getName();
854 					if (AdaptorManagement.getInstance().containsAdaptor(
855 							adapterName)
856 							&& AdaptorManagement.getInstance().getAdaptor(
857 									adapterName).containsReader(readerName)) {
858 
859 						Reader reader = AdaptorManagement.getInstance()
860 								.getAdaptor(adapterName).getReader(readerName);
861 
862 						if (reader.isConnected()) {
863 							log.debug("reader connected - disconnecting.");
864 							reader.disconnect();
865 						} else {
866 							log.debug("reader not connected - connecting.");
867 							reader.connect(reader.isClientInitiated());
868 						}
869 
870 						refresh();
871 					}
872 				} catch (Exception e) {
873 					log.debug("could not communicate with reader:\n"
874 							+ e.getMessage());
875 				}
876 			}
877 		});
878 	}
879 
880 	/**
881 	 * Passing the focus request to the viewer's control.
882 	 */
883 	public void setFocus() {
884 		viewer.getControl().setFocus();
885 	}
886 
887 	/**
888 	 * refreshes the viewer.
889 	 */
890 	public void refresh() {
891 		viewer.refresh(true);
892 		viewer.expandAll();
893 	}
894 
895 	/**
896 	 * @return the name of the currently selected adapter.
897 	 */
898 	public String getSelectedAdapter() {
899 		if ((null != currentSelectedReader)
900 				&& (currentSelectedReader.isReader())) {
901 			return currentSelectedReader.getParent().getName();
902 		} else if (null != currentSelectedReader) {
903 			return currentSelectedReader.getName();
904 		}
905 		return null;
906 	}
907 
908 	/**
909 	 * @return the name of the currently selected reader.
910 	 */
911 	public String getSelectedReader() {
912 		if ((null != currentSelectedReader)
913 				&& (currentSelectedReader.isReader())) {
914 			return currentSelectedReader.getName();
915 		}
916 		return null;
917 	}
918 
919 	/**
920 	 * When a user wants to send a START_ROSPEC message via the context menu of
921 	 * the ReaderExplorerView, a dialog asks him for a ROSpecID. This class
922 	 * validates the user input.
923 	 * 
924 	 * @author Ulrich Etter, ETHZ
925 	 * 
926 	 */
927 	class IDValidator implements IInputValidator {
928 
929 		private String iDName;
930 		private String iDParentName;
931 
932 		/**
933 		 * Creates a new IDValidator. <br/>
934 		 * <br/>
935 		 * Example: <br/>
936 		 * <br/>
937 		 * If this validator should validate the ROSpecID field of the
938 		 * START_ROSPEC message, you should call
939 		 * <code>new ROSpecIDValidator("ROSpecID", "START_ROSPEC")</code>.
940 		 * 
941 		 * @param iDName
942 		 *            the name of the ID to validate
943 		 * @param iDParentName
944 		 *            he name of the parent of the ID field
945 		 */
946 		public IDValidator(String iDName, String iDParentName) {
947 			this.iDName = iDName;
948 			this.iDParentName = iDParentName;
949 		}
950 
951 		public String isValid(String newText) {
952 			try {
953 				UnsignedInteger value = new UnsignedInteger(newText);
954 
955 				// find matching constraint and check it
956 				LLRPRangeConstraint[] rangeConstraints = LLRPConstraints.rangeConstraints;
957 				for (int i = 0; i < rangeConstraints.length; i++) {
958 					if (rangeConstraints[i].getMessageOrParameterName().equals(
959 							iDParentName)) {
960 						if (rangeConstraints[i].getFieldName().equals(iDName)) {
961 							// check constraint
962 							if (!rangeConstraints[i].isSatisfied(value
963 									.intValue())) {
964 								return rangeConstraints[i].getErrorMessage();
965 							}
966 							break;
967 						}
968 					}
969 				}
970 				return null;
971 			} catch (Exception e) {
972 				return "";
973 			}
974 		}
975 	}
976 }