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