001 /*
002 * Copyright (c) 1995-2010, The University of Sheffield. See the file
003 * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
004 *
005 * This file is part of GATE (see http://gate.ac.uk/), and is free
006 * software, licenced under the GNU Library General Public License,
007 * Version 2, June 1991 (in the distribution as file licence.html,
008 * and also available at http://gate.ac.uk/gate/licence.html).
009 *
010 * Valentin Tablan 23/01/2001
011 *
012 * $Id: SerialDatastoreViewer.java 12006 2009-12-01 17:24:28Z thomas_heitz $
013 *
014 */
015 package gate.gui;
016
017 import java.awt.Point;
018 import java.awt.event.*;
019 import java.beans.BeanInfo;
020 import java.beans.Introspector;
021 import java.text.NumberFormat;
022 import java.util.*;
023
024 import javax.swing.*;
025 import javax.swing.tree.*;
026
027 import gate.*;
028 import gate.creole.*;
029 import gate.creole.metadata.CreoleResource;
030 import gate.creole.metadata.GuiType;
031 import gate.event.DatastoreEvent;
032 import gate.event.DatastoreListener;
033 import gate.persist.PersistenceException;
034 import gate.security.SecurityException;
035 import gate.util.*;
036
037 @CreoleResource(name = "Serial Datastore Viewer", guiType = GuiType.LARGE,
038 resourceDisplayed = "gate.persist.SerialDataStore", mainViewer = true)
039 public class SerialDatastoreViewer extends JScrollPane implements
040 VisualResource,
041 DatastoreListener {
042
043 public SerialDatastoreViewer() {
044 }
045
046 public void cleanup() {
047 datastore.removeDatastoreListener(this);
048 myHandle = null;
049 datastore = null;
050 }
051
052 /** Accessor for features. */
053 public FeatureMap getFeatures() {
054 return features;
055 }// getFeatures()
056
057 /** Mutator for features */
058 public void setFeatures(FeatureMap features) {
059 this.features = features;
060 }// setFeatures()
061
062 // Parameters utility methods
063 /**
064 * Gets the value of a parameter of this resource.
065 *
066 * @param paramaterName the name of the parameter
067 * @return the current value of the parameter
068 */
069 public Object getParameterValue(String paramaterName)
070 throws ResourceInstantiationException {
071 return AbstractResource.getParameterValue(this, paramaterName);
072 }
073
074 /**
075 * Sets the value for a specified parameter.
076 *
077 * @param paramaterName the name for the parameteer
078 * @param parameterValue the value the parameter will receive
079 */
080 public void setParameterValue(String paramaterName, Object parameterValue)
081 throws ResourceInstantiationException {
082 // get the beaninfo for the resource bean, excluding data about
083 // Object
084 BeanInfo resBeanInf = null;
085 try {
086 resBeanInf = Introspector.getBeanInfo(this.getClass(), Object.class);
087 }
088 catch(Exception e) {
089 throw new ResourceInstantiationException(
090 "Couldn't get bean info for resource "
091 + this.getClass().getName() + Strings.getNl()
092 + "Introspector exception was: " + e);
093 }
094 AbstractResource.setParameterValue(this, resBeanInf, paramaterName,
095 parameterValue);
096 }
097
098 /**
099 * Sets the values for more parameters in one step.
100 *
101 * @param parameters a feature map that has paramete names as keys and
102 * parameter values as values.
103 */
104 public void setParameterValues(FeatureMap parameters)
105 throws ResourceInstantiationException {
106 AbstractResource.setParameterValues(this, parameters);
107 }
108
109 /** Initialise this resource, and return it. */
110 public Resource init() throws ResourceInstantiationException {
111 return this;
112 }// init()
113
114 public void clear() {
115 }
116
117 public void setTarget(Object target) {
118 if(target == null) {
119 datastore = null;
120 return;
121 }
122 if(target instanceof DataStore) {
123 datastore = (DataStore)target;
124 initLocalData();
125 initGuiComponents();
126 initListeners();
127 }
128 else {
129 throw new IllegalArgumentException(
130 "SerialDatastoreViewers can only be used with GATE serial datastores!\n"
131 + target.getClass().toString()
132 + " is not a GATE serial datastore!");
133 }
134 }
135
136 public void setHandle(Handle handle) {
137 if(handle instanceof NameBearerHandle) {
138 myHandle = (NameBearerHandle)handle;
139 }
140 }
141
142 protected void fireProgressChanged(int e) {
143 myHandle.fireProgressChanged(e);
144 }// protected void fireProgressChanged(int e)
145
146 protected void fireProcessFinished() {
147 myHandle.fireProcessFinished();
148 }// protected void fireProcessFinished()
149
150 protected void fireStatusChanged(String e) {
151 myHandle.fireStatusChanged(e);
152 }
153
154 protected void initLocalData() {
155 }
156
157 protected void initGuiComponents() {
158 treeRoot = new DefaultMutableTreeNode(datastore.getName(), true);
159 treeModel = new DefaultTreeModel(treeRoot, true);
160 mainTree = new JTree();
161 mainTree.setModel(treeModel);
162 mainTree.setExpandsSelectedPaths(true);
163 mainTree.expandPath(new TreePath(treeRoot));
164 try {
165 Iterator lrTypesIter = datastore.getLrTypes().iterator();
166 CreoleRegister cReg = Gate.getCreoleRegister();
167 while(lrTypesIter.hasNext()) {
168 String type = (String)lrTypesIter.next();
169 ResourceData rData = (ResourceData)cReg.get(type);
170 DefaultMutableTreeNode node = new DefaultMutableTreeNode(rData
171 .getName());
172 treeModel.insertNodeInto(node, treeRoot, treeRoot.getChildCount());
173 mainTree.expandPath(new TreePath(new Object[] {treeRoot, node}));
174 Iterator lrIDsIter = datastore.getLrIds(type).iterator();
175 while(lrIDsIter.hasNext()) {
176 String id = (String)lrIDsIter.next();
177 DSEntry entry = new DSEntry(datastore.getLrName(id), id, type);
178 DefaultMutableTreeNode lrNode = new DefaultMutableTreeNode(entry,
179 false);
180 treeModel.insertNodeInto(lrNode, node, node.getChildCount());
181 node.add(lrNode);
182 }
183 }
184 }
185 catch(PersistenceException pe) {
186 throw new GateRuntimeException(pe.toString());
187 }
188 DefaultTreeSelectionModel selectionModel = new DefaultTreeSelectionModel();
189 selectionModel
190 .setSelectionMode(DefaultTreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
191 mainTree.setSelectionModel(selectionModel);
192 getViewport().setView(mainTree);
193
194 popup = new JPopupMenu();
195 deleteAction = new DeleteAction();
196 loadAction = new LoadAction();
197 popup.add(deleteAction);
198 popup.add(loadAction);
199 }// protected void initGuiComponents()
200
201 protected void initListeners() {
202 datastore.addDatastoreListener(this);
203 mainTree.addMouseListener(new MouseAdapter() {
204 public void mouseClicked(MouseEvent e) {
205 if(SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
206 // double click -> just load the resource
207 TreePath path = mainTree.getPathForLocation(e.getX(), e.getY());
208 Object value = null;
209 if(path != null)
210 value = ((DefaultMutableTreeNode)path.getLastPathComponent())
211 .getUserObject();
212 if(value != null && value instanceof DSEntry) {
213 loadAction.ignoreSelection = true;
214 loadAction.setLocation(path);
215 loadAction.actionPerformed(null);
216 }
217 }
218 }// public void mouseClicked(MouseEvent e)
219
220 @Override
221 public void mousePressed(MouseEvent e) {
222 if(e.isPopupTrigger()) {
223 // where inside the tree?
224 TreePath path = mainTree.getPathForLocation(e.getX(), e.getY());
225 deleteAction.setLocation(path);
226 loadAction.setLocation(path);
227 popup.show(SerialDatastoreViewer.this, e.getX(), e.getY());
228 }
229 }
230
231 @Override
232 public void mouseReleased(MouseEvent e) {
233 if(e.isPopupTrigger()) {
234 // where inside the tree?
235 TreePath path = mainTree.getPathForLocation(e.getX(), e.getY());
236 deleteAction.setLocation(path);
237 loadAction.setLocation(path);
238 popup.show(SerialDatastoreViewer.this, e.getX(), e.getY());
239 }
240 }
241 });
242 }// protected void initListeners()
243
244 /**
245 * ACtion to delete all selected resources.
246 */
247 class DeleteAction extends AbstractAction {
248 public DeleteAction() {
249 super("Delete");
250 }
251
252 public void actionPerformed(ActionEvent e) {
253 // delete all selected resources
254 TreePath[] selectedPaths = mainTree.getSelectionPaths();
255 // if no selection -> delete path under cursor
256 if(selectedPaths == null && location != null) {
257 selectedPaths = new TreePath[] {location};
258 location = null;
259 }
260 if(selectedPaths != null) {
261 for(TreePath aPath : selectedPaths) {
262 Object value = ((DefaultMutableTreeNode)aPath.getLastPathComponent())
263 .getUserObject();
264 if(value instanceof DSEntry) {
265 DSEntry entry = (DSEntry)value;
266 try {
267 datastore.delete(entry.type, entry.id);
268 // project.frame.resourcesTreeModel.treeChanged();
269 }
270 catch(gate.persist.PersistenceException pe) {
271 JOptionPane.showMessageDialog(SerialDatastoreViewer.this,
272 "Error!\n" + pe.toString(), "GATE",
273 JOptionPane.ERROR_MESSAGE);
274 pe.printStackTrace(Err.getPrintWriter());
275 }
276 catch(SecurityException se) {
277 JOptionPane.showMessageDialog(SerialDatastoreViewer.this,
278 "Error!\n" + se.toString(), "GATE",
279 JOptionPane.ERROR_MESSAGE);
280 se.printStackTrace(Err.getPrintWriter());
281 }
282 }
283 }
284 }
285 }
286
287 /**
288 * The path where the mouse click occurred.
289 */
290 TreePath location;
291
292 public TreePath getLocation() {
293 return location;
294 }
295
296 public void setLocation(TreePath location) {
297 this.location = location;
298 }
299 }
300
301 /**
302 * Action to load all selected resources.
303 */
304 class LoadAction extends AbstractAction {
305 public LoadAction() {
306 super("Load");
307 }
308
309 public void actionPerformed(ActionEvent e) {
310 Runnable runner = new Runnable(){
311 public void run(){
312 // load all selected resources
313 TreePath[] selectedPaths = mainTree.getSelectionPaths();
314 if(ignoreSelection){
315 ignoreSelection = false;
316 selectedPaths = null;
317 }
318 // if no selection -> load path under cursor
319 if(selectedPaths == null && location != null) {
320 selectedPaths = new TreePath[] {location};
321 location = null;
322 }
323 if(selectedPaths != null) {
324 for(TreePath aPath : selectedPaths) {
325 Object value = ((DefaultMutableTreeNode)aPath.getLastPathComponent())
326 .getUserObject();
327 if(value instanceof DSEntry) {
328 DSEntry entry = (DSEntry)value;
329 try {
330 MainFrame.lockGUI("Loading " + entry.name);
331 long start = System.currentTimeMillis();
332 fireStatusChanged("Loading " + entry.name);
333 fireProgressChanged(0);
334 FeatureMap params = Factory.newFeatureMap();
335 params.put(DataStore.DATASTORE_FEATURE_NAME, datastore);
336 params.put(DataStore.LR_ID_FEATURE_NAME, entry.id);
337 FeatureMap features = Factory.newFeatureMap();
338 Resource res = Factory.createResource(entry.type, params, features,
339 entry.name);
340 // project.frame.resourcesTreeModel.treeChanged();
341 fireProgressChanged(0);
342 fireProcessFinished();
343 long end = System.currentTimeMillis();
344 fireStatusChanged(entry.name
345 + " loaded in "
346 + NumberFormat.getInstance().format(
347 (double)(end - start) / 1000) + " seconds");
348 }
349 catch(ResourceInstantiationException rie) {
350 MainFrame.unlockGUI();
351 JOptionPane.showMessageDialog(SerialDatastoreViewer.this,
352 "Error!\n" + rie.toString(), "GATE",
353 JOptionPane.ERROR_MESSAGE);
354 rie.printStackTrace(Err.getPrintWriter());
355 fireProgressChanged(0);
356 fireProcessFinished();
357 }
358 finally {
359 MainFrame.unlockGUI();
360 }
361 }
362 }
363 }
364 }
365 };
366 Thread thread = new Thread(runner,
367 SerialDatastoreViewer.this.getClass().getCanonicalName() +
368 " DS Loader");
369 thread.setPriority(Thread.MIN_PRIORITY);
370 thread.start();
371 }
372
373 /**
374 * The path where the mouse click occurred.
375 */
376 protected TreePath location;
377
378 protected boolean ignoreSelection = false;
379
380 public TreePath getLocation() {
381 return location;
382 }
383
384 public void setLocation(TreePath location) {
385 this.location = location;
386 }
387 }
388
389 class DSEntry {
390 DSEntry(String name, String id, String type) {
391 this.name = name;
392 this.type = type;
393 this.id = id;
394 }// DSEntry
395
396 public String toString() {
397 return name;
398 }
399
400
401 String name;
402
403 String type;
404
405 String id;
406
407 }// class DSEntry
408
409 DefaultMutableTreeNode treeRoot;
410
411 DefaultTreeModel treeModel;
412
413 JTree mainTree;
414
415 DataStore datastore;
416
417 NameBearerHandle myHandle;
418
419 /**
420 * Action used to delete selected resources
421 */
422 protected DeleteAction deleteAction;
423
424 /**
425 * Action object for loading resources.
426 */
427 protected LoadAction loadAction;
428
429 /**
430 * The popup used for actions.
431 */
432 protected JPopupMenu popup;
433
434 protected FeatureMap features;
435
436 private transient Vector progressListeners;
437
438 private transient Vector statusListeners;
439
440 public void resourceAdopted(DatastoreEvent e) {
441 // do nothing; SerialDataStore does actually nothing on adopt()
442 // we'll have to listen for RESOURE_WROTE events
443 }
444
445 public void resourceDeleted(DatastoreEvent e) {
446 String resID = (String)e.getResourceID();
447 DefaultMutableTreeNode node = null;
448 Enumeration nodesEnum = treeRoot.depthFirstEnumeration();
449 boolean found = false;
450 while(nodesEnum.hasMoreElements() && !found) {
451 node = (DefaultMutableTreeNode)nodesEnum.nextElement();
452 Object userObject = node.getUserObject();
453 found = userObject instanceof DSEntry
454 && ((DSEntry)userObject).id.equals(resID);
455 }
456 if(found) {
457 DefaultMutableTreeNode parent = (DefaultMutableTreeNode)node.getParent();
458 treeModel.removeNodeFromParent(node);
459 if(parent.getChildCount() == 0) treeModel.removeNodeFromParent(parent);
460 }
461 }
462
463 public void resourceWritten(DatastoreEvent e) {
464 Resource res = e.getResource();
465 String resID = (String)e.getResourceID();
466 String resType = ((ResourceData)Gate.getCreoleRegister().get(
467 res.getClass().getName())).getName();
468 DefaultMutableTreeNode parent = treeRoot;
469 DefaultMutableTreeNode node = null;
470 // first look for the type node
471 Enumeration childrenEnum = parent.children();
472 boolean found = false;
473 while(childrenEnum.hasMoreElements() && !found) {
474 node = (DefaultMutableTreeNode)childrenEnum.nextElement();
475 found = node.getUserObject().equals(resType);
476 }
477 if(!found) {
478 // exhausted the children without finding the node -> new type
479 node = new DefaultMutableTreeNode(resType);
480 treeModel.insertNodeInto(node, parent, parent.getChildCount());
481 }
482 mainTree.expandPath(new TreePath(new Object[] {parent, node}));
483
484 // now look for the resource node
485 parent = node;
486 childrenEnum = parent.children();
487 found = false;
488 while(childrenEnum.hasMoreElements() && !found) {
489 node = (DefaultMutableTreeNode)childrenEnum.nextElement();
490 found = ((DSEntry)node.getUserObject()).id.equals(resID);
491 }
492 if(!found) {
493 // exhausted the children without finding the node -> new resource
494 try {
495 DSEntry entry = new DSEntry(datastore.getLrName(resID), resID, res
496 .getClass().getName());
497 node = new DefaultMutableTreeNode(entry, false);
498 treeModel.insertNodeInto(node, parent, parent.getChildCount());
499 }
500 catch(PersistenceException pe) {
501 pe.printStackTrace(Err.getPrintWriter());
502 }
503 }
504 }// public void resourceWritten(DatastoreEvent e)
505
506 }// public class DSHandle
|