
import java.util.* ;
import java.awt.* ;

public class GenTree {

   boolean firstTime = true ;
	Model Tree = null ;

   Comentry comentry ;

   public GenTree ( Comentry c ){
   	this.comentry = c ;
   }

   //The method ProcessSample is overloaded
   //this version of the ProcessSample method is called if we have a +tve class Sample
   public void ProcessSample ( Sample e ){

      //We know the first sample to be +tve a Sample
      //Set up the most general node
      if ( Tree == null ){
         Vector atts = new Vector () ;
         Attribute at ;
         for ( int count = 0 ; count < e.Attributes.length  ; count ++){
            at = new Attribute (e.Attributes[count].index, "?") ;
            atts.addElement( at ) ;
         }
      	Model m = new Model ( atts, comentry ) ;
         Tree = m ;
      }
      //On each succesive +tve sample
      else{
         //To prune the leaf nodes that do not match +tve sample
         Vector leaves = new Vector () ;
      	Tree.returnLeaves( leaves );
         Model m ;
         Attribute SampleAttribute, modelAttribute ;

         for ( Enumeration en = leaves.elements() ; en.hasMoreElements() ;){
         	m = ( Model ) en.nextElement() ;
            for ( int count = 1 ; count < e.Attributes.length ; count ++ ){
            	SampleAttribute = e.Attributes[count] ;
           		modelAttribute = ( Attribute ) m.Attributes.elementAt( count ) ;
               if ( (!modelAttribute.value.equals("?"))&&
                    (!SampleAttribute.value.equals( modelAttribute.value )) ){
                  comentry.appendText ( "The node" ) ;
                  writeModel ( m ) ;
                  comentry.appendText ( "has an attribute value that does not match this positive sample, "+
                  							   modelAttribute.value + " != " + SampleAttribute.value +" so the model is pruned" ) ;
                  m.pruned = true ;
               }
            }
         }
      }
   }//


   //this is another version of ProcessSample that is also passed the attributes from
   //the specific model this is so that appropiate leaf nodes can produce children.
   public void ProcessSample ( Sample e, Vector SpecAttributes ) {

      Vector children = new Vector () ;
      Vector leaves   = new Vector () ;
      Vector temp     = new Vector () ;
      Tree.returnLeaves ( leaves )    ;

      //we must check for each leaf to see if an attribute value corresponds to -tve sample
      //if so we produce children
      Model m ;

      if ( firstTime == true ){
      //we should call a specific fristGeneration method in tree
         firstTime = false    ;
      	Tree.firstGeneration( e, SpecAttributes );
      }
      else{
      //if there is a match between attribute values in the negative sample and the general model
      //we know that the matching part is possibly part of the positive classification as it came from
      //the specific model
	     Attribute SampleAttribute, modelAttribute ;

  //for each leaf
  leafLoop: for ( Enumeration en = leaves.elements() ; en.hasMoreElements() ;){
      	   m = ( Model ) en.nextElement() ;

// Corrected by sakurai (the next 2 lines were added )
// check if a general model is a generalization of the sample (negative)
            int moregeneral=1;
            // for each attribute
            for ( int count = 0 ; count < e.Attributes.length  ; count ++ ){
          		SampleAttribute = e.Attributes[count] ;
	            modelAttribute = ( Attribute ) m.Attributes.elementAt( count ) ;

// nonsense               //If leaf node matches the -tve sample
// nonsense               //tell node to produce child
// Corrected by Sakurai
//      	      if ( SampleAttribute.value.equals( modelAttribute.value ) )
      	      if ( SampleAttribute.value.equals( modelAttribute.value ) || modelAttribute.value == "?")
              {
// Corrected  by Sakurai   added next 4 lines
              } else { 
              moregeneral = 0;
              }
// Corrected by Sakurai: the brace was moved here from far ahead.
           }
              if (moregeneral==1) {
                     comentry.appendText ( "The node " ) ;
                     writeModel ( m ) ;
//                     comentry.appendText ( "has an attribute value that matches the negative sample." +
//                                                       "  They both hold the value, " + modelAttribute.value + ", for the attribute, "   +
//                     										     modelAttribute.index + "." ) ;
//                     comentry.appendText ( "Because of this match we create new general models that are specializations of "+
//                                                       "the node.\n" );
                     comentry.appendText ( "is more general than the negative sample.");
                     comentry.appendText ( "Because of this we create new general models that are specializations of "+
                                                       "the node.\n" );

                     //produce children pass a vector of the new children back
            			children = m.produceChildren( e, SpecAttributes ) ;
                     temp = ( Vector ) leaves.clone ( ) ;
                     temp.removeElement( m ) ;

                     //We must check each new child to see if it is a specialisation of another leaf node ( excepting its parent )
                     checkSpecialisation ( children, temp ) ;
                     continue leafLoop ;
   	         }
// Corrected by Sakurai: there was a closing brace here for "count loop"
      	}

      }
	  }//end processSample

     //This method compares all the new child nodes against all the leaf nodes ( except the parent ) to see if there is
     //a specialisation.
     private void checkSpecialisation ( Vector children, Vector leaves){
     //we need for each child to check against each leaf and compare all attribute values.
      int count ;
      boolean spec ;
      Model  leaf  ;
      Model  child ;
      Vector leafAttributes  = new Vector ( ) ;
      Vector childAttributes = new Vector ( ) ;
      Attribute leafAtt  ;
      Attribute childAtt ;

      //for each child
     	for ( Enumeration enChild = children.elements ( ) ; enChild.hasMoreElements ( ) ; ){
      	child = ( Model ) enChild.nextElement ( ) ;
         childAttributes = child.Attributes ;

         //for each leaf
leafLoop :for ( Enumeration en = leaves.elements ( ) ; en.hasMoreElements ( ) ; ){
         spec = false ;
      	leaf = ( Model ) en.nextElement ( ) ;
         leafAttributes = leaf.Attributes ;

         //Compare the child and leaf attributes
         for ( count = 0 ; count < leafAttributes.size ( ) ; count ++ ){
            leafAtt  = ( Attribute ) leafAttributes.elementAt  ( count ) ;
         	childAtt = ( Attribute ) childAttributes.elementAt ( count ) ;

            if ( !childAtt.value.equals( leafAtt.value )){
               if ( (!childAtt.value.equals("?")) && ( leafAtt.value.equals("?")) ){
                	spec = true ;
               }
               else continue leafLoop ;
            }
         }
         //if child is a specialisation
         if ( spec ){
         		child.pruned = true  ;

               //we need to update the comentry
               comentry.appendText ("A new child is a specialisation of the node" )  ;
               writeModel ( leaf ) ;
               comentry.appendText("and so is marked as pruned.\n" )  ;
         }
      //continue jumps here
      }
     	}
      System.gc ( ) ;
     }//end checkSpecialisation


     //This method compares the leaf nodes of the general model tree with the specific model
     //to establish it the termination condition is reached.
     public boolean checkTerminationCondition ( SpecModel specific ){

     		Vector leaves = new Vector ( ) ;
         Tree.returnLeaves ( leaves ) ;

         boolean condition = false ;

         int count ;
         Model leaf ;
         Attribute leafAtt = null , specAtt = null ;

leafLoop:for ( Enumeration en = leaves.elements ( ) ; en.hasMoreElements ( ) ; ){

            condition = false ;
         	leaf = ( Model ) en.nextElement ( ) ;

            for ( count = 0 ; count < leaf.Attributes.size ( ) ; count ++ ){
            	leafAtt = ( Attribute ) leaf.Attributes.elementAt ( count ) ;
               specAtt = ( Attribute ) specific.Attributes.elementAt ( count ) ;
        	      if ( (leafAtt.value.equals ( specAtt.value ) ) && ( !leaf.pruned ) ){
               	condition = true;
               }
               else{
                  condition = false ;
               	continue leafLoop ;
               }
            }
          //continue
         }
         return condition ;
     }


     private void writeModel ( Model m ) {

     		StringBuffer buffer = new StringBuffer ( ) ;
         Attribute att ;

         for ( Enumeration en = m.Attributes.elements ( ) ; en.hasMoreElements ( ) ; ) {
         	att = ( Attribute ) en.nextElement  ( ) ;
            buffer.append ( att.index + " : " + att.value + "  " ) ;
         }
         comentry.appendText( buffer.toString ( )  ) ;
     }
     
}//end class