extensions/net.sf.basedb.relax/trunk/src/net/sf/basedb/relax/plugins/Level3ExporterPlugin.java

Code
Comments
Other
Rev Date Author Line
4571 14 Sep 17 nicklas 1 package net.sf.basedb.relax.plugins;
4571 14 Sep 17 nicklas 2
4571 14 Sep 17 nicklas 3 import java.io.IOException;
4571 14 Sep 17 nicklas 4 import java.io.OutputStreamWriter;
4571 14 Sep 17 nicklas 5 import java.io.Writer;
4577 19 Sep 17 nicklas 6 import java.net.URI;
4571 14 Sep 17 nicklas 7 import java.nio.charset.Charset;
4571 14 Sep 17 nicklas 8 import java.util.ArrayList;
4571 14 Sep 17 nicklas 9 import java.util.Arrays;
4571 14 Sep 17 nicklas 10 import java.util.Collections;
4571 14 Sep 17 nicklas 11 import java.util.HashMap;
4571 14 Sep 17 nicklas 12 import java.util.HashSet;
4571 14 Sep 17 nicklas 13 import java.util.List;
4571 14 Sep 17 nicklas 14 import java.util.Map;
4571 14 Sep 17 nicklas 15 import java.util.Set;
4571 14 Sep 17 nicklas 16 import java.util.regex.Matcher;
4571 14 Sep 17 nicklas 17 import java.util.regex.Pattern;
4571 14 Sep 17 nicklas 18
4571 14 Sep 17 nicklas 19 import org.json.simple.JSONArray;
4571 14 Sep 17 nicklas 20 import org.json.simple.JSONObject;
4576 18 Sep 17 nicklas 21 import org.json.simple.JSONStreamAware;
4571 14 Sep 17 nicklas 22
4571 14 Sep 17 nicklas 23 import net.sf.basedb.core.Annotatable;
4571 14 Sep 17 nicklas 24 import net.sf.basedb.core.AnnotationType;
4572 15 Sep 17 nicklas 25 import net.sf.basedb.core.AnnotationTypeCategory;
4571 14 Sep 17 nicklas 26 import net.sf.basedb.core.BaseException;
4571 14 Sep 17 nicklas 27 import net.sf.basedb.core.BooleanParameterType;
4575 15 Sep 17 nicklas 28 import net.sf.basedb.core.DataFileType;
4571 14 Sep 17 nicklas 29 import net.sf.basedb.core.DbControl;
4571 14 Sep 17 nicklas 30 import net.sf.basedb.core.DerivedBioAssay;
4571 14 Sep 17 nicklas 31 import net.sf.basedb.core.Extract;
4575 15 Sep 17 nicklas 32 import net.sf.basedb.core.File;
4571 14 Sep 17 nicklas 33 import net.sf.basedb.core.FileServer;
4575 15 Sep 17 nicklas 34 import net.sf.basedb.core.FileSetMember;
4575 15 Sep 17 nicklas 35 import net.sf.basedb.core.FileStoreEnabled;
4571 14 Sep 17 nicklas 36 import net.sf.basedb.core.Include;
4571 14 Sep 17 nicklas 37 import net.sf.basedb.core.Item;
4571 14 Sep 17 nicklas 38 import net.sf.basedb.core.ItemList;
4571 14 Sep 17 nicklas 39 import net.sf.basedb.core.ItemParameterType;
4571 14 Sep 17 nicklas 40 import net.sf.basedb.core.ItemQuery;
4571 14 Sep 17 nicklas 41 import net.sf.basedb.core.PermissionDeniedException;
4571 14 Sep 17 nicklas 42 import net.sf.basedb.core.Platform;
4571 14 Sep 17 nicklas 43 import net.sf.basedb.core.PlatformVariant;
4571 14 Sep 17 nicklas 44 import net.sf.basedb.core.PluginParameter;
4571 14 Sep 17 nicklas 45 import net.sf.basedb.core.ProgressReporter;
4571 14 Sep 17 nicklas 46 import net.sf.basedb.core.Project;
4571 14 Sep 17 nicklas 47 import net.sf.basedb.core.RawBioAssay;
4571 14 Sep 17 nicklas 48 import net.sf.basedb.core.RequestInformation;
4571 14 Sep 17 nicklas 49 import net.sf.basedb.core.StringParameterType;
4571 14 Sep 17 nicklas 50 import net.sf.basedb.core.Unit;
4571 14 Sep 17 nicklas 51 import net.sf.basedb.core.Job.ExecutionTime;
4571 14 Sep 17 nicklas 52 import net.sf.basedb.core.Listable;
4571 14 Sep 17 nicklas 53 import net.sf.basedb.core.Nameable;
4571 14 Sep 17 nicklas 54 import net.sf.basedb.core.plugin.AbstractPlugin;
4571 14 Sep 17 nicklas 55 import net.sf.basedb.core.plugin.ExportOutputStream;
4571 14 Sep 17 nicklas 56 import net.sf.basedb.core.plugin.GuiContext;
4571 14 Sep 17 nicklas 57 import net.sf.basedb.core.plugin.InteractivePlugin;
4571 14 Sep 17 nicklas 58 import net.sf.basedb.core.plugin.Request;
4571 14 Sep 17 nicklas 59 import net.sf.basedb.core.plugin.Response;
4571 14 Sep 17 nicklas 60 import net.sf.basedb.core.query.Expressions;
4571 14 Sep 17 nicklas 61 import net.sf.basedb.core.query.Hql;
4571 14 Sep 17 nicklas 62 import net.sf.basedb.core.query.Orders;
4571 14 Sep 17 nicklas 63 import net.sf.basedb.core.query.Restrictions;
4571 14 Sep 17 nicklas 64 import net.sf.basedb.core.signal.SignalHandler;
4571 14 Sep 17 nicklas 65 import net.sf.basedb.core.signal.SignalTarget;
4571 14 Sep 17 nicklas 66 import net.sf.basedb.core.signal.ThreadSignalHandler;
4571 14 Sep 17 nicklas 67 import net.sf.basedb.core.snapshot.AnnotationSnapshot;
4571 14 Sep 17 nicklas 68 import net.sf.basedb.core.snapshot.AnnotationTypeFilter;
4571 14 Sep 17 nicklas 69 import net.sf.basedb.core.snapshot.SnapshotManager;
4571 14 Sep 17 nicklas 70 import net.sf.basedb.opengrid.CmdResult;
4571 14 Sep 17 nicklas 71 import net.sf.basedb.opengrid.OpenGrid;
4571 14 Sep 17 nicklas 72 import net.sf.basedb.opengrid.RemoteHost;
4571 14 Sep 17 nicklas 73 import net.sf.basedb.opengrid.RemoteSession;
4571 14 Sep 17 nicklas 74 import net.sf.basedb.opengrid.ScriptBuilder;
4571 14 Sep 17 nicklas 75 import net.sf.basedb.opengrid.config.ConnectionInfo;
4571 14 Sep 17 nicklas 76 import net.sf.basedb.relax.Relax;
4608 03 Oct 17 nicklas 77 import net.sf.basedb.relax.ServerMode;
5245 18 Jan 19 nicklas 78 import net.sf.basedb.relax.dao.Annotationtype;
4575 15 Sep 17 nicklas 79 import net.sf.basedb.relax.dao.Datafiletype;
4571 14 Sep 17 nicklas 80 import net.sf.basedb.relax.dao.Fileserver;
4737 05 Apr 18 nicklas 81 import net.sf.basedb.relax.dao.Rawdatatype;
4575 15 Sep 17 nicklas 82 import net.sf.basedb.relax.dao.Subtype;
4771 19 Apr 18 nicklas 83 import net.sf.basedb.relax.json.FilteredJSONArray;
4571 14 Sep 17 nicklas 84 import net.sf.basedb.util.FileUtil;
4571 14 Sep 17 nicklas 85 import net.sf.basedb.util.NameableComparator;
4571 14 Sep 17 nicklas 86 import net.sf.basedb.util.Values;
4575 15 Sep 17 nicklas 87 import net.sf.basedb.util.filter.Filter;
4771 19 Apr 18 nicklas 88 import net.sf.basedb.util.filter.NotNullFilter;
4575 15 Sep 17 nicklas 89 import net.sf.basedb.util.filter.StaticFilter;
4571 14 Sep 17 nicklas 90
4571 14 Sep 17 nicklas 91 /**
4571 14 Sep 17 nicklas 92   Plug-in for generating JSON files for the level 3 publication
4571 14 Sep 17 nicklas 93   server. Input is an item list which rawbioassays of the same 
4571 14 Sep 17 nicklas 94   rawdata type. One JSON file is produced for item in the list. 
4571 14 Sep 17 nicklas 95   
4571 14 Sep 17 nicklas 96   @author nicklas
4571 14 Sep 17 nicklas 97   @since 1.x
4571 14 Sep 17 nicklas 98 */
4571 14 Sep 17 nicklas 99 public class Level3ExporterPlugin 
4571 14 Sep 17 nicklas 100   extends AbstractPlugin
4571 14 Sep 17 nicklas 101   implements InteractivePlugin, SignalTarget
4571 14 Sep 17 nicklas 102 {
4571 14 Sep 17 nicklas 103   
4571 14 Sep 17 nicklas 104   private Set<Item> itemTypes = new HashSet<>(Arrays.asList(
4571 14 Sep 17 nicklas 105     Item.RAWBIOASSAY));
4571 14 Sep 17 nicklas 106   
4571 14 Sep 17 nicklas 107   private RequestInformation configureExport;
4571 14 Sep 17 nicklas 108   
4571 14 Sep 17 nicklas 109   private ThreadSignalHandler signalHandler;
4571 14 Sep 17 nicklas 110   
4571 14 Sep 17 nicklas 111   public Level3ExporterPlugin() 
4571 14 Sep 17 nicklas 112   {}
4571 14 Sep 17 nicklas 113
4571 14 Sep 17 nicklas 114   @Override
4571 14 Sep 17 nicklas 115   public boolean requiresConfiguration()
4571 14 Sep 17 nicklas 116   {
4571 14 Sep 17 nicklas 117     return false;
4571 14 Sep 17 nicklas 118   }
4571 14 Sep 17 nicklas 119
4571 14 Sep 17 nicklas 120   /*
4571 14 Sep 17 nicklas 121      From the Plugin interface
4571 14 Sep 17 nicklas 122      --------------------------------
4571 14 Sep 17 nicklas 123   */
4571 14 Sep 17 nicklas 124   @Override
4571 14 Sep 17 nicklas 125   public boolean supportsConfigurations()
4571 14 Sep 17 nicklas 126   {
4571 14 Sep 17 nicklas 127     return false;
4571 14 Sep 17 nicklas 128   }
4571 14 Sep 17 nicklas 129   @Override
4571 14 Sep 17 nicklas 130   public MainType getMainType() 
4571 14 Sep 17 nicklas 131   {
4571 14 Sep 17 nicklas 132     return MainType.EXPORT;
4571 14 Sep 17 nicklas 133   }
4571 14 Sep 17 nicklas 134
4571 14 Sep 17 nicklas 135   @Override
4571 14 Sep 17 nicklas 136   public void run(Request request, Response response, ProgressReporter progress) 
4571 14 Sep 17 nicklas 137   {
4571 14 Sep 17 nicklas 138     if (signalHandler != null) signalHandler.setWorkerThread(null);
4571 14 Sep 17 nicklas 139     
4571 14 Sep 17 nicklas 140     DbControl dc = null;
4571 14 Sep 17 nicklas 141     DbControl readerDc = null;
4571 14 Sep 17 nicklas 142     FileServerOutputLocation outputLocation = null;
4571 14 Sep 17 nicklas 143     try
4571 14 Sep 17 nicklas 144     {
4571 14 Sep 17 nicklas 145       dc = sc.newDbControl();
4571 14 Sep 17 nicklas 146       
4571 14 Sep 17 nicklas 147       boolean overwrite = Boolean.TRUE.equals(job.getValue("overwrite"));
5557 13 Aug 19 nicklas 148       boolean debugMode = Boolean.TRUE.equals(job.getValue("debugMode"));
4571 14 Sep 17 nicklas 149       String releaseVersion = (String)job.getValue("releaseVersion");
4571 14 Sep 17 nicklas 150       
4571 14 Sep 17 nicklas 151       FileServer fileServer = (FileServer)job.getValue("fileServer");
4571 14 Sep 17 nicklas 152       fileServer = FileServer.getById(dc, fileServer.getId());
4571 14 Sep 17 nicklas 153       outputLocation = new FileServerOutputLocation(fileServer, releaseVersion);
4571 14 Sep 17 nicklas 154       outputLocation.setOverwrite(overwrite);
4571 14 Sep 17 nicklas 155       
4572 15 Sep 17 nicklas 156       // INCA annotation types that should be exported
4572 15 Sep 17 nicklas 157       AnnotationTypeCategory incaCategory = (AnnotationTypeCategory)job.getValue("incaCategory");
4772 19 Apr 18 nicklas 158       Set<AnnotationType> incaAnnotations = Collections.emptySet();
4572 15 Sep 17 nicklas 159       if (incaCategory != null)
4572 15 Sep 17 nicklas 160       {
4572 15 Sep 17 nicklas 161         ItemQuery<AnnotationType> query = incaCategory.getAnnotationTypes(null);
4572 15 Sep 17 nicklas 162         query.setIncludes(Relax.INCLUDE_IN_CURRENT_PROJECT);
4572 15 Sep 17 nicklas 163         incaAnnotations = new HashSet<>(query.list(dc));
4572 15 Sep 17 nicklas 164       }
4572 15 Sep 17 nicklas 165       
5245 18 Jan 19 nicklas 166       // Annotations that should never be exporter
5245 18 Jan 19 nicklas 167       Set<AnnotationType> excludeFromExport = new HashSet<>();
5245 18 Jan 19 nicklas 168       excludeFromExport.add(Annotationtype.FIRST_RELEASED_IN.get(dc));
5245 18 Jan 19 nicklas 169       
4571 14 Sep 17 nicklas 170       // Load the list...
4571 14 Sep 17 nicklas 171       ItemList list = (ItemList)job.getValue("itemList");
4571 14 Sep 17 nicklas 172       list = ItemList.getById(dc, list.getId());
4571 14 Sep 17 nicklas 173       // ...and all members (id only)
4571 14 Sep 17 nicklas 174       ItemQuery<? extends Listable> query = list.getMembers();
4571 14 Sep 17 nicklas 175       query.setIncludes(Relax.INCLUDE_IN_CURRENT_PROJECT);
4571 14 Sep 17 nicklas 176       query.order(Orders.asc(Hql.property("name")));
4571 14 Sep 17 nicklas 177       List<Integer> itemIds = query.idList(dc);
4771 19 Apr 18 nicklas 178
5244 18 Jan 19 nicklas 179       // Write information about the list
4576 18 Sep 17 nicklas 180       JSONObject jsonIndex = createIndex(list, releaseVersion);
4576 18 Sep 17 nicklas 181       writeJSON(outputLocation, "/index.json", jsonIndex);
5244 18 Jan 19 nicklas 182
4576 18 Sep 17 nicklas 183       // We do not use any batch index lookups but need to create an empty file
4576 18 Sep 17 nicklas 184       writeJSON(outputLocation, "/batch-index-lookup.json", new JSONObject());
5244 18 Jan 19 nicklas 185
4577 19 Sep 17 nicklas 186       ReleaseWriterOptions options = new ReleaseWriterOptions(list);
4577 19 Sep 17 nicklas 187       options.setVersion(releaseVersion);
5244 18 Jan 19 nicklas 188       Item memberType = list.getMemberType();
5244 18 Jan 19 nicklas 189       Map<String, CohortJSONWriter> writers = new HashMap<>();
4577 19 Sep 17 nicklas 190       ScriptWriter script = new ScriptWriter(dc, options);
5244 18 Jan 19 nicklas 191       JSONArray jsonTypeDefs = new JSONArray();
5244 18 Jan 19 nicklas 192       JSONArray jsonFiles = new JSONArray();
5244 18 Jan 19 nicklas 193       SnapshotManager manager = null;
4571 14 Sep 17 nicklas 194       int count = 0;
4571 14 Sep 17 nicklas 195       int totalCount = list.getSize();
4571 14 Sep 17 nicklas 196       for (int itemId : itemIds)
4571 14 Sep 17 nicklas 197       {
4571 14 Sep 17 nicklas 198         if (count % 100 == 0)
4571 14 Sep 17 nicklas 199         {
4571 14 Sep 17 nicklas 200           // Rollback and create new DbControl and Snapshot 
4571 14 Sep 17 nicklas 201           // Manager to allow GC to reclaim memory
4571 14 Sep 17 nicklas 202           if (readerDc != null) readerDc.close();
4571 14 Sep 17 nicklas 203           readerDc = dc.getSessionControl().newDbControl();
4571 14 Sep 17 nicklas 204           manager = new SnapshotManager();
4571 14 Sep 17 nicklas 205         }
4571 14 Sep 17 nicklas 206         if (count % 10 == 0)
4571 14 Sep 17 nicklas 207         {
4571 14 Sep 17 nicklas 208           ThreadSignalHandler.checkInterrupted();
4571 14 Sep 17 nicklas 209           if (progress != null)
4571 14 Sep 17 nicklas 210           {
4571 14 Sep 17 nicklas 211             progress.display(5 + (int)((90*count)/totalCount), 
4571 14 Sep 17 nicklas 212               "Exporting cohort data (" + count + " of " + totalCount + ")...");
4571 14 Sep 17 nicklas 213           }
4571 14 Sep 17 nicklas 214         }
4571 14 Sep 17 nicklas 215         count++;
4571 14 Sep 17 nicklas 216         
4571 14 Sep 17 nicklas 217         CohortItem rootItem = new CohortItem((Nameable)memberType.getById(readerDc, itemId));
4571 14 Sep 17 nicklas 218         CohortChain cohort = new CohortChain(readerDc, rootItem);
4571 14 Sep 17 nicklas 219
4576 18 Sep 17 nicklas 220         JSONArray json = new JSONArray();
4576 18 Sep 17 nicklas 221         List<CohortItem> parents = cohort.getParentItems();
4576 18 Sep 17 nicklas 222         for (CohortItem parent : parents)
4571 14 Sep 17 nicklas 223         {
4576 18 Sep 17 nicklas 224           String subtype = parent.getSubtype();
4576 18 Sep 17 nicklas 225           CohortJSONWriter writer = writers.get(subtype);
5244 18 Jan 19 nicklas 226           if (writer == null)
5244 18 Jan 19 nicklas 227           {
5244 18 Jan 19 nicklas 228             writer = new CohortJSONWriter(parent.getType(), subtype);
5245 18 Jan 19 nicklas 229             jsonTypeDefs.addAll(writer.getTypeDefs(dc, incaAnnotations, excludeFromExport));
5244 18 Jan 19 nicklas 230             writers.put(subtype, writer);
5244 18 Jan 19 nicklas 231           }
4577 19 Sep 17 nicklas 232           json.add(writer.getItemAsJSON(readerDc, parent, manager, script));
4571 14 Sep 17 nicklas 233         }
4571 14 Sep 17 nicklas 234
4576 18 Sep 17 nicklas 235         String file = "/json/"+rootItem.getName()+".json";
4576 18 Sep 17 nicklas 236         jsonFiles.add(file);
4576 18 Sep 17 nicklas 237         writeJSON(outputLocation, file, json);
4571 14 Sep 17 nicklas 238       }
4571 14 Sep 17 nicklas 239       
5244 18 Jan 19 nicklas 240       // All annotation and file type definitions
5244 18 Jan 19 nicklas 241       writeJSON(outputLocation, "/typedefs.json", jsonTypeDefs);
5244 18 Jan 19 nicklas 242
4577 19 Sep 17 nicklas 243       script.writeScripts(outputLocation);
4576 18 Sep 17 nicklas 244       writeJSON(outputLocation, "/files.json", jsonFiles);
4576 18 Sep 17 nicklas 245       
4576 18 Sep 17 nicklas 246       ExportOutputStream complete = outputLocation.getOutputStream("/exportcomplete", false);
4576 18 Sep 17 nicklas 247       FileUtil.close(complete);
4576 18 Sep 17 nicklas 248       
4571 14 Sep 17 nicklas 249       dc.commit();
4629 21 Nov 17 nicklas 250       String msg = totalCount + " items in the '" + list.getName() + "' list have been exported to " + fileServer.getName();
5557 13 Aug 19 nicklas 251       if (debugMode)
5557 13 Aug 19 nicklas 252       {
5557 13 Aug 19 nicklas 253         // DEBUG!! will make it easier to re-run a job with same settings
5557 13 Aug 19 nicklas 254         response.setError("[DEBUG] "+msg, null);
5557 13 Aug 19 nicklas 255       }
5557 13 Aug 19 nicklas 256       else
5557 13 Aug 19 nicklas 257       {
5557 13 Aug 19 nicklas 258         response.setDone(msg);
5557 13 Aug 19 nicklas 259       }
4571 14 Sep 17 nicklas 260     }
4571 14 Sep 17 nicklas 261     catch (Throwable t)
4571 14 Sep 17 nicklas 262     {
4571 14 Sep 17 nicklas 263       response.setError(t.getMessage(), Arrays.asList(t));
4571 14 Sep 17 nicklas 264     }
4571 14 Sep 17 nicklas 265     finally
4571 14 Sep 17 nicklas 266     {
4571 14 Sep 17 nicklas 267       FileUtil.close(outputLocation);
4571 14 Sep 17 nicklas 268       if (readerDc != null) readerDc.close();
4571 14 Sep 17 nicklas 269       if (dc != null) dc.close();
4571 14 Sep 17 nicklas 270     }
4571 14 Sep 17 nicklas 271     
4571 14 Sep 17 nicklas 272   }
4571 14 Sep 17 nicklas 273   // -------------------------------------
4571 14 Sep 17 nicklas 274   /*
4571 14 Sep 17 nicklas 275      From the InteractivePlugin interface
4571 14 Sep 17 nicklas 276      -------------------------------------------
4571 14 Sep 17 nicklas 277   */
4571 14 Sep 17 nicklas 278   /**
4571 14 Sep 17 nicklas 279     The plug-in will appear on the single-item view
4571 14 Sep 17 nicklas 280     for item lists.
4571 14 Sep 17 nicklas 281    */
4571 14 Sep 17 nicklas 282   @Override
4571 14 Sep 17 nicklas 283   public Set<GuiContext> getGuiContexts()
4571 14 Sep 17 nicklas 284   {
4571 14 Sep 17 nicklas 285     return Collections.singleton(GuiContext.item(Item.ITEMLIST));
4571 14 Sep 17 nicklas 286   }
4571 14 Sep 17 nicklas 287   /**
4571 14 Sep 17 nicklas 288     We accept all item lists with:
4571 14 Sep 17 nicklas 289     * Raw bioassays
4571 14 Sep 17 nicklas 290     The list must have at least one member.
4571 14 Sep 17 nicklas 291   */
4571 14 Sep 17 nicklas 292   @Override
4571 14 Sep 17 nicklas 293   public String isInContext(GuiContext context, Object item)
4571 14 Sep 17 nicklas 294   {
4571 14 Sep 17 nicklas 295     String message = null;
4571 14 Sep 17 nicklas 296     if (item == null)
4571 14 Sep 17 nicklas 297     {
4571 14 Sep 17 nicklas 298       message = "The object is null";
4571 14 Sep 17 nicklas 299     }
4571 14 Sep 17 nicklas 300     else if (!(item instanceof ItemList))
4571 14 Sep 17 nicklas 301     {
4571 14 Sep 17 nicklas 302       message = "The object is not an item list: " + item;
4571 14 Sep 17 nicklas 303     }
4571 14 Sep 17 nicklas 304     ItemList list = (ItemList)item;
4571 14 Sep 17 nicklas 305     if (!itemTypes.contains(list.getMemberType()))
4571 14 Sep 17 nicklas 306     {
4571 14 Sep 17 nicklas 307       throw new BaseException("This plug-in need an item list with one of: " + Values.getString(itemTypes, ", ", true));
4571 14 Sep 17 nicklas 308     }
4571 14 Sep 17 nicklas 309     else if (list.getSize() == 0)
4571 14 Sep 17 nicklas 310     {
4571 14 Sep 17 nicklas 311       throw new BaseException("The selected list is empty.");
4571 14 Sep 17 nicklas 312     }
4571 14 Sep 17 nicklas 313     else if (sc.getActiveProjectId() == 0)
4571 14 Sep 17 nicklas 314     {
4571 14 Sep 17 nicklas 315       throw new BaseException("This plug-in requires an active project!");
4571 14 Sep 17 nicklas 316     }
4571 14 Sep 17 nicklas 317     return message;
4571 14 Sep 17 nicklas 318   }
4571 14 Sep 17 nicklas 319   @Override
4571 14 Sep 17 nicklas 320   public RequestInformation getRequestInformation(GuiContext context, String command) 
4571 14 Sep 17 nicklas 321     throws BaseException
4571 14 Sep 17 nicklas 322   {
4571 14 Sep 17 nicklas 323     RequestInformation requestInformation = null;
4571 14 Sep 17 nicklas 324     if (Request.COMMAND_CONFIGURE_JOB.equals(command))
4571 14 Sep 17 nicklas 325     {
4571 14 Sep 17 nicklas 326       if (sc.getActiveProjectId() == 0)
4571 14 Sep 17 nicklas 327       {
4571 14 Sep 17 nicklas 328         throw new PermissionDeniedException("This plug-in requires an active project!");
4571 14 Sep 17 nicklas 329       }
4571 14 Sep 17 nicklas 330       requestInformation = getConfigureExportParameters();
4571 14 Sep 17 nicklas 331     }
4571 14 Sep 17 nicklas 332     return requestInformation;
4571 14 Sep 17 nicklas 333   }
4571 14 Sep 17 nicklas 334   
4571 14 Sep 17 nicklas 335   @Override
4571 14 Sep 17 nicklas 336   public void configure(GuiContext context, Request request, Response response) 
4571 14 Sep 17 nicklas 337   {
4571 14 Sep 17 nicklas 338     String command = request.getCommand();    
4571 14 Sep 17 nicklas 339     try
4571 14 Sep 17 nicklas 340     {
4571 14 Sep 17 nicklas 341       if (command.equals(Request.COMMAND_CONFIGURE_JOB))
4571 14 Sep 17 nicklas 342       {
4571 14 Sep 17 nicklas 343         RequestInformation ri = getConfigureExportParameters();
4571 14 Sep 17 nicklas 344         List<Throwable> errors = validateRequestParameters(ri.getParameters(), request);
4571 14 Sep 17 nicklas 345         if (errors != null)
4571 14 Sep 17 nicklas 346         {
4571 14 Sep 17 nicklas 347           response.setError(errors.size() + " invalid parameters were found in the request", errors);
4571 14 Sep 17 nicklas 348           return;
4571 14 Sep 17 nicklas 349         }
4571 14 Sep 17 nicklas 350         
4571 14 Sep 17 nicklas 351         // We need to verify that all items in the list are of the same subtype
4571 14 Sep 17 nicklas 352         ItemList list = (ItemList)request.getParameterValue("itemList");
4571 14 Sep 17 nicklas 353         String error = validateList(list);
4571 14 Sep 17 nicklas 354         if (error != null)
4571 14 Sep 17 nicklas 355         {
4571 14 Sep 17 nicklas 356           response.setError(error, null);
4571 14 Sep 17 nicklas 357           return;
4571 14 Sep 17 nicklas 358         }
4571 14 Sep 17 nicklas 359         
4571 14 Sep 17 nicklas 360         FileServer server = (FileServer)request.getParameterValue("fileServer");
4571 14 Sep 17 nicklas 361         String releaseVersion = (String)request.getParameterValue("releaseVersion");
4571 14 Sep 17 nicklas 362         if (!releaseVersion.matches("\\d+\\.\\d+"))
4571 14 Sep 17 nicklas 363         {
4571 14 Sep 17 nicklas 364           response.setError("Release version must match &lt;<i>major.minor</i>&gt; where " +
4571 14 Sep 17 nicklas 365               "<i>major</i> and <i>minor</i> are numeric values: " + releaseVersion, null);
4571 14 Sep 17 nicklas 366           return;
4571 14 Sep 17 nicklas 367         }
4571 14 Sep 17 nicklas 368         
4571 14 Sep 17 nicklas 369         if (!Boolean.TRUE.equals(request.getParameterValue("overwrite")))
4571 14 Sep 17 nicklas 370         {
4571 14 Sep 17 nicklas 371           // Check that the release directory doesn't already exists on the file server 
4571 14 Sep 17 nicklas 372           DbControl dc = null;
4571 14 Sep 17 nicklas 373           RemoteSession session = null;
4571 14 Sep 17 nicklas 374           try
4571 14 Sep 17 nicklas 375           {
4571 14 Sep 17 nicklas 376             // Make some pre-checks before accepting the job
4571 14 Sep 17 nicklas 377             dc = sc.newDbControl();
4571 14 Sep 17 nicklas 378             server = FileServer.getById(dc, server.getId());
4571 14 Sep 17 nicklas 379             String path = server.getRootPath() + "/" + releaseVersion;
4571 14 Sep 17 nicklas 380             
4571 14 Sep 17 nicklas 381             ConnectionInfo ci = new ConnectionInfo(server);
4571 14 Sep 17 nicklas 382             RemoteHost host = new RemoteHost(ci);
4571 14 Sep 17 nicklas 383             session = host.connect(5);
4571 14 Sep 17 nicklas 384             
4571 14 Sep 17 nicklas 385             ScriptBuilder script = new ScriptBuilder();
4571 14 Sep 17 nicklas 386             script.cmd("if [ -d " + path + " ]; then");
4571 14 Sep 17 nicklas 387             script.cmd("  exit 99");
4571 14 Sep 17 nicklas 388             script.cmd("fi");
4571 14 Sep 17 nicklas 389             
4571 14 Sep 17 nicklas 390             CmdResult<String> checkDir = session.executeCmd(script.toString(), 5);
4571 14 Sep 17 nicklas 391             if (checkDir.getExitStatus() == 99)
4571 14 Sep 17 nicklas 392             {
4571 14 Sep 17 nicklas 393               response.setError("Directory already exists on host '" + server.getHost() + "': " + path, null);
4571 14 Sep 17 nicklas 394               return;
4571 14 Sep 17 nicklas 395             }
4571 14 Sep 17 nicklas 396             checkDir.throwExceptionIfNonZeroExitStatus();
4571 14 Sep 17 nicklas 397           }
4571 14 Sep 17 nicklas 398           catch (RuntimeException ex)
4571 14 Sep 17 nicklas 399           {
4571 14 Sep 17 nicklas 400             response.setError(ex.getMessage(), Collections.singletonList(ex));
4571 14 Sep 17 nicklas 401             return;
4571 14 Sep 17 nicklas 402           }
4571 14 Sep 17 nicklas 403           finally
4571 14 Sep 17 nicklas 404           {
4571 14 Sep 17 nicklas 405             if (dc != null) dc.close();
4571 14 Sep 17 nicklas 406             OpenGrid.close(session);
4571 14 Sep 17 nicklas 407           }
4571 14 Sep 17 nicklas 408         }
4571 14 Sep 17 nicklas 409
4571 14 Sep 17 nicklas 410         storeValue(job, request, ri.getParameter("itemList"));
4571 14 Sep 17 nicklas 411         storeValue(job, request, ri.getParameter("fileServer"));
4571 14 Sep 17 nicklas 412         storeValue(job, request, ri.getParameter("releaseVersion"));
4571 14 Sep 17 nicklas 413         storeValue(job, request, ri.getParameter("overwrite"));
5557 13 Aug 19 nicklas 414         storeValue(job, request, ri.getParameter("debugMode"));
4572 15 Sep 17 nicklas 415         storeValue(job, request, ri.getParameter("incaCategory"));
4571 14 Sep 17 nicklas 416         job.getJob().setDescription("Specify version '" + releaseVersion + "' when importing on the level 3 server.");
4571 14 Sep 17 nicklas 417         
4571 14 Sep 17 nicklas 418         response.setSuggestedJobName("Level 3 export for '" + list.getName() + "' (version " + releaseVersion + ")");
4571 14 Sep 17 nicklas 419         response.setDone("The job configuration is complete", ExecutionTime.MEDIUM);
4571 14 Sep 17 nicklas 420       }
4571 14 Sep 17 nicklas 421     }
4571 14 Sep 17 nicklas 422     catch (Throwable ex)
4571 14 Sep 17 nicklas 423     {
4571 14 Sep 17 nicklas 424       response.setError(ex.getMessage(), Arrays.asList(ex));
4571 14 Sep 17 nicklas 425     }
4571 14 Sep 17 nicklas 426   }
4571 14 Sep 17 nicklas 427   
4571 14 Sep 17 nicklas 428   /**
4571 14 Sep 17 nicklas 429     Check that all items in the list are of the same subtype.
4571 14 Sep 17 nicklas 430     This is an initial check only which should be fairly quick.
4571 14 Sep 17 nicklas 431     During the export, additional checks are made to ensure that 
4571 14 Sep 17 nicklas 432     all parent items are following the same path up to the topmost 
4571 14 Sep 17 nicklas 433     parent.
4571 14 Sep 17 nicklas 434   */
4571 14 Sep 17 nicklas 435   private String validateList(ItemList list)
4571 14 Sep 17 nicklas 436   {
4571 14 Sep 17 nicklas 437     DbControl dc = null;
4571 14 Sep 17 nicklas 438     try
4571 14 Sep 17 nicklas 439     {
4571 14 Sep 17 nicklas 440       dc = sc.newDbControl();
4571 14 Sep 17 nicklas 441       ItemQuery<? extends Listable> query = list.getMembers();
4571 14 Sep 17 nicklas 442       query.setIncludes(Relax.INCLUDE_IN_CURRENT_PROJECT);
4571 14 Sep 17 nicklas 443       query.order(Orders.asc(Hql.property("name")));
4571 14 Sep 17 nicklas 444       
4571 14 Sep 17 nicklas 445       List<? extends Listable> items = query.list(dc);
5246 18 Jan 19 nicklas 446       if (items.size() == 0) return "The '"+list.getName()+"' list is empty.";
5246 18 Jan 19 nicklas 447       
5246 18 Jan 19 nicklas 448       if (list.getSize() != items.size())
5246 18 Jan 19 nicklas 449       {
5246 18 Jan 19 nicklas 450         int notInProject = list.getSize() - items.size();
5246 18 Jan 19 nicklas 451         return "The '"+list.getName()+"' list contains "+notInProject+" items that are not shared to the current project.";
5246 18 Jan 19 nicklas 452       }
5244 18 Jan 19 nicklas 453
4571 14 Sep 17 nicklas 454       for (Listable item : items)
4571 14 Sep 17 nicklas 455       {
4571 14 Sep 17 nicklas 456         CohortItem ch = new CohortItem(item);
4571 14 Sep 17 nicklas 457         String subtype = ch.getSubtype();
4571 14 Sep 17 nicklas 458         if (subtype == null) return "Missing subtype on item '" + item.getName() + "'.";
4571 14 Sep 17 nicklas 459       }
4571 14 Sep 17 nicklas 460     }
4571 14 Sep 17 nicklas 461     finally
4571 14 Sep 17 nicklas 462     {
4571 14 Sep 17 nicklas 463       if (dc != null) dc.close();
4571 14 Sep 17 nicklas 464     }
4571 14 Sep 17 nicklas 465     return null;
4571 14 Sep 17 nicklas 466   }
4571 14 Sep 17 nicklas 467   
4571 14 Sep 17 nicklas 468   
4571 14 Sep 17 nicklas 469   /*
4571 14 Sep 17 nicklas 470     From the SignalTarget interface
4571 14 Sep 17 nicklas 471     -------------------------------------------
4571 14 Sep 17 nicklas 472   */
4571 14 Sep 17 nicklas 473   @Override
4571 14 Sep 17 nicklas 474   public SignalHandler getSignalHandler()
4571 14 Sep 17 nicklas 475   {
4571 14 Sep 17 nicklas 476     signalHandler = new ThreadSignalHandler();
4571 14 Sep 17 nicklas 477     return signalHandler;
4571 14 Sep 17 nicklas 478   }
4571 14 Sep 17 nicklas 479   // -------------------------------------------
4571 14 Sep 17 nicklas 480
4571 14 Sep 17 nicklas 481   
4571 14 Sep 17 nicklas 482   private RequestInformation getConfigureExportParameters()
4571 14 Sep 17 nicklas 483   {
4571 14 Sep 17 nicklas 484     if (configureExport == null)
4571 14 Sep 17 nicklas 485     {
4571 14 Sep 17 nicklas 486       DbControl dc = null;
4571 14 Sep 17 nicklas 487       List<PluginParameter<?>> parameters = new ArrayList<PluginParameter<?>>();
4571 14 Sep 17 nicklas 488       try
4571 14 Sep 17 nicklas 489       {
4571 14 Sep 17 nicklas 490         dc = sc.newDbControl();
4571 14 Sep 17 nicklas 491         
4571 14 Sep 17 nicklas 492         // Load the current item list
4571 14 Sep 17 nicklas 493         ItemList currentList = null;
4571 14 Sep 17 nicklas 494         int currentListId = sc.getCurrentContext(Item.ITEMLIST).getId();
4571 14 Sep 17 nicklas 495         if (currentListId != 0)
4571 14 Sep 17 nicklas 496         {
4571 14 Sep 17 nicklas 497           currentList = ItemList.getById(dc, currentListId);
4571 14 Sep 17 nicklas 498         }
4571 14 Sep 17 nicklas 499         
4571 14 Sep 17 nicklas 500         parameters.add(new PluginParameter<ItemList>(
4571 14 Sep 17 nicklas 501           "itemList", "Item list", "Select the list with items to export. "+
4571 14 Sep 17 nicklas 502           "All items in the list must be of the same type and subtype. ", 
4571 14 Sep 17 nicklas 503           new ItemParameterType<ItemList>(ItemList.class, currentList, true, 1, null)
4571 14 Sep 17 nicklas 504         ));
4571 14 Sep 17 nicklas 505         
4571 14 Sep 17 nicklas 506         ItemQuery<FileServer> query = FileServer.getQuery();
4571 14 Sep 17 nicklas 507         query.setIncludes(Include.ALL);
4571 14 Sep 17 nicklas 508         query.restrict(
4571 14 Sep 17 nicklas 509           Restrictions.eq(
4571 14 Sep 17 nicklas 510             Hql.property("connectionManagerFactory"), 
4571 14 Sep 17 nicklas 511             Expressions.string("net.sf.basedb.xfiles.sftp-connection-manager")
4571 14 Sep 17 nicklas 512           ));
4571 14 Sep 17 nicklas 513         List<FileServer> fileServers = new ArrayList<FileServer>(query.list(dc));
4578 19 Sep 17 nicklas 514         FileServer level3Archive = Fileserver.LEVEL3_ARCHIVE.load(dc);
4578 19 Sep 17 nicklas 515         if (!fileServers.contains(level3Archive)) fileServers.add(level3Archive);
4608 03 Oct 17 nicklas 516         if (Relax.getServerMode() == ServerMode.RELAX)
4608 03 Oct 17 nicklas 517         {
4608 03 Oct 17 nicklas 518           // We should not store level-3 data on the relax release archive
4608 03 Oct 17 nicklas 519           // IT MAY OVERWRITE DATA FILES COMING FROM REGGIE
4608 03 Oct 17 nicklas 520           fileServers.remove(Fileserver.RELEASE_ARCHIVE.load(dc));
4608 03 Oct 17 nicklas 521         }
4571 14 Sep 17 nicklas 522         fileServers.sort(new NameableComparator<>(false));
4571 14 Sep 17 nicklas 523   
4571 14 Sep 17 nicklas 524         parameters.add(new PluginParameter<FileServer>(
4571 14 Sep 17 nicklas 525           "fileServer", "File server",
4571 14 Sep 17 nicklas 526           "Select the file server where the exported files should be saved.",
4578 19 Sep 17 nicklas 527           new ItemParameterType<>(FileServer.class, level3Archive, true, 1, fileServers)
4571 14 Sep 17 nicklas 528         ));
4571 14 Sep 17 nicklas 529   
4571 14 Sep 17 nicklas 530         Project p = Project.getById(dc, sc.getActiveProjectId());
4571 14 Sep 17 nicklas 531         Pattern getVersion = Pattern.compile("(\\d+\\.\\d+)");
4571 14 Sep 17 nicklas 532         Matcher m = getVersion.matcher(p.getName());
4571 14 Sep 17 nicklas 533         String releaseVersion = m.find() ? m.group(1) : null;
4571 14 Sep 17 nicklas 534         
4571 14 Sep 17 nicklas 535         parameters.add(new PluginParameter<String>(
4571 14 Sep 17 nicklas 536           "releaseVersion", "Release version",
4571 14 Sep 17 nicklas 537           "The version number of this release. It should consist of a major and minor " +
4571 14 Sep 17 nicklas 538           "number separated with a dot. For example: 1.0, 1.2, 2.1. When creating " + 
4571 14 Sep 17 nicklas 539           "a remote release the version must not already exist, unless the overwrite " +
4571 14 Sep 17 nicklas 540           "parameter is set.",
4571 14 Sep 17 nicklas 541           new StringParameterType(255, releaseVersion, true)));
4571 14 Sep 17 nicklas 542           
4571 14 Sep 17 nicklas 543         parameters.add(new PluginParameter<Boolean>(
4571 14 Sep 17 nicklas 544           "overwrite", "Overwrite", "Is it allowed to overwrite existing files or not?",
4571 14 Sep 17 nicklas 545           new BooleanParameterType(null, false)
4571 14 Sep 17 nicklas 546         ));
4572 15 Sep 17 nicklas 547         
4572 15 Sep 17 nicklas 548         ItemQuery<AnnotationTypeCategory> catQuery = AnnotationTypeCategory.getQuery();
4572 15 Sep 17 nicklas 549         catQuery.setIncludes(Relax.INCLUDE_IN_CURRENT_PROJECT);
4579 20 Sep 17 nicklas 550         catQuery.join(Hql.innerJoin("annotationTypes", "at"));
4737 05 Apr 18 nicklas 551         catQuery.restrict(Restrictions.like(Hql.property("at", "name"), Expressions.string("INCA%")));
4572 15 Sep 17 nicklas 552         catQuery.order(Orders.asc(Hql.property("name")));
4579 20 Sep 17 nicklas 553         catQuery.setDistinct(true);
4572 15 Sep 17 nicklas 554         
4572 15 Sep 17 nicklas 555         List<AnnotationTypeCategory> categories = new ArrayList<AnnotationTypeCategory>(catQuery.list(dc));
4572 15 Sep 17 nicklas 556   
4572 15 Sep 17 nicklas 557         parameters.add(new PluginParameter<AnnotationTypeCategory>(
4572 15 Sep 17 nicklas 558           "incaCategory", "INCA annotations",
4572 15 Sep 17 nicklas 559           "Select the category with INCA annotations. "+
4772 19 Apr 18 nicklas 560           "If no category is selected NO INCA annotations are included in the export.",
4572 15 Sep 17 nicklas 561           new ItemParameterType<>(AnnotationTypeCategory.class, null, false, 1, categories)
4572 15 Sep 17 nicklas 562         ));
5557 13 Aug 19 nicklas 563         
5557 13 Aug 19 nicklas 564         // If <developer-mode>1</developer-mode> is in relax-config.xml we allow debug via parameter
5557 13 Aug 19 nicklas 565         if (Values.getBoolean(Relax.getConfig().getConfig("developer-mode")))
5557 13 Aug 19 nicklas 566         {
5557 13 Aug 19 nicklas 567           parameters.add(new PluginParameter<Boolean>(
5557 13 Aug 19 nicklas 568             "debugMode", "Debug mode", "Runs the plug-in in debug mode. Major difference is "
5557 13 Aug 19 nicklas 569                 + "that it will always report an error making it easier to re-start the "
5557 13 Aug 19 nicklas 570                 + "plug-in with the same parameters.",
5557 13 Aug 19 nicklas 571             new BooleanParameterType(null, false)
5557 13 Aug 19 nicklas 572             ));
5557 13 Aug 19 nicklas 573         }
4572 15 Sep 17 nicklas 574
4571 14 Sep 17 nicklas 575       }
4571 14 Sep 17 nicklas 576       finally
4571 14 Sep 17 nicklas 577       {
4571 14 Sep 17 nicklas 578         if (dc != null) dc.close();
4571 14 Sep 17 nicklas 579       }
4571 14 Sep 17 nicklas 580
4571 14 Sep 17 nicklas 581     
4571 14 Sep 17 nicklas 582       configureExport = new RequestInformation
4571 14 Sep 17 nicklas 583       (
4571 14 Sep 17 nicklas 584         Request.COMMAND_CONFIGURE_JOB,
4571 14 Sep 17 nicklas 585         "Exporter options",
4571 14 Sep 17 nicklas 586         "Select the item list and where to save the exported data files.",
4571 14 Sep 17 nicklas 587         parameters
4571 14 Sep 17 nicklas 588       );
4571 14 Sep 17 nicklas 589     }
4571 14 Sep 17 nicklas 590     return configureExport;
4571 14 Sep 17 nicklas 591   }
4571 14 Sep 17 nicklas 592
4571 14 Sep 17 nicklas 593   
4576 18 Sep 17 nicklas 594   public JSONObject createIndex(ItemList list, String version)
4571 14 Sep 17 nicklas 595   {
4571 14 Sep 17 nicklas 596     JSONObject json = new JSONObject();
4571 14 Sep 17 nicklas 597     
4576 18 Sep 17 nicklas 598     JSONObject jsonRelease = new JSONObject();
4576 18 Sep 17 nicklas 599     jsonRelease.put("version", version);
4576 18 Sep 17 nicklas 600     json.put("release", jsonRelease);
4571 14 Sep 17 nicklas 601     
4576 18 Sep 17 nicklas 602     JSONObject jsonList = new JSONObject();
4576 18 Sep 17 nicklas 603     jsonList.put("name", list.getName());
4576 18 Sep 17 nicklas 604     jsonList.put("size", list.getSize());
4576 18 Sep 17 nicklas 605     json.put("list", jsonList);
4571 14 Sep 17 nicklas 606     
4571 14 Sep 17 nicklas 607     return json;
4571 14 Sep 17 nicklas 608   }
4571 14 Sep 17 nicklas 609   
4576 18 Sep 17 nicklas 610   public void writeJSON(FileServerOutputLocation location, String filename, JSONStreamAware json)
4571 14 Sep 17 nicklas 611   {
4571 14 Sep 17 nicklas 612     ExportOutputStream out = null;
4571 14 Sep 17 nicklas 613     try
4571 14 Sep 17 nicklas 614     {
4576 18 Sep 17 nicklas 615       out = location.getOutputStream(filename, false);
4571 14 Sep 17 nicklas 616       out.setCharacterSet("UTF-8");
4571 14 Sep 17 nicklas 617       out.setMimeType("application/json");
4571 14 Sep 17 nicklas 618       Writer writer = new OutputStreamWriter(out, Charset.forName("UTF-8"));
4576 18 Sep 17 nicklas 619       json.writeJSONString(writer);
4571 14 Sep 17 nicklas 620       writer.flush();
4571 14 Sep 17 nicklas 621       out.flush();
4571 14 Sep 17 nicklas 622       writer.close();
4571 14 Sep 17 nicklas 623     }
4571 14 Sep 17 nicklas 624     catch (IOException ex)
4571 14 Sep 17 nicklas 625     {
4571 14 Sep 17 nicklas 626       throw new RuntimeException(ex);
4571 14 Sep 17 nicklas 627     }
4571 14 Sep 17 nicklas 628     finally
4571 14 Sep 17 nicklas 629     {
4571 14 Sep 17 nicklas 630       FileUtil.close(out);
4576 18 Sep 17 nicklas 631     }
4571 14 Sep 17 nicklas 632   }
4576 18 Sep 17 nicklas 633
4571 14 Sep 17 nicklas 634   static class CohortJSONWriter
4571 14 Sep 17 nicklas 635   {
4571 14 Sep 17 nicklas 636     private final Item itemType;
4571 14 Sep 17 nicklas 637     private final String subtype;
4576 18 Sep 17 nicklas 638     private List<AnnotationTypeFilter> snapshotFilter;
4576 18 Sep 17 nicklas 639     private List<String> annotationNames;
4575 15 Sep 17 nicklas 640     private List<DataFileType> fileTypes;
4571 14 Sep 17 nicklas 641     
4571 14 Sep 17 nicklas 642     CohortJSONWriter(Item itemType, String subtype)
4571 14 Sep 17 nicklas 643     {
4571 14 Sep 17 nicklas 644       this.itemType = itemType;
4571 14 Sep 17 nicklas 645       this.subtype = subtype;
4571 14 Sep 17 nicklas 646     }
4571 14 Sep 17 nicklas 647     
5245 18 Jan 19 nicklas 648     JSONArray getTypeDefs(DbControl dc, Set<AnnotationType> incaAnnotations, Set<AnnotationType> excludeFromExport)
4571 14 Sep 17 nicklas 649     {
4571 14 Sep 17 nicklas 650       
4571 14 Sep 17 nicklas 651       ItemQuery<AnnotationType> query = AnnotationType.getQuery(itemType);
4571 14 Sep 17 nicklas 652       query.setIncludes(Relax.INCLUDE_IN_CURRENT_PROJECT);
5244 18 Jan 19 nicklas 653       if (subtype != null)
4571 14 Sep 17 nicklas 654       {
4571 14 Sep 17 nicklas 655         query.join(Hql.innerJoin("categories", "cat"));
4571 14 Sep 17 nicklas 656         query.restrict(Restrictions.eq(Hql.property("cat", "name"), Expressions.string(subtype)));
4571 14 Sep 17 nicklas 657       }
4571 14 Sep 17 nicklas 658       query.order(Orders.asc(Hql.property("name")));
4571 14 Sep 17 nicklas 659       
4571 14 Sep 17 nicklas 660       List<AnnotationType> list = query.list(dc);
4576 18 Sep 17 nicklas 661       this.snapshotFilter = new ArrayList<>(list.size());
4576 18 Sep 17 nicklas 662       this.annotationNames = new ArrayList<>(list.size());
4571 14 Sep 17 nicklas 663       
4571 14 Sep 17 nicklas 664       int col = 0;
4571 14 Sep 17 nicklas 665       JSONArray json = new JSONArray();
4571 14 Sep 17 nicklas 666       for (AnnotationType at : list)
4571 14 Sep 17 nicklas 667       {
5245 18 Jan 19 nicklas 668         // Skip excluded annotation types
5245 18 Jan 19 nicklas 669         if (excludeFromExport.contains(at)) continue;
5245 18 Jan 19 nicklas 670         
4572 15 Sep 17 nicklas 671         String name = at.getName();
4772 19 Apr 18 nicklas 672         if (name.startsWith("INCA") && !incaAnnotations.contains(at))
4572 15 Sep 17 nicklas 673         {
4772 19 Apr 18 nicklas 674           // Skip this INCA* annotation since it is not in the predefined set
4772 19 Apr 18 nicklas 675           continue;
4572 15 Sep 17 nicklas 676         }
4572 15 Sep 17 nicklas 677         
4576 18 Sep 17 nicklas 678         snapshotFilter.add(new AnnotationTypeFilter(at));
4576 18 Sep 17 nicklas 679         annotationNames.add(name);
4571 14 Sep 17 nicklas 680         json.add(createAnnotationTypeDef(at));
4571 14 Sep 17 nicklas 681         col++;
4571 14 Sep 17 nicklas 682       }
4575 15 Sep 17 nicklas 683       
4737 05 Apr 18 nicklas 684       if (itemType == Item.RAWBIOASSAY)
4575 15 Sep 17 nicklas 685       {
4575 15 Sep 17 nicklas 686         fileTypes = new ArrayList<>();
5244 18 Jan 19 nicklas 687         if (Rawdatatype.CUFFLINKS.getName().equals(subtype))
4737 05 Apr 18 nicklas 688         {
5244 18 Jan 19 nicklas 689           // We should export the FPKM file (isoforms.fpkm_tracking)
4737 05 Apr 18 nicklas 690           fileTypes.add(Datafiletype.FPKM.get(dc));
4737 05 Apr 18 nicklas 691           json.add(createFileTypeDef(Datafiletype.FPKM, Rawdatatype.CUFFLINKS));
4737 05 Apr 18 nicklas 692         }
5244 18 Jan 19 nicklas 693         else if (Rawdatatype.STRINGTIE.getName().equals(subtype))
4737 05 Apr 18 nicklas 694         {
5244 18 Jan 19 nicklas 695           // We should export the gene.tsv
4737 05 Apr 18 nicklas 696           fileTypes.add(Datafiletype.GENERIC_RAWDATA.get(dc));
4737 05 Apr 18 nicklas 697           json.add(createFileTypeDef(Datafiletype.GENERIC_RAWDATA, Rawdatatype.STRINGTIE));
4737 05 Apr 18 nicklas 698         }
4575 15 Sep 17 nicklas 699       }
4575 15 Sep 17 nicklas 700       
4571 14 Sep 17 nicklas 701       return json;
4571 14 Sep 17 nicklas 702     }
4571 14 Sep 17 nicklas 703     
4577 19 Sep 17 nicklas 704     JSONObject getItemAsJSON(DbControl dc, CohortItem item, SnapshotManager manager, ScriptWriter script)
4571 14 Sep 17 nicklas 705     {
4571 14 Sep 17 nicklas 706       JSONObject json = new JSONObject();
4571 14 Sep 17 nicklas 707
4571 14 Sep 17 nicklas 708       json.put("name",item.getName());
4571 14 Sep 17 nicklas 709       json.put("type", item.getType().name());
4571 14 Sep 17 nicklas 710       
4576 18 Sep 17 nicklas 711       Extract lib = null;
4571 14 Sep 17 nicklas 712       if (item.getType() == Item.RAWBIOASSAY)
4571 14 Sep 17 nicklas 713       {
4571 14 Sep 17 nicklas 714         RawBioAssay raw = (RawBioAssay)item.getItem();
4571 14 Sep 17 nicklas 715         json.put("rawdatatype", raw.getRawDataType().getId());
4571 14 Sep 17 nicklas 716         Platform platform = raw.getPlatform();
4571 14 Sep 17 nicklas 717         if (platform != null) json.put("platform", platform.getExternalId());
4571 14 Sep 17 nicklas 718         PlatformVariant variant = raw.getVariant();
4571 14 Sep 17 nicklas 719         if (variant != null) json.put("platformVariant", variant.getExternalId());
4576 18 Sep 17 nicklas 720         lib = raw.getParentExtract();
4571 14 Sep 17 nicklas 721       }
4571 14 Sep 17 nicklas 722       else if (item.getType() == Item.DERIVEDBIOASSAY)
4571 14 Sep 17 nicklas 723       {
4571 14 Sep 17 nicklas 724         DerivedBioAssay dba = (DerivedBioAssay)item.getItem();
4576 18 Sep 17 nicklas 725         lib = dba.getExtract();
4571 14 Sep 17 nicklas 726         json.put("subtype", item.getSubtype());
4571 14 Sep 17 nicklas 727       }
4571 14 Sep 17 nicklas 728       else
4571 14 Sep 17 nicklas 729       {
4571 14 Sep 17 nicklas 730         json.put("subtype", item.getSubtype());
4571 14 Sep 17 nicklas 731       }
4576 18 Sep 17 nicklas 732       
4571 14 Sep 17 nicklas 733       Nameable parent = item.getParentItem(dc);
4576 18 Sep 17 nicklas 734       if (parent != null && !parent.equals(lib))
4576 18 Sep 17 nicklas 735       {
4576 18 Sep 17 nicklas 736         json.put("parent", parent.getName());
4576 18 Sep 17 nicklas 737       }
4576 18 Sep 17 nicklas 738       if (lib != null) json.put("extract", lib.getName());
4571 14 Sep 17 nicklas 739       
4571 14 Sep 17 nicklas 740       JSONArray jsonAnnotations = new JSONArray();
4577 19 Sep 17 nicklas 741       String releaseFolder = null;
4576 18 Sep 17 nicklas 742       for (int index = 0; index < snapshotFilter.size(); index++)
4571 14 Sep 17 nicklas 743       {
4576 18 Sep 17 nicklas 744         AnnotationTypeFilter filter = snapshotFilter.get(index);
4576 18 Sep 17 nicklas 745         String annotation = annotationNames.get(index);
4577 19 Sep 17 nicklas 746         boolean isDataFilesFolder = "DataFilesFolder".equals(annotation);
4577 19 Sep 17 nicklas 747         if (isDataFilesFolder)
4572 15 Sep 17 nicklas 748         {
4572 15 Sep 17 nicklas 749           manager.setProject(null); // Force default values
4572 15 Sep 17 nicklas 750         }
4572 15 Sep 17 nicklas 751         else
4572 15 Sep 17 nicklas 752         {
4572 15 Sep 17 nicklas 753           manager.setNoProject(); // Use project-specific if they exists or default otherwise
4572 15 Sep 17 nicklas 754         }
4571 14 Sep 17 nicklas 755         List<AnnotationSnapshot> snapshots = manager.findAnnotations(dc, (Annotatable)item.getItem(), filter, false);
4571 14 Sep 17 nicklas 756         Object value = snapshots.size() > 0 ? snapshots.get(0).getThisValues().get(0) : null;
4571 14 Sep 17 nicklas 757         
4571 14 Sep 17 nicklas 758         if (value != null)
4571 14 Sep 17 nicklas 759         {
4577 19 Sep 17 nicklas 760           if (isDataFilesFolder)
4577 19 Sep 17 nicklas 761           {
4577 19 Sep 17 nicklas 762             releaseFolder = (String)value;
4577 19 Sep 17 nicklas 763             script.addMkDir(releaseFolder);
4577 19 Sep 17 nicklas 764           }
4577 19 Sep 17 nicklas 765           
4571 14 Sep 17 nicklas 766           JSONObject jsonAnnotation = new JSONObject();
4572 15 Sep 17 nicklas 767           jsonAnnotation.put("name", annotation);
4571 14 Sep 17 nicklas 768           jsonAnnotation.put("value", value);
4571 14 Sep 17 nicklas 769           jsonAnnotations.add(jsonAnnotation);
4571 14 Sep 17 nicklas 770         }
4571 14 Sep 17 nicklas 771       }
4571 14 Sep 17 nicklas 772       json.put("annotations", jsonAnnotations);
4571 14 Sep 17 nicklas 773       
4575 15 Sep 17 nicklas 774       if (fileTypes != null && fileTypes.size() > 0)
4575 15 Sep 17 nicklas 775       {
4771 19 Apr 18 nicklas 776         JSONArray jsonFiles = new FilteredJSONArray(new NotNullFilter<>(false));
4575 15 Sep 17 nicklas 777         FileStoreEnabled fs = (FileStoreEnabled)item.getItem();
4575 15 Sep 17 nicklas 778         for (DataFileType dft : fileTypes)
4575 15 Sep 17 nicklas 779         {
4575 15 Sep 17 nicklas 780           jsonFiles.addAll(getDataFilesJSON(dc, dft, fs, null));
4575 15 Sep 17 nicklas 781         }
4575 15 Sep 17 nicklas 782         json.put("files", jsonFiles);
4577 19 Sep 17 nicklas 783         script.addFiles(releaseFolder, jsonFiles);
4575 15 Sep 17 nicklas 784       }
4575 15 Sep 17 nicklas 785       
4571 14 Sep 17 nicklas 786       return json;
4571 14 Sep 17 nicklas 787     }
4571 14 Sep 17 nicklas 788     
4571 14 Sep 17 nicklas 789     
4571 14 Sep 17 nicklas 790     private JSONObject createAnnotationTypeDef(AnnotationType at)
4571 14 Sep 17 nicklas 791     {
4571 14 Sep 17 nicklas 792       JSONObject json = new JSONObject();
4571 14 Sep 17 nicklas 793       
4571 14 Sep 17 nicklas 794       json.put("type", Item.ANNOTATIONTYPE.name());
4571 14 Sep 17 nicklas 795       json.put("name", at.getName());
4571 14 Sep 17 nicklas 796       json.put("valueType", at.getValueType().name());
4571 14 Sep 17 nicklas 797       json.put("itemType", itemType.name());
5244 18 Jan 19 nicklas 798       if (subtype != null)
4571 14 Sep 17 nicklas 799       {
4571 14 Sep 17 nicklas 800         json.put("subtype", subtype);
4571 14 Sep 17 nicklas 801       }
4571 14 Sep 17 nicklas 802       if (at.getProjectAnnotations())
4571 14 Sep 17 nicklas 803       {
4571 14 Sep 17 nicklas 804         json.put("projectSpecificValues", true);
4571 14 Sep 17 nicklas 805       }
4571 14 Sep 17 nicklas 806       
4571 14 Sep 17 nicklas 807       if (at.isEnumeration())
4571 14 Sep 17 nicklas 808       {
4571 14 Sep 17 nicklas 809         JSONArray jsonEnum = new JSONArray();
4571 14 Sep 17 nicklas 810         jsonEnum.addAll(at.getValues());
4571 14 Sep 17 nicklas 811         json.put("enumeration", jsonEnum);
4571 14 Sep 17 nicklas 812       }
4571 14 Sep 17 nicklas 813       
4571 14 Sep 17 nicklas 814       if (at.supportUnits())
4571 14 Sep 17 nicklas 815       {
4571 14 Sep 17 nicklas 816         Unit unit = at.getDefaultUnit();
4571 14 Sep 17 nicklas 817         JSONObject jsonUnit = new JSONObject();
4571 14 Sep 17 nicklas 818         jsonUnit.put("symbol", unit.getDisplaySymbol());
4571 14 Sep 17 nicklas 819         jsonUnit.put("quantity", unit.getQuantity().getSystemId());
4571 14 Sep 17 nicklas 820         json.put("unit", jsonUnit);
4571 14 Sep 17 nicklas 821       }
4571 14 Sep 17 nicklas 822       
4571 14 Sep 17 nicklas 823       return json;
4571 14 Sep 17 nicklas 824     }
4575 15 Sep 17 nicklas 825     
4575 15 Sep 17 nicklas 826     
4737 05 Apr 18 nicklas 827     private JSONObject createFileTypeDef(Datafiletype dft, Rawdatatype platform)
4575 15 Sep 17 nicklas 828     {
4575 15 Sep 17 nicklas 829       JSONObject json = new JSONObject();
4575 15 Sep 17 nicklas 830             
4575 15 Sep 17 nicklas 831       json.put("type", Item.DATAFILETYPE.name());
4575 15 Sep 17 nicklas 832       json.put("name", dft.getName());
4575 15 Sep 17 nicklas 833       json.put("externalId", dft.getExternalId());
4575 15 Sep 17 nicklas 834       json.put("itemType", dft.getItemType().name());
4575 15 Sep 17 nicklas 835       json.put("extension", dft.getExtension());
4575 15 Sep 17 nicklas 836       Subtype genericType = dft.getSubtype();
4575 15 Sep 17 nicklas 837       if (genericType != null)
4575 15 Sep 17 nicklas 838       {
4575 15 Sep 17 nicklas 839         json.put("genericType", genericType.getName());
4575 15 Sep 17 nicklas 840       }
4575 15 Sep 17 nicklas 841       if (subtype != null && itemType != Item.RAWBIOASSAY)
4575 15 Sep 17 nicklas 842       {
4575 15 Sep 17 nicklas 843         json.put("subtype", subtype);
4575 15 Sep 17 nicklas 844         json.put("allowMultiple", dft.getAllowMultiple());
4575 15 Sep 17 nicklas 845         json.put("required", dft.isRequired());
4575 15 Sep 17 nicklas 846       }
4575 15 Sep 17 nicklas 847       if (platform != null)
4575 15 Sep 17 nicklas 848       {
4737 05 Apr 18 nicklas 849         json.put("platform", platform.getPlatformId());
4737 05 Apr 18 nicklas 850         if (platform.getVariantId() != null) json.put("variant", platform.getVariantId());
4575 15 Sep 17 nicklas 851         json.put("allowMultiple", dft.getAllowMultiple());
4575 15 Sep 17 nicklas 852         json.put("required", dft.isRequired());
4575 15 Sep 17 nicklas 853       }
4575 15 Sep 17 nicklas 854       
4575 15 Sep 17 nicklas 855       return json;
4575 15 Sep 17 nicklas 856     }
4571 14 Sep 17 nicklas 857
4575 15 Sep 17 nicklas 858     
4575 15 Sep 17 nicklas 859     public JSONArray getDataFilesJSON(DbControl dc, DataFileType dft, FileStoreEnabled item, Filter<File> filter)
4575 15 Sep 17 nicklas 860     {
4575 15 Sep 17 nicklas 861       ItemQuery<FileSetMember> query = item.getFileSet().getMembers(dft);
4575 15 Sep 17 nicklas 862       JSONArray jsonFiles = new JSONArray();
4575 15 Sep 17 nicklas 863       if (filter == null) filter = new StaticFilter<>(true);
4575 15 Sep 17 nicklas 864       for (FileSetMember mbr : query.list(dc))
4575 15 Sep 17 nicklas 865       {
4575 15 Sep 17 nicklas 866         File f = mbr.getFile();
4575 15 Sep 17 nicklas 867         if (filter.evaluate(f))
4575 15 Sep 17 nicklas 868         {
4577 19 Sep 17 nicklas 869           URI uri = f.getURI();
4577 19 Sep 17 nicklas 870           
4575 15 Sep 17 nicklas 871           JSONObject jsonFile = new JSONObject();
4575 15 Sep 17 nicklas 872           jsonFile.put("type", dft.getName());
4575 15 Sep 17 nicklas 873           jsonFile.put("name", f.getName());
4577 19 Sep 17 nicklas 874           if (uri != null)
4577 19 Sep 17 nicklas 875           {
4577 19 Sep 17 nicklas 876              // The "path" is needed for rsync script!!
4577 19 Sep 17 nicklas 877             jsonFile.put("path", uri.getPath());
4577 19 Sep 17 nicklas 878           }
4575 15 Sep 17 nicklas 879           jsonFile.put("size", f.getSize());
4575 15 Sep 17 nicklas 880           jsonFile.put("mimeType", f.getMimeType());
4575 15 Sep 17 nicklas 881           jsonFile.put("characterSet", f.getCharacterSet());
4575 15 Sep 17 nicklas 882           jsonFiles.add(jsonFile);
4575 15 Sep 17 nicklas 883         }
4575 15 Sep 17 nicklas 884       }
4575 15 Sep 17 nicklas 885       return jsonFiles;
4575 15 Sep 17 nicklas 886     }
4575 15 Sep 17 nicklas 887
4575 15 Sep 17 nicklas 888
4571 14 Sep 17 nicklas 889   }
4571 14 Sep 17 nicklas 890
4571 14 Sep 17 nicklas 891
4571 14 Sep 17 nicklas 892 }