/*
 *This library is free software; you can redistribute it and/or
 *modify it under the terms of the GNU Lesser General Public
 *License as published by the Free Software Foundation; either
 *version 2.1 of the License, or (at your option) any later version.
 *
 *This library 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
 *Lesser General Public License for more details.
 *
 *You should have received a copy of the GNU Lesser General Public
 *License along with this library; if not, write to the Free Software
 *Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/* 
 * This software was written by Phillip Lord (p.lord@hgmp.mrc.ac.uk)
 * whilst at the University of Manchester as a Pfizer post-doctoral 
 * Research Fellow. 
 *
 * The initial code base is copyright by Pfizer, or the University
 * of Manchester. Modifications to the initial code base are copyright
 * of their respective authors, or their employers as appropriate. 
 * Authorship of the modifications may be determined from the ChangeLog
 * placed at the end of this file
 */

package uk.ac.man.bioinf.sequence.test; // Package name inserted by JPack

import uk.ac.man.bioinf.sequence.complex.ComplexElement;
import uk.ac.man.bioinf.sequence.complex.Methylation;
import uk.ac.man.bioinf.sequence.complex.ModificationFactory;
import uk.ac.man.bioinf.sequence.complex.ComplexElementFactory;
import uk.ac.man.bioinf.sequence.complex.Modification;
import uk.ac.man.bioinf.sequence.types.RNANucleotide;


/**
 * ComplexElementAndModificationTest.java
 *
 *
 * Created: Tue Feb 29 11:32:15 2000
 *
 * @author Phillip Lord
 * @version $Id: ComplexElementAndModificationTest.java,v 1.4 2001/04/11 17:04:43 lord Exp $
 */

public class ComplexElementAndModificationTest 
{

  public static void main( String[] args )
  {
    System.out.println( "This class tests out the ComplexElement, and associated Factory methods" );
    System.out.println( "The essential rules are as follows:- " );
    System.out.println();
    
    System.out.println( "1) A request for a given modification to an specific Residue should always return" );
    System.out.println( "the same object" );
    System.out.println();
    
    System.out.println( "2) A complex element with a given set of modifications to a given residue should " );
    System.out.println( "always return the same object no matter what order the modifications are obtained" );
    System.out.println();
    
    System.out.println( "3) Modifications will be addressed in two ways. Either by name or by subclassing as singletons" );
    System.out.println( "or enumerations (the latter is not supported yet!). All modifications instances should have" );
    System.out.println( "different names however they are created. The factory should crash if duplicates are used" );
    System.out.println();
    
    System.out.println( "4) Although not tested by this class, performance should be good. The initial implementation has" );
    System.out.println( "performs look up in something approximately constant time, wrt to the number of ComplexElements in" );
    System.out.println( "existance, and linear wrt to the number of modifications to the ComplexElement in question" );
    System.out.println( "**************" );
    System.out.println();
    
    System.out.println( "Testing Modifications to residues" );
    System.out.println( "Using the " + RNANucleotide.ADENOSINE );
    System.out.println();
    
    System.out.println( "Attempting to gain the methylated version " );
    
    ComplexElement methylA = ComplexElementFactory.addComplexElement( RNANucleotide.ADENOSINE, Methylation.METHYLATION );
    
    System.out.println( "Have instance " + methylA );
    System.out.println();
    
    System.out.println( "Retrieving for a second time..." );
    
    ComplexElement methylASecond = ComplexElementFactory.addComplexElement( RNANucleotide.ADENOSINE, Methylation.METHYLATION );
    System.out.println( "Have second instance " + methylASecond );
    System.out.println();

    System.out.println( "Testing that these objects have same hash, and .equals, and == " );
    System.out.println( "Hash codes are " + methylA.hashCode() + " and " + methylASecond.hashCode() );
    System.out.println( "First is equal to the second " + methylA.equals( methylASecond ) );
    System.out.println( "First is == to the second " + (methylA == methylASecond ) );
    System.out.println( "************" );
    System.out.println();
    System.out.println();
    
    
    System.out.println( "Testing out modification factory with generic \"phospho\" element" );
  
    System.out.println( "Initial retrieval....should throw exception as this element has not been created" );
    
    Modification phospho = null;
    
    try{
      phospho = getPhosphoModification();
      System.out.println( "ERROR: The attempt to gain a modification should have failed " );
      Thread.dumpStack();
      System.exit( 1 );
    }
    catch( Exception exp ){
      System.out.println( "Have caught the exception correctly \n  " + exp.getMessage() );
    }
    System.out.println();

    System.out.println( "Attempting to create the phospho element " );
    try{
      phospho = createPhospoModification();
      System.out.println( "Modification created correctly " );
    }
    catch( Exception exp ){
      System.out.println( "ERROR: First attempt to create a modification has failed" );
    }
    System.out.println();
    
    System.out.println( "Attempting to re-create the phospho element. Should except" );
    try{
      phospho = createPhospoModification();
      System.out.println( "ERROR: Attempt to re-create the phospo element should have failed " );
    }
    catch( Exception exp ){
      System.out.println( "Have caught the exception correctly \n   " + exp.getMessage() );
    }
    System.out.println();
    
    System.out.println( "Also checking to see whether we get an exception when attempting to " );
    System.out.println( "create the methylation modification again" );
    
    try{
      ModificationFactory.createModification( "Methylation", '*' );
      System.out.println( "ERROR: Attempt to re-create the methyl element should have failed " );
    }
    catch( Exception exp ){
      System.out.println( "Have caught the exception correctly \n   " + exp.getMessage() );
    }
    System.out.println( "Exception testing complete" );
    System.out.println( "*************" );
    System.out.println();
    System.out.println();
    
    System.out.println( "Testing whether multiple retrieval of phospho are equal " );
    Modification phospho2 = getPhosphoModification();
       
    System.out.println( "Hash codes are " + phospho.hashCode() + " " + phospho2.hashCode() );
    System.out.println( "First is equal to the second " + phospho.equals( phospho2 ) );
    System.out.println( "First is == to the second " + ( phospho == phospho2 ) );
    
    System.out.println( "Multiple Modifications retrieval testing complete" );
    System.out.println( "*************" );
    System.out.println();
    System.out.println();
    
    
    System.out.println( "Testing associativity of the ComplexElement Retrieval" );
    System.out.println( "Retrieveing phosopho A element " );
    ComplexElement phosphoA = ComplexElementFactory.addComplexElement( RNANucleotide.ADENOSINE, phospho );
    System.out.println( "Have phospho A " + phosphoA );

    System.out.println( "Modifications to phosphoA :- " );
    printModifications( phosphoA.getModifications() );
    System.out.println( "Modifications to methylA :- " );
    printModifications( methylA.getModifications() );
    
    System.out.println( "Now getting phosphoMethylA, and MethylPhosphoA " );
    ComplexElement phosphoMethylA = ComplexElementFactory.addComplexElement( phosphoA, Methylation.METHYLATION );
    ComplexElement methylPhosphoA = ComplexElementFactory.addComplexElement( methylA, phospho );

    Modification[] phosMethMod = phosphoMethylA.getModifications();
    Modification[] methPhosMod = methylPhosphoA.getModifications();
    
    System.out.println( "Modifications to phosphoMethylA are :- " );
    printModifications( phosMethMod );
    System.out.println( "Modifications to methylPhosphoA are :- " );
    printModifications( methPhosMod );
    System.out.println();
    
    System.out.println( "Hash codes are " + methylPhosphoA.hashCode() + " " + phosphoMethylA.hashCode() );
    System.out.println( "First is equal to the second " + methylPhosphoA.equals( phosphoMethylA ) );
    System.out.println( "First is == to the second " + ( methylPhosphoA == phosphoMethylA ) );
    System.out.println( "Associative testing complete" );
    System.out.println( "**********************" );

    System.out.println();
    System.out.println();


    System.out.println( "Testing out removal" );
    ComplexElement phosMethModAMinusPhos = ComplexElementFactory.removeComplexElement
      ( phosphoMethylA, Methylation.METHYLATION );
    System.out.println( "Have remove methyl from A " );
    System.out.println( "Element should equal phosphoA " );
    System.out.println( "which is " + phosMethModAMinusPhos.equals( phosphoA ) );
    System.out.println( "and == " + ( phosMethModAMinusPhos == phosphoA ) );
    
    
    System.out.println( "Finished test!" );
    
  }
  
  private static void printModifications( Modification mod )
  {
    System.out.println( "   " + mod + mod.getName() );
  }
  
  private static void printModifications( Modification[] mods )
  {
    for( int i  = 0 ; i < mods.length ; i ++ ){
      System.out.println( "   " + mods[ i ] + mods[ i ].getName() );
    } //end for( i  < mods.length )
  }
  
  private static Modification createPhospoModification()
  {
    return ModificationFactory.createModification( "Phospho", 'p' );
  }
  
  private static Modification getPhosphoModification()
  {
    return ModificationFactory.getModification( "Phospho" );
  } //end main method 
  
  
} // ComplexElementAndModificationTest



/*
 * ChangeLog
 * $Log: ComplexElementAndModificationTest.java,v $
 * Revision 1.4  2001/04/11 17:04:43  lord
 * Added License agreements to all code
 *
 * Revision 1.3  2000/11/27 18:14:58  lord
 * *** empty log message ***
 *
 * Revision 1.2  2000/04/18 17:52:27  jns
 * o changes madde because of files moved to types package.
 *
 * Revision 1.1  2000/03/08 17:26:36  lord
 * To many changes to document
 *
 */
