Skip to content
Snippets Groups Projects
DatabaseDocument.java 94.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • tjc's avatar
    tjc committed
    /* DatabaseDocument.java
     *
    
    tjc's avatar
    tjc committed
     * created: 2005
    
    tjc's avatar
    tjc committed
     *
     * This file is part of Artemis
     * 
    
    tjc's avatar
    tjc committed
     * Copyright (C) 2005  Genome Research Limited
    
    tjc's avatar
    tjc committed
     * 
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * as published by the Free Software Foundation; either version 2
     * of the License, or (at your option) any later version.
     * 
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     * 
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     *
     */
    
    package uk.ac.sanger.artemis.util;
    
    
    import uk.ac.sanger.artemis.io.ChadoCanonicalGene;
    
    import uk.ac.sanger.artemis.io.DocumentEntry;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.GFFStreamFeature;
    
    import uk.ac.sanger.artemis.io.PartialSequence;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.Range;
    
    import uk.ac.sanger.artemis.io.ReadFormatException;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.chado.ArtemisUtils;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.chado.ChadoCvTermView;
    
    import uk.ac.sanger.artemis.chado.IBatisDAO;
    import uk.ac.sanger.artemis.chado.JdbcDAO;
    
    import uk.ac.sanger.artemis.chado.GmodDAO;
    
    import uk.ac.sanger.artemis.chado.ChadoTransaction;
    
    import uk.ac.sanger.artemis.components.database.DatabaseEntrySource;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.components.Splash;
    
    tjc's avatar
    tjc committed
    
    
    import org.gmod.schema.sequence.Feature;
    
    import org.gmod.schema.sequence.FeatureProp;
    import org.gmod.schema.sequence.FeatureLoc;
    
    tjc's avatar
    tjc committed
    import org.gmod.schema.sequence.FeaturePub;
    
    import org.gmod.schema.sequence.FeatureRelationship;
    import org.gmod.schema.sequence.FeatureSynonym;
    
    import org.gmod.schema.sequence.FeatureCvTerm;
    
    import org.gmod.schema.sequence.FeatureCvTermProp;
    
    tjc's avatar
    tjc committed
    import org.gmod.schema.sequence.FeatureCvTermDbXRef;
    
    tjc's avatar
    tjc committed
    import org.gmod.schema.sequence.FeatureCvTermPub;
    
    import org.gmod.schema.cv.Cv;
    
    import org.gmod.schema.cv.CvTerm;
    
    tjc's avatar
    tjc committed
    import org.gmod.schema.general.Db;
    
    import org.gmod.schema.general.DbXRef;
    
    tjc's avatar
    tjc committed
    import org.gmod.schema.organism.Organism;
    
    tjc's avatar
    tjc committed
    import org.gmod.schema.pub.PubDbXRef;
    import org.gmod.schema.pub.Pub;
    
    tjc's avatar
    tjc committed
    import java.sql.*;
    
    import java.text.SimpleDateFormat;
    
    tjc's avatar
    tjc committed
    import java.io.*;
    
    tjc's avatar
    tjc committed
    import java.net.ConnectException;
    
    tjc's avatar
    tjc committed
    import java.net.InetAddress;
    
    tjc's avatar
    tjc committed
    import java.util.Collections;
    import java.util.Comparator;
    
    tjc's avatar
    tjc committed
    import java.util.HashSet;
    
    tjc's avatar
    tjc committed
    import java.util.Hashtable;
    
    tjc's avatar
    tjc committed
    import java.util.HashMap;
    
    tjc's avatar
    tjc committed
    import java.util.Set;
    
    import java.util.Vector;
    
    tjc's avatar
    tjc committed
    import java.util.Enumeration;
    
    tjc's avatar
    tjc committed
    import java.util.List;
    import java.util.Iterator;
    
    tjc's avatar
    tjc committed
    import java.util.Collection;
    
    
    tjc's avatar
    tjc committed
    import javax.swing.JOptionPane;
    
    tjc's avatar
    tjc committed
    import javax.swing.JPasswordField;
    
    tjc's avatar
    tjc committed
    
    /**
    
    tjc's avatar
    tjc committed
     * Objects of this class are Documents created from a relational database.
     * 
     */
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
    public class DatabaseDocument extends Document
    
    tjc's avatar
    tjc committed
    {
      private String name = null;
    
    tjc's avatar
    tjc committed
    
    
      /** source feature_id */
      private String srcFeatureId = "1";
    
    tjc's avatar
    tjc committed
    
      /** database schema */
      private String schema = "public";
    
    
      private static Hashtable cvterms;
    
    tjc's avatar
    tjc committed
      
    
      private InputStreamProgressListener progress_listener;
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
      /** JDBC DAO */
      private JdbcDAO jdbcDAO = null;
    
      /** iBatis DAO */
      private IBatisDAO connIB = null;
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
      private ByteBuffer[] gff_buffer;
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
      private ByteBuffer gff_buff;
    
    tjc's avatar
    tjc committed
    
      /** entries to split into */
    
    tjc's avatar
    tjc committed
      private String[] types = { "repeat_region", "transcript" };
    
    tjc's avatar
    tjc committed
    
      /** true if splitting the GFF into entries */
    
    tjc's avatar
    tjc committed
      private boolean splitGFFEntry;
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
      private boolean iBatis = false;
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
      private JPasswordField pfield;
    
    tjc's avatar
    tjc committed
      
      private boolean singleSchema = true;
    
    tjc's avatar
    tjc committed
    
    
      private List schema_list;
      
    
    tjc's avatar
    tjc committed
      private static List organismNames;
      
    
      private boolean gene_builder;
      
    
      // include children in reading from the database
      private boolean readChildren = true;
      
    
    tjc's avatar
    tjc committed
      // range to retrieve features for
    
    tjc's avatar
    tjc committed
      private Range range;
      
      private Feature geneFeature;
      
    
    tjc's avatar
    tjc committed
      private Hashtable idFeatureStore;
      
      private boolean lazyFeatureLoad = true;
      
    
    tjc's avatar
    tjc committed
      public static String EXONMODEL  = "exon-model";
      public static String TRANSCRIPT = "mRNA";
    
      /** list of controlled_curation CV names */
      private static Vector cvControledCuratioNames;
      
    
    tjc's avatar
    tjc committed
      // controlled vocabulary
      /** controlled_curation controlled vocabulary */
    
    tjc's avatar
    tjc committed
      public static String CONTROLLED_CURATION_TAG_CVNAME = 
    
    tjc's avatar
    tjc committed
                                     "CC_";
    
    tjc's avatar
    tjc committed
      /** product controlled vocabulary */
    
    tjc's avatar
    tjc committed
      public static String PRODUCTS_TAG_CVNAME = "genedb_products";
    
    tjc's avatar
    tjc committed
      public static String RILEY_TAG_CVNAME = "RILEY";
    
    tjc's avatar
    tjc committed
      
    
    tjc's avatar
    tjc committed
      private static org.apache.log4j.Logger logger4j = 
        org.apache.log4j.Logger.getLogger(DatabaseDocument.class);
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
      
    
    tjc's avatar
    tjc committed
      /**
    
    tjc's avatar
    tjc committed
       * 
       * Create a new Document from a database.
       * 
       * @param location
       *          This should be a URL string giving:
       *          jdbc:postgresql://host:port/datbase_name?user=username
       * 
       */
    
    tjc's avatar
    tjc committed
      public DatabaseDocument(String location, JPasswordField pfield)
    
    tjc's avatar
    tjc committed
      {
        super(location);
    
    tjc's avatar
    tjc committed
        this.pfield = pfield;
    
    
    tjc's avatar
    tjc committed
        if(location.indexOf('=') > -1)
          this.schema = location.substring( location.indexOf('=')+ 1);
        
    
    tjc's avatar
    tjc committed
        if(System.getProperty("ibatis") != null)
    
    tjc's avatar
    tjc committed
        {
    
    tjc's avatar
    tjc committed
          iBatis = true;
    
    tjc's avatar
    tjc committed
          System.setProperty("chado", location);
    
    tjc's avatar
    tjc committed
        }
    
    tjc's avatar
    tjc committed
        initMDC(this);
    
    tjc's avatar
    tjc committed
      }
    
    
    tjc's avatar
    tjc committed
      /**
    
    tjc's avatar
    tjc committed
       * 
       * Create a new Document from a database.
       * 
       * @param location
       *          This should be a URL string giving:
    
    tjc's avatar
    tjc committed
       *          jdbc:postgresql://host:port/database_name?user=username
    
    tjc's avatar
    tjc committed
       * @param feature_id
       *          ID of a feature to be extracted.
       * 
       */
    
    tjc's avatar
    tjc committed
      public DatabaseDocument(String location, JPasswordField pfield,
    
                              String srcFeatureId, String schema)
    
    tjc's avatar
    tjc committed
      {
        super(location);
    
    tjc's avatar
    tjc committed
        this.pfield = pfield;
    
    
        this.srcFeatureId = srcFeatureId;
    
    tjc's avatar
    tjc committed
        this.schema = schema;
    
    
    tjc's avatar
    tjc committed
        if(System.getProperty("ibatis") != null)
    
    tjc's avatar
    tjc committed
        {
    
    tjc's avatar
    tjc committed
          iBatis = true;
    
    tjc's avatar
    tjc committed
          System.setProperty("chado", location);
    
    tjc's avatar
    tjc committed
        }
    
    tjc's avatar
    tjc committed
        initMDC(this);
    
    tjc's avatar
    tjc committed
      }
    
    
    tjc's avatar
    tjc committed
      /**
    
    tjc's avatar
    tjc committed
       * 
       * Create a new Document from a database.
       * 
       * @param location
       *          This should be a URL string giving:
       *          jdbc:postgresql://host:port/datbase_name?user=username
    
    tjc's avatar
    tjc committed
       *          ID of a feature to be extracted.
       * @param splitGFFEntry
       *          split into separate entries based on feature types.
       * @param progress_listener
       *          input stream progress listener
       * 
       */
    
    tjc's avatar
    tjc committed
      public DatabaseDocument(String location, JPasswordField pfield,
    
                              String srcFeatureId, String schema, boolean splitGFFEntry,
    
                              InputStreamProgressListener progress_listener)
      {
        super(location);
    
    tjc's avatar
    tjc committed
        this.pfield = pfield;
    
        this.srcFeatureId = srcFeatureId;
    
    tjc's avatar
    tjc committed
        this.schema = schema;
    
    tjc's avatar
    tjc committed
        this.splitGFFEntry = splitGFFEntry;
    
        this.progress_listener = progress_listener;
    
    tjc's avatar
    tjc committed
        if(System.getProperty("ibatis") != null)
    
    tjc's avatar
    tjc committed
        {
    
    tjc's avatar
    tjc committed
          iBatis = true;
    
    tjc's avatar
    tjc committed
          System.setProperty("chado", location);
    
    tjc's avatar
    tjc committed
        }
    
        
        reset(location, schema);
    
    tjc's avatar
    tjc committed
        initMDC(this);
    
    tjc's avatar
    tjc committed
    
    
      /**
       * Used by the gene builder to read a database entry
       * for a single gene.
       * @param location
       * @param pfield
    
       * @param schema
       * @param gene_builder
       */
      public DatabaseDocument(String location, JPasswordField pfield,
    
              String srcFeatureId, String schema, boolean gene_builder)
    
      {
        super(location);
        this.pfield = pfield;
    
        this.srcFeatureId = srcFeatureId;
    
        this.schema = schema;
        this.gene_builder = gene_builder;
    
        if(System.getProperty("ibatis") != null)
        {
          iBatis = true;
          System.setProperty("chado", location);
        }
    
    tjc's avatar
    tjc committed
        initMDC(this);
    
    tjc's avatar
    tjc committed
      public DatabaseDocument(String location, JPasswordField pfield,
    
                              String srcFeatureId, String schema,
    
    tjc's avatar
    tjc committed
                              ByteBuffer gff_buff, String name)
    
    tjc's avatar
    tjc committed
      {
        super(location);
    
    tjc's avatar
    tjc committed
        this.pfield = pfield;
    
        this.srcFeatureId = srcFeatureId;
    
    tjc's avatar
    tjc committed
        this.schema = schema;
        this.gff_buff = gff_buff;
    
    tjc's avatar
    tjc committed
        this.name = name;
    
    tjc's avatar
    tjc committed
        if(System.getProperty("ibatis") != null)
    
    tjc's avatar
    tjc committed
        {
    
    tjc's avatar
    tjc committed
          iBatis = true;
    
    tjc's avatar
    tjc committed
          System.setProperty("chado", location);
    
    tjc's avatar
    tjc committed
        }
    
    tjc's avatar
    tjc committed
        initMDC(this);
    
      /**
       * Use another DatabaseDocument to make a new document.
       * @param originalDocument
       * @param srcFeatureId
       * @param schema
       * @param gene_builder
    
    tjc's avatar
    tjc committed
       * @param region_grab
       * @param progress_listener
    
    tjc's avatar
    tjc committed
      public DatabaseDocument (final DatabaseDocument originalDocument,
                 final String schema, final Feature geneFeature,
                 final Range range,
                 final InputStreamProgressListener progress_listener)
      {
        this((String)originalDocument.getLocation(), 
             originalDocument.getPfield(),
             "-1", schema, false);
        this.progress_listener = progress_listener;
        this.range = range;
        this.geneFeature = geneFeature;
      }
      
      /**
       * Use another DatabaseDocument to make a new document.
       * @param originalDocument
       * @param srcFeatureId
       * @param schema
       * @param gene_builder
       * @param region_grab
       * @param progress_listener
       */
      public DatabaseDocument (final DatabaseDocument originalDocument,
                 final String srcFeatureId, 
                 final String schema, 
                 final boolean gene_builder,
    
                 final InputStreamProgressListener progress_listener)
    
      {
        this((String)originalDocument.getLocation(), 
             originalDocument.getPfield(),
             srcFeatureId, schema, gene_builder);
    
        this.progress_listener = progress_listener;
    
    tjc's avatar
    tjc committed
      public static void initMDC(final DatabaseDocument doc)
    
    tjc's avatar
    tjc committed
      {
        // add username & host to MDC data for logging
        try
    
    tjc's avatar
    tjc committed
          org.apache.log4j.MDC.put("username",doc.getUserName());
    
    tjc's avatar
    tjc committed
      	}
    
      	catch(NullPointerException npe)
    	  {
    	    org.apache.log4j.MDC.put("username",System.getProperty("user.name"));
    	  }
    
    tjc's avatar
    tjc committed
    	
    
    	  try 
    	  {
    	    org.apache.log4j.MDC.put("host",
    
    tjc's avatar
    tjc committed
        		  InetAddress.getLocalHost().getHostAddress());
    
    	  } 
    	  catch(Exception e) {}
      }
      
      public void setReadChildren(final boolean readChildren)
      {
        this.readChildren = readChildren; 
    
      /**
       * Reset the schema.
       * @param location
       * @param schema
       */
      private void reset(String location, String schema)
      {
        this.schema = schema;
    
    tjc's avatar
    tjc committed
    
    
        if(!location.endsWith("="+schema))
        {
          int index = location.lastIndexOf('=');
          setLocation(location.substring(0,index+1) + schema);
    
          if(iBatis && connIB != null)
          {
            try
            {
              connIB.close();
            }
            catch(SQLException e)
            {
              logger4j.warn(e.getMessage());
            }
            connIB  = null;
          }
          
    
          jdbcDAO = null;
          System.setProperty("chado", (String)getLocation());
    
    tjc's avatar
    tjc committed
          logger4j.debug((String)getLocation());
    
    tjc's avatar
    tjc committed
      /**
    
    tjc's avatar
    tjc committed
       * Append a String to the Document location.
    
    tjc's avatar
    tjc committed
       * @param name  the name to append.
    
    tjc's avatar
    tjc committed
       */
      public Document append(String name) throws IOException
    
    tjc's avatar
    tjc committed
      {
    
    tjc's avatar
    tjc committed
        return new DatabaseDocument( ((String)getLocation()) + name, pfield);
    
    tjc's avatar
    tjc committed
      }
    
      /**
    
    tjc's avatar
    tjc committed
       * Return the name of this Document (the last element of the Document
       * location).
       */
      public String getName()
    
    tjc's avatar
    tjc committed
      {
        if(name == null)
        {
    
    tjc's avatar
    tjc committed
          int ind     = ((String) getLocation()).indexOf("?");
          String name = ((String) getLocation()).substring(0, ind);
    
    tjc's avatar
    tjc committed
          ind = name.lastIndexOf("/");
    
    tjc's avatar
    tjc committed
          return name.substring(ind + 1);
    
    tjc's avatar
    tjc committed
        }
        return name;
      }
    
    
    tjc's avatar
    tjc committed
    
      /**
      *  Set the name of this document.
      */
      public void setName(String name)
      {
        this.name = name;
      }
    
    
    
      public DatabaseDocument createDatabaseDocument()
    
    tjc's avatar
    tjc committed
      {
    
        return new DatabaseDocument( (String)getLocation(), pfield,
    
    tjc's avatar
    tjc committed
      }
    
    tjc's avatar
    tjc committed
      /**
    
    tjc's avatar
    tjc committed
       * Return true if and only if the Document refered to by this object exists
       * and is readable. Always returns true.
       */
      public boolean readable()
    
    tjc's avatar
    tjc committed
      {
        return true;
      }
    
      /**
    
    tjc's avatar
    tjc committed
       * Return true if and only if the Document refered to by this object exists
       * and can be written to. Always returns false.
       */
      public boolean writable()
    
    tjc's avatar
    tjc committed
      {
        return true;
      }
    
      /**
    
    tjc's avatar
    tjc committed
       * Create a new InputStream object from this Document. The contents of the
       * Document can be read from the InputStream.
       * 
       * @exception IOException
       *              Thrown if the Document can't be read from (for example if it
       *              doesn't exist).
       */
      public InputStream getInputStream() throws IOException
    
    tjc's avatar
    tjc committed
      {
    
    tjc's avatar
    tjc committed
        ByteArrayInputStream instream;
    
        if(gff_buff != null)
        {
    
    tjc's avatar
    tjc committed
          instream = new ByteArrayInputStream(gff_buff.getBytes());
    
    tjc's avatar
    tjc committed
          return instream;
        }
    
    
    tjc's avatar
    tjc committed
        try
        {
    
          GmodDAO dao = getDAO();
    
    tjc's avatar
    tjc committed
    
          if(gene_builder)
          {
    
    tjc's avatar
    tjc committed
            // creating a gene builder
    
    tjc's avatar
    tjc committed
            List schemaList = new Vector();
            schemaList.add(schema);
              
            ByteBuffer bb = getGeneFeature(srcFeatureId,
    
                                           schemaList, dao, readChildren);          
    
    tjc's avatar
    tjc committed
            return new ByteArrayInputStream(bb.getBytes());
          }
    
    tjc's avatar
    tjc committed
          else if(range != null)
          {
            //
            // Retrieve all features within a range
    
    tjc's avatar
    tjc committed
           // List schemaList = new Vector();
           // schemaList.add(schema);
    
    tjc's avatar
    tjc committed
            final Feature srcFeature;
            if(geneFeature != null)
            {
              Collection featureLocs = geneFeature.getFeatureLocsForFeatureId();
              Iterator it = featureLocs.iterator();
              final FeatureLoc featureLoc = (FeatureLoc)it.next();
    
    tjc's avatar
    tjc committed
    
    
              int srcfeatureid = featureLoc.getFeatureBySrcFeatureId().getFeatureId();
              srcFeature = dao.getFeatureById(srcfeatureid);
    
    tjc's avatar
    tjc committed
              setName(srcFeature.getUniqueName());
    
              this.srcFeatureId = Integer.toString(srcfeatureid);     
    
    tjc's avatar
    tjc committed
            }
            else
            {
              srcFeature = dao.getFeatureById(Integer.parseInt(srcFeatureId));
            }
    
    tjc's avatar
    tjc committed
            
    
            final ByteBuffer entryBuffer = getFeaturesInRange(srcFeature, range, dao);
    
    tjc's avatar
    tjc committed
            getChadoSequence(srcFeature, entryBuffer);
    
            return new ByteArrayInputStream(entryBuffer.getBytes());
          }
          
          ByteBuffer entryBuffer = new ByteBuffer();
    
    tjc's avatar
    tjc committed
          try
    
    tjc's avatar
    tjc committed
            ByteBuffer sequenceBuffer = new ByteBuffer();
    
    tjc's avatar
    tjc committed
            if(dao instanceof IBatisDAO)
              ((IBatisDAO) dao).startTransaction();
    
            logger4j.debug("RETRIEVE SOURCE FEATURE FROM: "+getLocation());
    
    tjc's avatar
    tjc committed
            Feature srcFeature = getChadoSequence(dao, sequenceBuffer);
            gff_buffer = getGff(dao, srcFeature);
    
    tjc's avatar
    tjc committed
            
            if(splitGFFEntry)
    
    tjc's avatar
    tjc committed
            {
    
    tjc's avatar
    tjc committed
              if(gff_buffer[0].size() > 0)
    
    tjc's avatar
    tjc committed
                entryBuffer.append(gff_buffer[0]);
    
    tjc's avatar
    tjc committed
            }
            else
            {
              for(int i = 0; i < gff_buffer.length; i++)
              {
                if(gff_buffer[i].size() > 0)
    
    tjc's avatar
    tjc committed
                  entryBuffer.append(gff_buffer[i]);
    
    tjc's avatar
    tjc committed
              }
    
    tjc's avatar
    tjc committed
            }
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
            if(dao instanceof IBatisDAO)
              ((IBatisDAO) dao).commitTransaction();
    
    tjc's avatar
    tjc committed
            entryBuffer.append(sequenceBuffer);
    
    tjc's avatar
    tjc committed
          }
          finally
          {
            if(dao instanceof IBatisDAO)
              ((IBatisDAO) dao).endTransaction();
    
    tjc's avatar
    tjc committed
          instream = new ByteArrayInputStream(entryBuffer.getBytes());
    
    tjc's avatar
    tjc committed
          return instream;
        }
    
        catch(RuntimeException re)
        {
          JOptionPane.showMessageDialog(null, "Problems Reading...\n" +
              re.getMessage(),
              "Problems Reading From the Database ",
              JOptionPane.ERROR_MESSAGE);
          
          re.printStackTrace();
        }
    
    tjc's avatar
    tjc committed
        catch(java.sql.SQLException sqlExp)
        {
    
    tjc's avatar
    tjc committed
          JOptionPane.showMessageDialog(null, "Problems Reading...\n" +
              sqlExp.getMessage(),
    
              "Problems Reading From the Database ",
    
    tjc's avatar
    tjc committed
              JOptionPane.ERROR_MESSAGE);
          
    
    tjc's avatar
    tjc committed
          sqlExp.printStackTrace();
        }
    
        return null;
      }
    
    
    tjc's avatar
    tjc committed
      /**
    
    tjc's avatar
    tjc committed
       * 
       * Called (by DatabaseEntrySource) to retrieve all the documents for each
       * entry created.
       * 
       */
      public DatabaseDocument[] getGffDocuments(String location, String id,
                                                String schema)
    
    tjc's avatar
    tjc committed
        int nentries = 0;
    
    tjc's avatar
    tjc committed
        for(int i = 1; i < gff_buffer.length; i++)
    
    tjc's avatar
    tjc committed
        {
          if(gff_buffer[i].size() > 0)
            nentries++;
        }
    
        DatabaseDocument[] new_docs = new DatabaseDocument[nentries];
        nentries = 0;
    
    tjc's avatar
    tjc committed
        for(int i = 1; i < gff_buffer.length; i++)
    
    tjc's avatar
    tjc committed
          if(gff_buffer[i].size() == 0)
            continue;
    
    
    tjc's avatar
    tjc committed
          String name = types[i-1];
    
    tjc's avatar
    tjc committed
          new_docs[nentries] = new DatabaseDocument(location, pfield, id, schema,
                                                    gff_buffer[i], name);
    
    tjc's avatar
    tjc committed
          nentries++;
    
    tjc's avatar
    tjc committed
        }
    
        return new_docs;
      }
    
    
    tjc's avatar
    tjc committed
      /**
    
    tjc's avatar
    tjc committed
       * Create an array of GFF lines.
       * @param dao                 the data access object 
       * @param parentFeatureID     the parent identifier for the features to 
       *                            extract
       * @return   the <code>ByteBuffer</code> array of GFF lines
    
    tjc's avatar
    tjc committed
       */
    
    tjc's avatar
    tjc committed
      private ByteBuffer[] getGff(final GmodDAO dao, 
                                  final Feature srcFeature)
    
    tjc's avatar
    tjc committed
      {
    
    tjc's avatar
    tjc committed
        //final int srcfeature_id = Integer.parseInt(srcFeatureId);
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        logger4j.debug("BUILD GFF FEATURES");
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        // build srcfeature object
    
    tjc's avatar
    tjc committed
        FeatureLoc featureloc = new FeatureLoc();
    
        featureloc.setFeatureBySrcFeatureId(srcFeature);
    
    tjc's avatar
    tjc committed
        Feature child = new Feature();
        child.setFeatureLoc(featureloc);
    
    tjc's avatar
    tjc committed
        final List featList = dao.getFeaturesByLocatedOnFeature(child);
        final ByteBuffer[] buffers = new ByteBuffer[types.length + 1];
    
    tjc's avatar
    tjc committed
        for(int i = 0; i < buffers.length; i++)
    
    tjc's avatar
    tjc committed
          buffers[i] = new ByteBuffer();
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        ByteBuffer this_buff;
    
        int feature_size = featList.size();
    
    tjc's avatar
    tjc committed
        final Hashtable id_store = new Hashtable(feature_size);
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        // build feature store
    
        for(int i = 0; i < feature_size; i++)
        {
    
    tjc's avatar
    tjc committed
          Feature feat = (Feature)featList.get(i);
    
    tjc's avatar
    tjc committed
          id_store.put(Integer.toString(feat.getFeatureId()), feat);
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        if(lazyFeatureLoad)
          idFeatureStore = id_store;
        
    
    tjc's avatar
    tjc committed
        // get all dbrefs & synonyms etc
    
    tjc's avatar
    tjc committed
        final Hashtable dbxrefs;
        final Hashtable synonym;
        final Hashtable featureCvTerms;
        final Hashtable featureCvTermDbXRefs;
    
        Hashtable featureCvTermPubs = null;
    
    tjc's avatar
    tjc committed
        final Hashtable featurePubs;
        final List pubDbXRefs;
        
        if(lazyFeatureLoad)
        {
          dbxrefs = null;
          synonym = null;
          featureCvTerms = null;
          featureCvTermDbXRefs = null;
          featureCvTermPubs = null;
          featurePubs = null;
          pubDbXRefs = null;
        }
        else
        {
          dbxrefs= IBatisDAO.mergeDbXRef(
    
    tjc's avatar
    tjc committed
            dao.getFeatureDbXRefsBySrcFeature(srcFeature));
    
    tjc's avatar
    tjc committed
          synonym = getAllFeatureSynonyms(
    
    tjc's avatar
    tjc committed
            dao.getFeatureSynonymsBySrcFeature(srcFeature));
    
    tjc's avatar
    tjc committed
          featureCvTerms = getFeatureCvTermsByFeature(dao, 
    
    tjc's avatar
    tjc committed
            dao.getFeatureCvTermsBySrcFeature(srcFeature));
    
    tjc's avatar
    tjc committed
          featureCvTermDbXRefs = getFeatureCvTermDbXRef(dao, 
    
    tjc's avatar
    tjc committed
            dao.getFeatureCvTermDbXRefBySrcFeature(srcFeature));
    
          
          try
          {
            featureCvTermPubs = getFeatureCvTermPub(dao, 
              dao.getFeatureCvTermPubBySrcFeature(srcFeature));
          } 
          catch(Exception e) 
          { 
            e.printStackTrace();
            if(dao instanceof IBatisDAO)
            {
              try
              {
                ((IBatisDAO) dao).endTransaction();
                ((IBatisDAO) dao).startTransaction();
              }
              catch(SQLException sqle){}  
            }
          }
    
    tjc's avatar
    tjc committed
          featurePubs = getFeaturePubs(dao,
    
              dao.getFeaturePubsBySrcFeature(srcFeature));
    
    tjc's avatar
    tjc committed
          pubDbXRefs= dao.getPubDbXRef();
        }
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        // create gff byte stream
    
    tjc's avatar
    tjc committed
        for(int i = 0; i < feature_size; i++)
    
    tjc's avatar
    tjc committed
          // select buffer based on feature type
    
    tjc's avatar
    tjc committed
          Feature feat = (Feature)featList.get(i);
    
    tjc's avatar
    tjc committed
          int type_id = feat.getCvTerm().getCvTermId();
    
          String typeName = getCvtermName(type_id, dao, gene_builder);
    
    tjc's avatar
    tjc committed
          this_buff = buffers[0];
    
    tjc's avatar
    tjc committed
          for(int j = 0; j < types.length; j++)
    
    tjc's avatar
    tjc committed
          {
            if(types[j].equals(typeName))
    
    tjc's avatar
    tjc committed
              this_buff = buffers[j+1];
    
    tjc's avatar
    tjc committed
          }
    
    tjc's avatar
    tjc committed
    
          chadoToGFF(feat, srcFeature.getUniqueName(),
    
                     dbxrefs, synonym, featureCvTerms,
    
    tjc's avatar
    tjc committed
                     pubDbXRefs, featureCvTermDbXRefs, featureCvTermPubs,
    
    tjc's avatar
    tjc committed
                     featurePubs,
    
    tjc's avatar
    tjc committed
                     id_store, dao, 
    
                     feat.getFeatureLoc(), this_buff, gene_builder);
    
          if( i%10 == 0 || i == feature_size-1)
            progress_listener.progressMade("Read from database: " + 
    
    tjc's avatar
    tjc committed
                                           feat.getUniqueName());
    
    tjc's avatar
    tjc committed
        }
    
        return buffers;
      }
    
    
    tjc's avatar
    tjc committed
      /**
    
    tjc's avatar
    tjc committed
       * Get a <code>Hashtable</code> of feature_id keys and their corresponding 
       * feature_synonym
    
    tjc's avatar
    tjc committed
       * 
       */
    
      private Hashtable getAllFeatureSynonyms(final List list) 
      {   
    
    tjc's avatar
    tjc committed
        Hashtable synonym = new Hashtable();
    
    tjc's avatar
    tjc committed
        List value;
    
    tjc's avatar
    tjc committed
        FeatureSynonym alias;
    
    tjc's avatar
    tjc committed
        
        for(int i=0; i<list.size(); i++)
        {
    
    tjc's avatar
    tjc committed
          alias = (FeatureSynonym)list.get(i);
    
          featureId = new Integer(alias.getFeature().getFeatureId());
          if(synonym.containsKey(featureId))
            value = (Vector)synonym.get(featureId);
    
    tjc's avatar
    tjc committed
          else
            value = new Vector();
          
          value.add(alias);
    
          synonym.put(featureId, value);
    
    tjc's avatar
    tjc committed
        }
        
        return synonym;
    
    tjc's avatar
    tjc committed
      /**
       * Get FeaturePub's (i.e. /literature qualifiers).
       * @param dao
    
    tjc's avatar
    tjc committed
       * @param list
    
    tjc's avatar
    tjc committed
       * @return
       */
    
    tjc's avatar
    tjc committed
      private Hashtable getFeaturePubs(final GmodDAO dao,
                                       final List list)
    
    tjc's avatar
    tjc committed
      {
    
    tjc's avatar
    tjc committed
        final Hashtable featurePubs = new Hashtable();
    
    tjc's avatar
    tjc committed
        Integer featureId;
        List value;
        FeaturePub featurePub;
        
        for(int i=0; i<list.size(); i++)
        {
          featurePub = (FeaturePub)list.get(i);
          featureId = new Integer(featurePub.getFeature().getFeatureId());
          if(featurePubs.containsKey(featureId))
            value = (Vector)featurePubs.get(featureId);
          else
            value = new Vector();
          
          value.add(featurePub);
          featurePubs.put(featureId, value);
        }
        
        return featurePubs;
      }
      
    
    tjc's avatar
    tjc committed
      /**
       * 
       * @param dao
       * @param chadoFeature null if we want them all
       * @return
       */
      private Hashtable getFeatureCvTermsByFeature(final GmodDAO dao, 
    
    tjc's avatar
    tjc committed
                                                   final List list)
    
      {
        Hashtable featureCvTerms = new Hashtable();
    
        List value;
        FeatureCvTerm feature_cvterm;
        
        for(int i=0; i<list.size(); i++)
        {
          feature_cvterm = (FeatureCvTerm)list.get(i);
    
          featureId = new Integer(feature_cvterm.getFeature().getFeatureId());
          if(featureCvTerms.containsKey(featureId))
            value = (Vector)featureCvTerms.get(featureId);
    
          else
            value = new Vector();
          
          value.add(feature_cvterm);
    
          featureCvTerms.put(featureId, value);
    
    tjc's avatar
    tjc committed
      
    
    tjc's avatar
    tjc committed
      /**
       * 
       * @param dao
       * @param chadoFeature null if we want all
       * @return
       */
    
    tjc's avatar
    tjc committed
      private Hashtable getFeatureCvTermDbXRef(final GmodDAO dao, final List list)
    
    tjc's avatar
    tjc committed
      {
        if(list == null || list.size() == 0)
          return null;
        
    
    tjc's avatar
    tjc committed
        Integer featureCvTermDbXRefId;
        List value;
        
    
    tjc's avatar
    tjc committed
        Hashtable featureCvTermDbXRefs = new Hashtable(list.size());
        for(int i=0; i<list.size(); i++)
        {
          FeatureCvTermDbXRef featureCvTermDbXRef =
            (FeatureCvTermDbXRef)list.get(i);
    
    tjc's avatar
    tjc committed
          
          featureCvTermDbXRefId = new Integer(
              featureCvTermDbXRef.getFeatureCvTerm().getFeatureCvTermId());
          
          if(featureCvTermDbXRefs.containsKey(featureCvTermDbXRefId))
            value = (Vector)featureCvTermDbXRefs.get(featureCvTermDbXRefId);
          else
            value = new Vector();
          
          value.add(featureCvTermDbXRef);
          featureCvTermDbXRefs.put(featureCvTermDbXRefId, value);
    
    tjc's avatar
    tjc committed
        }
         
        return featureCvTermDbXRefs;
      }
      
    
    tjc's avatar
    tjc committed
      private Hashtable getFeatureCvTermPub(final GmodDAO dao,
    
    tjc's avatar
    tjc committed
                                            final List list)
    
    tjc's avatar
    tjc committed
      {
        if(list == null || list.size() == 0)
          return null;
        
        Integer featureCvTermId;
        List value;
        
        Hashtable featureCvTermPubs = new Hashtable(list.size());
        for(int i=0; i<list.size(); i++)
        {
          FeatureCvTermPub featureCvTermPub =
            (FeatureCvTermPub)list.get(i);
          
          featureCvTermId = new Integer(
              featureCvTermPub.getFeatureCvTerm().getFeatureCvTermId());
          
          if(featureCvTermPubs.containsKey(featureCvTermId))
            value = (Vector)featureCvTermPubs.get(featureCvTermId);
          else
            value = new Vector();
          
          value.add(featureCvTermPub);
          featureCvTermPubs.put(featureCvTermId, value);
        }
         
        return featureCvTermPubs;
      }
      
    
    tjc's avatar
    tjc committed
      /**
       * Retrieve the features in a given range
       * @param srcFeature
       * @param range
       * @param dao
       * @return
       */
      private ByteBuffer getFeaturesInRange(final Feature srcFeature,
                                            final Range range, 
                                            final GmodDAO dao)
      { 
        ByteBuffer buff = new ByteBuffer();
    
    
    tjc's avatar
    tjc committed
        logger4j.debug("GET FEATURES IN RANGE:: "+range.toString());
    
    tjc's avatar
    tjc committed
        List featuresInRange = dao.getFeaturesByRange(range.getStart()-1, 
                                    range.getEnd(), 0, srcFeature, null);
        
        List featureIds = new Vector(featuresInRange.size());
        for(int i=0; i<featuresInRange.size(); i++)
        {
          Feature thisFeature = (Feature)featuresInRange.get(i);
          featureIds.add(new Integer(thisFeature.getFeatureId()));
        }
        
        FeatureLoc featureLoc = new FeatureLoc();
        featureLoc.setFmin(new Integer(range.getStart()));
        featureLoc.setFmax(new Integer(range.getEnd()));
        srcFeature.setFeatureLoc(featureLoc);
        
        Hashtable dbxrefs = IBatisDAO.mergeDbXRef(
            dao.getFeatureDbXRefsBySrcFeature(srcFeature));
        Hashtable synonym = getAllFeatureSynonyms(
            dao.getFeatureSynonymsBySrcFeature(srcFeature));
        Hashtable featureCvTerms = getFeatureCvTermsByFeature(dao, 
            dao.getFeatureCvTermsBySrcFeature(srcFeature));
        Hashtable featureCvTermDbXRefs = getFeatureCvTermDbXRef(dao, 
            dao.getFeatureCvTermDbXRefBySrcFeature(srcFeature));
        Hashtable featureCvTermPubs = getFeatureCvTermPub(dao, 
            dao.getFeatureCvTermPubBySrcFeature(srcFeature));
    
    tjc's avatar
    tjc committed
        Hashtable featurePubs = getFeaturePubs(dao,
            dao.getFeaturePubsBySrcFeature(srcFeature));
    
    tjc's avatar
    tjc committed
    
        List pubDbXRefs = dao.getPubDbXRef();
        
        Hashtable id_store = new Hashtable(featuresInRange.size());
    
        // build feature name store
        for(int i = 0; i < featuresInRange.size(); i++)
        {
          Feature chadoFeature = (Feature)featuresInRange.get(i);
          String featureId = Integer.toString(chadoFeature.getFeatureId());
    
    tjc's avatar
    tjc committed
          id_store.put(featureId, chadoFeature);
    
    tjc's avatar
    tjc committed
        }
        
        for(int i=0; i<featuresInRange.size(); i++)
        {
          Feature chadoFeature = (Feature)featuresInRange.get(i);
    
    tjc's avatar
    tjc committed
          id_store.put(Integer.toString(chadoFeature.getFeatureId()), chadoFeature);
    
    tjc's avatar
    tjc committed
    
          chadoToGFF(chadoFeature, srcFeature.getUniqueName(), dbxrefs, synonym, featureCvTerms,
              pubDbXRefs, featureCvTermDbXRefs, featureCvTermPubs, featurePubs,
              id_store, dao, chadoFeature.getFeatureLoc(), buff, gene_builder);
          if( i%10 == 0 || i == featuresInRange.size()-1)
            progress_listener.progressMade("Read from database: " + 
                                           chadoFeature.getUniqueName());
        }
        return buff;
      }
      
    
    tjc's avatar
    tjc committed
      /**
       * Use by the gene editor to retrieve the gene and related
       * features
       * @param search_gene     gene uniquename
       * @param schema_search   schema list to search
       * @param dao             data access method
       * @return  GFF byte buffer
       * @throws SQLException
       * @throws ReadFormatException
    
       * @throws ConnectException 
    
    tjc's avatar
    tjc committed
       */
    
      private ByteBuffer getGeneFeature(final String search_gene, 
                                        final List schema_search,
    
                                        GmodDAO dao, 
                                        final boolean readChildren) 
    
              throws SQLException, ReadFormatException, ConnectException
    
        CvTermThread cvThread = null;
    
    tjc's avatar
    tjc committed
        if(DatabaseDocument.cvterms == null)
    
        {
          cvThread = new CvTermThread(dao);
          cvThread.start();
        }
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        final Hashtable id_store = new Hashtable();
    
        boolean singleSchema = true;
        final List pg_schemas = dao.getSchema(); 
        Iterator schemasIt = pg_schemas.iterator();
        while(schemasIt.hasNext())
        {
          String thisSchema = (String)schemasIt.next();
          
          if( thisSchema.equalsIgnoreCase(schema) )
          {
            singleSchema = false;
            break;
          }
        }
        if(singleSchema)
          logger4j.debug("SINGLE SCHEMA");
        else
          reset((String)getLocation(), (String)schema_search.get(0));
    
        dao = getDAO();
    
    tjc's avatar
    tjc committed
        Feature chadoFeature = 
    
          (Feature)(dao.getFeaturesByUniqueName(search_gene).get(0));
    
        ChadoCanonicalGene chado_gene = new ChadoCanonicalGene();
    
    tjc's avatar
    tjc committed
        id_store.put(Integer.toString(chadoFeature.getFeatureId()), 
    
    tjc's avatar
    tjc committed
                     chadoFeature);
    
    tjc's avatar
    tjc committed
        List featurelocs = new Vector(chadoFeature.getFeatureLocsForFeatureId());