plugins/base2/net.sf.basedb.examples/trunk/src/net/sf/basedb/exampleplugins/ExampleAnalyzer.java

Code
Comments
Other
Rev Date Author Line
647 11 Apr 08 nicklas 1 /*
647 11 Apr 08 nicklas 2   Copyright (C) 2006, 2007 Nicklas Nordborg
647 11 Apr 08 nicklas 3
647 11 Apr 08 nicklas 4   This file is part of BASE - BioArray Software Environment.
647 11 Apr 08 nicklas 5   Available at http://base.thep.lu.se/
647 11 Apr 08 nicklas 6
647 11 Apr 08 nicklas 7   BASE is free software; you can redistribute it and/or
647 11 Apr 08 nicklas 8   modify it under the terms of the GNU General Public License
647 11 Apr 08 nicklas 9   as published by the Free Software Foundation; either version 2
647 11 Apr 08 nicklas 10   of the License, or (at your option) any later version.
647 11 Apr 08 nicklas 11
647 11 Apr 08 nicklas 12   BASE is distributed in the hope that it will be useful,
647 11 Apr 08 nicklas 13   but WITHOUT ANY WARRANTY; without even the implied warranty of
647 11 Apr 08 nicklas 14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
647 11 Apr 08 nicklas 15   GNU General Public License for more details.
647 11 Apr 08 nicklas 16
647 11 Apr 08 nicklas 17   You should have received a copy of the GNU General Public License
647 11 Apr 08 nicklas 18   along with this program; if not, write to the Free Software
647 11 Apr 08 nicklas 19   Foundation, Inc., 59 Temple Place - Suite 330,
647 11 Apr 08 nicklas 20   Boston, MA  02111-1307, USA.
647 11 Apr 08 nicklas 21 */
647 11 Apr 08 nicklas 22 package net.sf.basedb.exampleplugins;
647 11 Apr 08 nicklas 23
647 11 Apr 08 nicklas 24 import net.sf.basedb.core.BaseException;
647 11 Apr 08 nicklas 25 import net.sf.basedb.core.BioAssaySet;
647 11 Apr 08 nicklas 26 import net.sf.basedb.core.DbControl;
647 11 Apr 08 nicklas 27 import net.sf.basedb.core.DynamicSpotQuery;
647 11 Apr 08 nicklas 28 import net.sf.basedb.core.Item;
647 11 Apr 08 nicklas 29 import net.sf.basedb.core.Job;
647 11 Apr 08 nicklas 30 import net.sf.basedb.core.FloatParameterType;
647 11 Apr 08 nicklas 31 import net.sf.basedb.core.PluginParameter;
647 11 Apr 08 nicklas 32 import net.sf.basedb.core.ProgressReporter;
647 11 Apr 08 nicklas 33 import net.sf.basedb.core.RequestInformation;
647 11 Apr 08 nicklas 34 import net.sf.basedb.core.SpotBatcher;
647 11 Apr 08 nicklas 35 import net.sf.basedb.core.Transformation;
647 11 Apr 08 nicklas 36 import net.sf.basedb.core.VirtualColumn;
647 11 Apr 08 nicklas 37
647 11 Apr 08 nicklas 38 import net.sf.basedb.core.query.Dynamic;
647 11 Apr 08 nicklas 39 import net.sf.basedb.core.query.Expression;
647 11 Apr 08 nicklas 40 import net.sf.basedb.core.query.Expressions;
647 11 Apr 08 nicklas 41 import net.sf.basedb.core.query.Restrictions;
647 11 Apr 08 nicklas 42 import net.sf.basedb.core.query.Selects;
647 11 Apr 08 nicklas 43 import net.sf.basedb.core.signal.SignalHandler;
647 11 Apr 08 nicklas 44 import net.sf.basedb.core.signal.SignalTarget;
647 11 Apr 08 nicklas 45 import net.sf.basedb.core.signal.ThreadSignalHandler;
647 11 Apr 08 nicklas 46
647 11 Apr 08 nicklas 47 import net.sf.basedb.core.plugin.About;
647 11 Apr 08 nicklas 48 import net.sf.basedb.core.plugin.AboutImpl;
1292 24 Feb 11 nicklas 49 import net.sf.basedb.core.plugin.AbstractAnalysisPlugin;
647 11 Apr 08 nicklas 50 import net.sf.basedb.core.plugin.InteractivePlugin;
647 11 Apr 08 nicklas 51 import net.sf.basedb.core.plugin.GuiContext;
647 11 Apr 08 nicklas 52 import net.sf.basedb.core.plugin.Request;
647 11 Apr 08 nicklas 53 import net.sf.basedb.core.plugin.Response;
647 11 Apr 08 nicklas 54
647 11 Apr 08 nicklas 55 import java.util.ArrayList;
647 11 Apr 08 nicklas 56 import java.util.Arrays;
647 11 Apr 08 nicklas 57 import java.util.Collections;
647 11 Apr 08 nicklas 58 import java.util.List;
647 11 Apr 08 nicklas 59 import java.util.Set;
647 11 Apr 08 nicklas 60
647 11 Apr 08 nicklas 61
647 11 Apr 08 nicklas 62 /**
647 11 Apr 08 nicklas 63   An example analysis plugin that creates a new bioassay set 
647 11 Apr 08 nicklas 64   by multiplying each intensitity value with the same factor, filtering
647 11 Apr 08 nicklas 65   out intensities below a cutoff value.
647 11 Apr 08 nicklas 66   
647 11 Apr 08 nicklas 67   @base.modified $Date$
647 11 Apr 08 nicklas 68   @author Nicklas
647 11 Apr 08 nicklas 69   @version 2.0
647 11 Apr 08 nicklas 70 */
647 11 Apr 08 nicklas 71 public class ExampleAnalyzer 
1292 24 Feb 11 nicklas 72   extends AbstractAnalysisPlugin
647 11 Apr 08 nicklas 73   implements InteractivePlugin, SignalTarget
647 11 Apr 08 nicklas 74 {
647 11 Apr 08 nicklas 75
647 11 Apr 08 nicklas 76   private static final About about = 
647 11 Apr 08 nicklas 77     new AboutImpl
647 11 Apr 08 nicklas 78     (
647 11 Apr 08 nicklas 79       "Copy spot intensity",
647 11 Apr 08 nicklas 80       "An example analysis plugin that creates a new bioassay set " + 
647 11 Apr 08 nicklas 81       "by multiplying each intensitity value with the same factor, filtering " +
647 11 Apr 08 nicklas 82       "out intensities below a cutoff value.",
1292 24 Feb 11 nicklas 83       "2.17",
647 11 Apr 08 nicklas 84       "2006, Base 2 development team",
647 11 Apr 08 nicklas 85       null,
647 11 Apr 08 nicklas 86       null,
647 11 Apr 08 nicklas 87       "http://base.thep.lu.se"
647 11 Apr 08 nicklas 88     );
647 11 Apr 08 nicklas 89
647 11 Apr 08 nicklas 90   private static final Set<GuiContext> guiContexts = Collections.singleton(
647 11 Apr 08 nicklas 91     new GuiContext(Item.BIOASSAYSET, GuiContext.Type.ITEM)
647 11 Apr 08 nicklas 92   );
647 11 Apr 08 nicklas 93   
647 11 Apr 08 nicklas 94   // Job configuration is created by getConfigureJob()
647 11 Apr 08 nicklas 95   private RequestInformation configureJob;
647 11 Apr 08 nicklas 96   
647 11 Apr 08 nicklas 97   // Intensities below this value will be filtered out
647 11 Apr 08 nicklas 98   private PluginParameter<Float> cutoffParameter;
647 11 Apr 08 nicklas 99   
647 11 Apr 08 nicklas 100   // Multiply each intensity with this value
647 11 Apr 08 nicklas 101   private PluginParameter<Float> factorParameter;
647 11 Apr 08 nicklas 102   
647 11 Apr 08 nicklas 103   // So we can react to ABORT requests
647 11 Apr 08 nicklas 104   private ThreadSignalHandler signalHandler;
647 11 Apr 08 nicklas 105   
647 11 Apr 08 nicklas 106   /**
647 11 Apr 08 nicklas 107     Create a new plugin instance.
647 11 Apr 08 nicklas 108   */
647 11 Apr 08 nicklas 109   public ExampleAnalyzer()
647 11 Apr 08 nicklas 110   {}
647 11 Apr 08 nicklas 111   
647 11 Apr 08 nicklas 112   /*
647 11 Apr 08 nicklas 113     From the Plugin interface
647 11 Apr 08 nicklas 114     -------------------------------------------
647 11 Apr 08 nicklas 115   */
1292 24 Feb 11 nicklas 116   @Override
647 11 Apr 08 nicklas 117   public About getAbout()
647 11 Apr 08 nicklas 118   {
647 11 Apr 08 nicklas 119     return about;
647 11 Apr 08 nicklas 120   }
1292 24 Feb 11 nicklas 121   @Override
647 11 Apr 08 nicklas 122   public boolean supportsConfigurations()
647 11 Apr 08 nicklas 123   {
647 11 Apr 08 nicklas 124     return false;
647 11 Apr 08 nicklas 125   }
1292 24 Feb 11 nicklas 126   @Override
647 11 Apr 08 nicklas 127   public boolean requiresConfiguration()
647 11 Apr 08 nicklas 128   {
647 11 Apr 08 nicklas 129     return false;
647 11 Apr 08 nicklas 130   }
1292 24 Feb 11 nicklas 131   @Override
647 11 Apr 08 nicklas 132   public void run(Request request, Response response, ProgressReporter progress)
647 11 Apr 08 nicklas 133   {
647 11 Apr 08 nicklas 134     // Ensure that the ABORT signal gets sent to this thread
647 11 Apr 08 nicklas 135     if (signalHandler != null) signalHandler.setWorkerThread(null);
647 11 Apr 08 nicklas 136
647 11 Apr 08 nicklas 137     // Open a connection to the database
647 11 Apr 08 nicklas 138     // sc is set by init() method
647 11 Apr 08 nicklas 139     DbControl dc = sc.newDbControl();
647 11 Apr 08 nicklas 140     try
647 11 Apr 08 nicklas 141     {
647 11 Apr 08 nicklas 142       // Get job parameters
647 11 Apr 08 nicklas 143       float cutoff = (Float)job.getValue("cutoff");
647 11 Apr 08 nicklas 144       float factor = (Float)job.getValue("factor");
1292 24 Feb 11 nicklas 145       BioAssaySet source = getSourceBioAssaySet(dc);
647 11 Apr 08 nicklas 146       int channels = source.getRawDataType().getChannels();
647 11 Apr 08 nicklas 147         
647 11 Apr 08 nicklas 148       // Create transformation and child bioassay set
647 11 Apr 08 nicklas 149       Job j = Job.getById(dc, job.getId());
647 11 Apr 08 nicklas 150       Transformation t = source.newTransformation(j);
647 11 Apr 08 nicklas 151       t.setName("Multiply " + factor + "; filter < " + cutoff);
647 11 Apr 08 nicklas 152       BioAssaySet result = t.newProduct(null, "new", true);
647 11 Apr 08 nicklas 153       result.setName("After: multiply and filter");
647 11 Apr 08 nicklas 154       dc.saveItem(t);
647 11 Apr 08 nicklas 155       dc.saveItem(result);
647 11 Apr 08 nicklas 156         
647 11 Apr 08 nicklas 157       // Get query for source data
647 11 Apr 08 nicklas 158       DynamicSpotQuery query = source.getSpotData();
647 11 Apr 08 nicklas 159         
647 11 Apr 08 nicklas 160       // Query expressions for multiplication factor and cutoff
647 11 Apr 08 nicklas 161       Expression factorExpression = Expressions.aFloat(factor);
647 11 Apr 08 nicklas 162       Expression cutoffExpression = Expressions.aFloat(cutoff);
647 11 Apr 08 nicklas 163               
647 11 Apr 08 nicklas 164       // Specify select columns
647 11 Apr 08 nicklas 165       query.select(Dynamic.select(VirtualColumn.COLUMN));
647 11 Apr 08 nicklas 166       query.select(Dynamic.select(VirtualColumn.POSITION));
647 11 Apr 08 nicklas 167       for (int ch = 1; ch <= channels; ch++)
647 11 Apr 08 nicklas 168       {
1292 24 Feb 11 nicklas 169         Expression chExpression = Dynamic.column(VirtualColumn.channelRaw(ch));
647 11 Apr 08 nicklas 170         // Selects: ch * factor for each channel
647 11 Apr 08 nicklas 171         query.select(
647 11 Apr 08 nicklas 172           Selects.expression(Expressions.multiply(chExpression, factorExpression), "ch" + ch)
647 11 Apr 08 nicklas 173         );
647 11 Apr 08 nicklas 174         // Restricts: ch >= cutoff for each channel
647 11 Apr 08 nicklas 175         query.restrict(Restrictions.gteq(chExpression, cutoffExpression));
647 11 Apr 08 nicklas 176       }
647 11 Apr 08 nicklas 177         
647 11 Apr 08 nicklas 178       // Create batcher and copy data
647 11 Apr 08 nicklas 179       SpotBatcher batcher = result.getSpotBatcher();
647 11 Apr 08 nicklas 180       // Check for the ABORT signal before a lengthy operation
1292 24 Feb 11 nicklas 181       ThreadSignalHandler.checkInterrupted(); 
647 11 Apr 08 nicklas 182       int spotsCopied = batcher.insert(query);
647 11 Apr 08 nicklas 183       batcher.close();
647 11 Apr 08 nicklas 184       int spotsRemoved = source.getNumSpots() - spotsCopied;
647 11 Apr 08 nicklas 185         
647 11 Apr 08 nicklas 186       // Commit the work
647 11 Apr 08 nicklas 187       dc.commit();
647 11 Apr 08 nicklas 188       response.setDone("Multiplied " + spotsCopied + " spots with factor " + factor + 
647 11 Apr 08 nicklas 189         "; removed " + spotsRemoved + " spots with intensity < " + cutoff);
647 11 Apr 08 nicklas 190     }
647 11 Apr 08 nicklas 191     catch (Throwable t)
647 11 Apr 08 nicklas 192     {
647 11 Apr 08 nicklas 193       // All exceptions must be catched and sent back 
647 11 Apr 08 nicklas 194       // using the response object
647 11 Apr 08 nicklas 195       response.setError(t.getMessage(), Arrays.asList(t));
647 11 Apr 08 nicklas 196     }
647 11 Apr 08 nicklas 197     finally
647 11 Apr 08 nicklas 198     {
647 11 Apr 08 nicklas 199       // IMPORTANT!!! Make sure opened connections are closed
647 11 Apr 08 nicklas 200       if (dc != null) dc.close();
647 11 Apr 08 nicklas 201     }
647 11 Apr 08 nicklas 202   }
647 11 Apr 08 nicklas 203   // -------------------------------------------
647 11 Apr 08 nicklas 204   
647 11 Apr 08 nicklas 205   /*
647 11 Apr 08 nicklas 206     From the InteractivePlugin interface
647 11 Apr 08 nicklas 207     -------------------------------------------
647 11 Apr 08 nicklas 208   */
647 11 Apr 08 nicklas 209   /**
647 11 Apr 08 nicklas 210     Return a set containing the context [BIOASSAYSET, ITEM].
647 11 Apr 08 nicklas 211   */
1292 24 Feb 11 nicklas 212   @Override
647 11 Apr 08 nicklas 213   public Set<GuiContext> getGuiContexts()
647 11 Apr 08 nicklas 214   {
647 11 Apr 08 nicklas 215     return guiContexts;
647 11 Apr 08 nicklas 216   }
647 11 Apr 08 nicklas 217   /**
647 11 Apr 08 nicklas 218     Check if the item is a {@link BioAssaySet} and the logged in
1292 24 Feb 11 nicklas 219     user has USE permission to the experiment. Also verify that
1292 24 Feb 11 nicklas 220     the bioassay set has data stored in the database.
647 11 Apr 08 nicklas 221   */
1292 24 Feb 11 nicklas 222   @Override
647 11 Apr 08 nicklas 223   public String isInContext(GuiContext context, Object item)
647 11 Apr 08 nicklas 224   {
1292 24 Feb 11 nicklas 225     String message = super.isInContext(context, item);
1292 24 Feb 11 nicklas 226     if (message == null)
647 11 Apr 08 nicklas 227     {
1292 24 Feb 11 nicklas 228       BioAssaySet bas = (BioAssaySet)item;
1292 24 Feb 11 nicklas 229       if (bas.getNumSpots() <= 0)
1292 24 Feb 11 nicklas 230       {
1292 24 Feb 11 nicklas 231         message = "This plug-in requires spot data in the database";
1292 24 Feb 11 nicklas 232       }
647 11 Apr 08 nicklas 233     }
647 11 Apr 08 nicklas 234     return message;
647 11 Apr 08 nicklas 235   }
647 11 Apr 08 nicklas 236   /**
647 11 Apr 08 nicklas 237     The {@link Request#COMMAND_CONFIGURE_PLUGIN} command will not ask
647 11 Apr 08 nicklas 238     for any parameters.
647 11 Apr 08 nicklas 239     <p>
647 11 Apr 08 nicklas 240     The {@link Request#COMMAND_CONFIGURE_JOB} command will ask for
647 11 Apr 08 nicklas 241     a bioassay set, a multiplcation factor and a cutoff value.
647 11 Apr 08 nicklas 242   */
1292 24 Feb 11 nicklas 243   @Override
647 11 Apr 08 nicklas 244   public RequestInformation getRequestInformation(GuiContext context, String command)
647 11 Apr 08 nicklas 245     throws BaseException
647 11 Apr 08 nicklas 246   {
647 11 Apr 08 nicklas 247     RequestInformation requestInformation = null;
647 11 Apr 08 nicklas 248     if (command.equals(Request.COMMAND_CONFIGURE_JOB))
647 11 Apr 08 nicklas 249     {
647 11 Apr 08 nicklas 250       requestInformation = getConfigureJob(context);
647 11 Apr 08 nicklas 251     }
647 11 Apr 08 nicklas 252     return requestInformation;
647 11 Apr 08 nicklas 253   }
647 11 Apr 08 nicklas 254   /**
647 11 Apr 08 nicklas 255     Store configuration settings for {@link Request#COMMAND_CONFIGURE_PLUGIN} and
647 11 Apr 08 nicklas 256     {@link Request#COMMAND_CONFIGURE_JOB}.
647 11 Apr 08 nicklas 257   */
1292 24 Feb 11 nicklas 258   @Override
647 11 Apr 08 nicklas 259   public void configure(GuiContext context, Request request, Response response)
647 11 Apr 08 nicklas 260   {
647 11 Apr 08 nicklas 261     String command = request.getCommand();
647 11 Apr 08 nicklas 262     try
647 11 Apr 08 nicklas 263     {
647 11 Apr 08 nicklas 264       if (command.equals(Request.COMMAND_CONFIGURE_JOB))
647 11 Apr 08 nicklas 265       {
1292 24 Feb 11 nicklas 266         RequestInformation ri = getConfigureJob(context);
647 11 Apr 08 nicklas 267         List<Throwable> errors = 
1292 24 Feb 11 nicklas 268           validateRequestParameters(ri.getParameters(), request);
647 11 Apr 08 nicklas 269         if (errors != null)
647 11 Apr 08 nicklas 270         {
647 11 Apr 08 nicklas 271           response.setError(errors.size()+" invalid parameter(s) were found in the request", errors);
647 11 Apr 08 nicklas 272           return;
647 11 Apr 08 nicklas 273         }
647 11 Apr 08 nicklas 274
1292 24 Feb 11 nicklas 275         // Source bioassay set
1292 24 Feb 11 nicklas 276         storeValue(job, request, ri.getParameter(SOURCE_BIOASSAYSET));
1292 24 Feb 11 nicklas 277                 
1292 24 Feb 11 nicklas 278         // Other options
647 11 Apr 08 nicklas 279         storeValue(job, request, factorParameter);
647 11 Apr 08 nicklas 280         storeValue(job, request, cutoffParameter);
1292 24 Feb 11 nicklas 281         BioAssaySet bioAssaySet = (BioAssaySet)job.getValue(SOURCE_BIOASSAYSET);
1292 24 Feb 11 nicklas 282         response.setSuggestedJobName("Example analysis on bioassay set '" + 
1292 24 Feb 11 nicklas 283             bioAssaySet.getName() + "'");
647 11 Apr 08 nicklas 284         response.setDone("Job configuration complete", Job.ExecutionTime.SHORT);
647 11 Apr 08 nicklas 285         // TODO - maybe check file size to make a better estimate
647 11 Apr 08 nicklas 286       }
647 11 Apr 08 nicklas 287     }
647 11 Apr 08 nicklas 288     catch (Throwable ex)
647 11 Apr 08 nicklas 289     {
647 11 Apr 08 nicklas 290       response.setError(ex.getMessage(), Arrays.asList(ex));
647 11 Apr 08 nicklas 291     }
647 11 Apr 08 nicklas 292   }
647 11 Apr 08 nicklas 293   // -------------------------------------------
647 11 Apr 08 nicklas 294   /*
647 11 Apr 08 nicklas 295     From the SignalTarget interface
647 11 Apr 08 nicklas 296     -------------------------------------------
647 11 Apr 08 nicklas 297   */
1292 24 Feb 11 nicklas 298   @Override
647 11 Apr 08 nicklas 299   public SignalHandler getSignalHandler()
647 11 Apr 08 nicklas 300   {
647 11 Apr 08 nicklas 301     signalHandler = new ThreadSignalHandler();
647 11 Apr 08 nicklas 302     return signalHandler;
647 11 Apr 08 nicklas 303   }
647 11 Apr 08 nicklas 304   // -------------------------------------------
647 11 Apr 08 nicklas 305
647 11 Apr 08 nicklas 306
647 11 Apr 08 nicklas 307   private RequestInformation getConfigureJob(GuiContext context)
647 11 Apr 08 nicklas 308   {
1292 24 Feb 11 nicklas 309     DbControl dc = null;
1292 24 Feb 11 nicklas 310     try
647 11 Apr 08 nicklas 311     {
1292 24 Feb 11 nicklas 312       if (configureJob == null)
1292 24 Feb 11 nicklas 313       {
1292 24 Feb 11 nicklas 314         dc = sc.newDbControl();
1292 24 Feb 11 nicklas 315         BioAssaySet bas = getCurrentBioAssaySet(dc);
1292 24 Feb 11 nicklas 316         // Create parameter list and request informaion
1292 24 Feb 11 nicklas 317         List<PluginParameter<?>> parameters = new ArrayList<PluginParameter<?>>();
1292 24 Feb 11 nicklas 318         
1292 24 Feb 11 nicklas 319         // Source bioassay set parameter
1292 24 Feb 11 nicklas 320         parameters.add(getSourceBioAssaySetParameter(null, null));    
1292 24 Feb 11 nicklas 321   
1292 24 Feb 11 nicklas 322         // Other parameters
1292 24 Feb 11 nicklas 323         // Create multiplication factor parameter
1292 24 Feb 11 nicklas 324         factorParameter = new PluginParameter<Float>(
1292 24 Feb 11 nicklas 325           "factor",
1292 24 Feb 11 nicklas 326           "Multiplication factor",
1292 24 Feb 11 nicklas 327           "The factor to multiply each spot intensity with.",
1292 24 Feb 11 nicklas 328           new FloatParameterType(0.0f, 100.0f, 1.0f, true)
1292 24 Feb 11 nicklas 329         );
1292 24 Feb 11 nicklas 330   
1292 24 Feb 11 nicklas 331         // Create cutoff parameter
1292 24 Feb 11 nicklas 332         cutoffParameter = new PluginParameter<Float>(
1292 24 Feb 11 nicklas 333           "cutoff",
1292 24 Feb 11 nicklas 334           "Cut-off value",
1292 24 Feb 11 nicklas 335           "Original intensities falling below this value are filtered out.",
1292 24 Feb 11 nicklas 336           new FloatParameterType(null, null, 0.0f, true)
1292 24 Feb 11 nicklas 337         );
1292 24 Feb 11 nicklas 338         parameters.add(factorParameter);
1292 24 Feb 11 nicklas 339         parameters.add(cutoffParameter);
1292 24 Feb 11 nicklas 340         
1292 24 Feb 11 nicklas 341         configureJob = new RequestInformation
1292 24 Feb 11 nicklas 342         (
1292 24 Feb 11 nicklas 343           Request.COMMAND_CONFIGURE_JOB,
1292 24 Feb 11 nicklas 344           "Specify multiplication factor and cutoff",
1292 24 Feb 11 nicklas 345           about.getDescription(),
1292 24 Feb 11 nicklas 346           parameters
1292 24 Feb 11 nicklas 347         );
1292 24 Feb 11 nicklas 348       }
647 11 Apr 08 nicklas 349     }
1292 24 Feb 11 nicklas 350     finally
1292 24 Feb 11 nicklas 351     {
1292 24 Feb 11 nicklas 352       if (dc != null) dc.close();
1292 24 Feb 11 nicklas 353     }
647 11 Apr 08 nicklas 354     return configureJob;
647 11 Apr 08 nicklas 355   }
647 11 Apr 08 nicklas 356 }