View Javadoc
1   package com.github.celldynamics.quimp.plugin;
2   
3   import java.io.File;
4   
5   import com.github.celldynamics.quimp.QParams;
6   import com.github.celldynamics.quimp.QuimpException;
7   import com.github.celldynamics.quimp.QuimpException.MessageSinkTypes;
8   import com.github.celldynamics.quimp.filesystem.FileExtensions;
9   import com.github.celldynamics.quimp.filesystem.QconfLoader;
10  
11  /**
12   * Template of plugin focused at processing QCONF/paQP files.
13   * 
14   * <p>This type of plugin opens QCONF/paQP file immediately after run, process it and returns
15   * results. User interface is not directly supported here unless you override {@link #executer()}.
16   * For UI plugins use {@link AbstractPluginTemplate}. If {@link AbstractPluginOptions#paramFile} is
17   * not null and not empty, it will be used, otherwise template displays file dialog.
18   * 
19   * <p>Following workflow specified in {@link AbstractPluginBase}, this implementation calls
20   * {@link #loadFile(String)} from {@link #executer()}. If default constructor
21   * {@link #AbstractPluginQconf(String, AbstractPluginOptions, String)} is called from constructor in
22   * implementing class and any additional configuration is needed before plugin executes (that
23   * typically should go after calling super (this) constructor) that configuration can be added in
24   * overridden {@link #loadFile(String)} method before calling super#loadFile.
25   * 
26   * @author p.baniukiewicz
27   * @see AbstractPluginBase
28   */
29  public abstract class AbstractPluginQconf extends AbstractPluginBase {
30  
31    /**
32     * Loaded configuration file.
33     */
34    protected QconfLoader qconfLoader; // main object representing loaded configuration file
35  
36    /**
37     * Extension of file plugin asks for after execution in IJ mode.
38     */
39    protected String fileExt = FileExtensions.newConfigFileExt;
40  
41    /**
42     * This default constructor must be overridden in concrete class. It is called by IJ when plugin
43     * instance is created. A concrete instance of {@link AbstractPluginOptions} class should be
44     * created there and then passed to {@link #AbstractPluginQconf(AbstractPluginOptions,String)}.
45     */
46    protected AbstractPluginQconf() {
47      super();
48    }
49  
50    /**
51     * Default constructor.
52     * 
53     * <p>Set api call to false and assign provided options to object.
54     * 
55     * @param options Reference to plugin configuration container.
56     * @param pluginName name of the plugin that will be displayed in Macro Recorder
57     */
58    protected AbstractPluginQconf(AbstractPluginOptions options, String pluginName) {
59      super(options, pluginName);
60    }
61  
62    /**
63     * Constructor that allows to provide own parameters.
64     * 
65     * <p>Intended to run from API. Set {@link #apiCall} to true and {@link #errorSink} to
66     * {@link MessageSinkTypes#CONSOLE}.
67     * {@link AbstractPluginOptions} is initialised from specified string and assigned to this
68     * instance.
69     * 
70     * <p>It loads QCONF.paQP file specified in {@link AbstractPluginOptions#paramFile}. If file is
71     * not specified it shows load file window.
72     * 
73     * @param argString parameters string like that passed in macro. If it is empty string or null
74     *        constructor exits before deserialisation.
75     * @param options Reference to plugin configuration container.
76     * @param pluginName name of the plugin that will be displayed in Macro Recorder
77     * @throws QuimpPluginException on any error in plugin execution.
78     * @see #loadFile(String)
79     */
80    protected AbstractPluginQconf(String argString, AbstractPluginOptions options, String pluginName)
81            throws QuimpPluginException {
82      super(argString, options, pluginName);
83      try {
84        loadFile(this.options.paramFile); // load configuration file and verify it
85      } catch (QuimpPluginException qe) {
86        throw qe;
87      } catch (Exception qe) {
88        throw new QuimpPluginException(qe);
89      }
90    }
91  
92    /*
93     * (non-Javadoc)
94     * 
95     * @see com.github.celldynamics.quimp.plugin.AbstractPluginBase#executer()
96     */
97    @Override
98    protected void executer() throws QuimpException {
99      loadFile(options.paramFile);
100     // FIXME It should call either runFromPaqp or validate();runFromQconf(); here
101   }
102 
103   /**
104    * Load specified configuration file and execute plugin depending on file type.
105    * 
106    * <p>This method executes only once, if {@link #getQconfLoader()} is null. Should be overridden
107    * if there is any additional configuration needed before execution.
108    * 
109    * <p>If file is QCONF then {@link #runFromQconf()} is executed, if it is paQP then
110    * {@link #runFromPaqp()}. Validate loaded QCONF file by {@link #validate()}.
111    * 
112    * @param paramFile path to the file. It can be null or empty string to allow user pick the file.
113    * 
114    * @throws QuimpException When configuration file could not be loaded or it does not meet
115    *         requirements.
116    * @see #validate()
117    */
118   protected void loadFile(String paramFile) throws QuimpException {
119     File pf;
120     if (paramFile == null || paramFile.isEmpty()) {
121       pf = null;
122     } else {
123       pf = new File(paramFile);
124     }
125     if (qconfLoader == null || qconfLoader.getQp() == null) {
126       // load new file
127       qconfLoader = new QconfLoader(pf, fileExt);
128       if (qconfLoader.getQp() == null) {
129         // not loaded (cancelled)
130         throw new QuimpPluginException("Cancelled", MessageSinkTypes.MESSAGE, true);
131       }
132       if (qconfLoader.isFileLoaded() == QParams.QUIMP_11) { // old path
133         runFromPaqp();
134       } else if (qconfLoader.isFileLoaded() == QParams.NEW_QUIMP) { // new path
135         validate();
136         runFromQconf();
137       } else {
138         qconfLoader = null; // failed load or checking
139         throw new QuimpPluginException(
140                 "QconfLoader returned unsupported version of QuimP or error.");
141       }
142     }
143   }
144 
145   /**
146    * Override this method to pass your own validation of QCONF structure.
147    * 
148    * @throws QuimpException if file can not be validated.
149    */
150   protected void validate() throws QuimpException {
151     qconfLoader.getBOA();
152   }
153 
154   /**
155    * Return {@link QconfLoader} object.
156    * 
157    * @return the qconfLoader
158    */
159   public QconfLoader getQconfLoader() {
160     return qconfLoader;
161   }
162 
163   /**
164    * Remove loaded QCONF file and allows to load new one.
165    * 
166    * <p>Note that file can be processed once, therefore next call of {@link #run(String)} wil do
167    * nothing unless {@link #unload()} is used.
168    * 
169    * @see AbstractPluginQconf#loadFile(String)
170    */
171   public final void unload() {
172     qconfLoader = null;
173   }
174 
175   /**
176    * Called if loaded file is QCONF.
177    * 
178    * <p>This method expects that {@link #qconfLoader} is already set up ({@link #run(String)}. In
179    * macro or IJ mode exceptions will be handled in place and displayed as IJERROR or GUI message.
180    * For API call (only if initialised by
181    * {@link #AbstractPluginQconf(String, AbstractPluginOptions, String)})
182    * exceptions are re-thrown.
183    * 
184    * @throws QuimpException on error
185    */
186   protected abstract void runFromQconf() throws QuimpException;
187 
188   /**
189    * Called if loaded file is paQP.
190    * 
191    * <p>This method expects that {@link #qconfLoader} is already set up ({@link #run(String)}. In
192    * macro or IJ mode exceptions will be handled in place and displayed as IJERROR or GUI message.
193    * For API call (only if initialised by
194    * {@link #AbstractPluginQconf(String, AbstractPluginOptions, String)})
195    * exceptions are re-thrown.
196    * 
197    * @throws QuimpException on error
198    */
199   protected abstract void runFromPaqp() throws QuimpException;
200 
201 }