Skip to content
Snippets Groups Projects
ChadoTransactionManager.java 96.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • tjc's avatar
    tjc committed
    /* ChadoTransactionManager.java
     *
     * created: July 2005
     *
     * This file is part of Artemis
     *
     * Copyright (C) 2005  Genome Research Limited
     *
     * 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.chado;
    
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.Feature;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.FeatureSegment;
    import uk.ac.sanger.artemis.FeatureSegmentVector;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.sequence.SequenceChangeListener;
    import uk.ac.sanger.artemis.sequence.SequenceChangeEvent;
    
    import uk.ac.sanger.artemis.components.genebuilder.GeneUtils;
    
    import uk.ac.sanger.artemis.components.genebuilder.ProteinMapPanel;
    
    import uk.ac.sanger.artemis.components.genebuilder.cv.GoBox;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.components.genebuilder.ortholog.MatchPanel;
    import uk.ac.sanger.artemis.components.genebuilder.ortholog.OrthoParalogTable;
    
    import uk.ac.sanger.artemis.components.genebuilder.ortholog.SimilarityTable;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.DatabaseDocumentEntry;
    
    import uk.ac.sanger.artemis.io.DatabaseInferredFeature;
    
    import uk.ac.sanger.artemis.io.DocumentEntry;
    
    import uk.ac.sanger.artemis.io.LazyQualifierValue;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.QualifierLazyLoading;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.QualifierVector;
    import uk.ac.sanger.artemis.io.Qualifier;
    import uk.ac.sanger.artemis.io.RangeVector;
    import uk.ac.sanger.artemis.io.StreamQualifier;
    import uk.ac.sanger.artemis.io.GFFStreamFeature;
    import uk.ac.sanger.artemis.io.Range;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.InvalidRelationException;
    
    import uk.ac.sanger.artemis.io.EntryInformationException;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.Key;
    
    import uk.ac.sanger.artemis.io.ChadoCanonicalGene;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.util.StringVector;
    import uk.ac.sanger.artemis.util.DatabaseDocument;
    
    import uk.ac.sanger.artemis.util.ReadOnlyException;
    
    import uk.ac.sanger.artemis.EntryGroup;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.FeatureChangeListener;
    import uk.ac.sanger.artemis.FeatureChangeEvent;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.EntryChangeListener;
    import uk.ac.sanger.artemis.EntryChangeEvent;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.Options;
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
    import java.util.Collection;
    
    tjc's avatar
    tjc committed
    import java.util.Set;
    
    tjc's avatar
    tjc committed
    import java.util.StringTokenizer;
    
    tjc's avatar
    tjc committed
    import java.util.Vector;
    
    tjc's avatar
    tjc committed
    import java.util.Hashtable;
    
    tjc's avatar
    tjc committed
    import java.util.List;
    import java.util.Enumeration;
    
    tjc's avatar
    tjc committed
    import java.util.regex.Pattern;
    
    
    tjc's avatar
    tjc committed
    import javax.swing.JOptionPane;
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
    import org.gmod.schema.sequence.FeatureCvTermProp;
    
    tjc's avatar
    tjc committed
    import org.gmod.schema.sequence.FeatureCvTermPub;
    
    import org.gmod.schema.sequence.FeatureLoc;
    import org.gmod.schema.sequence.FeatureProp;
    import org.gmod.schema.sequence.FeatureDbXRef;
    
    import org.gmod.schema.sequence.FeaturePub;
    
    import org.gmod.schema.sequence.FeatureRelationship;
    import org.gmod.schema.sequence.FeatureSynonym;
    
    tjc's avatar
    tjc committed
    import org.gmod.schema.sequence.FeatureCvTerm;
    
    import org.gmod.schema.sequence.Synonym;
    
    
    tjc's avatar
    tjc committed
    import org.gmod.schema.analysis.AnalysisFeature;
    
    import org.gmod.schema.cv.*;
    
    tjc's avatar
    tjc committed
    import org.gmod.schema.pub.Pub;
    
    import org.gmod.schema.general.Db;
    import org.gmod.schema.general.DbXRef;
    
    tjc's avatar
    tjc committed
    import org.gmod.schema.sequence.FeatureCvTermDbXRef;
    
    tjc's avatar
    tjc committed
    
    /**
    
    tjc's avatar
    tjc committed
     *
     * Chado transaction manager listens for feature, entry and sequence changes.
     * <code>ChadoTransactionManager</code> creates and tracks the feature insertions,
    
    tjc's avatar
    tjc committed
     * deletions, and updates to commit back to the database.
    
    tjc's avatar
    tjc committed
     *
     **/
    
    tjc's avatar
    tjc committed
    public class ChadoTransactionManager
    
    tjc's avatar
    tjc committed
           implements FeatureChangeListener, EntryChangeListener, SequenceChangeListener 
    
    tjc's avatar
    tjc committed
    {
    
    tjc's avatar
    tjc committed
      private static org.apache.log4j.Logger logger4j = 
    
    tjc's avatar
    tjc committed
        org.apache.log4j.Logger.getLogger(ChadoTransactionManager.class);
      
    
    tjc's avatar
    tjc committed
      public static boolean addSegments = true;
    
      private Vector<ChadoTransaction> sql = new Vector<ChadoTransaction>();
    
    tjc's avatar
    tjc committed
      
    
      /** GFF3 predefined tags, i.e. not feature_prop's */
    
      private static String reserved_tags[] = 
    
    tjc's avatar
    tjc committed
              {   "ID",
                  "Name",
                  "Alias",
                  "Parent",
                  "Target",
                  "Gap",
                  "Derives_from",
                  "Dbxref",
                  "Ontology_term",
    
                  "score",
                  "codon_start",
    
                  "isFminPartial",
                  "isFmaxPartial",
    
    tjc's avatar
    tjc committed
                  "isObsolete",
    
    tjc's avatar
    tjc committed
                  MatchPanel.SIMILARITY,
                  MatchPanel.ORTHOLOG,
                  MatchPanel.PARALOG,
    
                  "literature",
    
    tjc's avatar
    tjc committed
                  "gff_source",      // program or database
                  "gff_seqname" };   // seqID of coord system
               
    
    tjc's avatar
    tjc committed
      //controlled vocab tags
    
    tjc's avatar
    tjc committed
      public static String CV_NAME[];
    
    tjc's avatar
    tjc committed
      
    
      //synonym tags from cv
    
      private static String synonym_tags[] = null;
    
      public static String SYNONYM_TAG_CVNAME = 
             Options.getOptions().getProperty("synonym_cvname");
    
      private EntryGroup entryGroup;
    
      // Db where db entries  are stored corresponding to controlled curation CV terms
      public static String CONTROLLED_CURATION_DB = "CCGEN";
      public static String PRODUCT_DB = "PRODUCT";
    
      public static String PRODUCT_CV = 
             Options.getOptions().getProperty("product_cvname");
    
      public static String HISTORY_CV = 
              Options.getOptions().getProperty("history_cvname");
    
      
      // number of SQL commands successfully processed during a commit
      public static int commitReturnValue = 0;
      
    
      public ChadoTransactionManager()
      {
        
      }
    
    tjc's avatar
    tjc committed
      private static void initCV()
      {
        if(Options.getOptions().getPropertyTruthValue("product_cv"))
        { 
    
          logger4j.debug("PRODUCT STORED AS A CV (product_cv=yes) IN "+PRODUCT_CV);
    
    tjc's avatar
    tjc committed
          CV_NAME = new String[]
    
    tjc's avatar
    tjc committed
            { "GO",
              "controlled_curation",
              "product",
              "class" };
        }
        else
        {
          logger4j.debug("PRODUCT STORED AS A FEATUREPROP (product_cv=no)");
    
    tjc's avatar
    tjc committed
          CV_NAME = new String[]
    
    tjc's avatar
    tjc committed
            { "GO",
              "controlled_curation",
              "class" };
        }
    
        if(HISTORY_CV != null)
          CV_NAME[CV_NAME.length-1] = "history";
    
        logger4j.debug("SYNONYM NAMES ARE STORED IN "+SYNONYM_TAG_CVNAME);
    
    tjc's avatar
    tjc committed
      }
    
      public void setEntryGroup(final EntryGroup entryGroup)
      {
        this.entryGroup = entryGroup;
      }
      
    
    tjc's avatar
    tjc committed
      private void logMDC()
      {
    	try
    	{
      	  DatabaseDocument.initMDC((DatabaseDocument)
            ((DocumentEntry)entryGroup.getSequenceEntry().getEMBLEntry()).getDocument());
    	}
    	catch(Exception e){}
      }
      
    
      /**
       *  Invoked when a deletion or insertion occurs in a Bases object.
       **/
      public void sequenceChanged(final SequenceChangeEvent event)
      {
    
    tjc's avatar
    tjc committed
    	logMDC();
    
        if(event.getType() == SequenceChangeEvent.DELETION ||
           event.getType() == SequenceChangeEvent.INSERTION)
        {
          int start  = event.getPosition();
          int length = event.getSubSequence().length();
          
          //
          // update residues in srcfeature  
          DatabaseDocument doc = (DatabaseDocument)
             ((DocumentEntry)entryGroup.getSequenceEntry().getEMBLEntry()).getDocument();
    
    tjc's avatar
    tjc committed
          int newSequenceLength = entryGroup.getSequenceEntry().getEMBLEntry().getSequence().length();
          
          /*org.gmod.schema.sequence.Feature regionFeature = new org.gmod.schema.sequence.Feature();
          CvTerm cvTerm = new CvTerm();
          cvTerm.setName("region");
          regionFeature.setCvTerm(cvTerm);
          org.gmod.schema.sequence.Feature srcFeature = new org.gmod.schema.sequence.Feature();
          srcFeature.setFeatureId( Integer.parseInt(doc.getSrcFeatureId()) );
          srcFeature.setSeqLen(new Integer(
              entryGroup.getSequenceEntry().getEMBLEntry().getSequence().length()));
          FeatureLoc featureLoc = new FeatureLoc();
          featureLoc.setFeatureBySrcFeatureId(srcFeature);
          featureLoc.setFmin(new Integer(start-1));
          regionFeature.setFeatureLoc(featureLoc);
          regionFeature.setSeqLen(new Integer(length));
          
          if(event.getType() == SequenceChangeEvent.INSERTION)
          {
            regionFeature.setResidues(event.getSubSequence().getBytes());
            featureLoc.setFmax(new Integer(start));
          }
          else
          {
            featureLoc.setFmax(new Integer(start+length));
          }  
          ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.UPDATE, regionFeature, 
              null, null, null);*/
    
          final FeatureForUpdatingResidues chadoFeature = new FeatureForUpdatingResidues();
    
          chadoFeature.setStartBase(start-1);
    
    tjc's avatar
    tjc committed
          chadoFeature.setLength(length);    
    
    tjc's avatar
    tjc committed
    
    
          final String logMsg;
    
          if(event.getType() == SequenceChangeEvent.INSERTION)
          {
            chadoFeature.setNewSubSequence(event.getSubSequence());
            chadoFeature.setEndBase(start);
    
    tjc's avatar
    tjc committed
            chadoFeature.setBasesToEnd(newSequenceLength-event.getSubSequence().length()-start+1);
    
            logMsg = "SEQUENCE INSERT AT "+start;
    
    tjc's avatar
    tjc committed
          {
    
            chadoFeature.setEndBase(start+length);
    
    tjc's avatar
    tjc committed
            chadoFeature.setBasesToEnd(newSequenceLength+event.getSubSequence().length()-start);
    
            logMsg = "SEQUENCE DELETE AT "+start;
    
    tjc's avatar
    tjc committed
          }
    
          
          chadoFeature.setFeatureId( Integer.parseInt(doc.getSrcFeatureId()) );
          chadoFeature.setSeqLen(new Integer(
              entryGroup.getSequenceEntry().getEMBLEntry().getSequence().length()));
          
          ChadoTransaction tsn = 
    
            new ChadoTransaction(ChadoTransaction.UPDATE, chadoFeature, 
                                 null, null, null, logMsg);
    
    tjc's avatar
    tjc committed
      /**
    
    tjc's avatar
    tjc committed
       *  Implementation of the FeatureChangeListener interface.  We listen for
       *  changes in every feature of every entry in this group.
       **/ 
    
    tjc's avatar
    tjc committed
      public void featureChanged(FeatureChangeEvent event)
      {
    
    tjc's avatar
    tjc committed
    	logMDC();
    
    tjc's avatar
    tjc committed
        if(event.featureHasChanged())
        {
    
          if(!(event.getFeature().getEmblFeature() instanceof GFFStreamFeature) ||
              (event.getFeature().getEmblFeature() instanceof DatabaseInferredFeature))
    
    tjc's avatar
    tjc committed
            return;
          
    
    tjc's avatar
    tjc committed
          final GFFStreamFeature feature = 
            (GFFStreamFeature)event.getFeature().getEmblFeature();
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
          if(event.getType() == FeatureChangeEvent.SEGMENT_CHANGED)
          {
            RangeVector rv_new = event.getNewLocation().getRanges();
            RangeVector rv_old = event.getOldLocation().getRanges();
    
            segmentNumberChanged(feature, rv_new, rv_old);
    
    tjc's avatar
    tjc committed
          }
          else if(event.getType() == FeatureChangeEvent.LOCATION_CHANGED)
    
    tjc's avatar
    tjc committed
          {
    
            final RangeVector rv_new = event.getNewLocation().getRanges();
            final RangeVector rv_old = event.getOldLocation().getRanges();
    
    tjc's avatar
    tjc committed
    
    
            logger4j.debug("LOCATION_CHANGED "+
                           feature.getFirstBase()+".."+feature.getLastBase()+
                           " new="+rv_new.size()+" old="+rv_old.size());
    
    tjc's avatar
    tjc committed
            if(rv_new.size() != rv_old.size())
    
            {
              // location and segment number change
    
    tjc's avatar
    tjc committed
              final RangeVector rangesToAdd = new RangeVector();
    
              for(int i=0;i<rv_new.size();i++)
              {  
                final Range range = (Range) rv_new.get(i);
                if(!rv_old.containsRange(range))
    
    tjc's avatar
    tjc committed
                  rangesToAdd.add(range);
              }
    
              try
              {
                final String parent = 
                  (String)feature.getQualifierByName("Parent").getValues().get(0);
                GeneUtils.addSegment(feature, rangesToAdd, parent);
    
    tjc's avatar
    tjc committed
              catch(ReadOnlyException e)
              {
                e.printStackTrace();
              }
              catch(EntryInformationException e)
              {
                e.printStackTrace();
              }
              
    
              segmentNumberChanged(feature, rv_new, rv_old);
    
    tjc's avatar
    tjc committed
              return;
    
    tjc's avatar
    tjc committed
            
    
    tjc's avatar
    tjc committed
            ChadoTransaction tsn;
    
    tjc's avatar
    tjc committed
            int ichanged;
    
    tjc's avatar
    tjc committed
            Vector changes = new Vector();
    
    tjc's avatar
    tjc committed
            for(ichanged=0; ichanged<rv_old.size(); ichanged++)
            {
    
    tjc's avatar
    tjc committed
              Range rnew = (Range)rv_new.elementAt(ichanged);
              Range rold = (Range)rv_old.elementAt(ichanged);
       
              if(rnew.getStart() != rold.getStart() ||
    
                 rnew.getEnd()   != rold.getEnd() ||
                 (event.getOldLocation().isComplement(rold) !=
                  event.getNewLocation().isComplement(rnew)))
    
    tjc's avatar
    tjc committed
                changes.add(new Integer(ichanged));
    
    tjc's avatar
    tjc committed
            }
     
    
    tjc's avatar
    tjc committed
            for(int i=0; i<changes.size();i++)
            {
              ichanged = ((Integer)changes.elementAt(i)).intValue();
    
    tjc's avatar
    tjc committed
              
    
    tjc's avatar
    tjc committed
              Range range_new = (Range)rv_new.elementAt(ichanged);
              Range range_old = (Range)rv_old.elementAt(ichanged);
              String seg_id   = feature.getSegmentID(range_new);
    
    tjc's avatar
    tjc committed
              
              if(seg_id == null)
                seg_id   = feature.getSegmentID(range_old);
              
    
    tjc's avatar
    tjc committed
              if(feature.getSegmentRangeStore() != null)
    
    tjc's avatar
    tjc committed
                feature.getSegmentRangeStore().put(seg_id, range_new);
    
              if(sql.size() > 0)
              {
                // collapse updating featureloc into one statement
                ChadoTransaction lastTsn = (ChadoTransaction)sql.lastElement();
    
                String thisKey = feature.getKey().getKeyString();
                if(thisKey.equals(DatabaseDocument.EXONMODEL))
                  thisKey = "exon";
    
                if(lastTsn.getGff_feature() != null &&
                   lastTsn.getType() == ChadoTransaction.UPDATE &&
    
    tjc's avatar
    tjc committed
                   lastTsn.getFeatureKey() != null &&
    
                   lastTsn.getFeatureKey().equals( thisKey ) &&
    
                   lastTsn.getFeatureObject() instanceof FeatureLoc)
                {
                  FeatureLoc floc = (FeatureLoc)lastTsn.getFeatureObject();
                  if(floc.getFeatureByFeatureId().getUniqueName().equals(seg_id))
                  {
    
                    logger4j.debug("REMOVE LAST FeatureLoc ChadoTransaction");
    
                    sql.remove(sql.size()-1);
                  }
                }
              }
              
    
              logger4j.debug("UPDATE FEATURELOC: "+seg_id);
    
    tjc's avatar
    tjc committed
              FeatureLoc featureloc = getFeatureLoc(feature, seg_id, range_new);
              
              tsn = new ChadoTransaction(ChadoTransaction.UPDATE,
                                         featureloc,
    
                                         feature.getLastModified(), feature,
    
                                         feature.getKey().getKeyString(),
                                         "FEATURELOC: ID="+seg_id+" "+
                                         featureloc.getFmin()+".."+featureloc.getFmax());
    
    tjc's avatar
    tjc committed
              sql.add(tsn);
    
              updateResidueColumn(tsn);
    
    tjc's avatar
    tjc committed
            }
    
    tjc's avatar
    tjc committed
          }
    
    tjc's avatar
    tjc committed
          else if(event.getType() == FeatureChangeEvent.QUALIFIER_CHANGED)
    
    tjc's avatar
    tjc committed
          {
    
    tjc's avatar
    tjc committed
            logger4j.debug("QUALIFIER_CHANGED for "
    
    tjc's avatar
    tjc committed
                +event.getOldQualifiers().getQualifierByName("ID").getValues().get(0));
            
            editKeyAndQualifiers(event.getOldQualifiers(),event.getNewQualifiers(),
                event.getOldKey(), event.getNewKey(),
                feature, FeatureChangeEvent.QUALIFIER_CHANGED);
    
    tjc's avatar
    tjc committed
          }
    
    tjc's avatar
    tjc committed
          else if(event.getType() == FeatureChangeEvent.ALL_CHANGED)
    
    tjc's avatar
    tjc committed
          {
    
    tjc's avatar
    tjc committed
            logger4j.debug("ALL_CHANGED "+event.getOldKey().toString()+"  "+
    
                                              event.getNewKey().toString());
    
    tjc's avatar
    tjc committed
            
    
    tjc's avatar
    tjc committed
            editKeyAndQualifiers(event.getOldQualifiers(),event.getNewQualifiers(),
                                 event.getOldKey(), event.getNewKey(),
    
    tjc's avatar
    tjc committed
                                 feature, FeatureChangeEvent.ALL_CHANGED);
    
            
            if(event.getOldKey().compareTo( event.getNewKey() ) != 0 &&
    
    tjc's avatar
    tjc committed
               (event.getNewKey().toString().equals("gene") ||
                event.getNewKey().toString().equals("pseudogene")) &&
    
               feature.getChadoGene() == null)
            {
              ChadoCanonicalGene chado_gene = new ChadoCanonicalGene();
              chado_gene.setGene(feature);
              feature.setChadoGene(chado_gene);
            }
    
    tjc's avatar
    tjc committed
          }
    
    tjc's avatar
    tjc committed
        }
      }
     
    
    tjc's avatar
    tjc committed
      /**
       *  Invoked when an Entry is changed.
       **/
    
    tjc's avatar
    tjc committed
      public void entryChanged(EntryChangeEvent event)
      {
    
    tjc's avatar
    tjc committed
    	logMDC();
    
    tjc's avatar
    tjc committed
        if(event.getType() == EntryChangeEvent.FEATURE_ADDED)
    
    tjc's avatar
    tjc committed
          // if this is a duplicate feature then ignore
          if(event.isDuplicate())
          {
    
    tjc's avatar
    tjc committed
            Feature feature = event.getFeature();
            Qualifier qualifier_uniquename;
            try
            {
              qualifier_uniquename = feature.getQualifierByName("ID");
    
    tjc's avatar
    tjc committed
              logger4j.debug("FEATURE_ADDED ------> DUPLICATE "+
    
    tjc's avatar
    tjc committed
                  (String)(qualifier_uniquename.getValues()).elementAt(0));
            }
            catch(InvalidRelationException e)
            {
              // TODO Auto-generated catch block
              e.printStackTrace();
            }
    
    
    tjc's avatar
    tjc committed
            return;
          }
    
          if(!(event.getFeature().getEmblFeature() instanceof GFFStreamFeature) ||
               event.getFeature().getEmblFeature() instanceof DatabaseInferredFeature)
    
    tjc's avatar
    tjc committed
            return;
          
    
          final Feature feature = event.getFeature();
          
    
          if(! (((GFFStreamFeature)feature.getEmblFeature()).getDocumentEntry().getDocument() instanceof DatabaseDocument))
            return;
          
    
          final FeatureSegmentVector segments = feature.getSegments();
          
          if(segments != null && segments.size() > 1)
          {
            for(int iadd = 0; iadd < segments.size(); iadd++)
            {
              FeatureSegment segment = segments.elementAt(iadd);
              Range range = segment.getRawRange();
              final String segment_uniquename = 
                ((GFFStreamFeature)feature.getEmblFeature()).getSegmentID(range);
              insertFeatureSegment(segment, segment_uniquename);
            }
          }
          else
            insertFeature(feature);
    
    tjc's avatar
    tjc committed
        }
        else if(event.getType() == EntryChangeEvent.FEATURE_DELETED)
        { 
    
          if(event.isDuplicate())
          {
    
    tjc's avatar
    tjc committed
            logger4j.debug("FEATURE_DELETED looks like duplicate - ignore");
    
    tjc's avatar
    tjc committed
          if(!(event.getFeature().getEntry().getEMBLEntry() instanceof DatabaseDocumentEntry) )
          {
            logger4j.debug("FEATURE_DELETED not a Database deletion");
            return;
          }
          
    
    tjc's avatar
    tjc committed
            Qualifier qualifier_uniquename = event.getFeature().getQualifierByName("ID");
            String feature_uniquename = 
                                 (String)(qualifier_uniquename.getValues()).elementAt(0);
    
    tjc's avatar
    tjc committed
            final GFFStreamFeature gff_feature =
    
              (GFFStreamFeature)event.getFeature().getEmblFeature();
    
            
            deletePolypetideDomains(gff_feature, event.getFeature());
            deleteSimilarity(feature_uniquename, gff_feature);
            
    
    tjc's avatar
    tjc committed
            if(event.getFeature().getSegments().size() > 0)
    
            {
              RangeVector ranges = gff_feature.getLocation().getRanges();
              for(int i=0; i<ranges.size(); i++)
              {
                Range range = (Range)ranges.get(i);
                feature_uniquename = gff_feature.getSegmentID(range);
    
                deleteFeature(feature_uniquename, gff_feature.getKey().getKeyString(), gff_feature);
    
              deleteFeature(feature_uniquename, gff_feature.getKey().getKeyString(), gff_feature);
    
    tjc's avatar
    tjc committed
          catch(InvalidRelationException e)
    
    tjc's avatar
    tjc committed
            e.printStackTrace();
    
    tjc's avatar
    tjc committed
        }
    
    //  System.out.println(event.getEntry().getName());
      }
      
    
      /**
       * Update this features residue column where necessary.
       * @param tsn
       */
      private void updateResidueColumn(final ChadoTransaction tsn)
      {
        String keyStr = tsn.getGff_feature().getKey().getKeyString();
        if(GeneUtils.isFeatureToUpdateResidues(keyStr))
        {   
          FeatureForUpdatingResidues featureForUpdatingResidues =
            GeneUtils.getFeatureForUpdatingResidues(tsn.getGff_feature());
          if(featureForUpdatingResidues != null)
          {
            ChadoTransaction tsnResidue = 
              new ChadoTransaction(ChadoTransaction.UPDATE, 
                featureForUpdatingResidues, 
    
    tjc's avatar
    tjc committed
                null, null, null, "RESIDUE SEQUENCE UPDATE ");
    
            sql.add(tsnResidue);
          }
        } 
      }
      
    
    tjc's avatar
    tjc committed
      /**
       * Process segment additions and deletions
       * @param feature
       * @param rv_new
       * @param rv_old
       */
    
      private void segmentNumberChanged(final GFFStreamFeature feature,
                                        final RangeVector rv_new,
                                        final RangeVector rv_old)
      {
        logger4j.debug("SEGMENT_CHANGED "+rv_new.size()+"  "+rv_old.size());
    
    tjc's avatar
    tjc committed
    
        // check for deleted segments
        final Vector deleted = new Vector();
        for(int ideleted = 0; ideleted < rv_old.size(); ideleted++)
    
    tjc's avatar
    tjc committed
          final Range range = (Range) rv_old.get(ideleted);
          if(!rv_new.containsRange(range))
            deleted.add(new Integer(ideleted));
        }
    
    tjc's avatar
    tjc committed
        for(int i = 0; i < deleted.size(); i++)
        {
          Range range_old = (Range) rv_old.elementAt(((Integer) deleted
              .elementAt(i)).intValue());
          String seg_id = feature.getSegmentID(range_old);
          deleteFeature(seg_id, feature.getKey().getKeyString(), feature);
          feature.getSegmentRangeStore().remove(seg_id);
          logger4j.debug("SEGMENT_CHANGED DELETED: " + seg_id);
        }
    
    tjc's avatar
    tjc committed
        if(deleted.size() > 0)
        {
    
          String new_id = feature.getSegmentID(rv_new);
          Qualifier qualifier = new Qualifier("ID", new_id);
          try
          {
            feature.setQualifier(qualifier);
          }
    
    tjc's avatar
    tjc committed
          catch(ReadOnlyException e){}
          catch(EntryInformationException e){}
    
        }
    
        if(addSegments)
        {
          FeatureSegmentVector segments = ((uk.ac.sanger.artemis.Feature) feature
              .getUserData()).getSegments();
    
          for(int iadd = 0; iadd < segments.size(); iadd++)
          {
            final FeatureSegment segment = segments.elementAt(iadd);
            final Range range = segment.getRawRange();
            if(rv_old.containsRange(range))
              continue;
    
            String segment_uniquename = feature.getSegmentID(range);
            logger4j.debug("SEGMENT_CHANGED ADDED: " + segment_uniquename);
            insertFeatureSegment(segment, segment_uniquename);
          }
        }
    
        processFeatureRelationshipRank(feature, rv_new, ChadoTransaction.UPDATE);
      }
      
    
    tjc's avatar
    tjc committed
      /**
       * Update spliced features rank
       * @param feature
       * @param rv_new
    
      private void processFeatureRelationshipRank(final GFFStreamFeature feature,
    
    tjc's avatar
    tjc committed
                                                  final RangeVector rv_new,
                                                  final int type)
    
    tjc's avatar
    tjc committed
        // update feature_relationship.rank
        ChadoTransaction tsn;
        Hashtable feature_relationship_rank_store = new Hashtable();
    
    tjc's avatar
    tjc committed
        Qualifier qualifier_relation = feature.getQualifierByName("Parent");
    
    tjc's avatar
    tjc committed
        for(int rank=0; rank<rv_new.size(); rank++)
    
    tjc's avatar
    tjc committed
          Range range   = (Range)rv_new.elementAt(rank);
    
    tjc's avatar
    tjc committed
          String seq_id = feature.getSegmentID(range);
          
    
          org.gmod.schema.sequence.Feature chado_feature = 
                   new org.gmod.schema.sequence.Feature();
    
    tjc's avatar
    tjc committed
          chado_feature.setUniqueName(seq_id);
    
    tjc's avatar
    tjc committed
    
          List featureRelationshipsForSubjectId = null;
          if(qualifier_relation != null)
          {
            StringVector parents = qualifier_relation.getValues();
            if(parents.size() > 0)
              featureRelationshipsForSubjectId = new Vector();
            
            for(int i=0; i<parents.size(); i++)
            {
    
              org.gmod.schema.sequence.Feature parent =
                  new org.gmod.schema.sequence.Feature();
    
    tjc's avatar
    tjc committed
              parent.setUniqueName((String)parents.get(i));
    
    tjc's avatar
    tjc committed
              FeatureRelationship feature_relationship =
                  new FeatureRelationship();
    
              
              //
              // should be retrieved from relationship ontology !!
    
              CvTerm cvterm = DatabaseDocument.getCvTermByCvAndCvTerm("part_of", "relationship");
              
              //CvTerm cvterm = new CvTerm();
              //cvterm.setCvTermId(DatabaseDocument.getCvtermID("part_of").intValue());
    
    tjc's avatar
    tjc committed
              feature_relationship.setFeatureByObjectId(parent);
              feature_relationship.setFeatureBySubjectId(chado_feature);
    
    tjc's avatar
    tjc committed
              feature_relationship.setCvTerm(cvterm);
    
    tjc's avatar
    tjc committed
              feature_relationship.setRank(rank);
              featureRelationshipsForSubjectId.add(feature_relationship);
              
    
              tsn = new ChadoTransaction(type,
    
    tjc's avatar
    tjc committed
                  feature_relationship,
    
                  feature.getLastModified(), feature,
    
                  feature.getKey().getKeyString(),
    
    tjc's avatar
    tjc committed
                  "FEATURE_RELATIONSHIP: ID="+seq_id+
                  " part_of "+parent.getUniqueName()+" RANK="+rank);
    
    tjc's avatar
    tjc committed
              sql.add(tsn);
            }
          }
    
          feature_relationship_rank_store.put(seq_id, new Integer(rank));
    
    tjc's avatar
    tjc committed
        }
        feature.setFeature_relationship_rank_store(feature_relationship_rank_store);  
      }
      
    
    tjc's avatar
    tjc committed
      /**
       * Create transaction for inserting a feature.
       * @param feature
       */
      private void insertFeature(final Feature feature)
      {
        String feature_uniquename = null;
    
        Qualifier qualifier_name = null;
    
    tjc's avatar
    tjc committed
        try
        {
    
          final Qualifier qualifier_uniquename = feature.getQualifierByName("ID");
    
          qualifier_name = feature.getQualifierByName("Name");
    
    tjc's avatar
    tjc committed
          if(qualifier_uniquename != null)
    
    tjc's avatar
    tjc committed
            feature_uniquename = (String)(qualifier_uniquename.getValues()).elementAt(0);
    
    tjc's avatar
    tjc committed
            logger4j.debug("FEATURE_ADDED "+feature_uniquename);
    
    tjc's avatar
    tjc committed
          
    
    tjc's avatar
    tjc committed
          while(feature_uniquename == null ||
                feature_uniquename.equals("") ||
                feature_uniquename.equals("to_be_set"))
          {
            feature_uniquename = JOptionPane.showInputDialog(null,
                                 "Provide a systematic_id : ",
                                 "systematic_id missing in "+
                                 feature.getIDString(),
    
    tjc's avatar
    tjc committed
                                 JOptionPane.QUESTION_MESSAGE);
            
            if(feature_uniquename == null)
              return;
    
    tjc's avatar
    tjc committed
          }
    
    tjc's avatar
    tjc committed
          feature.setQualifier(new Qualifier("ID", feature_uniquename.trim()));
    
    tjc's avatar
    tjc committed
        }
        catch(EntryInformationException eie)
        {
          eie.printStackTrace();
        }
        catch(ReadOnlyException roe)
        {
          roe.printStackTrace();
        }
    
        
        FeatureLoc featureloc = getFeatureLoc(
                       (GFFStreamFeature)feature.getEmblFeature(),
                       feature_uniquename, 
                      feature.getLocation().getTotalRange());
    
        org.gmod.schema.sequence.Feature chado_feature = 
                  new org.gmod.schema.sequence.Feature();
        chado_feature.setFeatureLoc(featureloc);
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        final StringBuffer log = new StringBuffer();
        log.append("FEATURELOC="+
            ((featureloc.getStrand().intValue() == -1) ? "complement(" : "(")+
             (featureloc.getFmin().intValue()+1)+".."+featureloc.getFmax().intValue()+")");
        
    
    tjc's avatar
    tjc committed
        try
    
    tjc's avatar
    tjc committed
          // relationship attributes
          Qualifier qualifier_relation = feature.getQualifierByName("Parent");
    
    tjc's avatar
    tjc committed
          List featureRelationshipsForSubjectId = null;
    
    tjc's avatar
    tjc committed
          if(qualifier_relation != null)
          {
            StringVector parents = qualifier_relation.getValues();
            if(parents.size() > 0)
    
    tjc's avatar
    tjc committed
              featureRelationshipsForSubjectId = new Vector();
    
    tjc's avatar
    tjc committed
            for(int i=0; i<parents.size(); i++)
    
              org.gmod.schema.sequence.Feature parent =
                  new org.gmod.schema.sequence.Feature();
    
    tjc's avatar
    tjc committed
              parent.setUniqueName((String)parents.get(i));
    
    tjc's avatar
    tjc committed
              FeatureRelationship feature_relationship =
                  new FeatureRelationship();
    
              
              //
              // should be retrieved from relationship ontology !!
    
              CvTerm cvterm = DatabaseDocument.getCvTermByCvAndCvTerm("part_of", "relationship");
              
              //CvTerm cvterm = new CvTerm();
              //cvterm.setCvTermId(DatabaseDocument.getCvtermID("part_of").intValue());
    
    tjc's avatar
    tjc committed
              feature_relationship.setFeatureByObjectId(parent);
              feature_relationship.setFeatureBySubjectId(chado_feature);
    
    tjc's avatar
    tjc committed
              feature_relationship.setCvTerm(cvterm);
    
    tjc's avatar
    tjc committed
              featureRelationshipsForSubjectId.add(feature_relationship);
    
    tjc's avatar
    tjc committed
              
              log.append(" PART_OF="+parent.getUniqueName());
    
    tjc's avatar
    tjc committed
          }
          
          qualifier_relation = feature.getQualifierByName("Derives_from");
          if(qualifier_relation != null)
          {
            StringVector derives = qualifier_relation.getValues();
    
    tjc's avatar
    tjc committed
            if(derives.size() > 0 && featureRelationshipsForSubjectId == null)
              featureRelationshipsForSubjectId = new Vector();
    
    tjc's avatar
    tjc committed
            for(int i=0; i<derives.size(); i++)
    
              org.gmod.schema.sequence.Feature parent =
                                          new org.gmod.schema.sequence.Feature();
    
    tjc's avatar
    tjc committed
              parent.setUniqueName((String) derives.get(i));
    
    tjc's avatar
    tjc committed
              FeatureRelationship feature_relationship = new FeatureRelationship();
    
              
              //
              // should be retrieved from relationship ontology !!
    
    tjc's avatar
    tjc committed
              CvTerm cvterm = new CvTerm();
              cvterm.setCvTermId(DatabaseDocument.getCvtermID("derives_from")
    
                  .intValue());
    
    tjc's avatar
    tjc committed
              feature_relationship.setFeatureByObjectId(parent);
              feature_relationship.setFeatureBySubjectId(chado_feature);
    
    tjc's avatar
    tjc committed
              feature_relationship.setCvTerm(cvterm);
    
    tjc's avatar
    tjc committed
              featureRelationshipsForSubjectId.add(feature_relationship);
    
    tjc's avatar
    tjc committed
              log.append(" DERIVES_FROM="+parent.getUniqueName());
    
    tjc's avatar
    tjc committed
          }
    
    tjc's avatar
    tjc committed
          chado_feature.setFeatureRelationshipsForSubjectId(
                           featureRelationshipsForSubjectId);
    
    tjc's avatar
    tjc committed
        }
        catch(InvalidRelationException ire){}
    
    tjc's avatar
    tjc committed
        chado_feature.setUniqueName(feature_uniquename);
    
        if(qualifier_name != null)
          chado_feature.setName((String)(qualifier_name.getValues()).elementAt(0));
    
    tjc's avatar
    tjc committed
        String key = feature.getKey().toString();
    
        if(key.equals(DatabaseDocument.EXONMODEL))
          key = "exon";
    
    tjc's avatar
    tjc committed
        CvTerm cvTerm = DatabaseDocument.getCvTermByCvAndCvTerm(key, "sequence");
    
    tjc's avatar
    tjc committed
        if(cvTerm == null)
        {
          final String msg = 
            key+" is not a valid/known database key (check the sequence ontology)!";
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
          logger4j.error(msg);
    
    tjc's avatar
    tjc committed
          JOptionPane.showMessageDialog(null,msg);
    
    tjc's avatar
    tjc committed
          return;
        }
        
        chado_feature.setCvTerm(cvTerm);
    
    tjc's avatar
    tjc committed
        // create transaction object
    
    tjc's avatar
    tjc committed
        
        ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.INSERT,
                                   chado_feature,
    
                                   null, (GFFStreamFeature)feature.getEmblFeature(), null,
    
    tjc's avatar
    tjc committed
                                   "FEATURE: ID="+feature_uniquename+
                                   " "+log.toString()+
                                   " KEY="+key);
    
        sql.add(tsn); 
        
        addQualifiers(feature.getQualifiers(), chado_feature, 
            (GFFStreamFeature)feature.getEmblFeature(), feature_uniquename);
    
    tjc's avatar
    tjc committed
      }
      
      /**
       * Create transaction for inserting a feature.
       * @param feature
       */
      private void insertFeatureSegment(final FeatureSegment segment,
                                        final String segment_uniquename)
      {
    
        org.gmod.schema.sequence.Feature chado_feature = 
          new org.gmod.schema.sequence.Feature();
    
    tjc's avatar
    tjc committed
        FeatureLoc featureloc = new FeatureLoc();
    
        chado_feature.setFeatureLoc(featureloc);
    
    tjc's avatar
    tjc committed
        
        if(segment.isForwardSegment())
    
          featureloc.setStrand(new Short((short)1));
    
    tjc's avatar
    tjc committed
        else
    
          featureloc.setStrand(new Short((short)-1));
    
    tjc's avatar
    tjc committed
        
        // codon_start attribute
        Feature feature = segment.getFeature();
        try
        {
          Qualifier qualifier_phase = feature.getQualifierByName("codon_start");
          if(qualifier_phase != null)
    
    tjc's avatar
    tjc committed
          {
    
    tjc's avatar
    tjc committed
            String phase = (String)(qualifier_phase.getValues()).elementAt(0);
    
            if(phase.equals ("1"))
    
              featureloc.setPhase(new Integer(0));
    
    tjc's avatar
    tjc committed
            else if(phase.equals("2"))
    
              featureloc.setPhase(new Integer(1));
    
    tjc's avatar
    tjc committed
            else if(phase.equals("3")) 
    
              featureloc.setPhase(new Integer(2));
    
    tjc's avatar
    tjc committed
          }
    
          else
            featureloc.setPhase(null);
    
    tjc's avatar
    tjc committed
          
          // relationship attributes
          Qualifier qualifier_relation = feature.getQualifierByName("Parent");
    
    tjc's avatar
    tjc committed
          List featureRelationshipsForSubjectId = null;
    
    tjc's avatar
    tjc committed
          if(qualifier_relation != null)
    
    tjc's avatar
    tjc committed
          {
    
    tjc's avatar
    tjc committed
            StringVector parents = qualifier_relation.getValues();
            if(parents.size() > 0)
    
    tjc's avatar
    tjc committed
              featureRelationshipsForSubjectId = new Vector();
    
    tjc's avatar
    tjc committed
            
            for(int i=0; i<parents.size(); i++)
    
              org.gmod.schema.sequence.Feature parent =
                  new org.gmod.schema.sequence.Feature();
    
    tjc's avatar
    tjc committed
              parent.setUniqueName((String)parents.get(i));
    
    tjc's avatar
    tjc committed
              FeatureRelationship feature_relationship =
                  new FeatureRelationship();
    
              
              //
              // should be retrieved from relationship ontology !!
    
              CvTerm cvterm = DatabaseDocument.getCvTermByCvAndCvTerm("part_of", "relationship");
              
              //CvTerm cvterm = new CvTerm();
              //cvterm.setCvTermId(DatabaseDocument.getCvtermID("part_of").intValue());
    
    tjc's avatar
    tjc committed
              feature_relationship.setFeatureByObjectId(parent);
              feature_relationship.setFeatureBySubjectId(chado_feature);
    
    tjc's avatar
    tjc committed
              feature_relationship.setCvTerm(cvterm);
    
    tjc's avatar
    tjc committed
              featureRelationshipsForSubjectId.add(feature_relationship);
            }
    
    tjc's avatar
    tjc committed
          }
          
          qualifier_relation = feature.getQualifierByName("Derives_from");
          if(qualifier_relation != null)
          {
            StringVector derives = qualifier_relation.getValues();
    
    tjc's avatar
    tjc committed
            if(derives.size() > 0 && featureRelationshipsForSubjectId == null)
              featureRelationshipsForSubjectId = new Vector();
    
    tjc's avatar
    tjc committed
            
            for(int i=0; i<derives.size(); i++)
    
              org.gmod.schema.sequence.Feature parent =
                                          new org.gmod.schema.sequence.Feature();
    
    tjc's avatar
    tjc committed
              parent.setUniqueName((String) derives.get(i));
    
    tjc's avatar
    tjc committed
              FeatureRelationship feature_relationship = new FeatureRelationship();
    
              
              //
              // should be retrieved from relationship ontology !!
    
    tjc's avatar
    tjc committed
              CvTerm cvterm = new CvTerm();
              cvterm.setCvTermId(DatabaseDocument.getCvtermID("derives_from")
    
                  .intValue());
    
    tjc's avatar
    tjc committed
              feature_relationship.setFeatureByObjectId(parent);
              feature_relationship.setFeatureBySubjectId(chado_feature);
    
    tjc's avatar
    tjc committed
              feature_relationship.setCvTerm(cvterm);
    
    tjc's avatar
    tjc committed
              featureRelationshipsForSubjectId.add(feature_relationship);
            }
    
    tjc's avatar
    tjc committed
          }
    
    tjc's avatar
    tjc committed
          chado_feature.setFeatureRelationshipsForSubjectId(
                           featureRelationshipsForSubjectId);
    
    tjc's avatar
    tjc committed
        }
    
    tjc's avatar
    tjc committed
        catch(InvalidRelationException ire){}
    
    tjc's avatar
    tjc committed
    
    
        featureloc.setFmin(new Integer(segment.getRawRange().getStart()-1));
        featureloc.setFmax(new Integer(segment.getRawRange().getEnd()));
    
    tjc's avatar
    tjc committed
        chado_feature.setUniqueName(segment_uniquename);
    
        //chado_feature.setName(segment_uniquename);
    
    tjc's avatar
    tjc committed
    
    
        String key = feature.getKey().toString();
        if(key.equals(DatabaseDocument.EXONMODEL))
          key = "exon";
    
        CvTerm cvterm = getCvTerm(key, "sequence");
    
    tjc's avatar
    tjc committed
        chado_feature.setCvTerm(cvterm);
    
    tjc's avatar
    tjc committed
    
        //addQualifiers(feature.getQualifiers(), chado_feature);
        // create transaction object
    
    tjc's avatar
    tjc committed
        
        ChadoTransaction tsn = new ChadoTransaction(ChadoTransaction.INSERT,
            chado_feature,
    
            null, (GFFStreamFeature)segment.getFeature().getEmblFeature(), null,
    
    tjc's avatar
    tjc committed
            "SEGMENT: ID="+segment_uniquename+" KEY="+key);
    
        sql.add(tsn);
        
        List tsns = DatabaseDocument.getUpdateResiduesColumnTransactions(tsn);
        if(tsns != null)
          sql.addAll(tsns);
    
    tjc's avatar
    tjc committed
      }
    
      /**
       * Delete protein domains, non_cytoplasm_location, cytoplasm_location,
       * membrane_structure, transmembrane, signal_peptide
       * @param gff_feature
       * @param feature
       */
      private void deletePolypetideDomains(final GFFStreamFeature gff_feature,
                                           final Feature feature)
      {
        if(!gff_feature.getKey().getKeyString().equals("polypeptide"))
          return;
    
        QualifierVector qualifiers =
            ProteinMapPanel.getProteinMapQualifiers(feature);
        
        if(qualifiers == null)
          return;
        for(int i=0; i<qualifiers.size(); i++)
        {
          if(!(qualifiers.get(i) instanceof QualifierLazyLoading))
            continue;