NameBearerHandle.java
0001 /*
0002  *  Copyright (c) 1995-2012, The University of Sheffield. See the file
0003  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
0004  *
0005  *  This file is part of GATE (see http://gate.ac.uk/), and is free
0006  *  software, licenced under the GNU Library General Public License,
0007  *  Version 2, June 1991 (in the distribution as file licence.html,
0008  *  and also available at http://gate.ac.uk/gate/licence.html).
0009  *
0010  *  Valentin Tablan 23/01/2001
0011  *
0012  *  $Id: NameBearerHandle.java 19917 2017-01-06 16:24:05Z ian_roberts $
0013  *
0014  */
0015 
0016 package gate.gui;
0017 
0018 import gate.Controller;
0019 import gate.Corpus;
0020 import gate.CorpusController;
0021 import gate.DataStore;
0022 import gate.DataStoreRegister;
0023 import gate.Document;
0024 import gate.Executable;
0025 import gate.Factory;
0026 import gate.FeatureMap;
0027 import gate.Gate;
0028 import gate.LanguageResource;
0029 import gate.ProcessingResource;
0030 import gate.Resource;
0031 import gate.VisualResource;
0032 import gate.creole.AbstractResource;
0033 import gate.creole.AnnotationSchema;
0034 import gate.creole.ConditionalController;
0035 import gate.creole.ConditionalSerialAnalyserController;
0036 import gate.creole.ResourceData;
0037 import gate.creole.ResourceInstantiationException;
0038 import gate.creole.RunningStrategy;
0039 import gate.creole.SerialAnalyserController;
0040 import gate.creole.ir.IndexedCorpus;
0041 import gate.event.ProgressListener;
0042 import gate.event.StatusListener;
0043 import gate.persist.LuceneDataStoreImpl;
0044 import gate.persist.PersistenceException;
0045 import gate.swing.XJFileChooser;
0046 import gate.swing.XJMenuItem;
0047 import gate.swing.XJPopupMenu;
0048 import gate.util.Err;
0049 import gate.util.ExtensionFileFilter;
0050 import gate.util.GateRuntimeException;
0051 import gate.util.NameBearer;
0052 import gate.util.ant.packager.PackageGappTask;
0053 
0054 import java.awt.Component;
0055 import java.awt.Window;
0056 import java.awt.event.ActionEvent;
0057 import java.io.File;
0058 import java.io.IOException;
0059 import java.net.MalformedURLException;
0060 import java.net.URL;
0061 import java.text.NumberFormat;
0062 import java.util.ArrayList;
0063 import java.util.Collections;
0064 import java.util.EventListener;
0065 import java.util.HashMap;
0066 import java.util.Iterator;
0067 import java.util.List;
0068 import java.util.Map;
0069 import java.util.Set;
0070 import java.util.Vector;
0071 
0072 import javax.swing.AbstractAction;
0073 import javax.swing.Action;
0074 import javax.swing.Icon;
0075 import javax.swing.JComponent;
0076 import javax.swing.JFileChooser;
0077 import javax.swing.JOptionPane;
0078 import javax.swing.JPopupMenu;
0079 import javax.swing.JTabbedPane;
0080 import javax.swing.KeyStroke;
0081 import javax.swing.SwingUtilities;
0082 
0083 import org.apache.log4j.Logger;
0084 import org.apache.tools.ant.BuildEvent;
0085 import org.apache.tools.ant.BuildException;
0086 import org.apache.tools.ant.BuildListener;
0087 import org.apache.tools.ant.Project;
0088 import org.apache.tools.ant.taskdefs.Delete;
0089 import org.apache.tools.ant.taskdefs.Zip;
0090 import org.apache.tools.ant.types.FileSet;
0091 
0092 /**
0093  * Class used to store the GUI information about an open entity
0094  * (resource, controller, datastore). Such information will include icon
0095  * to be used for tree components, popup menu for right click events,
0096  * large and small views, etc.
0097  */
0098 public class NameBearerHandle implements Handle, StatusListener,
0099                              ProgressListener {
0100 
0101   public NameBearerHandle(NameBearer target, Window window) {
0102     this.target = target;
0103     this.window = window;
0104     actionPublishers = new ArrayList<ActionsPublisher>();
0105 
0106     sListenerProxy = new ProxyStatusListener();
0107     String iconName = null;
0108     if(target instanceof Resource) {
0109       rData = Gate.getCreoleRegister().get(target.getClass().getName());
0110       
0111       iconName = (String)((Resource)target).getFeatures().get("gate.gui.icon");
0112 
0113       if(iconName == null || MainFrame.getIcon(iconName== null) {
0114         
0115         if(rData != null) {
0116           iconName = rData.getIcon();
0117           if(iconName == null) {
0118             if(target instanceof Controller)
0119               iconName = "application";
0120             else if(target instanceof LanguageResource)
0121               iconName = "lr";
0122             else if(target instanceof ProcessingResourceiconName = "pr";
0123           }          
0124         else {
0125           iconName = "lr";
0126         }
0127       }
0128       
0129       if (rData != null) {
0130         tooltipText =
0131           "<HTML> <b>" + rData.getComment() "</b><br>(<i>"
0132               + rData.getClassName() "</i>)</HTML>";
0133       }      
0134     }
0135     else if(target instanceof DataStore) {
0136       iconName = ((DataStore)target).getIconName();
0137       tooltipText = ((DataStore)target).getComment();
0138     }    
0139     
0140     this.icon = MainFrame.getIcon(iconName);
0141 
0142     if(target instanceof ActionsPublisher)
0143       actionPublishers.add((ActionsPublisher)target);
0144 
0145     buildStaticPopupItems();
0146 
0147     viewsBuilt = false;
0148   }// public DefaultResourceHandle(FeatureBearer res)
0149 
0150   @Override
0151   public Icon getIcon() {
0152     return icon;
0153   }
0154 
0155   public void setIcon(Icon icon) {
0156     this.icon = icon;
0157   }
0158 
0159   @Override
0160   public String getTitle() {
0161     return target == null null : target.getName();
0162   }
0163 
0164   /**
0165    * Returns <tt>true</tt> if the views have already been built for this
0166    * handle.
0167    
0168    @return <tt>boolean</tt> value.
0169    */
0170   @Override
0171   public boolean viewsBuilt() {
0172     return viewsBuilt;
0173   }
0174 
0175   /**
0176    * Returns a GUI component to be used as a small viewer/editor, e.g.
0177    * below the main tree in the Gate GUI for the selected resource
0178    */
0179   @Override
0180   public JComponent getSmallView() {
0181     if(!viewsBuiltbuildViews();
0182     return smallView;
0183   }
0184 
0185   /**
0186    * Returns the large view for this resource. This view will go into
0187    * the main display area.
0188    */
0189   @Override
0190   public JComponent getLargeView() {
0191     if(!viewsBuiltbuildViews();
0192     return largeView;
0193   }
0194 
0195   @Override
0196   public JPopupMenu getPopup() {
0197     JPopupMenu popup = new XJPopupMenu();
0198     // first add the static items
0199     Iterator<JComponent> itemIter = staticPopupItems.iterator();
0200     while(itemIter.hasNext()) {
0201       JComponent anItem = itemIter.next();
0202       if(anItem == null)
0203         popup.addSeparator();
0204       else popup.add(anItem);
0205     }
0206 
0207     // next add the dynamic list from the target and its editors
0208     Iterator<ActionsPublisher> publishersIter = actionPublishers.iterator();
0209     while(publishersIter.hasNext()) {
0210       ActionsPublisher aPublisher = publishersIter.next();
0211       if(aPublisher.getActions() != null) {
0212         Iterator<Action> actionIter = aPublisher.getActions().iterator();
0213         while(actionIter.hasNext()) {
0214           Action anAction = actionIter.next();
0215           if(anAction == null)
0216             popup.addSeparator();
0217           else {
0218             popup.add(new XJMenuItem(anAction, sListenerProxy));
0219           }
0220         }
0221       }
0222     }
0223     
0224     if (target instanceof Resource) {
0225       Set<String> toolTypes = Gate.getCreoleRegister().getToolTypes();
0226       for(String type : toolTypes) {
0227         List<Resource> instances = Gate.getCreoleRegister()
0228                     .get(type).getInstantiations();
0229         for(Resource res : instances) {
0230           if(res instanceof ResourceHelper) {
0231             Iterator<Action> actionIter = ((ResourceHelper)res).getActions(NameBearerHandle.this).iterator();
0232             while(actionIter.hasNext()) {
0233               Action anAction = actionIter.next();
0234               if(anAction == null)
0235                 popup.addSeparator();
0236               else {
0237                 popup.add(new XJMenuItem(anAction, sListenerProxy));
0238               }
0239             }
0240           }
0241         }
0242       }
0243     }
0244 
0245     return popup;
0246   }
0247 
0248   @Override
0249   public String getTooltipText() {
0250     return tooltipText;
0251   }
0252 
0253   public void setTooltipText(String text) {
0254     this.tooltipText = text;
0255   }
0256 
0257   @Override
0258   public Object getTarget() {
0259     return target;
0260   }
0261 
0262   public Action getCloseAction() {
0263     return new CloseAction();
0264   }
0265 
0266   public Action getCloseRecursivelyAction() {
0267     return new CloseRecursivelyAction();
0268   }
0269   
0270   protected void buildStaticPopupItems() {
0271     // build the static part of the popup
0272     staticPopupItems = new ArrayList<JComponent>();
0273 
0274     if(target instanceof ProcessingResource && !(target instanceof Controller)) {
0275       // actions for PRs (but not Controllers)
0276       staticPopupItems.add(null);
0277       staticPopupItems.add(new XJMenuItem(new ReloadAction(), sListenerProxy));
0278       staticPopupItems.add(new XJMenuItem(new ApplicationWithPRAction(), sListenerProxy));
0279 
0280     }
0281     else if(target instanceof LanguageResource) {
0282       // Language Resources
0283       staticPopupItems.add(null);
0284       if(target instanceof Document) {
0285         staticPopupItems.add(new XJMenuItem(new CreateCorpusForDocAction(),
0286                 sListenerProxy));
0287       }
0288       if(target instanceof gate.TextualDocument) {
0289         staticPopupItems.add(null);
0290         staticPopupItems.add(new DocumentExportMenu(this));
0291       }
0292       else if(target instanceof Corpus) {
0293         corpusFiller = new CorpusFillerComponent();
0294         scfInputDialog = new SingleConcatenatedFileInputDialog();
0295         staticPopupItems.add(new XJMenuItem(new PopulateCorpusAction(),
0296                 sListenerProxy));
0297         staticPopupItems.add(new XJMenuItem(
0298                 new PopulateCorpusFromSingleConcatenatedFileAction(),
0299                 sListenerProxy));
0300         staticPopupItems.add(null);
0301         staticPopupItems.add(new DocumentExportMenu(this));
0302       }
0303       if(((LanguageResource)target).getDataStore() != null) {
0304         // this item can be used only if the resource belongs to a
0305         // datastore
0306         staticPopupItems.add(new XJMenuItem(new SaveAction(), sListenerProxy));
0307       }
0308       if(!(target instanceof AnnotationSchema)) {
0309         staticPopupItems
0310                 .add(new XJMenuItem(new SaveToAction(), sListenerProxy));
0311       }
0312     }
0313 
0314     if(target instanceof Controller) {
0315       // Applications
0316       staticPopupItems.add(null);
0317       
0318       if (target instanceof SerialAnalyserController) {
0319         staticPopupItems.add(new XJMenuItem(new MakeConditionalAction(), sListenerProxy));
0320       }
0321             
0322       staticPopupItems.add(new XJMenuItem(new DumpToFileAction(),
0323               sListenerProxy));
0324       staticPopupItems.add(new XJMenuItem(new ExportApplicationAction(),
0325               sListenerProxy));
0326     }
0327   }
0328 
0329   protected void buildViews() {
0330     viewsBuilt = true;
0331     fireStatusChanged("Building views...");
0332 
0333     // build the large views
0334     List<String> largeViewNames = Gate.getCreoleRegister().getLargeVRsForResource(
0335             target.getClass().getName());
0336     if(largeViewNames != null && !largeViewNames.isEmpty()) {
0337       largeView = new JTabbedPane(JTabbedPane.BOTTOM);
0338       Iterator<String> classNameIter = largeViewNames.iterator();
0339       while(classNameIter.hasNext()) {
0340         try {
0341           String className = classNameIter.next();
0342           ResourceData rData = Gate.getCreoleRegister().get(
0343                   className);
0344           FeatureMap params = Factory.newFeatureMap();
0345           FeatureMap features = Factory.newFeatureMap();
0346           Gate.setHiddenAttribute(features, true);
0347           VisualResource view = (VisualResource)Factory.createResource(
0348                   className, params, features);
0349           try{
0350             view.setTarget(target);
0351           catch (IllegalArgumentException iae) {
0352             // the view cannot display this particular target
0353             Factory.deleteResource(view);
0354             view = null;
0355           }
0356           if(view != null) {
0357             view.setHandle(this);
0358             ((JTabbedPane)largeView).add((Component)view, rData.getName());
0359             // if view provide actions, add it to the list of action
0360             // publishers
0361             if(view instanceof ActionsPublisher)
0362               actionPublishers.add((ActionsPublisher)view);            
0363           }
0364         }
0365         catch(ResourceInstantiationException rie) {
0366           rie.printStackTrace(Err.getPrintWriter());
0367         }
0368       }
0369       // select the first view by default
0370       ((JTabbedPane)largeView).setSelectedIndex(0);
0371     }
0372 
0373     // build the small views
0374     List<String> smallViewNames = Gate.getCreoleRegister().getSmallVRsForResource(
0375             target.getClass().getName());
0376     if(smallViewNames != null && !smallViewNames.isEmpty()) {
0377       smallView = new JTabbedPane(JTabbedPane.BOTTOM);
0378       Iterator<String> classNameIter = smallViewNames.iterator();
0379       while(classNameIter.hasNext()) {
0380         try {
0381           String className = classNameIter.next();
0382           ResourceData rData = Gate.getCreoleRegister().get(
0383                   className);
0384           FeatureMap params = Factory.newFeatureMap();
0385           FeatureMap features = Factory.newFeatureMap();
0386           Gate.setHiddenAttribute(features, true);
0387           VisualResource view = (VisualResource)Factory.createResource(
0388                   className, params, features);
0389           try{
0390             view.setTarget(target);
0391           catch (IllegalArgumentException iae) {
0392             // the view cannot display this particular target
0393             Factory.deleteResource(view);
0394             view = null;
0395           }
0396           if(view != null) {
0397             view.setHandle(this);
0398             ((JTabbedPane)smallView).add((Component)view, rData.getName());
0399             if(view instanceof ActionsPublisher)
0400               actionPublishers.add((ActionsPublisher)view);
0401           }
0402         }
0403         catch(ResourceInstantiationException rie) {
0404           rie.printStackTrace(Err.getPrintWriter());
0405         }
0406       }
0407       ((JTabbedPane)smallView).setSelectedIndex(0);
0408     }
0409     fireStatusChanged("Views built!");
0410 
0411     // Add the CTRL +F4 key & action combination to the resource
0412     JComponent largeView = this.getLargeView();
0413     if(largeView != null) {
0414       largeView.getActionMap().put("Close resource"new CloseAction());
0415       if(target instanceof Controller) {
0416         largeView.getActionMap().put("Close recursively",
0417                 new CloseRecursivelyAction());
0418       }
0419       /*if(target instanceof gate.TextualDocument) {
0420         largeView.getActionMap().put("Save As XML", new SaveAsXmlAction());
0421       }// End if*/
0422     }// End if
0423   }// protected void buildViews
0424 
0425   @Override
0426   public String toString() {
0427     return getTitle();
0428   }
0429 
0430   @SuppressWarnings("unchecked")
0431   public synchronized void removeProgressListener(ProgressListener l) {
0432     if(progressListeners != null && progressListeners.contains(l)) {
0433       Vector<ProgressListener> v = (Vector<ProgressListener>)progressListeners
0434               .clone();
0435       v.removeElement(l);
0436       progressListeners = v;
0437     }
0438   }// public synchronized void removeProgressListener(ProgressListener
0439 
0440   // l)
0441 
0442   @SuppressWarnings("unchecked")
0443   public synchronized void addProgressListener(ProgressListener l) {
0444     Vector<ProgressListener> v = progressListeners == null
0445             new Vector<ProgressListener>(2)
0446             (Vector<ProgressListener>)progressListeners.clone();
0447     if(!v.contains(l)) {
0448       v.addElement(l);
0449       progressListeners = v;
0450     }
0451   }// public synchronized void addProgressListener(ProgressListener l)
0452 
0453   String tooltipText;
0454 
0455   NameBearer target;
0456 
0457   /**
0458    * Stores all the action providers for this resource. They will be
0459    * questioned when the getPopup() method is called.
0460    */
0461   protected List<ActionsPublisher> actionPublishers;
0462 
0463   /**
0464    * A list of menu items that constitute the static part of the popup.
0465    * Null values are used for separators.
0466    */
0467   protected List<JComponent> staticPopupItems;
0468 
0469   /**
0470    * The top level GUI component this handle belongs to.
0471    */
0472   Window window;
0473 
0474   ResourceData rData;
0475 
0476   Icon icon;
0477 
0478   JComponent smallView;
0479 
0480   JComponent largeView;
0481 
0482   protected boolean viewsBuilt = false;
0483 
0484   /**
0485    * Component used to select the options for corpus populating
0486    */
0487   protected CorpusFillerComponent corpusFiller;
0488 
0489   protected SingleConcatenatedFileInputDialog scfInputDialog;
0490 
0491   StatusListener sListenerProxy;
0492 
0493   private transient Vector<ProgressListener> progressListeners;
0494 
0495   private transient Vector<StatusListener> statusListeners;
0496 
0497   class CloseAction extends AbstractAction {
0498     private static final long serialVersionUID = -89664884870963556L;
0499 
0500     public CloseAction() {
0501       super("Close");
0502       putValue(SHORT_DESCRIPTION, "Close this resource");
0503       putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("control F4"));
0504     }
0505 
0506     @Override
0507     public void actionPerformed(ActionEvent e) {
0508       if(target instanceof Controller) {
0509         // empty the controller of all its processing resources
0510         List<ProcessingResource> empty = Collections.emptyList();
0511         ((Controller)target).setPRs(empty);
0512         if(target instanceof ConditionalController) {
0513           List<RunningStrategy> emptyRS = Collections.emptyList();
0514           ((ConditionalController)target).setRunningStrategies(emptyRS);
0515         }
0516       }
0517       if(target instanceof Resource) {
0518         Factory.deleteResource((Resource)target);
0519       }
0520       else if(target instanceof DataStore) {
0521         try {
0522           ((DataStore)target).close();
0523         }
0524         catch(PersistenceException pe) {
0525           JOptionPane.showMessageDialog(largeView != null
0526                   ? largeView
0527                   : smallView, "Error!\n" + pe.toString()"GATE",
0528                   JOptionPane.ERROR_MESSAGE);
0529         }
0530       }
0531       statusListeners.clear();
0532       progressListeners.clear();
0533     }
0534   }
0535 
0536   class CloseRecursivelyAction extends AbstractAction {
0537     private static final long serialVersionUID = 6110698764173549317L;
0538 
0539     public CloseRecursivelyAction() {
0540       super("Close Recursively");
0541       putValue(SHORT_DESCRIPTION,
0542               "Close this application and recursively all contained resources");
0543       putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("shift F4"));
0544     }
0545 
0546     @Override
0547     public void actionPerformed(ActionEvent e) {
0548       Factory.deleteResource((Resource)target);
0549       statusListeners.clear();
0550       progressListeners.clear();
0551     }
0552   }
0553 
0554   class MakeConditionalAction extends AbstractAction {
0555     private static final long serialVersionUID = 1L;
0556 
0557     public MakeConditionalAction() {
0558       super("Make Pipeline Conditional");
0559       putValue(SHORT_DESCRIPTION, "Convert to a Conditional Corpus Pipeline");
0560     }
0561 
0562     @Override
0563     public void actionPerformed(ActionEvent e) {
0564       SerialAnalyserController existingController =
0565           (SerialAnalyserController)target;
0566       try {
0567         ConditionalSerialAnalyserController newController =
0568             (ConditionalSerialAnalyserController)Factory
0569                 .createResource("gate.creole.ConditionalSerialAnalyserController");
0570         newController.getFeatures().putAll(existingController.getFeatures());
0571         newController.setName(existingController.getName());
0572         Iterator<?> it = existingController.getPRs().iterator();
0573         while(it.hasNext()) {
0574           newController.add((ProcessingResource)it.next());
0575         }
0576         List<ProcessingResource> empty = Collections.emptyList();
0577         existingController.setPRs(empty);
0578         Factory.deleteResource(existingController);
0579       catch(Exception ex) {
0580         JOptionPane.showMessageDialog(getLargeView(),
0581             "Error!\n" + ex.toString()"GATE", JOptionPane.ERROR_MESSAGE);
0582         ex.printStackTrace(Err.getPrintWriter());
0583       }
0584     }
0585   }
0586 
0587   class SaveAction extends AbstractAction {
0588     private static final long serialVersionUID = 1L;
0589 
0590     public SaveAction() {
0591       super("Save to its Datastore");
0592       putValue(SHORT_DESCRIPTION, "Save back to its datastore");
0593     }
0594 
0595     @Override
0596     public void actionPerformed(ActionEvent e) {
0597       Runnable runnable = new Runnable() {
0598         @Override
0599         public void run() {
0600           DataStore ds = ((LanguageResource)target).getDataStore();
0601           if(ds != null) {
0602             try {
0603               MainFrame.lockGUI("Saving "
0604                       ((LanguageResource)target).getName());
0605               StatusListener sListener = (StatusListener)gate.Gate
0606                       .getListeners().get("gate.event.StatusListener");
0607               if(sListener != null)
0608                 sListener.statusChanged("Saving: "
0609                         ((LanguageResource)target).getName());
0610               double timeBefore = System.currentTimeMillis();
0611               ((LanguageResource)target).getDataStore().sync(
0612                       (LanguageResource)target);
0613               double timeAfter = System.currentTimeMillis();
0614               if(sListener != null)
0615                 sListener.statusChanged(((LanguageResource)target).getName()
0616                         " saved in "
0617                         + NumberFormat.getInstance().format(
0618                                 (timeAfter - timeBefore1000" seconds");
0619             }
0620             catch(PersistenceException pe) {
0621               MainFrame.unlockGUI();
0622               JOptionPane.showMessageDialog(getLargeView()"Save failed!\n "
0623                       + pe.toString()"GATE", JOptionPane.ERROR_MESSAGE);
0624             }
0625             catch(SecurityException se) {
0626               MainFrame.unlockGUI();
0627               JOptionPane.showMessageDialog(getLargeView()"Save failed!\n "
0628                       + se.toString()"GATE", JOptionPane.ERROR_MESSAGE);
0629             }
0630             finally {
0631               MainFrame.unlockGUI();
0632             }
0633           }
0634           else {
0635             JOptionPane
0636                     .showMessageDialog(
0637                             getLargeView(),
0638                             "This resource has not been loaded from a datastore.\n"
0639                                     "Please use the \"Save to Datastore...\" option.\n",
0640                             "GATE", JOptionPane.ERROR_MESSAGE);
0641 
0642           }
0643         }
0644       };
0645       new Thread(runnable).start();
0646     }// public void actionPerformed(ActionEvent e)
0647   }// class SaveAction
0648 
0649   class DumpToFileAction extends AbstractAction {
0650     private static final long serialVersionUID = 1L;
0651 
0652     public DumpToFileAction() {
0653       super("Save Application State");
0654       putValue(SHORT_DESCRIPTION,
0655               "Saves the data needed to recreate this application");
0656     }
0657 
0658     @Override
0659     public void actionPerformed(ActionEvent ae) {
0660       final XJFileChooser fileChooser = MainFrame.getFileChooser();
0661       ExtensionFileFilter filter = new ExtensionFileFilter(
0662               "GATE Application files""gapp");
0663       fileChooser.addChoosableFileFilter(filter);
0664       fileChooser
0665               .setDialogTitle("Select a file where to save the application "
0666                       ((target instanceof CorpusController && ((CorpusController)target)
0667                               .getCorpus() != null"WITH" "WITHOUT")
0668                       " corpus.");
0669       fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
0670       fileChooser.setResource("application." + target.getName());
0671 
0672       if(fileChooser.showSaveDialog(largeView== JFileChooser.APPROVE_OPTION) {
0673         final File file = fileChooser.getSelectedFile();
0674         Runnable runnable = new Runnable() {
0675           @Override
0676           public void run() {
0677             try {
0678               Map<String, String> locations = fileChooser.getLocations();
0679               // When saving an application state, use paths relative to
0680               // GATE HOME for resources inside GATE HOME and warn about
0681               // them.
0682               gate.util.persistence.PersistenceManager.saveObjectToFile(target,
0683                       file, true, true);
0684               // save also the location of the application as last
0685               // application
0686               locations.put("lastapplication", file.getAbsolutePath());
0687               // add this application to the list of recent applications
0688               String list = locations.get("applications");
0689               if(list == null) {
0690                 list = "";
0691               }
0692               list = list.replaceFirst("\\Q" + target.getName() "\\E(;|$)",
0693                       "");
0694               list = target.getName() ";" + list;
0695               locations.put("applications", list);
0696               fileChooser.setLocations(locations);
0697             }
0698             catch(Exception e) {
0699               JOptionPane.showMessageDialog(getLargeView()"Error!\n"
0700                       + e.toString()"GATE", JOptionPane.ERROR_MESSAGE);
0701               e.printStackTrace(Err.getPrintWriter());
0702             }
0703           }
0704         };
0705         Thread thread = new Thread(runnable);
0706         thread.setPriority(Thread.MIN_PRIORITY);
0707         thread.start();
0708       }
0709     }
0710 
0711   }
0712 
0713   class ExportApplicationAction extends AbstractAction {
0714     private Logger log = Logger.getLogger("gate.gui.ExportApplicationAction");
0715 
0716     private static final long serialVersionUID = 1L;
0717 
0718     public ExportApplicationAction() {
0719       super("Export for GATE Cloud");
0720       putValue(SHORT_DESCRIPTION,
0721               "Saves the resources of this application in a ZIP file");
0722     }
0723 
0724     /**
0725      * Build listener to receive log messages from Ant tasks and forward
0726      * them to the GATE status listener (i.e. the status bar). This
0727      * class implements Executable not because it is itself executed,
0728      * but in order to support interruption. If the user presses the
0729      * stop button in the GUI lock window this object will be
0730      * interrupted, and will throw an exception at the next call to
0731      * messageLogged, which has the effect of interrupting the currently
0732      * executing Ant task.
0733      */
0734     class ExporterBuildListener implements BuildListener, Executable {
0735       private boolean interrupted = false;
0736 
0737       @Override
0738       public boolean isInterrupted() {
0739         return interrupted;
0740       }
0741 
0742       @Override
0743       public void interrupt() {
0744         interrupted = true;
0745       }
0746 
0747       /**
0748        * Set status message appropriately when task completes or fails.
0749        */
0750       @Override
0751       public void taskFinished(BuildEvent buildEvent) {
0752         if(buildEvent.getException() != null) {
0753           statusChanged("Error exporting application");
0754         }
0755         else {
0756           statusChanged("Export complete");
0757         }
0758       }
0759 
0760       /**
0761        * This is called for every log message (of any priority). If the
0762        * current process has been interrupted (the user pressed the stop
0763        * button) then we throw an exception to interrupt the currently
0764        * executing Ant task. Other than that, we simply pass INFO and
0765        * higher messages to the GATE status listener.
0766        */
0767       @Override
0768       public void messageLogged(BuildEvent buildEvent) {
0769         // check for interruption
0770         if(interrupted) {
0771           interrupted = false;
0772           throw new BuildException("Export interrupted");
0773         }
0774         if(buildEvent.getPriority() <= Project.MSG_INFO) {
0775           statusChanged(buildEvent.getMessage());
0776         }
0777         // log the message to log4j for debugging purposes
0778         log.debug(buildEvent.getPriority() ": " + buildEvent.getMessage());
0779       }
0780 
0781       // not interested in these events
0782       @Override
0783       public void buildStarted(BuildEvent buildEvent) {
0784       }
0785 
0786       @Override
0787       public void buildFinished(BuildEvent buildEvent) {
0788       }
0789 
0790       @Override
0791       public void targetStarted(BuildEvent buildEvent) {
0792       }
0793 
0794       @Override
0795       public void targetFinished(BuildEvent buildEvent) {
0796       }
0797 
0798       @Override
0799       public void taskStarted(BuildEvent buildEvent) {
0800       }
0801 
0802       @Override
0803       public void execute() {
0804         // do nothing, only here to match the interface
0805       }
0806     }
0807 
0808     @Override
0809     public void actionPerformed(ActionEvent ae) {
0810       XJFileChooser fileChooser = MainFrame.getFileChooser();
0811       ExtensionFileFilter filter = new ExtensionFileFilter("ZIP file""zip");
0812       fileChooser.addChoosableFileFilter(filter);
0813       fileChooser
0814               .setDialogTitle("Select a file where to save the application "
0815                       ((target instanceof CorpusController && ((CorpusController)target)
0816                               .getCorpus() != null"WITH" "WITHOUT")
0817                       " corpus.");
0818       fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
0819       fileChooser.setResource("application.zip." + target.getName());
0820 
0821       if(fileChooser.showSaveDialog(largeView== JFileChooser.APPROVE_OPTION) {
0822         
0823         //ensure that the ZIP file we produce actually ends .zip
0824         File checkFile = fileChooser.getSelectedFile();        
0825         if (!checkFile.getName().toLowerCase().endsWith(".zip")) {
0826           checkFile = new File(checkFile.getParent(), checkFile.getName()+".zip");
0827         }
0828         
0829         final File targetZipFile = checkFile;
0830         
0831         Runnable runnable = new Runnable() {
0832           @Override
0833           public void run() {
0834             try {
0835               // create and configure Ant Project
0836               Project project = new Project();
0837               ExporterBuildListener buildListener = new ExporterBuildListener();
0838               Gate.setExecutable(buildListener);
0839               project.addBuildListener(buildListener);
0840               project.init();
0841               MainFrame.lockGUI("Exporting application...");
0842 
0843               // create a temporary directory, and save the
0844               // application
0845               // in the normal way to that directory
0846               File temporaryDirectory = File.createTempFile("gapp-packager",
0847                       ""null);
0848               if(!temporaryDirectory.delete() || !temporaryDirectory.mkdir()) {
0849                 throw new IOException(
0850                         "Unable to create temporary directory.\n"
0851                                 + temporaryDirectory.getCanonicalPath());
0852               }
0853               // canonicalise (e.g. on Mac OS X java.io.tmpdir is
0854               // /var/folders/something, but /var is a symlink to
0855               // /private/var,
0856               // and this can confuse the relpaths which are based on
0857               // canonical
0858               // path strings)
0859               temporaryDirectory = temporaryDirectory.getCanonicalFile();
0860               File originalGapp = new File(temporaryDirectory,
0861                       "original.xgapp");
0862               File targetGapp = new File(temporaryDirectory,
0863                       "application.xgapp");
0864 
0865               // save the application in a gapp file
0866               // When exporting to cloud, the gapp file should not
0867               // contain
0868               // any paths relative to GATE HOME, but we still warn
0869               // about
0870               // resources under GATE HOME
0871               gate.util.persistence.PersistenceManager.saveObjectToFile(
0872                       target, originalGapp, false, true);
0873 
0874               // create instance of packager task and configure it
0875               PackageGappTask task = new PackageGappTask();
0876               task.setProject(project);
0877               task.setSrc(originalGapp);
0878               task.setDestFile(targetGapp);
0879               // sensible default settings
0880               task.setCopyPlugins(true);
0881               task.setExpandIvy(true);
0882               task.setCopyResourceDirs(true);
0883               task.setOnUnresolved(PackageGappTask.UnresolvedAction.recover);
0884               task.init();
0885 
0886               // run the task.
0887               task.perform();
0888 
0889               // create zip file using standard Ant zip task
0890               Zip zipTask = new Zip();
0891               zipTask.setProject(project);
0892               zipTask.setDestFile(targetZipFile);
0893               FileSet fs = new FileSet();
0894               fs.setProject(project);
0895               zipTask.addFileset(fs);
0896               fs.setDir(temporaryDirectory);
0897               // exclude the unpackaged gapp file from the zip
0898               fs.setExcludes("original.xgapp");
0899               zipTask.perform();
0900 
0901               // delete temporary files
0902               Delete deleteTask = new Delete();
0903               deleteTask.setProject(project);
0904               deleteTask.setDir(temporaryDirectory);
0905               deleteTask.perform();
0906             }
0907             catch(Exception e) {
0908               MainFrame.unlockGUI();
0909               JOptionPane.showMessageDialog(getLargeView()"Error!\n"
0910                       + e.toString()"GATE", JOptionPane.ERROR_MESSAGE);
0911               e.printStackTrace(Err.getPrintWriter());
0912             }
0913             finally {
0914               MainFrame.unlockGUI();
0915               Gate.setExecutable(null);
0916             }
0917           }
0918         };
0919         Thread thread = new Thread(runnable);
0920         thread.setPriority(Thread.MIN_PRIORITY);
0921         thread.start();
0922       }
0923     }
0924 
0925   }
0926 
0927   class SaveToAction extends AbstractAction {
0928     private static final long serialVersionUID = 1L;
0929 
0930     public SaveToAction() {
0931       super("Save to Datastore...");
0932       putValue(SHORT_DESCRIPTION, "Save this resource to a datastore");
0933     }
0934 
0935     @Override
0936     public void actionPerformed(ActionEvent e) {
0937       
0938           try {
0939             DataStoreRegister dsReg = Gate.getDataStoreRegister();
0940             Map<String, DataStore> dsByName = new HashMap<String, DataStore>();
0941             Iterator<DataStore> dsIter = dsReg.iterator();
0942             while(dsIter.hasNext()) {
0943               DataStore oneDS = dsIter.next();
0944               String name;
0945               if((name = oneDS.getName()) != null) {
0946               }
0947               else {
0948                 name = oneDS.getStorageUrl();
0949                 try {
0950                   URL tempURL = new URL(name);
0951                   name = tempURL.getFile();
0952                 }
0953                 catch(java.net.MalformedURLException ex) {
0954                   throw new GateRuntimeException();
0955                 }
0956               }
0957               dsByName.put(name, oneDS);
0958             }
0959             List<String> dsNames = new ArrayList<String>(dsByName.keySet());
0960             if(dsNames.isEmpty()) {
0961               JOptionPane.showMessageDialog(getLargeView(),
0962                       "There are no open datastores!\n "
0963                               "Please open a datastore first!""GATE",
0964                       JOptionPane.ERROR_MESSAGE);
0965 
0966             }
0967             else {
0968               Object answer = JOptionPane.showInputDialog(getLargeView(),
0969                       "Select the datastore""GATE",
0970                       JOptionPane.QUESTION_MESSAGE, null, dsNames.toArray(),
0971                       dsNames.get(0));
0972               if(answer == nullreturn;
0973               DataStore ds = dsByName.get(answer);
0974               if(ds == null) {
0975                 Err.prln("The datastore does not exists. Saving procedure"
0976                         " has FAILED! This should never happen again!");
0977                 return;
0978               }// End if
0979               DataStore ownDS = ((LanguageResource)target).getDataStore();
0980               if(ds == ownDS) {
0981                 MainFrame.lockGUI("Saving "
0982                         ((LanguageResource)target).getName());
0983 
0984                 StatusListener sListener = (StatusListener)gate.Gate
0985                         .getListeners().get("gate.event.StatusListener");
0986                 if(sListener != null)
0987                   sListener.statusChanged("Saving: "
0988                           ((LanguageResource)target).getName());
0989                 double timeBefore = System.currentTimeMillis();
0990                 ds.sync((LanguageResource)target);
0991                 double timeAfter = System.currentTimeMillis();
0992                 if(sListener != null)
0993                   sListener
0994                           .statusChanged(((LanguageResource)target).getName()
0995                                   " saved in "
0996                                   + NumberFormat.getInstance().format(
0997                                           (timeAfter - timeBefore1000)
0998                                   " seconds");
0999               }
1000               else {
1001                 
1002                 StatusListener sListener = (StatusListener)gate.Gate
1003                         .getListeners().get("gate.event.StatusListener");
1004                 MainFrame.lockGUI("Saving "
1005                         ((LanguageResource)target).getName());
1006 
1007                 if(sListener != null)
1008                   sListener.statusChanged("Saving: "
1009                           ((LanguageResource)target).getName());
1010                 double timeBefore = System.currentTimeMillis();
1011                 LanguageResource lr = ds.adopt((LanguageResource)target);
1012                 ds.sync(lr);
1013                 if(ds instanceof LuceneDataStoreImpl
1014                         && lr instanceof IndexedCorpus) {
1015                   Object persistanceID = lr.getLRPersistenceId();
1016                   String lrType = lr.getClass().getName();
1017                   String lrName = lr.getName();
1018                   Factory.deleteResource(lr);
1019                   FeatureMap params = Factory.newFeatureMap();
1020                   params.put(DataStore.DATASTORE_FEATURE_NAME, ds);
1021                   params.put(DataStore.LR_ID_FEATURE_NAME, persistanceID);
1022                   FeatureMap features = Factory.newFeatureMap();
1023                   try {
1024                     lr = (LanguageResource)Factory.createResource(lrType,
1025                             params, features, lrName);
1026                   }
1027                   catch(ResourceInstantiationException rie) {
1028                     throw new GateRuntimeException("Could not load the corpus",
1029                             rie);
1030                   }
1031                 }
1032 
1033                 double timeAfter = System.currentTimeMillis();
1034                 if(sListener != null)
1035                   sListener
1036                           .statusChanged(((LanguageResource)target).getName()
1037                                   " saved in "
1038                                   + NumberFormat.getInstance().format(
1039                                           (timeAfter - timeBefore1000)
1040                                   " seconds");
1041 
1042                 // check whether the new LR is different from the
1043                 // transient one and
1044                 // if so, unload the transient LR, so the user realises
1045                 // it is no longer valid. Don't do this in the adopt()
1046                 // code itself
1047                 // because the batch code might wish to keep the
1048                 // transient
1049                 // resource for some purpose.
1050                 if(lr != target) {
1051                   Factory.deleteResource((LanguageResource)target);
1052                 }
1053               }
1054             }
1055           }
1056           catch(PersistenceException pe) {
1057             MainFrame.unlockGUI();
1058             JOptionPane.showMessageDialog(getLargeView()"Save failed!\n "
1059                     + pe.toString()"GATE", JOptionPane.ERROR_MESSAGE);
1060           }
1061           finally {
1062             MainFrame.unlockGUI();
1063           }
1064 
1065         
1066     }
1067   }// class SaveToAction extends AbstractAction
1068 
1069   class ApplicationWithPRAction extends AbstractAction {
1070     private static final long serialVersionUID = 1L;
1071 
1072     ApplicationWithPRAction() {
1073       super("Create Application");
1074       putValue(SHORT_DESCRIPTION, "Creates a corpus pipeline application with the given PR");
1075     }
1076 
1077     @Override
1078     public void actionPerformed(ActionEvent e) {
1079       Runnable runnable = new Runnable() {
1080         @Override
1081         public void run() {
1082           if(!(target instanceof ProcessingResource)) return;
1083           if(target instanceof Controllerreturn;
1084 
1085           try {
1086             ConditionalSerialAnalyserController newController =
1087                     (ConditionalSerialAnalyserController)Factory
1088                             .createResource("gate.creole.ConditionalSerialAnalyserController");
1089 
1090             ProcessingResource pr = (ProcessingResourcetarget;
1091             newController.add(pr);
1092 
1093             newController.setName(pr.getName());
1094           catch (ResourceInstantiationException e) {
1095             e.printStackTrace();
1096           catch (ClassCastException e) {
1097             e.printStackTrace();
1098             return// Not a processing resource
1099           }
1100         }// public void run()
1101     };
1102     Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1103             runnable, "DefaultResourceHandle1");
1104     thread.setPriority(Thread.MIN_PRIORITY);
1105     thread.start();
1106   }// public void actionPerformed(ActionEvent e)
1107 
1108 }// class ApplicationWithPRAction
1109 
1110   class ReloadAction extends AbstractAction {
1111     private static final long serialVersionUID = 1L;
1112 
1113     ReloadAction() {
1114       super("Reinitialise");
1115       putValue(SHORT_DESCRIPTION, "Reloads this resource");
1116     }
1117 
1118     @Override
1119     public void actionPerformed(ActionEvent e) {
1120       Runnable runnable = new Runnable() {
1121         @Override
1122         public void run() {
1123           if(!(target instanceof ProcessingResource)) return;
1124           if(target instanceof Controllerreturn;
1125           try {
1126             long startTime = System.currentTimeMillis();
1127             fireStatusChanged("Reinitialising " + target.getName());
1128             Map<String, EventListener> listeners = new HashMap<String, EventListener>();
1129             StatusListener sListener = new StatusListener() {
1130               @Override
1131               public void statusChanged(String text) {
1132                 fireStatusChanged(text);
1133               }
1134             };
1135             listeners.put("gate.event.StatusListener", sListener);
1136 
1137             ProgressListener pListener = new ProgressListener() {
1138               @Override
1139               public void progressChanged(int value) {
1140                 fireProgressChanged(value);
1141               }
1142 
1143               @Override
1144               public void processFinished() {
1145                 fireProcessFinished();
1146               }
1147             };
1148             listeners.put("gate.event.ProgressListener", pListener);
1149 
1150             ProcessingResource res = (ProcessingResource)target;
1151             try {
1152               AbstractResource.setResourceListeners(res, listeners);
1153             }
1154             catch(Exception e) {
1155               e.printStackTrace(Err.getPrintWriter());
1156             }
1157             // show the progress indicator
1158             fireProgressChanged(0);
1159             // the actual reinitialisation
1160             res.reInit();
1161             try {
1162               AbstractResource.removeResourceListeners(res, listeners);
1163             }
1164             catch(Exception e) {
1165               e.printStackTrace(Err.getPrintWriter());
1166             }
1167             long endTime = System.currentTimeMillis();
1168             fireStatusChanged(target.getName()
1169                     " reinitialised in "
1170                     + NumberFormat.getInstance().format(
1171                             (double)(endTime - startTime1000" seconds");
1172             fireProcessFinished();
1173           }
1174           catch(ResourceInstantiationException rie) {
1175             fireStatusChanged("reinitialisation failed");
1176             rie.printStackTrace(Err.getPrintWriter());
1177             fireProcessFinished();
1178             
1179             SwingUtilities.invokeLater(new Runnable() {
1180 
1181               @Override
1182               public void run() {
1183                 JOptionPane.showMessageDialog(getLargeView()"Reload failed!\n "
1184                         "See \"Messages\" tab for details!""GATE",
1185                         JOptionPane.ERROR_MESSAGE);                
1186               }              
1187             });
1188             
1189           }
1190         }// public void run()
1191       };
1192       Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1193               runnable, "DefaultResourceHandle1");
1194       thread.setPriority(Thread.MIN_PRIORITY);
1195       thread.start();
1196     }// public void actionPerformed(ActionEvent e)
1197 
1198   }// class ReloadAction
1199 
1200   class PopulateCorpusAction extends AbstractAction {
1201     private static final long serialVersionUID = 1L;
1202 
1203     PopulateCorpusAction() {
1204       super("Populate");
1205       putValue(SHORT_DESCRIPTION,
1206               "Fills this corpus with documents from a directory");
1207     }
1208 
1209     @Override
1210     public void actionPerformed(ActionEvent e) {
1211       corpusFiller.setExtensions(new ArrayList<String>());
1212       corpusFiller.setEncoding("");
1213       final boolean answer = OkCancelDialog.showDialog(window, corpusFiller,
1214               "Select a directory and allowed extensions");
1215       Runnable runnable = new Runnable() {
1216         @Override
1217         public void run() {
1218           if(answer) {
1219             long startTime = System.currentTimeMillis();
1220             URL url;
1221             try {
1222               url = new URL(corpusFiller.getUrlString());
1223               List<String> extensions = corpusFiller.getExtensions();
1224               ExtensionFileFilter filter;
1225               if(extensions == null || extensions.isEmpty()) {
1226                 filter = null;
1227               }
1228               else {
1229                 filter = new ExtensionFileFilter();
1230                 Iterator<String> extIter = corpusFiller.getExtensions().iterator();
1231                 while(extIter.hasNext()) {
1232                   filter.addExtension(extIter.next());
1233                 }
1234               }
1235               String encoding = corpusFiller.getEncoding();
1236               if(encoding != null && encoding.trim().length() == 0) {
1237                 encoding = null;
1238               }
1239               String mimeType = corpusFiller.getMimeType();
1240               if(mimeType != null && mimeType.trim().length() == 0) {
1241                 mimeType = null;
1242               }
1243               ((Corpus)target).populate(url, filter, encoding, mimeType,
1244                       corpusFiller.isRecurseDirectories());
1245               if(((Corpus)target).getDataStore() != null) {
1246                 ((LanguageResource)target).getDataStore().sync(
1247                         (LanguageResource)target);
1248               }
1249 
1250               long endTime = System.currentTimeMillis();
1251               fireStatusChanged("Corpus populated in "
1252                       + NumberFormat.getInstance().format(
1253                               (double)(endTime - startTime1000)
1254                       " seconds!");
1255 
1256             }
1257             catch(final MalformedURLException mue) {
1258               SwingUtilities.invokeLater(new Runnable() {
1259                 
1260                 @Override
1261                 public void run() {
1262                   JOptionPane.showMessageDialog(MainFrame.getInstance()"Invalid URL!\n "
1263                       "See \"Messages\" tab for details!""GATE",
1264                       JOptionPane.ERROR_MESSAGE);
1265                   mue.printStackTrace(Err.getPrintWriter());                  
1266                 }
1267               });              
1268             }
1269             catch(final IOException ioe) {
1270               SwingUtilities.invokeLater(new Runnable() {
1271                 
1272                 @Override
1273                 public void run() {
1274                   JOptionPane.showMessageDialog(MainFrame.getInstance()"I/O error!\n "
1275                       "See \"Messages\" tab for details!""GATE",
1276                       JOptionPane.ERROR_MESSAGE);
1277                   ioe.printStackTrace(Err.getPrintWriter());                  
1278                 }
1279               });              
1280             }
1281             catch(final ResourceInstantiationException rie) {
1282               SwingUtilities.invokeLater(new Runnable() {
1283                 
1284                 @Override
1285                 public void run() {
1286                   JOptionPane.showMessageDialog(MainFrame.getInstance(),
1287                       "Could not create document!\n "
1288                               "See \"Messages\" tab for details!""GATE",
1289                       JOptionPane.ERROR_MESSAGE);
1290                   rie.printStackTrace(Err.getPrintWriter());                  
1291                 }
1292               });              
1293             }
1294             catch(final PersistenceException pe) {
1295               SwingUtilities.invokeLater(new Runnable() {
1296                 
1297                 @Override
1298                 public void run() {
1299                   JOptionPane.showMessageDialog(MainFrame.getInstance(),
1300                       "Corpus couldn't be synchronized!\n "
1301                               "See \"Messages\" tab for details!""GATE",
1302                       JOptionPane.ERROR_MESSAGE);
1303                   pe.printStackTrace(Err.getPrintWriter());
1304                   
1305                 }
1306               });              
1307             }
1308             catch(final SecurityException pe) {
1309               SwingUtilities.invokeLater(new Runnable() {
1310                 
1311                 @Override
1312                 public void run() {
1313                   JOptionPane.showMessageDialog(MainFrame.getInstance(),
1314                       "Corpus couldn't be synchronized!\n "
1315                               "See \"Messages\" tab for details!""GATE",
1316                       JOptionPane.ERROR_MESSAGE);
1317                   pe.printStackTrace(Err.getPrintWriter());                  
1318                 }
1319               });              
1320             }
1321           }
1322         }
1323       };
1324       Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1325               runnable, "PopulateCorpusAction");
1326       thread.setPriority(Thread.MIN_PRIORITY);
1327       thread.start();
1328     }
1329   }
1330 
1331   class PopulateCorpusFromSingleConcatenatedFileAction extends AbstractAction {
1332     private static final long serialVersionUID = 2342321851865139492L;
1333 
1334     PopulateCorpusFromSingleConcatenatedFileAction() {
1335       super("Populate from Single Concatenated File");
1336       putValue(SHORT_DESCRIPTION,
1337               "Fills this corpus by extracting multiple documents from a single file");
1338     }
1339 
1340     @Override
1341     public void actionPerformed(ActionEvent e) {
1342       scfInputDialog.reset();
1343       final boolean answer = OkCancelDialog.showDialog(window, scfInputDialog,
1344               "Populate from Single Concatenated File");
1345       Runnable runnable = new Runnable() {
1346         @Override
1347         public void run() {
1348           if(answer) {
1349 
1350             String message = null;
1351             // lets first check the parameters
1352             if(scfInputDialog.getUrlString().trim().length() == 0) {
1353               message = "file URL cannot be empty";
1354             }
1355             else if(scfInputDialog.getDocumentRootElement().trim().length() == 0) {
1356               message = "document root element cannot be empty";
1357             }
1358 
1359             // if something wrong say it to the user
1360             if(message != null) {
1361               JOptionPane.showMessageDialog(getLargeView(), message, "GATE",
1362                       JOptionPane.ERROR_MESSAGE);
1363               return;
1364             }
1365 
1366             // all parameters fine, proceed 
1367             long startTime = System.currentTimeMillis();
1368             URL url = null;
1369             try {
1370               url = new URL(scfInputDialog.getUrlString());
1371               ((Corpus)target).populate(url, scfInputDialog
1372                       .getDocumentRootElement(), scfInputDialog.getEncoding(),
1373                       scfInputDialog.getNumOfDocumentsToFetch(), scfInputDialog
1374                               .getDocumentNamePrefix(), scfInputDialog
1375                               .getDocumentMimeType(), scfInputDialog.includeRootElement());
1376               if(((Corpus)target).getDataStore() != null) {
1377                 ((LanguageResource)target).getDataStore().sync(
1378                         (LanguageResource)target);
1379               }
1380 
1381               long endTime = System.currentTimeMillis();
1382               fireStatusChanged("Corpus populated in "
1383                       + NumberFormat.getInstance().format(
1384                               (double)(endTime - startTime1000)
1385                       " seconds!");
1386 
1387             }
1388             catch(MalformedURLException mue) {
1389               JOptionPane.showMessageDialog(getLargeView()"Invalid URL!\n "
1390                       "See \"Messages\" tab for details!""GATE",
1391                       JOptionPane.ERROR_MESSAGE);
1392               mue.printStackTrace(Err.getPrintWriter());
1393             }
1394             catch(IOException ioe) {
1395               JOptionPane.showMessageDialog(getLargeView()"I/O error!\n "
1396                       "See \"Messages\" tab for details!""GATE",
1397                       JOptionPane.ERROR_MESSAGE);
1398               ioe.printStackTrace(Err.getPrintWriter());
1399             }
1400             catch(ResourceInstantiationException rie) {
1401               JOptionPane.showMessageDialog(getLargeView(),
1402                       "Could not create document!\n "
1403                               "See \"Messages\" tab for details!""GATE",
1404                       JOptionPane.ERROR_MESSAGE);
1405               rie.printStackTrace(Err.getPrintWriter());
1406             }
1407             catch(PersistenceException pe) {
1408               JOptionPane.showMessageDialog(getLargeView(),
1409                       "Corpus couldn't be synchronized!\n "
1410                               "See \"Messages\" tab for details!""GATE",
1411                       JOptionPane.ERROR_MESSAGE);
1412               pe.printStackTrace(Err.getPrintWriter());
1413             }
1414             catch(SecurityException pe) {
1415               JOptionPane.showMessageDialog(getLargeView(),
1416                       "Corpus couldn't be synchronized!\n "
1417                               "See \"Messages\" tab for details!""GATE",
1418                       JOptionPane.ERROR_MESSAGE);
1419               pe.printStackTrace(Err.getPrintWriter());
1420             }
1421           }
1422         }
1423       };
1424       Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
1425               runnable, "PopulateCorpusFromSingleConcatenatedFileAction");
1426       thread.setPriority(Thread.MIN_PRIORITY);
1427       thread.start();
1428     }
1429   }
1430 
1431   
1432 
1433   class CreateCorpusForDocAction extends AbstractAction {
1434     /**
1435      
1436      */
1437     private static final long serialVersionUID = -3698451324578510407L;
1438 
1439     public CreateCorpusForDocAction() {
1440       super("New Corpus with this Document");
1441     }
1442 
1443     @Override
1444     public void actionPerformed(ActionEvent e) {
1445       try {
1446         Corpus corpus = Factory.newCorpus("Corpus for " + target.getName());
1447         corpus.add((Document)target);
1448       }
1449       catch(ResourceInstantiationException rie) {
1450         Err.println("Exception creating corpus");
1451         rie.printStackTrace(Err.getPrintWriter());
1452       }
1453     }
1454   }
1455 
1456   @Override
1457   public void removeViews() {
1458     // delete all the VRs that were created
1459     if(largeView != null) {
1460       if(largeView instanceof VisualResource) {
1461         // we only had a view so no tabbed pane was used
1462         if(largeView instanceof ActionsPublisher)
1463           actionPublishers.remove(largeView);
1464         Factory.deleteResource((VisualResource)largeView);
1465       }
1466       else {
1467         Component vrs[] ((JTabbedPane)largeView).getComponents();
1468         for(int i = 0; i < vrs.length; i++) {
1469           if(vrs[iinstanceof VisualResource) {
1470             if(vrs[iinstanceof ActionsPublisher)
1471               actionPublishers.remove(vrs[i]);
1472             Factory.deleteResource((VisualResource)vrs[i]);
1473           }
1474         }
1475       }
1476       largeView = null;
1477     }
1478 
1479     if(smallView != null) {
1480       if(smallView instanceof VisualResource) {
1481         // we only had a view so no tabbed pane was used
1482         if(smallView instanceof ActionsPublisher)
1483           actionPublishers.remove(smallView);
1484         Factory.deleteResource((VisualResource)smallView);
1485       }
1486       else {
1487         Component vrs[] ((JTabbedPane)smallView).getComponents();
1488         for(int i = 0; i < vrs.length; i++) {
1489           if(vrs[iinstanceof VisualResource) {
1490             if(vrs[iinstanceof ActionsPublisher)
1491               actionPublishers.remove(vrs[i]);
1492             Factory.deleteResource((VisualResource)vrs[i]);
1493           }
1494         }
1495       }
1496       smallView = null;
1497     }
1498     viewsBuilt = false;
1499   }
1500 
1501   /**
1502    * Releases the memory, removes the listeners, cleans up. Will get
1503    * called when the target resource is unloaded from the system
1504    */
1505   @Override
1506   public void cleanup() {
1507     removeViews();
1508     target = null;
1509   }
1510 
1511   class ProxyStatusListener implements StatusListener {
1512     @Override
1513     public void statusChanged(String text) {
1514       fireStatusChanged(text);
1515     }
1516   }
1517 
1518   public void fireProgressChanged(int e) {
1519     if(progressListeners != null) {
1520       Vector<ProgressListener> listeners = progressListeners;
1521       int count = listeners.size();
1522       for(int i = 0; i < count; i++) {
1523         listeners.elementAt(i).progressChanged(e);
1524       }
1525     }
1526   }// protected void fireProgressChanged(int e)
1527 
1528   public void fireProcessFinished() {
1529     if(progressListeners != null) {
1530       Vector<ProgressListener> listeners = progressListeners;
1531       int count = listeners.size();
1532       for(int i = 0; i < count; i++) {
1533         listeners.elementAt(i).processFinished();
1534       }
1535     }
1536   }// protected void fireProcessFinished()
1537 
1538   @SuppressWarnings("unchecked")
1539   public synchronized void removeStatusListener(StatusListener l) {
1540     if(statusListeners != null && statusListeners.contains(l)) {
1541       Vector<StatusListener> v = (Vector<StatusListener>)statusListeners
1542               .clone();
1543       v.removeElement(l);
1544       statusListeners = v;
1545     }
1546   }// public synchronized void removeStatusListener(StatusListener l)
1547 
1548   @SuppressWarnings("unchecked")
1549   public synchronized void addStatusListener(StatusListener l) {
1550     Vector<StatusListener> v = statusListeners == null
1551             new Vector<StatusListener>(2)
1552             (Vector<StatusListener>)statusListeners.clone();
1553     if(!v.contains(l)) {
1554       v.addElement(l);
1555       statusListeners = v;
1556     }
1557   }// public synchronized void addStatusListener(StatusListener l)
1558 
1559   public void fireStatusChanged(String e) {
1560     if(statusListeners != null) {
1561       Vector<StatusListener> listeners = statusListeners;
1562       int count = listeners.size();
1563       for(int i = 0; i < count; i++) {
1564         listeners.elementAt(i).statusChanged(e);
1565       }
1566     }
1567   }
1568 
1569   @Override
1570   public void statusChanged(String e) {
1571     fireStatusChanged(e);
1572   }
1573 
1574   @Override
1575   public void progressChanged(int e) {
1576     fireProgressChanged(e);
1577   }
1578 
1579   @Override
1580   public void processFinished() {
1581     fireProcessFinished();
1582   }
1583 
1584   @Override
1585   public Window getWindow() {
1586     return window;
1587   }
1588 }// class DefaultResourceHandle