plugins/base1/se.lu.onk.BaseFile/trunk/src/basefile/BASEFile.java

Code
Comments
Other
Rev Date Author Line
248 28 Mar 07 enell 1 /*
248 28 Mar 07 enell 2   $Id$
248 28 Mar 07 enell 3
248 28 Mar 07 enell 4   Copyright (C) 2006 Johan Enell
248 28 Mar 07 enell 5
782 18 Sep 08 jari 6   This file is part of the se.lu.onk.BaseFile package, a utility
782 18 Sep 08 jari 7   package for reading files generated by BASE. The package is
782 18 Sep 08 jari 8   available at http://baseplugins.thep.lu.se/ and BASE web site is
782 18 Sep 08 jari 9   http://base.thep.lu.se
248 28 Mar 07 enell 10
782 18 Sep 08 jari 11   This is free software; you can redistribute it and/or modify it
248 28 Mar 07 enell 12   under the terms of the GNU General Public License as published by
782 18 Sep 08 jari 13   the Free Software Foundation; either version 3 of the License, or
248 28 Mar 07 enell 14   (at your option) any later version.
248 28 Mar 07 enell 15
782 18 Sep 08 jari 16   The software is distributed in the hope that it will be useful, but
248 28 Mar 07 enell 17   WITHOUT ANY WARRANTY; without even the implied warranty of
782 18 Sep 08 jari 18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
248 28 Mar 07 enell 19   General Public License for more details.
248 28 Mar 07 enell 20
248 28 Mar 07 enell 21   You should have received a copy of the GNU General Public License
782 18 Sep 08 jari 22   along with BASE. If not, see <http://www.gnu.org/licenses/>.
248 28 Mar 07 enell 23 */
248 28 Mar 07 enell 24 package basefile;
248 28 Mar 07 enell 25
248 28 Mar 07 enell 26 import java.io.File;
248 28 Mar 07 enell 27 import java.io.IOException;
250 30 Mar 07 enell 28 import java.io.PrintWriter;
248 28 Mar 07 enell 29 import java.io.RandomAccessFile;
248 28 Mar 07 enell 30 import java.util.ArrayList;
250 30 Mar 07 enell 31 import java.util.HashMap;
263 24 Apr 07 enell 32 import java.util.List;
248 28 Mar 07 enell 33
248 28 Mar 07 enell 34 public class BASEFile<R, S>
248 28 Mar 07 enell 35 {
250 30 Mar 07 enell 36   private final File file;
248 28 Mar 07 enell 37   private final RandomAccessFile raf;
250 30 Mar 07 enell 38   private final boolean write;
250 30 Mar 07 enell 39   private BASEFileAssaySection assaySection = null;
250 30 Mar 07 enell 40   private ArrayList<BASEFileSpotSection<R, S>> spotSections = new ArrayList<BASEFileSpotSection<R,S>>();
250 30 Mar 07 enell 41   private ArrayList<BASEFileSection> sections = new ArrayList<BASEFileSection>();
250 30 Mar 07 enell 42   private HashMap<Integer, long[]> sectionPointers = new HashMap<Integer, long[]>();
250 30 Mar 07 enell 43   
248 28 Mar 07 enell 44   private BASEFileSection currentSection = null;
248 28 Mar 07 enell 45   
250 30 Mar 07 enell 46   @SuppressWarnings("unchecked")
250 30 Mar 07 enell 47   public BASEFile(File file, String mode) throws BASEFileException
248 28 Mar 07 enell 48   {
248 28 Mar 07 enell 49     try
248 28 Mar 07 enell 50     {
250 30 Mar 07 enell 51       this.file = file;
250 30 Mar 07 enell 52       if ("r".equals(mode))
248 28 Mar 07 enell 53       {
250 30 Mar 07 enell 54         write = false;
250 30 Mar 07 enell 55         raf = new RandomAccessFile(file, "r");
250 30 Mar 07 enell 56         String line = raf.readLine();
250 30 Mar 07 enell 57         if (!"BASEfile".equals(line))
250 30 Mar 07 enell 58         {
250 30 Mar 07 enell 59           throw new BASEFileException("File "+file.getAbsolutePath()+" is no basefile. First line must be 'BASEfile'");
250 30 Mar 07 enell 60         }
250 30 Mar 07 enell 61         BASEFileSection bfs = readSection();
250 30 Mar 07 enell 62         while (bfs != null)
250 30 Mar 07 enell 63         {
250 30 Mar 07 enell 64           if (bfs instanceof BASEFileAssaySection)
250 30 Mar 07 enell 65           {
250 30 Mar 07 enell 66             if (assaySection != null)
250 30 Mar 07 enell 67             {
250 30 Mar 07 enell 68               throw new BadFormatException("This basefile already has an assay section");
250 30 Mar 07 enell 69             }
250 30 Mar 07 enell 70             assaySection = (BASEFileAssaySection) bfs;
250 30 Mar 07 enell 71           }
250 30 Mar 07 enell 72           else if (bfs instanceof BASEFileSpotSection)
250 30 Mar 07 enell 73           {
250 30 Mar 07 enell 74             spotSections.add((BASEFileSpotSection<R, S>) bfs);
250 30 Mar 07 enell 75           }
250 30 Mar 07 enell 76           else
250 30 Mar 07 enell 77           {
250 30 Mar 07 enell 78             sections.add(bfs);
250 30 Mar 07 enell 79           }
250 30 Mar 07 enell 80           bfs = readSection();
250 30 Mar 07 enell 81         }
248 28 Mar 07 enell 82       }
250 30 Mar 07 enell 83       else if("rw".equals(mode))
248 28 Mar 07 enell 84       {
250 30 Mar 07 enell 85         write = true;
250 30 Mar 07 enell 86         raf = new RandomAccessFile(file, "rwd");
250 30 Mar 07 enell 87       }
250 30 Mar 07 enell 88       else
250 30 Mar 07 enell 89       {
250 30 Mar 07 enell 90         throw new IllegalArgumentException("Mode must be 'r' or 'rw'");
250 30 Mar 07 enell 91       }
250 30 Mar 07 enell 92     }
250 30 Mar 07 enell 93     catch (IOException e)
250 30 Mar 07 enell 94     {
250 30 Mar 07 enell 95       throw new BASEFileException(e);
250 30 Mar 07 enell 96     }
250 30 Mar 07 enell 97   }
250 30 Mar 07 enell 98
250 30 Mar 07 enell 99   private BASEFileSection readSection() throws BASEFileException
250 30 Mar 07 enell 100   {
250 30 Mar 07 enell 101     try
250 30 Mar 07 enell 102     {
250 30 Mar 07 enell 103       String line = raf.readLine();
250 30 Mar 07 enell 104       BASEFileSection bfs = null;
250 30 Mar 07 enell 105       while(line != null)
250 30 Mar 07 enell 106       {
250 30 Mar 07 enell 107         String[] head = line.split("\t", 2);
250 30 Mar 07 enell 108         if(head[0].equals("section") && head.length == 2)
248 28 Mar 07 enell 109         {
250 30 Mar 07 enell 110           bfs = newSection(head[1]);
250 30 Mar 07 enell 111           sectionPointers.put(bfs.hashCode(), new long[]{raf.getFilePointer(), -1L});
248 28 Mar 07 enell 112         }
250 30 Mar 07 enell 113         else if (head[0].equals("%") && bfs != null)
248 28 Mar 07 enell 114         {
250 30 Mar 07 enell 115           bfs.init();
250 30 Mar 07 enell 116           if (bfs instanceof BASEFileDataSection)
250 30 Mar 07 enell 117           {
250 30 Mar 07 enell 118             sectionPointers.get(bfs.hashCode())[1] = raf.getFilePointer();
250 30 Mar 07 enell 119           }
250 30 Mar 07 enell 120           return bfs;
248 28 Mar 07 enell 121         }
250 30 Mar 07 enell 122         else if (bfs != null && head.length == 2)
248 28 Mar 07 enell 123         {
250 30 Mar 07 enell 124           bfs.setHeader(head[0], head[1]);
248 28 Mar 07 enell 125         }
250 30 Mar 07 enell 126         line = raf.readLine();
248 28 Mar 07 enell 127       }
248 28 Mar 07 enell 128     }
248 28 Mar 07 enell 129     catch (IOException e)
248 28 Mar 07 enell 130     {
248 28 Mar 07 enell 131       throw new BASEFileException(e);
248 28 Mar 07 enell 132     }
250 30 Mar 07 enell 133     return null;
248 28 Mar 07 enell 134   }
250 30 Mar 07 enell 135   
250 30 Mar 07 enell 136   public final void addSpotSection(BASEFileSpotSection<R, S> bfss) throws BASEFileException
250 30 Mar 07 enell 137   {
250 30 Mar 07 enell 138     if (!write)
250 30 Mar 07 enell 139       throw new BASEFileException("Onlu aloud to set assaysection in write mode");
250 30 Mar 07 enell 140     spotSections.add(bfss);
250 30 Mar 07 enell 141   }
248 28 Mar 07 enell 142
250 30 Mar 07 enell 143   private BASEFileSection newSection(String type)
248 28 Mar 07 enell 144   {
250 30 Mar 07 enell 145     if (type.equals("assays"))
248 28 Mar 07 enell 146     {
250 30 Mar 07 enell 147       return new BASEFileAssaySection();
248 28 Mar 07 enell 148     }
250 30 Mar 07 enell 149     else if (type.equals("spots"))
250 30 Mar 07 enell 150     {
250 30 Mar 07 enell 151       return new BASEFileSpotSection();
250 30 Mar 07 enell 152     }
250 30 Mar 07 enell 153     else
250 30 Mar 07 enell 154     {
250 30 Mar 07 enell 155       return new BASEFileSection(type);
250 30 Mar 07 enell 156     }
248 28 Mar 07 enell 157   }
250 30 Mar 07 enell 158   
248 28 Mar 07 enell 159   /**
248 28 Mar 07 enell 160    * Get the assay section.
248 28 Mar 07 enell 161    * 
248 28 Mar 07 enell 162    * @return the assay section
248 28 Mar 07 enell 163    */
248 28 Mar 07 enell 164   public BASEFileAssaySection getAssaySection()
248 28 Mar 07 enell 165   {
248 28 Mar 07 enell 166     return assaySection;
248 28 Mar 07 enell 167   }
248 28 Mar 07 enell 168
248 28 Mar 07 enell 169   /**
263 24 Apr 07 enell 170    * Get a section of a specific type.
263 24 Apr 07 enell 171    * 
263 24 Apr 07 enell 172    * @param type the section type
263 24 Apr 07 enell 173    * @return a section or null the type type couldn't be found.
263 24 Apr 07 enell 174    */
263 24 Apr 07 enell 175   public BASEFileSection getSection(String type)
263 24 Apr 07 enell 176   {
263 24 Apr 07 enell 177     for (BASEFileSection bfs : sections)
263 24 Apr 07 enell 178     {
263 24 Apr 07 enell 179       if (bfs.isType(type)) return bfs;
263 24 Apr 07 enell 180     }
263 24 Apr 07 enell 181     return null;
263 24 Apr 07 enell 182   }
263 24 Apr 07 enell 183
263 24 Apr 07 enell 184   /**
263 24 Apr 07 enell 185    * Get all sections of a specific type.
263 24 Apr 07 enell 186    * 
263 24 Apr 07 enell 187    * @param type the section type
263 24 Apr 07 enell 188    * @return a section or an empty list the type type couldn't be found.
263 24 Apr 07 enell 189    */
263 24 Apr 07 enell 190   public List<BASEFileSection> getSections(String type)
263 24 Apr 07 enell 191   {
263 24 Apr 07 enell 192     ArrayList<BASEFileSection> list = new ArrayList<BASEFileSection>();
263 24 Apr 07 enell 193     for (BASEFileSection bfs : sections)
263 24 Apr 07 enell 194     {
263 24 Apr 07 enell 195       if (bfs.isType(type)) list.add(bfs);
263 24 Apr 07 enell 196     }
263 24 Apr 07 enell 197     return list;
263 24 Apr 07 enell 198   }
263 24 Apr 07 enell 199   
263 24 Apr 07 enell 200   /**
248 28 Mar 07 enell 201    * This method assumes that the basefile only contains one spot section and
248 28 Mar 07 enell 202    * returns the fist in the list.
248 28 Mar 07 enell 203    * 
248 28 Mar 07 enell 204    * @return a spot section.
248 28 Mar 07 enell 205    */
250 30 Mar 07 enell 206   public BASEFileSpotSection<R, S> getSpotSection() throws BASEFileException
248 28 Mar 07 enell 207   {
250 30 Mar 07 enell 208     if (spotSections.size() == 0)
250 30 Mar 07 enell 209     {
250 30 Mar 07 enell 210       throw new BASEFileException("No spot section avalible");
250 30 Mar 07 enell 211     }
250 30 Mar 07 enell 212     return getSpotSection(0);
248 28 Mar 07 enell 213   }
248 28 Mar 07 enell 214
250 30 Mar 07 enell 215   public BASEFileSpotSection<R, S> getSpotSection(int i)
250 30 Mar 07 enell 216   {
250 30 Mar 07 enell 217     return spotSections.get(i);
250 30 Mar 07 enell 218   }
250 30 Mar 07 enell 219
250 30 Mar 07 enell 220   public final void setAssaySection(BASEFileAssaySection bfas) throws BASEFileException
250 30 Mar 07 enell 221   {
250 30 Mar 07 enell 222     if (assaySection != null)
250 30 Mar 07 enell 223       throw new BASEFileException("Assaysection is already set");
250 30 Mar 07 enell 224     if (!write)
250 30 Mar 07 enell 225       throw new BASEFileException("Only aloud to set assaysection in write mode");
250 30 Mar 07 enell 226       
250 30 Mar 07 enell 227     assaySection = bfas;
250 30 Mar 07 enell 228   }
250 30 Mar 07 enell 229   
248 28 Mar 07 enell 230   /**
250 30 Mar 07 enell 231    * Sets the current section to this section and sets the reading pointer to 
248 28 Mar 07 enell 232    * the data pointer of this section if it is a data section. If it an ordinary 
248 28 Mar 07 enell 233    * section the reading pointer is set to the start point.
248 28 Mar 07 enell 234    * 
248 28 Mar 07 enell 235    * @param bfs the section
250 30 Mar 07 enell 236    * @throws BASEFileException if thee isn't part of this basefile or if the section
250 30 Mar 07 enell 237    *   lacks filepointer
248 28 Mar 07 enell 238    */
248 28 Mar 07 enell 239   public void setCurrentSection(BASEFileSection bfs) throws BASEFileException
248 28 Mar 07 enell 240   {
248 28 Mar 07 enell 241     try
248 28 Mar 07 enell 242     {
250 30 Mar 07 enell 243       long[] pointers = sectionPointers.get(bfs.hashCode());
250 30 Mar 07 enell 244       if (pointers == null)
248 28 Mar 07 enell 245       {
250 30 Mar 07 enell 246         throw new BASEFileException("This section is not part of this basefile");
248 28 Mar 07 enell 247       }
250 30 Mar 07 enell 248       currentSection = bfs;
250 30 Mar 07 enell 249       if (pointers[1] != -1)
250 30 Mar 07 enell 250       {
250 30 Mar 07 enell 251         raf.seek(pointers[1]);
250 30 Mar 07 enell 252       }
250 30 Mar 07 enell 253       else if (pointers[0] != -1)
250 30 Mar 07 enell 254       {
250 30 Mar 07 enell 255         raf.seek(pointers[0]);
250 30 Mar 07 enell 256       }
248 28 Mar 07 enell 257       else
248 28 Mar 07 enell 258       {
250 30 Mar 07 enell 259         throw new BASEFileException("This section has no file pointer");
248 28 Mar 07 enell 260       }
248 28 Mar 07 enell 261     }
248 28 Mar 07 enell 262     catch (IOException e)
248 28 Mar 07 enell 263     {
248 28 Mar 07 enell 264       throw new BASEFileException(e);
248 28 Mar 07 enell 265     }
248 28 Mar 07 enell 266   }
248 28 Mar 07 enell 267   
248 28 Mar 07 enell 268   /**
248 28 Mar 07 enell 269    * Read data from file starts from the current data pointer.
248 28 Mar 07 enell 270    * 
248 28 Mar 07 enell 271    * @return the data line as an string array
248 28 Mar 07 enell 272    * @throws BASEFileException if current section isn't an data section
248 28 Mar 07 enell 273    */
248 28 Mar 07 enell 274   public String[] readData() throws BASEFileException
248 28 Mar 07 enell 275   {
248 28 Mar 07 enell 276     if (currentSection == null)
248 28 Mar 07 enell 277     {
248 28 Mar 07 enell 278       throw new BASEFileException("The current section must be set.");
248 28 Mar 07 enell 279     }
248 28 Mar 07 enell 280     if (!(currentSection instanceof BASEFileDataSection))
248 28 Mar 07 enell 281     {
248 28 Mar 07 enell 282       throw new BASEFileException("The current section must be set to a data section.");
248 28 Mar 07 enell 283     }
248 28 Mar 07 enell 284     
248 28 Mar 07 enell 285     try
248 28 Mar 07 enell 286     {
248 28 Mar 07 enell 287       BASEFileDataSection bfds = (BASEFileDataSection) currentSection;
248 28 Mar 07 enell 288       String line = raf.readLine();
248 28 Mar 07 enell 289       if (line == null || line.equals(""))
248 28 Mar 07 enell 290       {
250 30 Mar 07 enell 291         currentSection = null;
250 30 Mar 07 enell 292         raf.seek(0);
248 28 Mar 07 enell 293         return null;
248 28 Mar 07 enell 294       }
248 28 Mar 07 enell 295       else
248 28 Mar 07 enell 296       {
250 30 Mar 07 enell 297         String[] ret = line.split("\t", -1);
250 30 Mar 07 enell 298         if (ret.length != bfds.getDataLineLength())
250 30 Mar 07 enell 299         {
250 30 Mar 07 enell 300           throw new BASEFileException("Dataline must have "+bfds.getDataLineLength()+" fields");
250 30 Mar 07 enell 301         }
250 30 Mar 07 enell 302         return ret;
248 28 Mar 07 enell 303       }
248 28 Mar 07 enell 304     }
248 28 Mar 07 enell 305     catch (IOException e)
248 28 Mar 07 enell 306     {
248 28 Mar 07 enell 307       throw new BASEFileException(e);
248 28 Mar 07 enell 308     }
248 28 Mar 07 enell 309   }
250 30 Mar 07 enell 310   
250 30 Mar 07 enell 311   public void validate() throws BASEFileException
250 30 Mar 07 enell 312   {
250 30 Mar 07 enell 313     assaySection.validate();
250 30 Mar 07 enell 314     for (BASEFileSpotSection<R, S> bfss : spotSections)
250 30 Mar 07 enell 315     {
250 30 Mar 07 enell 316       bfss.validate();
250 30 Mar 07 enell 317     }
250 30 Mar 07 enell 318     for (BASEFileSection bfs : sections)
250 30 Mar 07 enell 319     {
250 30 Mar 07 enell 320       bfs.validate();
250 30 Mar 07 enell 321     }
250 30 Mar 07 enell 322   }
250 30 Mar 07 enell 323
250 30 Mar 07 enell 324   public void write() throws BASEFileException
250 30 Mar 07 enell 325   {
250 30 Mar 07 enell 326     if (!write)
250 30 Mar 07 enell 327       throw new BASEFileException("This basefile isn't writable");
250 30 Mar 07 enell 328     try
250 30 Mar 07 enell 329     {
250 30 Mar 07 enell 330       validate();
250 30 Mar 07 enell 331       
250 30 Mar 07 enell 332       PrintWriter out = new PrintWriter(file);
250 30 Mar 07 enell 333       out.println("BASEfile");
250 30 Mar 07 enell 334       if (assaySection != null)
250 30 Mar 07 enell 335       {
250 30 Mar 07 enell 336         out.println(assaySection);
250 30 Mar 07 enell 337         for (int i = 0; i < assaySection.getHeight(); ++i)
250 30 Mar 07 enell 338         {
253 10 Apr 07 enell 339           out.println(assaySection.getDataLine(i));
250 30 Mar 07 enell 340         }
250 30 Mar 07 enell 341         out.println();
250 30 Mar 07 enell 342       }
250 30 Mar 07 enell 343       for (BASEFileSpotSection<R, S> bfss : spotSections)
250 30 Mar 07 enell 344       {
250 30 Mar 07 enell 345         out.println(bfss.toString());
253 10 Apr 07 enell 346         for (int i = 0; i < bfss.getHeight(); ++i)
253 10 Apr 07 enell 347         {
253 10 Apr 07 enell 348           out.println(bfss.getDataLine(i));
253 10 Apr 07 enell 349         }
250 30 Mar 07 enell 350         out.println();
250 30 Mar 07 enell 351       }
250 30 Mar 07 enell 352       out.close();
250 30 Mar 07 enell 353     }
250 30 Mar 07 enell 354     catch (IOException e)
250 30 Mar 07 enell 355     {
250 30 Mar 07 enell 356       throw new BASEFileException(e);
250 30 Mar 07 enell 357     }
250 30 Mar 07 enell 358   }
248 28 Mar 07 enell 359 }