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