import string
import sys
import random
from xml.sax import ContentHandler
Nvars=[0]
variables_list=[]
variables_pos={}

result=[""]

def lesso(a,b):
     return a<b

def difforzero(a):
     if(a<0):
          return 0
     else:
          return a

def fumag(rho,rho_a,p_b):
     if(rho>rho_a):
          return 1.0
     else:
          return 1-p_b*(rho_a - rho)

def isFloat(string):
     is_float=1
     try:
         float(string)
     except:
         is_float=0
     if(is_float==0):
          try:
               exec("res="+string)
               if( type(res) in [type(1), type(1.0)]):
                    is_float=1
          except:
               is_float=0
          if(is_float==0):
               if( "+" in string or "-" in string or "*" in string or "/" in string):
                    is_float=1
               

     if(is_float):
          print "res="+string, "  va bene come float"
     else:
          print "res="+string, " no  va bene come float"
     return is_float

class generic_processor:
    def __init__(self):
        self.arguments=[]
        self.symbol=""
        self.toend=0
        self.attrs={}
	# self.possible_keywords=[]
	self.necessary_keywords=[]
        self.proc_char_count=0

    def process_startElement(self, name, attrs):
        # print " sono in startElement di ", name
        self.name=name
        for key in attrs.keys():
          self.attrs[key]=attrs[key]
        
    def tratta_symbol(self):
        pass

    def checkKeywords(self):
	used_keyword=[]
	for arg in self.arguments:
            if( "key" in  arg.attrs.keys() ) :
                 used_keyword.append(arg.attrs["key"])
        for tok in self.necessary_keywords:
	    if(tok not in used_keyword):
               s=  " necessary keywords are " + str(self.necessary_keywords)
               s= str(tok + " not found in keywords of "+self.name +" object \n" ) +s
               # raise s



    def process_endElement(self, name):

        self.end_pre_process()

        if(name=="AAscan"):
	   debug=1
        else:
           debug=0

        if debug:
          print " sono in endElement di ", name
          print "self.symbol ", self.symbol, "AAA"
          print "#"*40

        if (self.symbol=="" and self.arguments !=[]):
            self.symbol="symbol_tmp"+str(Nvars[0])
            Nvars[0]=Nvars[0]+1
        self.tratta_symbol()
        if(debug):print "self.symbol ", self.symbol, "AAA"

        if (name!=self.name) :
            raise " problem name!=self.name "

        for arg in self.arguments:
           if arg.toend:
                  arg.process_endElement(arg.name)
 
        self.checkKeywords()

        if self.arguments !=[]:
           s=self.symbol+"="+self.constructor
           if(s[-1]!=","): s=s+"("
	   for arg in self.arguments:
             if ( debug): print arg.symbol
             if( "key" in  arg.attrs.keys() ) :
                 s=s+arg.attrs["key"] + "="
             s=s+arg.symbol+","
           s=s[:-1]
           s=s+self.add_post_arguments()
           result[0]=result[0]+ "\n"+s+")"

        self.end_post_process()

    
    def add_post_arguments(self):
        return ""

    def end_post_process(self):
        pass
    def end_pre_process(self):
        pass
        
    def process_characters(self,ch ):
        for c in ch:
          if( (c not   in " \n\t") ):
             self.symbol=self.symbol+c
       



class Layer_processor(generic_processor):
     constructor = "PPM_SimpleLayer"
     def __init__( self,*args):
	apply(   generic_processor.__init__, (self,)+ args  )
        self.necessary_keywords = ["thickness", "roughness", "material"]  

class Scan_processor(generic_processor):
    constructor = "ScanReader"
    def process_endElement(self, name):

        self.noise="0.0"
        self.norm="1.0"
        self.nstack="0"
        self.cutoff="1.0e-12"

        
        if(name=="AAscan"):
	   debug=1
        else:
           debug=0

        if debug:
          print " sono in endElement di ", name
          print "self.symbol ", self.symbol, "AAA"
          print "#"*40

        if (self.symbol=="" and self.arguments !=[]):
            self.symbol="symbol_tmp"+str(Nvars[0])
            Nvars[0]=Nvars[0]+1
        self.tratta_symbol()
        if(debug):print "self.symbol ", self.symbol, "AAA"

        if (name!=self.name) :
            raise " problem name!=self.name "

        for arg in self.arguments:
           if arg.toend:
                  arg.process_endElement(arg.name)
 
        self.checkKeywords()

        if self.arguments !=[]:
           s=self.symbol+"="+self.constructor
           if(s[-1]!=","): s=s+"("
	   for arg in self.arguments:
             if ( debug): print arg.symbol
             if( "key" in  arg.attrs.keys() ) :
               if(arg.attrs["key"]=="noise"):
		 self.noise=arg.symbol
               elif(arg.attrs["key"]=="norm"):
		 self.norm=arg.symbol
               elif(arg.attrs["key"]=="CutOffRatio"):
                    self.cutoff=arg.symbol
               else:
                 s=s+arg.attrs["key"] + "="
                 s=s+arg.symbol+","
	     else:
                 s=s+arg.symbol+","
           s=s[:-1]
           s=s+self.add_post_arguments()
           result[0]=result[0]+ "\n"+s+")"

           
        if ( self.attrs.has_key("nstack")):
             self.nstack=self.attrs["nstack"]
        self.end_post_process()




class IndexFromTable_processor(generic_processor):
    constructor = "IndexFromTable(tf0, tf12,"

class MagScatterer_processor(generic_processor):
    constructor = "MagScatterer"

class CreateVariableArray_processor(generic_processor):
    constructor = "CreateVariableArray"

class Minimise_processor(generic_processor):
    constructor = "Minimise(list_of_variables=variables_list,"


class MinimiseGeFit_processor(generic_processor):
    constructor = "MinimiseGeFit(list_of_variables=variables_list,"

class addvariables_processor(generic_processor):
    constructor = "variables_list=variables_list+"
    def process_endElement(self, name):

        if (name!=self.name) :
            raise " problem name!=self.name "

        s="variables_list=variables_list+"

        if self.arguments !=[] :
	   for arg in self.arguments:
             s=s+arg.symbol+"+"
           s=s[:-1]
           result[0]=result[0] + "\n"+s  
    



class BetaManipulator_ContributionsFromFile_processor(generic_processor):
    constructor = "BetaManipulator_ContributionsFromFile"
    def __init__( self,*args):
	apply(   generic_processor.__init__, (self,)+ args  )
        self.necessary_keywords = ["shift", "factor", "rescaleXlambda"]  


class BetaManipulator_BetaJoin_processor(generic_processor):
    constructor = "BetaManipulator_BetaJoin"


class BetaManipulator_ContributionsFromInterpolation_processor(generic_processor):
    constructor = "BetaManipulator_ContributionsFromInterpolation"

    
class KK_write_processor(generic_processor):
   constructor = "KK_write"
 
    
class Write_Stack_processor(generic_processor):
   constructor = "Write_Stack"
 
class comparison_write_processor(generic_processor):
   constructor = "writeFit2File"



class fit_processor(generic_processor):
   constructor = "PPM_ComparisonTheoryExperiment(stacks,scan2stack, scanlist,[1]*len(scanlist), normlist=scannorms_list, noise=scannoises_list,printpartial=[variables_list, variables_names],CutOffRatio=cutoffs_list,"
   def end_pre_process(self):
    result[0]=result[0]+"\n"+"variables_list=[" 
    for tok in variables_list : result[0]=result[0]+ tok+","
    result[0]=result[0]+ "]"+"\n"
    result[0]=result[0]+"\n"+"variables_names=[" 
    for tok in variables_list : result[0]=result[0] +"\""+tok+"\""+","
    result[0]=result[0]+ "]"+"\n"
              
class Beta_write_processor(generic_processor):
   constructor = "Beta_write"

class IndexFromObject_processor(generic_processor):
    constructor = "IndexFromObject"


class IndexFromObjects_processor(generic_processor):
    constructor = "IndexFromObjects"

class IndexFromFile_processor(generic_processor):
    constructor = "IndexFromFile"

class BetaContinuum_processor(generic_processor):
    constructor = "BetaManipulator_ContributionsFromContinuum"
class BetaLorentz_processor(generic_processor):
    constructor = "BetaManipulator_ContributionsFromLorentz"
class BetaSum_processor(generic_processor):
    constructor = "BetaManipulator_SumOfContributions"

class KK_processor(generic_processor):
    constructor = "KK"

class ScanList_processor(generic_processor):
    def process_endElement(self, name):
        if (name!=self.name) :
            raise " problem name!=self.name "
        s="tmp_len_scans_before=len(scanlist)\n"
        s1="scannoises_list.extend(["
        s2="scannorms_list.extend(["
        s3="cutoffs_list.extend(["

           
        noisearg=[]
        normarg=[]
        cutoffs=[]
        
        Nstack=[]
        if self.arguments !=[] :
	   for arg in self.arguments:
             noisearg=noisearg+[arg.noise]
             normarg=normarg+[arg.norm]
             cutoffs=cutoffs+[arg.cutoff]
             
             # Nstack=arg.nstack
             Nstack=Nstack+[string.atoi(arg.nstack)]
             
             if( "key" in  arg.attrs.keys() ) :
                 s=s+arg.attrs["key"] + "="
                 s=s+arg.symbol+","
             else:
		 s=s+"scanlist.append("+arg.symbol+")"
           for t in noisearg :
              s1=s1+t+","
           for t in normarg :
             s2=s2+t+","
           for t in cutoffs :
                s3=s3+t+","
           # s=s[:-1]
           result[0]=result[0]+ "\n"+s+"\n"    +s1+"])"+"\n"+s2+"])"+"\n"+s3+"])"
           # result[0]=result[0]+ "\n"+"scan2stack[len(scanlist)]="+str(Nstack)+"\n"
           result[0]=result[0]+ "\n"+"for tmp_ind_loop in range(tmp_len_scans_before,len(scanlist) ) : scan2stack[tmp_ind_loop+1]="+str(Nstack)+"[tmp_ind_loop-tmp_len_scans_before]\n"

class tf0_processor(generic_processor):
    def process_endElement(self, name):
        if (name!=self.name) :
            raise " problem name!=self.name "
        s="tf0=Dabax_f0_Table("

           
        if self.arguments !=[] :
	   for arg in self.arguments:
             if( "key" in  arg.attrs.keys() ) :
                 s=s+arg.attrs["key"] + "="
             s=s+arg.symbol+","
           s=s[:-1]
           result[0]=result[0]+ "\n"+s+")"  

class tf12_processor(generic_processor):
    def process_endElement(self, name):
        if (name!=self.name) :
            raise " problem name!=self.name "
        s="tf12=Dabax_f1f2_Table("

           
        if self.arguments !=[] :
	   for arg in self.arguments:
             if( "key" in  arg.attrs.keys() ) :
                 s=s+arg.attrs["key"] + "="
             s=s+arg.symbol+","
           s=s[:-1]
           result[0]=result[0]+ "\n"+s+")"  


class String_processor(generic_processor):
    constructor = ""
    def tratta_symbol(self):
        pass
	self.symbol= "\"" + self.symbol +"\""


class DependentVariable_processor(generic_processor):
    constructor = "DependentVariable"
    def add_post_arguments(self):
        return ",dictio=locals(),"
      

class Variable_processor(generic_processor):
	constructor = "Variable"
	def end_post_process(self):
	   variables_list.append(self.symbol)
           variables_pos[self.symbol] = self.pos_float
       
class Float_processor(generic_processor):
    constructor = ""
    def process_endElement(self, name):
        # print " sono in endElement di ", name
        # print "self.symbol ", self.symbol, "AAA"
        # print "#"*40
        # print self.arguments


        if (name!=self.name) :
            raise " problem name!=self.name "

        for arg in self.arguments:
           if arg.toend:
                  arg.process_endElement(arg.name)

        if (self.symbol=="" and self.arguments !=[]):
            self.symbol=self.arguments[0].symbol
            schanged=1
        else:
            schanged=0

        if self.arguments !=[] and schanged==0:
           s=self.symbol+"="+self.constructor+"("
	   for arg in self.arguments:
             # print arg
             if( "key" in  arg.attrs.keys() ) :
                 s=s+arg.attrs["key"] + "="
             s=s+arg.symbol+","
           s=s[:-1]
           result[0]=result[0]+ "\n"+s+")"       
    
    def process_characters(self,chs ):
        if( self.proc_char_count ):
           raise " float items should keep on one line only "
        self.proc_char_count+=1
        chl = string.split(chs)
        # print ch
        Nfloat=0
        pos_float=None
        for ch in chl:
          if(isFloat(ch)):
	      Nfloat=Nfloat+1
              if( Nfloat==1) :
                 pos_float = [ parser.getLineNumber(), parser.getColumnNumber() + chs.find(ch) , len(ch)]
        if(len(chl)>1 ):
         # print " METTO ", chl
         if(Nfloat>1):
           vo = Variable_processor()
           vo.toend=1
           vo.name="v"
           vo.pos_float = pos_float
         else:
           vo = Float_processor()
           vo.toend=1
           vo.name="f"

         self.arguments.append( vo )
  	 for token in chl:
             if( isFloat(token)==0):
                if(token[0]!="\""):
                 vo.symbol = token
	        else:
                 self.attrs["key"]=token[1:-1] 

             else:
	       toappend = Float_processor()
               toappend.name="f"
               toappend.symbol = token
               toappend.toend=1
               vo.arguments.append( toappend )
        else:
         for c in ch:
           if( (c not   in " \n\t") ):
              self.symbol=self.symbol+c
       
       
class Prova_processor(generic_processor):
    constructor = ""
    
    
    def process_characters(self,ch ):
 	print "ECCO ! ",  ch , "ECCO  2"
        print parser.getColumnNumber()
        print parser.getLineNumber()
        apply( generic_processor.process_characters, (self, ch) )


class Stack_processor(generic_processor):
     def process_endElement(self, name):
        self.nstack="0"
        if ( self.attrs.has_key("nstack")):
             self.nstack=self.attrs["nstack"]
         
        if (name!=self.name) :
            raise " problem name!=self.name "
       
        if(self.symbol!=""):
              s=self.symbol+"=SumThings( PPM_Stack()  , "
        else:
             s="stacks[%s]=SumThings(stacks[%s], "%(self.nstack,self.nstack)
        np=1
	if( "repetitions" in  self.attrs.keys() ) :
           s=s + "MultiplyAThing(" +self.attrs["repetitions"]+",SumThings("
           np=3
           
        if self.arguments !=[] :
	   for arg in self.arguments:
             if( "key" in  arg.attrs.keys() ) :
                 s=s+arg.attrs["key"] + "="
             s=s+arg.symbol+","
           s=s[:-1]
           result[0]=result[0] + "\n"+s+")"*np       
    
class PPMHandler(ContentHandler):
    classes_to_use = {"f": Float_processor , "layer": Layer_processor, "variable": Variable_processor ,
                      "stack":Stack_processor, "scan":Scan_processor,"scanlist":ScanList_processor, "s":String_processor,
		      "ift":IndexFromTable_processor, "ifo":IndexFromObject_processor, "dv":DependentVariable_processor,
		      "KK":KK_processor, "bff":BetaManipulator_ContributionsFromFile_processor,
		"bjoin":BetaManipulator_BetaJoin_processor, "iff":IndexFromFile_processor,
		"KK_write":KK_write_processor, "tf0":tf0_processor, "tf12":tf12_processor,
		"Beta_write":Beta_write_processor,"comparison_write":comparison_write_processor,
	"fit":fit_processor, "Minimise":Minimise_processor , "MinimiseGeFit":MinimiseGeFit_processor , "prova": Prova_processor,
                      "bfc":BetaContinuum_processor , "bfl":BetaLorentz_processor , "bsum":BetaSum_processor
                      , "ifos":IndexFromObjects_processor, "Write_Stack": Write_Stack_processor
                      , "MagScatterer":MagScatterer_processor,
                      "bfinterp":BetaManipulator_ContributionsFromInterpolation_processor,
                      "arrofvar":CreateVariableArray_processor, "addvars": addvariables_processor
                      
                      }
    def __init__(self):
        self.processors_list=[]

    def startElement(self, name, attrs):
        if name=="system": return
        actual=None
	if( len(self.processors_list)!=0):
	   actual=self.processors_list[-1]
        else:
           dummy=   generic_processor()
	   actual=dummy
 
        nuovo = self.classes_to_use[name]()

        nuovo.process_startElement(name,attrs)

        actual.arguments.append(nuovo)
	self.processors_list.append(nuovo)

    def endElement(self, name):
        if name=="system": return
        self.processors_list[-1].process_endElement(name)
	del self.processors_list[-1]
        
    def characters(self, ch):
        if self.processors_list==[]: return
	self.processors_list[-1].process_characters(ch)



            
from xml.sax import make_parser
from xml.sax.handler import feature_namespaces

if __name__ == '__main__':
    # Create a parser
    parser = make_parser()

    # Tell the parser we are not interested in XML namespaces
    parser.setFeature(feature_namespaces, 0)

    # Create the handler
    dh = PPMHandler()

    # Tell the parser to use our handler
    parser.setContentHandler(dh)

    # Parse the input
    print "\n"*4
    
    result[0]=result[0]+ "\n"+"stacks=[PPM_Stack()]"
    result[0]=result[0]+ "\n"+"scan2stack={}" 
    result[0]=result[0]+ "\n"+ "scanlist=[]"
    result[0]=result[0]+ "\n"+ "cutoffs_list=[]"
    result[0]=result[0]+ "\n"+ "scannoises_list=[]"
    result[0]=result[0]+ "\n"+ "scannorms_list=[]"
    parser.parse(sys.argv[1])
    result[0]=result[0]+"\n"+"variables_list=[" 
    for tok in variables_list : result[0]=result[0]+ tok+","
    result[0]=result[0]+ "]"+"\n"

    if(string.find( sys.argv[0],  "ppmxmlTens.py" )>=0 ,   ):
	headers =(
	"from Numeric import *\n"
	"from  PPMlayerclass import *\n"
	"from Dabax import *\n"
	"from Minimiser import *\n"
	"import string\n"
        "import random\n"
	)

    result[0]=headers+result[0]
    print "#"*80
    print result[0]
    print "\n"*10


    if( len( sys.argv)==2):
      open("/tmp/debug.py","w").write(result[0])
      exec(result[0])
    else:
      class sub:
         exec( open(sys.argv[2]).read() )
      sl = string.split(open( sys.argv[1],"r").read(),"\n" )
      variables_list.reverse()
      for var in variables_list:
         pos = variables_pos[var]
         nl = pos[0]-1
         nc = pos[1]
         sz = pos[2]
         sl[nl] = sl[nl][:nc]+str(getattr(sub, var)) + sl[nl][nc+sz:]

      f=open("NEW_"+sys.argv[1],"w")
      for l in sl:
         f.write( l+"\n")

         






