1   /*
2    *  Copyright (c) 1998-2001, The University of Sheffield.
3    *
4    *  This file is part of GATE (see http://gate.ac.uk/), and is free
5    *  software, licenced under the GNU Library General Public License,
6    *  Version 2, June 1991 (in the distribution as file licence.html,
7    *  and also available at http://gate.ac.uk/gate/licence.html).
8    *
9    *  Valentin Tablan 23/01/2001
10   *
11   *  $Id: SerialDatastoreViewer.java,v 1.16 2002/03/07 16:50:18 valyt Exp $
12   *
13   */
14  package gate.gui;
15  
16  import gate.*;
17  import gate.creole.*;
18  import gate.util.*;
19  import gate.persist.*;
20  import gate.security.SecurityException;
21  
22  import javax.swing.*;
23  import java.awt.event.*;
24  import javax.swing.tree.*;
25  
26  import java.util.*;
27  import java.text.NumberFormat;
28  
29  import gate.event.*;
30  import java.beans.*;
31  
32  public class SerialDatastoreViewer extends JTree
33                                     implements VisualResource,
34                                                DatastoreListener {
35  
36    public SerialDatastoreViewer() {
37    }
38  
39  
40    public void cleanup(){
41      myHandle = null;
42      datastore = null;
43    }
44  
45    /** Accessor for features. */
46    public FeatureMap getFeatures(){
47      return features;
48    }//getFeatures()
49  
50    /** Mutator for features*/
51    public void setFeatures(FeatureMap features){
52      this.features = features;
53    }// setFeatures()
54  
55    //Parameters utility methods
56    /**
57     * Gets the value of a parameter of this resource.
58     * @param paramaterName the name of the parameter
59     * @return the current value of the parameter
60     */
61    public Object getParameterValue(String paramaterName)
62                  throws ResourceInstantiationException{
63      return AbstractResource.getParameterValue(this, paramaterName);
64    }
65  
66    /**
67     * Sets the value for a specified parameter.
68     *
69     * @param paramaterName the name for the parameteer
70     * @param parameterValue the value the parameter will receive
71     */
72    public void setParameterValue(String paramaterName, Object parameterValue)
73                throws ResourceInstantiationException{
74      // get the beaninfo for the resource bean, excluding data about Object
75      BeanInfo resBeanInf = null;
76      try {
77        resBeanInf = Introspector.getBeanInfo(this.getClass(), Object.class);
78      } catch(Exception e) {
79        throw new ResourceInstantiationException(
80          "Couldn't get bean info for resource " + this.getClass().getName()
81          + Strings.getNl() + "Introspector exception was: " + e
82        );
83      }
84      AbstractResource.setParameterValue(this, resBeanInf, paramaterName, parameterValue);
85    }
86  
87    /**
88     * Sets the values for more parameters in one step.
89     *
90     * @param parameters a feature map that has paramete names as keys and
91     * parameter values as values.
92     */
93    public void setParameterValues(FeatureMap parameters)
94                throws ResourceInstantiationException{
95      AbstractResource.setParameterValues(this, parameters);
96    }
97  
98    /** Initialise this resource, and return it. */
99    public Resource init() throws ResourceInstantiationException {
100     return this;
101   }//init()
102 
103   public void clear(){
104   }
105 
106   public void setTarget(Object target){
107     if(target == null){
108       datastore = null;
109       return;
110     }
111     if(target instanceof DataStore){
112       datastore = (DataStore)target;
113       initLocalData();
114       initGuiComponents();
115       initListeners();
116     }else{
117       throw new IllegalArgumentException(
118         "SerialDatastoreViewers can only be used with GATE serial datastores!\n" +
119         target.getClass().toString() + " is not a GATE serial datastore!");
120     }
121   }
122 
123 
124   public void setHandle(Handle handle){
125     if(handle instanceof NameBearerHandle){
126       myHandle = (NameBearerHandle)handle;
127     }
128   }
129 
130   protected void fireProgressChanged(int e) {
131     myHandle.fireProgressChanged(e);
132   }//protected void fireProgressChanged(int e)
133 
134   protected void fireProcessFinished() {
135     myHandle.fireProcessFinished();
136   }//protected void fireProcessFinished()
137 
138   protected void fireStatusChanged(String e) {
139     myHandle.fireStatusChanged(e);
140   }
141 
142   protected void initLocalData(){
143   }
144 
145   protected void initGuiComponents(){
146     treeRoot = new DefaultMutableTreeNode(
147                  datastore.getName(), true);
148     treeModel = new DefaultTreeModel(treeRoot, true);
149     setModel(treeModel);
150     setExpandsSelectedPaths(true);
151     expandPath(new TreePath(treeRoot));
152     try {
153       Iterator lrTypesIter = datastore.getLrTypes().iterator();
154       CreoleRegister cReg = Gate.getCreoleRegister();
155       while(lrTypesIter.hasNext()){
156         String type = (String)lrTypesIter.next();
157         ResourceData rData = (ResourceData)cReg.get(type);
158         DefaultMutableTreeNode node = new DefaultMutableTreeNode(
159                                                               rData.getName());
160         treeModel.insertNodeInto(node, treeRoot, treeRoot.getChildCount());
161         expandPath(new TreePath(new Object[]{treeRoot, node}));
162         Iterator lrIDsIter = datastore.getLrIds(type).iterator();
163         while(lrIDsIter.hasNext()){
164           String id = (String)lrIDsIter.next();
165           DSEntry entry = new DSEntry(datastore.getLrName(id), id, type);
166           DefaultMutableTreeNode lrNode =
167             new DefaultMutableTreeNode(entry, false);
168           treeModel.insertNodeInto(lrNode, node, node.getChildCount());
169           node.add(lrNode);
170         }
171       }
172     } catch(PersistenceException pe) {
173       throw new GateRuntimeException(pe.toString());
174     }
175     DefaultTreeSelectionModel selectionModel = new DefaultTreeSelectionModel();
176     selectionModel.setSelectionMode(
177         DefaultTreeSelectionModel.SINGLE_TREE_SELECTION);
178     setSelectionModel(selectionModel);
179 
180   }//protected void initGuiComponents()
181 
182   protected void initListeners(){
183     datastore.addDatastoreListener(this);
184     addMouseListener(new MouseAdapter() {
185       public void mouseClicked(MouseEvent e) {
186         //where inside the tree?
187         TreePath path = getPathForLocation(e.getX(), e.getY());
188         Object value = null;
189         if(path != null) value = ((DefaultMutableTreeNode)
190                                   path.getLastPathComponent()).getUserObject();
191 
192         if(SwingUtilities.isRightMouseButton(e)){
193           //right click
194           if(value != null && value instanceof DSEntry){
195             JPopupMenu popup = ((DSEntry)value).getPopup();
196             popup.show(SerialDatastoreViewer.this, e.getX(), e.getY());
197           }
198         }else if(SwingUtilities.isLeftMouseButton(e) &&
199                  e.getClickCount() == 2){
200           //double click -> just load the resource
201           if(value != null && value instanceof DSEntry){
202             new LoadAction((DSEntry)value).actionPerformed(null);
203           }
204         }
205       }//public void mouseClicked(MouseEvent e)
206     });
207   }//protected void initListeners()
208 
209 
210   class LoadAction extends AbstractAction {
211     LoadAction(DSEntry entry){
212       super("Load");
213       this.entry = entry;
214     }
215 
216     public void actionPerformed(ActionEvent e){
217       Runnable runnable = new Runnable(){
218         public void run(){
219           try{
220             MainFrame.lockGUI("Loading " + entry.name);
221             long start = System.currentTimeMillis();
222             fireStatusChanged("Loading " + entry.name);
223             fireProgressChanged(0);
224             FeatureMap params = Factory.newFeatureMap();
225             params.put(DataStore.DATASTORE_FEATURE_NAME, datastore);
226             params.put(DataStore.LR_ID_FEATURE_NAME, entry.id);
227             FeatureMap features = Factory.newFeatureMap();
228             Resource res = Factory.createResource(entry.type, params, features,
229                                                    entry.name);
230             //project.frame.resourcesTreeModel.treeChanged();
231             fireProgressChanged(0);
232             fireProcessFinished();
233             long end = System.currentTimeMillis();
234             fireStatusChanged(entry.name + " loaded in " +
235                               NumberFormat.getInstance().format(
236                               (double)(end - start) / 1000) + " seconds");
237           } catch(ResourceInstantiationException rie){
238             MainFrame.unlockGUI();
239             JOptionPane.showMessageDialog(SerialDatastoreViewer.this,
240                                           "Error!\n" + rie.toString(),
241                                           "Gate", JOptionPane.ERROR_MESSAGE);
242             rie.printStackTrace(Err.getPrintWriter());
243             fireProgressChanged(0);
244             fireProcessFinished();
245           }finally{
246             MainFrame.unlockGUI();
247           }
248         }
249       };//runnable
250       Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
251                                  runnable,
252                                  "Loader from DS");
253       thread.setPriority(Thread.MIN_PRIORITY);
254       thread.start();
255     }// public void actionPerformed(ActionEvent e)
256     DSEntry entry;
257   }//class LoadAction extends AbstractAction
258 
259   class DeleteAction extends AbstractAction {
260     DeleteAction(DSEntry entry){
261       super("Delete");
262       this.entry = entry;
263     }
264 
265     public void actionPerformed(ActionEvent e){
266       try{
267         datastore.delete(entry.type, entry.id);
268         //project.frame.resourcesTreeModel.treeChanged();
269       }catch(gate.persist.PersistenceException pe){
270         JOptionPane.showMessageDialog(SerialDatastoreViewer.this,
271                                       "Error!\n" + pe.toString(),
272                                       "Gate", JOptionPane.ERROR_MESSAGE);
273         pe.printStackTrace(Err.getPrintWriter());
274       } catch(SecurityException se){
275         JOptionPane.showMessageDialog(SerialDatastoreViewer.this,
276                                       "Error!\n" + se.toString(),
277                                       "Gate", JOptionPane.ERROR_MESSAGE);
278         se.printStackTrace(Err.getPrintWriter());
279       }
280     }// public void actionPerformed(ActionEvent e)
281     DSEntry entry;
282   }// class DeleteAction
283 
284 
285   class DSEntry {
286     DSEntry(String name, String id, String type){
287       this.name = name;
288       this.type = type;
289       this.id = id;
290       popup = new JPopupMenu();
291       popup.add(new LoadAction(this));
292       popup.add(new DeleteAction(this));
293     }// DSEntry
294 
295     public String toString(){
296       return name;
297     }
298 
299     public JPopupMenu getPopup(){
300       return popup;
301     }
302 
303     String name;
304     String type;
305     String id;
306     JPopupMenu popup;
307   }// class DSEntry
308 
309   DefaultMutableTreeNode treeRoot;
310   DefaultTreeModel treeModel;
311   DataStore datastore;
312   NameBearerHandle myHandle;
313   protected FeatureMap features;
314 
315   private transient Vector progressListeners;
316   private transient Vector statusListeners;
317   public void resourceAdopted(DatastoreEvent e) {
318     //do nothing; SerialDataStore does actually nothing on adopt()
319     //we'll have to listen for RESOURE_WROTE events
320   }
321 
322   public void resourceDeleted(DatastoreEvent e) {
323     String resID = (String) e.getResourceID();
324     DefaultMutableTreeNode node = null;
325     Enumeration nodesEnum = treeRoot.depthFirstEnumeration();
326     boolean found = false;
327     while(nodesEnum.hasMoreElements() && !found){
328       node = (DefaultMutableTreeNode)nodesEnum.nextElement();
329       Object userObject = node.getUserObject();
330       found = userObject instanceof DSEntry &&
331               ((DSEntry)userObject).id.equals(resID);
332     }
333     if(found){
334       DefaultMutableTreeNode parent = (DefaultMutableTreeNode)node.getParent();
335       treeModel.removeNodeFromParent(node);
336       if(parent.getChildCount() == 0) treeModel.removeNodeFromParent(parent);
337     }
338   }
339 
340   public void resourceWritten(DatastoreEvent e) {
341     Resource res = e.getResource();
342     String resID = (String) e.getResourceID();
343     String resType = ((ResourceData)Gate.getCreoleRegister().
344                       get(res.getClass().getName())).getName();
345     DefaultMutableTreeNode parent = treeRoot;
346     DefaultMutableTreeNode node = null;
347     //first look for the type node
348     Enumeration childrenEnum = parent.children();
349     boolean found = false;
350     while(childrenEnum.hasMoreElements() && !found){
351       node = (DefaultMutableTreeNode)childrenEnum.nextElement();
352       found = node.getUserObject().equals(resType);
353     }
354     if(!found){
355       //exhausted the children without finding the node -> new type
356       node = new DefaultMutableTreeNode(resType);
357       treeModel.insertNodeInto(node, parent, parent.getChildCount());
358     }
359     expandPath(new TreePath(new Object[]{parent, node}));
360 
361     //now look for the resource node
362     parent = node;
363     childrenEnum = parent.children();
364     found = false;
365     while(childrenEnum.hasMoreElements() && !found){
366       node = (DefaultMutableTreeNode)childrenEnum.nextElement();
367       found = ((DSEntry)node.getUserObject()).id.equals(resID);
368     }
369     if(!found){
370       //exhausted the children without finding the node -> new resource
371       try{
372         DSEntry entry = new DSEntry(datastore.getLrName(resID), resID,
373                                     res.getClass().getName());
374         node = new DefaultMutableTreeNode(entry, false);
375         treeModel.insertNodeInto(node, parent, parent.getChildCount());
376       }catch(PersistenceException pe){
377         pe.printStackTrace(Err.getPrintWriter());
378       }
379     }
380   }//public void resourceWritten(DatastoreEvent e)
381 
382 }//public class DSHandle