#!/usr/bin/env python
import os,os.path,string
import sys
import xml.dom.minidom
from optparse import OptionParser
class deltaGenerator:
    def __init__(self):
        """
        Generate schema evolution xml file for a given base mapping xml. The result xml file can be customised by the user. The mapping xml file name rule: basemappingxml_e_newclassversion.xml.        
        usage: %prog [options]
        -b, --basemapping : base mapping xml file (required). 
        -c, --classversion : new class version. This parameter is only used in the result xml file name (default old classversion+1)
        -u, --usemode : simply use the existing old mapping. This switch should be used in case: the new class version only changes the order of the data members wrt the old class version. (default off) 
        -v, --verbose: verbose mode
        -h, --help: print usage
        """
        self.__verbose=False
        self.__classversion=""
        self.__classname=""
        self.__usemapping=False
        self.__basemappingversion=""
        self.__basemappingxml=""
        self.__XMLheader="\n".join([
            "<?xml version=\'1.0\' encoding=\"UTF-8\"?>",
            "<!DOCTYPE PoolDatabase SYSTEM \"InMemory\">",
            "<PoolDatabase>",
            "<PoolContainer name=\"##CONTAINERNAME##\" tech=\"homogeneous\" >",
            "<Class name=\"##CLASSNAME##\" base_mapping=\"##MAPPINGVERSION##\">",
            "</Class>",
            "</PoolContainer>",
            "</PoolDatabase>"])
        
    def parsebasemappingxml(self):
        """
        Parse base mapping xml 
        """
        f=open(self.__basemappingxml,'r')
        containertag="PoolContainer"
        mappingtag="mapping_version"
        for line in f:
            pos=line.find(containertag)
            if pos!=-1: #found container line
                self.__XMLheader=self.__XMLheader.replace("<PoolContainer name=\"##CONTAINERNAME##\" tech=\"homogeneous\" >",line)
                continue
            pos=line.find(mappingtag)
            if pos!=-1: #found mapping line
                fields=line.split(" ")
                for field in fields:
                    if field.find("name")!=-1:
                        self.__classname=field.split("\"")[1]
                        self.__XMLheader=self.__XMLheader.replace("##CLASSNAME##",self.__classname)
                    if field.find("mapping_version")!=-1:
                        self.__basemappingversion=field.split("\"")[1]
                        if self.__usemapping==True:
                            self.__XMLheader=self.__XMLheader.replace("base_mapping=\"##MAPPINGVERSION##\"","use_mapping=\""+self.__basemappingversion+"\"")
                        else:
                            self.__XMLheader=self.__XMLheader.replace("##MAPPINGVERSION##",self.__basemappingversion)
        f.close()
        
    def parsecmdln(self):
        """
        Parse commandline
        """
        usage = "usage: \%prog [options] \n"
        parser = OptionParser()
        parser.add_option("-b","--basemapping",action="store",dest="base",
                          help="base mapping xml file( required )")
        parser.add_option("-c","--classversion",action="store",dest="classversion",
                          help="new classversion (default old classversion+1)")
        parser.add_option("-u","--usemapping",action="store_true",dest="usemapping",
                          help="use the existing old mapping instead of based on it to evolve. This switch should be used in case: the new class version only changes the order of the data members wrt the old class version. (default off)")
        parser.add_option("-v","--verbose",action="store_true",dest="verbose",
                          help="verbose mode")
        oldclassversion=""
        (options, args) = parser.parse_args()
        self.__basemappingxml=os.path.abspath(options.base)
        self.__usemapping=options.usemapping
        if options.classversion:
            self.__classversion=options.classversion
        else:
            mappingfilename=os.path.splitext(os.path.basename(self.__basemappingxml))[0]
            oldclassversion=mappingfilename.rsplit("_",1)[1]
            self.__classversion=int(oldclassversion)+1
        self.parsebasemappingxml()
        self.__verbose=options.verbose
        if self.__verbose is True:
            if self.__usemapping:
                print "usemapping mode "
            print "classname : %s " % self.__classname
            print "base mapping xml : %s " % self.__basemappingxml
            print "base mapping version : %s " % self.__basemappingversion
            print "old class version : %s " %  oldclassversion
            print "new class version : %s " %  self.__classversion
    def generate(self):
        '''create evolution xml 
        '''
        outfilename=os.path.splitext(os.path.basename(self.__basemappingxml))[0]
        outfilename="_".join([outfilename,"e",str(self.__classversion)])
        outfilename=outfilename+".xml"
        f = open(outfilename,'w')
        f.write(self.__XMLheader)
        f.close()
if __name__ == "__main__":
    me=deltaGenerator()    
    me.parsecmdln()
    me.generate()


