import logging
from orangescape.model.engine.exception.ErrorMessage import Server1003
from orangescape.model.server.Metadata import *
from orangescape.model.engine.exception.Error import MetadataError
from orangescape.model.server.util.JsonUtil import jsonWrite,DeepSerialize,export,specifiedSerialize
from orangescape.model.server.util.ServerUtil import _get_class
from google.appengine.ext import db
from orangescape.model.server.util.listutil import split_seq

class DeSerializer:
    dictionary = dict()
    json = dict()
    localCache = dict()
    max_commit_objects = 500
    def getKeyList(self, key):
        if self.dictionary.get(key):
            return self.dictionary.get(key).keys()
        else:
            return list()

    def getKey(self, key):
        if self.dictionary.get(key):
            keyList = self.dictionary.get(key).keys()
            if(len(keyList)==1):
                return self.dictionary.get(key).keys().pop()
            elif(len(keyList)>1):
                raise MetadataError , Server1003 % (key, self.dictionary.get('SheetType'), self.dictionary.get('SheetName'))
            else:
                return None
        else:
            return None

    def getValue(self, key):
        if self.dictionary.__contains__(key):
            return self.dictionary.get(key)

    def getStaticModel(self, metadataName, key):
        result = _get_class('orangescape.model.server.Metadata.'+metadataName+'Model').get_by_key_name(key)
        return result

    def saveStaticModel(self, json):
        self.json = json
        methods = {
            'Version': self.saveVersion,
            'Application': self.saveApplication,
            'SheetMetadata':self.saveSheetMetadata,
            'RowMetadata':self.saveRowMetadata,
            'ColumnMetadata':self.saveColumnMetadata,
            'CellMetadata':self.saveCellMetadata,
            'Branch':self.saveBranch,
            'ActivityDefinition':self.saveActivityDefinition,
            'SerialProcess':self.saveSerialProcess,
            'Level':self.saveLevel,
            'Department':self.saveDepartment,
            'Designation':self.saveDesignation,
            'SearchDefinition':self.saveSearchDefinition,
            'Header':self.saveHeader,
            'Hierarchy':self.saveHierarchy,
            'Section':self.saveSection,
            'GridView':self.saveGridView,
            'GridRow':self.saveGridRow,
            'GridColumn':self.saveGridColumn,
            'GridCell':self.saveGridCell,
            'Style':self.saveStyle,
            'MenuGroup':self.saveMenuGroup,
            'LayoutView':self.saveLayoutView,
            'LayoutRow':self.saveLayoutRow,
            'LayoutColumn':self.saveLayoutColumn,
            'LayoutCell':self.saveLayoutCell,
            'RowSpan':self.saveRowSpan,
            'GridRowSpan':self.saveGridRowSpan,
            'TableStyle':self.saveTableStyle,
            'Criteria':self.saveCriteria,
            'Condition':self.saveCondition,
            'LevelRowSpan':self.saveLevelRowSpan,
            'Button':self.saveButton,
            'ActivityPermission':self.saveActivityPermission,
            'Range':self.saveRange,
            'RangeValue':self.saveRangeValue,
            'OutputportMetadata':self.saveOutputportMetadata,
            'InputportMetadata':self.saveInputportMetadata,
            'Property':self.saveProperty
             }
        for key in json:
            if not key.__eq__('root'):
                self.dictionary = json.get(key)
                method = methods.get(self.getValue('SheetMetadataName'))
                if method is not None:
                    method(key)
        self.save(self.localCache.values())

    def saveStaticModelPart1(self, json):
        self.json = json
        methods = {
            'Version': self.saveVersion,
            'Application': self.saveApplication,
            'SheetMetadata':self.saveSheetMetadata,
            'ColumnMetadata':self.saveColumnMetadata,
            'TableStyle':self.saveTableStyle,
            'Criteria':self.saveCriteria,
            'Condition':self.saveCondition,
             }
        for key in json:
            if not key.__eq__('root'):
                self.dictionary = json.get(key)
                method = methods.get(self.getValue('SheetMetadataName'))
                if method is not None:
                    method(key)
        self.save(self.localCache.values())

    def saveStaticModelPart2(self, json):
        methods = {
            'RowMetadata':self.saveRowMetadata,
            'Branch':self.saveBranch,
            'ActivityDefinition':self.saveActivityDefinition,
            'SerialProcess':self.saveSerialProcess,
            'Level':self.saveLevel,
            'Department':self.saveDepartment,
            'Designation':self.saveDesignation,
            'SearchDefinition':self.saveSearchDefinition,
            'Header':self.saveHeader,
            'Hierarchy':self.saveHierarchy,
            'Section':self.saveSection,
            'GridView':self.saveGridView,
            'GridRow':self.saveGridRow,
            'GridColumn':self.saveGridColumn,
            'GridCell':self.saveGridCell,
            'Style':self.saveStyle,
            'MenuGroup':self.saveMenuGroup,
            'LayoutView':self.saveLayoutView,
            'LayoutRow':self.saveLayoutRow,
            'LayoutColumn':self.saveLayoutColumn,
            'LayoutCell':self.saveLayoutCell,
            'RowSpan':self.saveRowSpan,
            'GridRowSpan':self.saveGridRowSpan,
            'TableStyle':self.saveTableStyle,
            'Criteria':self.saveCriteria,
            'Condition':self.saveCondition,
            'LevelRowSpan':self.saveLevelRowSpan,
            'Button':self.saveButton,
            'ActivityPermission':self.saveActivityPermission,
            'Range':self.saveRange,
            'RangeValue':self.saveRangeValue,
            'OutputportMetadata':self.saveOutputportMetadata,
            'InputportMetadata':self.saveInputportMetadata,
            'Property':self.saveProperty
             }
        for key in json:
            if not key.__eq__('root'):
                self.dictionary = json.get(key)
                method = methods.get(self.getValue('SheetMetadataName'))
                if method is not None:
                    method(key)
        self.save(self.localCache.values())

    def saveStaticModelPart3(self, json, startRange,endRange):
        self.json = json
        cellMetadataList = list()
        for key in self.json:
            if not key.__eq__('root'):
                if self.json.get(key).get('SheetMetadataName').__eq__('CellMetadata'):
                    cellMetadataList.append(key)
        cellMetadataList.sort(key = str)
        for key in cellMetadataList[int(startRange):int(endRange)]:
            self.dictionary = self.json.get(key)
            self.saveCellMetadata(key)
        self.save(self.localCache.values())

    def saveVersion(self, sheetId):
        version = self.getStaticModel('Version', sheetId)
        if(version is None):
            version = VersionModel(key_name=sheetId)
        version.sheetName = self.getValue('SheetName')
        version.versionNumber =  float(self.getValue('VersionNumber'))
        version.applicationList =  self.getKeyList('Version.Application')
        self.put(version)

    def saveApplication(self, sheetId):
        application = self.getStaticModel('Application', sheetId)
        if(application is None):
            application = ApplicationModel(key_name=sheetId)
        application.sheetName = self.getValue('SheetName')
        application.sheetMetadataList = self.getKeyList('Application.SheetMetadata')
        application.levelList = self.getKeyList('Application.Level')
        application.departmentList = self.getKeyList('Application.Department')
        application.version = self.getKey('Version')
        application.menuGroupList=self.getKeyList("Application.MenuGroup")
        application.styleList = self.getKeyList('Application.Style')
        application.tableStyleList=self.getKeyList('Application.TableStyle')
        self.put(application)

    def saveSheetMetadata(self, sheetId):
        sheetMetadata = self.getStaticModel('SheetMetadata', sheetId)
        if(sheetMetadata is None):
            sheetMetadata = SheetMetadataModel(key_name=sheetId)
        sheetMetadata.sheetName = self.getValue('SheetName')
        sheetMetadata.systemModel=float(self.getValue('SystemModel') or 0.0)
        sheetMetadata.application = self.getKey('Application')
        sheetMetadata.rowMetadataList = self.getKeyList('SheetMetadata.RowMetadata')
        sheetMetadata.columnMetadataList = self.getKeyList('SheetMetadata.ColumnMetadata')
        sheetMetadata.cellMetadataList = self.getKeyList('SheetMetadata.CellMetadata')
        sheetMetadata.oneToManyList = self.getKeyList('ReferredSheetMetadata.CellMetadata')
        sheetMetadata.manyToOneList = self.constructManyToOneList(sheetMetadata.cellMetadataList)
        sheetMetadata.activityDefinitionList = self.getKeyList('SheetMetadata.ActivityDefinition')
        sheetMetadata.sectionList = self.getKeyList('SheetMetadata.Section')
        sheetMetadata.gridViewList = self.getKeyList('SheetMetadata.GridView')
        sheetMetadata.hierarchyList=self.getKeyList('SheetMetadata.Hierarchy')
        self.put(sheetMetadata)

    def constructManyToOneList(self,cellMetadataList):
        return [key for key in cellMetadataList if self.json.get(key).get('ReferredSheetMetadata')]

    def saveRowMetadata(self, sheetId):
        rowMetadata = self.getStaticModel('RowMetadata', sheetId)
        if(rowMetadata is None):
            rowMetadata = RowMetadataModel(key_name=sheetId)
        rowMetadata.sheetName = self.getValue('SheetName')
        rowMetadata.rowNumber = float(self.getValue('RowNumber') or 0)
        rowMetadata.rowHeight = float(self.getValue('RowHeight') or 0)
        rowMetadata.sheetMetadata = self.getKey('SheetMetadata')
        rowMetadata.cellMetadataList = self.getKeyList('RowMetadata.CellMetadata')
        rowMetadata.style = self.getKey('Style')
        rowMetadata.previousRef = self.getKey('PreviousRef')
        self.put(rowMetadata)

    def saveColumnMetadata(self, sheetId):
        columnMetadata = self.getStaticModel('ColumnMetadata', sheetId)
        if(columnMetadata is None):
            columnMetadata = ColumnMetadataModel(key_name=sheetId)
        columnMetadata.sheetName = self.getValue('SheetName')
        columnMetadata.columnName = self.getValue('ColumnName')
        columnMetadata.columnNumber = float(self.getValue('ColumnNumber'))
        columnMetadata.columnWidth = float(self.getValue('ColumnWidth') or 100)
        columnMetadata.sheetMetadata = self.getKey('SheetMetadata')
        columnMetadata.cellMetadataList = self.getKeyList('ColumnMetadata.CellMetadata')
        columnMetadata.previousRef = self.getKey('PreviousRef')
        self.put(columnMetadata)

    def saveCellMetadata(self, sheetId):
        cellMetadata = self.getStaticModel('CellMetadata', sheetId)
        if(cellMetadata is None):
            cellMetadata = CellMetadataModel(key_name=sheetId)
        cellMetadata.sheetName = self.getValue('SheetName')
        cellMetadata.cellType = self.getValue('CellType')
        cellMetadata.cellName = self.getValue('CellName')
        cellMetadata.cellDisplayName = self.getValue('CellDisplayName')
        cellMetadata.widgetType = self.getValue('WidgetType')
        cellMetadata.rowSpanned = float(self.getValue('RowSpanned') or 0)
        cellMetadata.columnSpanned = float(self.getValue('ColumnSpanned') or 0)
#        cellMetadata.defaultValue = str(self.getValue('DefaultValue'))
#        cellMetadata.cellValue = str(self.getValue('CellValue'))
        if self.getValue('DefaultValue') is not None:
            cellMetadata.defaultValue = str(self.getValue('DefaultValue'))
        else:
            cellMetadata.defaultValue = None
        if self.getValue('DefaultValue') is not None:
            cellMetadata.cellValue = str(self.getValue('CellValue'))
        else:
            cellMetadata.cellValue = None
        cellMetadata.cascade = float(self.getValue('Cascade') or 0.0)
        cellMetadata.rowMetadata = self.getKey('RowMetadata')
        cellMetadata.columnMetadata = self.getKey('ColumnMetadata')
        cellMetadata.sheetMetadata = self.getKey('SheetMetadata')
        cellMetadata.referredSheetMetadata = self.getKey('ReferredSheetMetadata')
        cellMetadata.style = self.getKey('Style')
        cellMetadata.rowSpan = self.getKey('RowSpan')
        cellMetadata.rowSpanList = self.getKeyList('CellMetadata.RowSpan')
        cellMetadata.columnNumber = float(self.getValue('ColumnNumber') or 0)
        cellMetadata.rowNumber = float(self.getValue('RowNumber') or 0)
        cellMetadata.headerList = self.getKeyList('CellMetadata.Header')
        cellMetadata.hidden = float(self.getValue('Hidden') or 0.0)
        cellMetadata.header = float(self.getValue('IsHeader') or 0.0)
        cellMetadata.format=self.getValue('Format')
        cellMetadata.category=self.getValue('Category')
        cellMetadata.searchDefinitionList=self.getKeyList('CellMetadata.SearchDefinition')
        cellMetadata.nodeList = self.constructDescendantNodeList(self.getKeyList('CellMetadata.Node'))
        if len(self.getKeyList('CellMetadata.Formula')) == 1:
            cellMetadata.formulaJson = self.constructFormulaJson(self.getKeyList('CellMetadata.Formula').pop())
        cellMetadata.isString = float(self.getValue('IsStr') or 0.0)
        self.put(cellMetadata)

    def constructDescendantNodeList(self,nodeKeyList):
        descendantNodeList = list()
        for nodeKey in nodeKeyList:
            listValue = list()
            nodeDict = self.json.get(nodeKey)
            self.getDescendantCellMetadata(nodeDict,listValue)
            if len(listValue)>0:
                self.getNodeProperties(nodeDict,listValue)
                descendantNodeList.append(".".join(listValue))
        return descendantNodeList

    def getDescendantCellMetadata(self,nodeDict,listValue):
        if nodeDict.get('Formula') and len(nodeDict.get('Formula')) == 1:
            formulaKey = nodeDict.get('Formula').keys().pop()
            formulaCell = self.json.get(formulaKey).get('CellMetadata')
            if len(formulaCell)>0:
                listValue.append(formulaCell.keys().pop())
        else:
            parentNodeKey = nodeDict.get('Node').keys().pop()
            self.getDescendantCellMetadata(self.json.get(parentNodeKey),listValue)

    def getNodeProperties(self,nodeDict,listValue):
        if not nodeDict.get('Formula'):
            parentNodeKey = nodeDict.get('Node').keys().pop()
            parentNodeDict = self.json.get(parentNodeKey)
            listValue.append(parentNodeDict.get('NodeType'))
            if parentNodeDict.get('NodeType').__eq__('Fetch3DFunction') or parentNodeDict.get('NodeType').__eq__('Aggrigate3DFunction'):
                nodeList = parentNodeDict.get('Node.Node')
                nodeObjList = [self.json.get(key) for key in nodeList]
                nodeObjList.sort(self.sortNodeCompare)
                listValue.append(nodeObjList[0].get('CellMetadata').keys().pop())
                if len(nodeObjList) == 4:
                    listValue.append(nodeObjList[3].get('NodeValue'))
                else:
                    listValue.append('')
            else:
                listValue.append('.')

    def sortNodeCompare(self,a,b):
        return cmp(a.get('ArgNo'),b.get('ArgNo'))

    def constructFormulaJson(self,formulaKey):
        formulaDict = self.json.get(formulaKey)
        nodeKey = formulaDict.get('Formula.Node').keys().pop()
        formulaDict['Formula.Node'] = {nodeKey:self.constructNodeJson(nodeKey)}
        return str({formulaKey:formulaDict})
#        return jsonWrite({formulaKey:formulaDict})

    def constructNodeJson(self,nodeKey):
        nodeDict = self.json.get(nodeKey)
        nodeList = nodeDict.get('Node.Node')
        if nodeList and len(nodeList) >= 1:
            childNodeDict = {}
            for childNode in nodeList:
                childNodeDict[childNode]=self.constructNodeJson(childNode)
            nodeDict['Node.Node']=childNodeDict
        return nodeDict

    def saveActivityDefinition(self, sheetId):
        activityDefinition = self.getStaticModel('ActivityDefinition',sheetId)
        if(activityDefinition is None):
            activityDefinition = ActivityDefinitionModel(key_name=sheetId)

        activityDefinition.sheetName = self.getValue('SheetName')
        activityDefinition.sequenceNo = float(self.getValue('SequenceNo') or 0.0)
        activityDefinition.taskStatus = self.getValue('TaskStatus')
        activityDefinition.searchDefintionList = self.getKeyList('ActivityDefinition.SearchDefinition')
        activityDefinition.buttonList = self.getKeyList('ActivityDefinition.Button')
        activityDefinition.branch = self.getKey('Branch')
        activityDefinition.user = self.getValue('User')
        activityDefinition.static=float(self.getValue('Static') or 0.0)
        activityDefinition.nodeType=self.getValue('NodeType')
#        activityDefinition.formulaList = self.getKeyList('ActivityDefinition.Formula')
        if len(self.getKeyList('ActivityDefinition.Formula')) == 1:
            activityDefinition.formulaJson = self.constructFormulaJson(self.getKeyList('ActivityDefinition.Formula').pop())
        activityDefinition.branchList = self.getKeyList('ActivityDefinition.Branch')
        activityDefinition.gridView = self.getKey('GridView')
        activityDefinition.previousRef = self.getKey('PreviousRef')
        activityDefinition.cellmetadata=self.getKey('CellMetadata')
        activityDefinition.section=self.getKey('Section')
        activityDefinition.assignedFor=self.getValue('AssignedFor')
        activityDefinition.goTo=self.getValue('GoTo')
        activityDefinition.root=self.getValue('Root')

        activityDefinition.continueOnError = float(self.getValue('ContinueOnError') or 0.0)

        activityDefinition.inputPortList = self.getKeyList('ActivityDefinition.InputportMetadata')
        activityDefinition.outputPortList = self.getKeyList('ActivityDefinition.OutputportMetadata')

        if len(self.getKeyList('GroupFormula.Formula')) == 1:
            activityDefinition.groupFormulaJson = self.constructFormulaJson(self.getKeyList('GroupFormula.Formula').pop())

        if len(self.getKeyList('AllowActivity.Formula')) == 1:
            activityDefinition.allowedFormulaJson = self.constructFormulaJson(self.getKeyList('AllowActivity.Formula').pop())

        activityDefinition.processType = self.getValue('ProcessType')
        activityDefinition.inputPortList = self.getKeyList('ActivityDefinition.InputportMetadata')
        activityDefinition.outputPortList = self.getKeyList('ActivityDefinition.OutputportMetadata')

        self.put(activityDefinition)

    def saveBranch(self, sheetId):
        branch = self.getStaticModel('Branch', sheetId)
        if branch is None:
            branch = BranchModel(key_name=sheetId)
        branch.sheetName = self.getValue('SheetName')
        branch.processType = self.getValue('ProcessType')
        branch.nodeType = self.getValue('NodeType')
        branch.sequenceNo = float(self.getValue('SequenceNo') or 0.0)
#        branch.formulaList = self.getKeyList('Branch.Formula')
        if len(self.getKeyList('Branch.Formula')) == 1:
            branch.formulaJson = self.constructFormulaJson(self.getKeyList('Branch.Formula').pop())
        branch.activityDefinition = self.getKey('ActivityDefinition')
        branch.activityDefinitionList = self.getKeyList('Branch.ActivityDefinition')
        branch.root=self.getValue('Root')

        branch.sheetMetadata = self.getKey('SheetMetadata')
        self.put(branch)

    def saveInputportMetadata(self, sheetId):
        inputportMetadata = self.getStaticModel('InputportMetadata', sheetId)
        if not inputportMetadata:
            inputportMetadata = InputportMetadataModel(key_name=sheetId)

        inputportMetadata.sheetName = self.getValue('SheetName')
        inputportMetadata.sequenceNo = float(self.getValue('SequenceNo') or 0.0)
        inputportMetadata.value = self.getValue('Value')
        inputportMetadata.cellMetadata = self.getKey('CellMetadata')
        inputportMetadata.activityDefinition = self.getKey('ActivityDefinition')
        inputportMetadata.paramName = self.getValue('Param_Name')

        if len(self.getKeyList('InputportMetadata.Formula'))==1:
            inputportMetadata.formulaJson = self.constructFormulaJson(self.getKeyList('InputportMetadata.Formula').pop())
        self.put(inputportMetadata)

    def saveOutputportMetadata(self, sheetId):

        outputportMetadata = self.getStaticModel('OutputportMetadata',sheetId)
        if not outputportMetadata:
            outputportMetadata = OutputportMetadataModel(key_name=sheetId)

        outputportMetadata.sheetName = self.getValue('SheetName')
        outputportMetadata.sequenceNo = self.getValue('SequenceNo')
        outputportMetadata.cellMetadata = self.getKey('CellMetadata')
        outputportMetadata.activityDefinition = self.getKey('ActivityDefinition')
        outputportMetadata.paramName = self.getValue('Param_Name')

        self.put(outputportMetadata)

    def saveSerialProcess(self, sheetId):
        serialProcess = self.getStaticModel('SerialProcess', sheetId)
        if(serialProcess is None):
            serialProcess = SerialProcessModel(key_name=sheetId)
        serialProcess.sheetName = self.getValue('SheetName')
        serialProcess.conditionType = self.getValue('ConditionType')
        serialProcess.conditionExpression = self.getValue('ConditionExpression')
        serialProcess.sheetMetadata = self.getKey('SheetMetadata')
        serialProcess.activityDefinition = self.getKey('ActivityDefinition')
        serialProcess.nextActivityDefinition = self.getKey('NextActivityDefinition')
        self.put(serialProcess)

    def saveSearchDefinition(self, sheetId):
        searchDefinition = self.getStaticModel('SearchDefinition', sheetId)
        if(searchDefinition is None):
            searchDefinition = SearchDefinitionModel(key_name=sheetId)
        searchDefinition.sheetName = self.getValue('SheetName')
        searchDefinition.activityDefinition = self.getKey('ActivityDefinition')
        searchDefinition.cellMetadata=self.getKey('CellMetadata')
        searchDefinition.displayCell=self.getKey('DisplayCell')
        searchDefinition.itemsPerPage=self.getValue('ItemsPerPage')
        searchDefinition.default=float(self.getValue('Default') or 0.0)
        searchDefinition.tableStyle=self.getKey('TableStyle')
        searchDefinition.criteriaList=self.getKeyList('SearchDefinition.Criteria')
        self.put(searchDefinition)

    def saveHeader(self,sheetId):
        header = self.getStaticModel('Header', sheetId)
        if (header is None):
            header = HeaderModel(key_name=sheetId)
        header.sheetName=self.getValue('SheetName')
        header.cellMetadata=self.getKey('CellMetadata')
        header.index=float(self.getValue('Index') or 0.0)
        header.format=self.getKey('Format')
        header.orderBy = self.getValue('OrderBy')
        header.hierarchy = self.getKey('Hierarchy')
        header.width=self.getValue('Width')
        self.put(header)

    def saveHierarchy(self,sheetId):
        hierarchyInstance=self.getStaticModel('Hierarchy', sheetId)
        if (hierarchyInstance is None):
            hierarchyInstance=HierarchyModel(key_name=sheetId)
        hierarchyInstance.sheetName=self.getValue('SheetName')
        hierarchyInstance.headerList=self.getKeyList('Hierarchy.Header')
        hierarchyInstance.hierarchyList=self.getKeyList('Hierarchy.Hierarchy')
        hierarchyInstance.referenceCell=self.getKey('ReferenceCell')
        self.put(hierarchyInstance)

    def saveSection(self, sheetId):
        section = self.getStaticModel('Section', sheetId)
        if(section is None):
            section = SectionModel(key_name=sheetId)
        section.sheetName=self.getValue('SheetName')
        section.fromCell=self.getKey('From')
        section.toCell=self.getKey('To')
        section.sheetMetadata=self.getKey('SheetMetadata')
        self.put(section)

    def saveGridView(self, sheetId):
        gridView = self.getStaticModel('GridView', sheetId)
        if(gridView is None):
            gridView = GridViewModel(key_name=sheetId)
        gridView.sheetName=self.getValue('SheetName')
        gridView.sheetMetadata=self.getKey('SheetMetadata')
        gridView.gridCell=self.getKey('GridCell')
        gridView.gridRowList=self.getKeyList('GridView.GridRow')
        gridView.gridColumnList=self.getKeyList('GridView.GridColumn')
        gridView.default = float(self.getValue('Default') or 0.0)
        gridView.property = self.getValue('Property')
        gridView.gridViewHeight = float(self.getValue('GridViewHeight') or 0)
        gridView.gridViewWidth = float(self.getValue('GridViewWidth') or 0)
        self.put(gridView)

    def saveGridRow(self, sheetId):
        gridRow = self.getStaticModel('GridRow', sheetId)
        if(gridRow is None):
            gridRow = GridRowModel(key_name=sheetId)
        gridRow.sheetName=self.getValue('SheetName')
        gridRow.rowNumber=float(self.getValue('RowNumber'))
        gridRow.rowHeight = float(self.getValue('RowHeight')or 0)
        gridRow.cellMetadata=self.getKey('CellMetadata')
        gridRow.gridView=self.getKey('GridView')
        gridRow.gridCellList=self.getKeyList('GridRow.GridCell')
        gridRow.style = self.getKey('Style')
        gridRow.finalHeight = float(self.getValue('FinalHeight') or 0.0)
        self.put(gridRow)

    def saveGridColumn(self, sheetId):
        gridColumn = self.getStaticModel('GridColumn', sheetId)
        if(gridColumn is None):
            gridColumn = GridColumnModel(key_name=sheetId)
        gridColumn.sheetName=self.getValue('SheetName')
        gridColumn.columnNumber=float(self.getValue('ColumnNumber'))
        gridColumn.columnWidth = float(self.getValue('ColumnWidth')or 0)
        gridColumn.cellMetadata=self.getKey('CellMetadata')
        gridColumn.gridView=self.getKey('GridView')
        gridColumn.gridCellList=self.getKeyList('GridColumn.GridCell')
        gridColumn.finalWidth = float(self.getValue('FinalWidth') or 0.0)
        self.put(gridColumn)

    def saveGridCell(self, sheetId):
        gridCell = self.getStaticModel('GridCell', sheetId)
        if(gridCell is None):
            gridCell = GridCellModel(key_name=sheetId)
        gridCell.sheetName=self.getValue('SheetName')
        gridCell.rowSpanned = float(self.getValue('RowSpanned') or 0)
        gridCell.columnSpanned = float(self.getValue('ColumnSpanned') or 0)
        gridCell.cellValue = self.getValue('CellValue')
        gridCell.gridRow=self.getKey('GridRow')
        gridCell.gridColumn=self.getKey('GridColumn')
        gridCell.section=self.getKey('Section')
        gridCell.cellMetadata=self.getKey('CellMetadata')
        gridCell.gridViewList=self.getKeyList('GridCell.GridView')
        gridCell.style = self.getKey('Style')
        gridCell.gridRowSpan = self.getKey('GridRowSpan')
        gridCell.gridRowSpanList = self.getKeyList('GridCell.GridRowSpan')
        gridCell.columnNumber = float(self.getValue('ColumnNumber') or 0)
        gridCell.rowNumber = float(self.getValue('RowNumber') or 0)
        gridCell.hidden = float(self.getValue('Hidden') or 0.0)
        gridCell.widgetType = self.getValue('WidgetType')
        gridCell.activityPermissionList = self.getKeyList('GridCell.ActivityPermission')
        gridCell.gridViewHeight = float(self.getValue('GridViewHeight') or 0)
        gridCell.gridViewWidth = float(self.getValue('GridViewWidth') or 0)
        gridCell.criteriaList = self.getKeyList('GridCell.Criteria')
        gridCell.propertyList = self.getKeyList('GridCell.Property')
        gridCell.hintMessage = self.getValue('HintMessage')
        gridCell.errorMessage = self.getValue('ErrorMessage')
        gridCell.read = float(self.getValue('Read') or 0)
        gridCell.write = float(self.getValue('Write') or 0)
        gridCell.visible = float(self.getValue('Visible') or 0)
        self.put(gridCell)

    def saveStyle(self, sheetId):
        style = self.getStaticModel('Style', sheetId)
        if(style is None):
            style = StyleModel(key_name=sheetId)
        style.sheetName=self.getValue('SheetName')
        style.application=self.getKey('Application')
        style.font_family=self.getValue('Font_family')
        style.font_weight=self.getValue('Font_weight')
#        logging.info('Font_size %s'%(self.getValue('Font_size')))
        style.font_size=str(self.getValue('Font_size'))
        style.font_style=self.getValue('Font_style')
        style.color=self.getValue('Color')
        style.text_align=self.getValue('Text_align')
        style.text_decoration=self.getValue('Text_decoration')
        style.border_top=self.getValue('Border_top')
        style.border_bottom=self.getValue('Border_bottom')
        style.border_left=self.getValue('Border_left')
        style.border_right=self.getValue('Border_right')
        style.border_color=self.getValue('Border_color')
        style.border_style=self.getValue('Border_style')
        style.text_indent=self.getValue('Text_indent')
        style.text_transform=self.getValue('Text_transform')
        style.background_color=self.getValue('Background_color')
        style.displayText=self.getValue('DisplayText')
        style.category=self.getValue('Category')
        style.border=self.getValue('Border')
        style.width=self.getValue('Width')
        style.height=self.getValue('Height')
        style.nowrap=self.getValue('Nowrap')
        style.border_bottom_style=self.getValue('Border_bottom_style')


        self.put(style)

    def saveMenuGroup(self, sheetId):
        menuGroup = self.getStaticModel('MenuGroup', sheetId)
        if(menuGroup is None):
            menuGroup = MenuGroupModel(key_name=sheetId)
        menuGroup.sheetName=self.getValue('SheetName')
        menuGroup.parentMenuGroup=self.getKey('MenuGroup')
        menuGroup.menuGroupList=self.getKeyList('MenuGroup.MenuGroup')
        menuGroup.designation=self.getKey('Designation')
        menuGroup.layoutViewList=self.getKeyList('MenuGroup.LayoutView')
        menuGroup.application=self.getKey('Application')
        self.put(menuGroup)

    def saveLayoutView(self, sheetId):
        layoutView = self.getStaticModel('LayoutView', sheetId)
        if(layoutView is None):
            layoutView = LayoutViewModel(key_name=sheetId)
        layoutView.sheetName=self.getValue('SheetName')
        layoutView.application = self.getKey('Application')
        layoutView.layoutRowList=self.getKeyList('LayoutView.LayoutRow')
        layoutView.layoutColumnList=self.getKeyList('LayoutView.LayoutColumn')
        layoutView.menuGroup=self.getKey('MenuGroup')
        layoutView.width=self.getValue('Width')
        self.put(layoutView)

    def saveLayoutRow(self, sheetId):
        layoutRow = self.getStaticModel('LayoutRow', sheetId)
        if(layoutRow is None):
            layoutRow = LayoutRowModel(key_name=sheetId)
        layoutRow.sheetName=self.getValue('SheetName')
        layoutRow.layoutView=self.getKey('LayoutView')
        layoutRow.layoutCellList=self.getKeyList('LayoutRow.LayoutCell')
        layoutRow.rowHeight=float(self.getValue('RowHeight'))
        layoutRow.rowNumber=float(self.getValue('RowNumber'))
        self.put(layoutRow)

    def saveLayoutColumn(self, sheetId):
        layoutColumn = self.getStaticModel('LayoutColumn', sheetId)
        if(layoutColumn is None):
            layoutColumn = LayoutColumnModel(key_name=sheetId)
        layoutColumn.sheetName=self.getValue('SheetName')
        layoutColumn.layoutView=self.getKey('LayoutView')
        layoutColumn.layoutCellList=self.getKeyList('LayoutColumn.LayoutCell')
        layoutColumn.columnWidth=float(self.getValue('ColumnWidth'))
        layoutColumn.colNumber=float(self.getValue('ColumnNumber'))
        layoutColumn.columnName=self.getValue('ColumnName')
        self.put(layoutColumn)

    def saveLayoutCell(self, sheetId):
        layoutCell = self.getStaticModel('LayoutCell', sheetId)
        if(layoutCell is None):
            layoutCell = LayoutCellModel(key_name=sheetId)
        layoutCell.sheetName=self.getValue('SheetName')
        layoutCell.layoutRow=self.getKey('LayoutRow')
        layoutCell.rowSpanned=float(self.getValue('RowSpanned') or 0)
        layoutCell.colSpanned=float(self.getValue('ColumnSpanned') or 0)
        layoutCell.columnNumber = float(self.getValue('ColumnNumber') or 0)
        layoutCell.rowNumber = float(self.getValue('RowNumber') or 0)
        layoutCell.cellDisplayName = self.getValue('CellDisplayName')
        layoutCell.layoutColumn=self.getKey('LayoutColumn')
        layoutCell.activityDefinitionList=self.getKeyList('LayoutCell.ActivityDefinition')
        layoutCell.type=self.getValue('Type')
        self.put(layoutCell)

    def saveLevel(self, sheetId):
        level = self.getStaticModel('Level', sheetId)
        if(level is None):
            level = LevelModel(key_name=sheetId)
        level.sheetName = self.getValue('SheetName')
        level.rowNumber = float(self.getValue('RowNumber') or 0)
        level.rowHeight = float(self.getValue('RowHeight') or 0)
        level.designationList = self.getKeyList('Level.Designation')
        level.application = self.getKey('Application')
        level.activityDefinitionList=self.getKeyList('Level.ActivityDefinition')
        self.put(level)

    def saveDepartment(self, sheetId):
        department = self.getStaticModel('Department', sheetId)
        if(department is None):
            department = DepartmentModel(key_name=sheetId)
        department.sheetName = self.getValue('SheetName')
        department.columnNumber = float(self.getValue('ColumnNumber') or 0)
        department.columnName = self.getValue('ColumnName')
        department.columnWidth = float(self.getValue('ColumnWidth')or 0)
        department.designationList = self.getKeyList('Department.Designation')
        department.application = self.getKey('Application')
        self.put(department)

    def saveDesignation(self, sheetId):
        designation = self.getStaticModel('Designation', sheetId)
        if(designation is None):
            designation = DesignationModel(key_name=sheetId)
        designation.sheetName = self.getValue('SheetName')
        designation.designationName = self.getValue('DesignationName')
        designation.level = self.getKey('Level')
        designation.department = self.getKey('Department')
        designation.menuGroupList = self.getKeyList('Designation.MenuGroup')
        designation.activityDefinitionList=self.getKeyList('Designation.ActivityDefinition')
        designation.rowSpanned = float(self.getValue('RowSpanned') or 0)
        designation.columnSpanned = float(self.getValue('ColumnSpanned') or 0)
        designation.columnNumber = float(self.getValue('ColumnNumber') or 0)
        designation.rowNumber = float(self.getValue('RowNumber') or 0)
        designation.cellDisplayName = self.getValue('CellDisplayName')
        designation.levelRowSpan = self.getKey('LevelRowSpan')
        designation.levelRowSpanList = self.getKeyList('Designation.LevelRowSpan')
        self.put(designation)

    def saveRowSpan(self,sheetId):
        rowSpan = self.getStaticModel('RowSpan', sheetId)
        if(rowSpan is None):
            rowSpan = RowSpanModel(key_name=sheetId)
        rowSpan.sheetName = self.getValue('SheetName')
        rowSpan.cellMetadata = self.getKey('CellMetadata')
        rowSpan.cellMetadataList = self.getKeyList('RowSpan.CellMetadata')
        rowSpan.columnSpanned = float(self.getValue('ColumnSpanned') or 0.0)
        self.put(rowSpan)

    def saveGridRowSpan(self,sheetId):
        gridRowSpan = self.getStaticModel('GridRowSpan', sheetId)
        if(gridRowSpan is None):
            gridRowSpan = GridRowSpanModel(key_name=sheetId)
        gridRowSpan.sheetName = self.getValue('SheetName')
        gridRowSpan.gridCell = self.getKey('GridCell')
        gridRowSpan.gridCellList = self.getKeyList('GridRowSpan.GridCell')
        gridRowSpan.gridColumnSpanned = self.getValue('GridColumnSpanned')
        self.put(gridRowSpan)

    def saveTableStyle(self,sheetId):
        tableStyle=self.getStaticModel('TableStyle', sheetId)
        if (tableStyle is None):
            tableStyle=TableStyleModel(key_name=sheetId)
        tableStyle.sheetName=self.getValue('SheetName')
        tableStyle.application=self.getKey('Application')
        tableStyle.category=self.getValue('Category')
        tableStyle.firstRowBGColor=self.getValue('FirstRowBGcolor')
        tableStyle.rowFontStyle=self.getValue('RowFontStyle')
        tableStyle.rowFontWeight=self.getValue('RowFontWeight')
        tableStyle.rowFontSize=self.getValue('RowFontSize')
        tableStyle.rowFontFace=self.getValue('RowFontFace')
        tableStyle.secondRowBGColor=self.getValue('SecondRowBGcolor')
        tableStyle.headerBGColor=self.getValue('HeaderBGcolor')
        tableStyle.headerFontColor=self.getValue('HeaderFontColor')
        tableStyle.headerFontStyle=self.getValue('HeaderFontStyle')
        tableStyle.headerFontWeight=self.getValue('HeaderFontWeight')
        tableStyle.headerFontSize=self.getValue('HeaderFontSize')
        tableStyle.headerFontFace=self.getValue('HeaderFontFace')
        self.put(tableStyle)

    def saveCriteria(self,sheetId):
        criteria=self.getStaticModel('Criteria', sheetId)
        if (criteria is None):
            criteria=CriteriaModel(key_name=sheetId)
        criteria.sheetName=self.getValue('SheetName')
        criteria.andOper=float(self.getValue('AndOper') or 0.0)
        criteria.criteria=self.getKey('Criteria')
        criteria.conditionList=self.getKeyList('Criteria.Condition')
        criteria.serachDefinition=self.getKey('SearchDefinition')
        criteria.gridCell = self.getKey('GridCell')
        criteria.gridCell_read = self.getKey('GridCell_Read')
        criteria.gridCell_write = self.getKey('GridCell_Write')
        criteria.gridCell_visible = self.getKey('GridCell_Visible')
        criteria.activityPermission_read = self.getKey('ActivityPermission_Read')
        criteria.activityPermission_write = self.getKey('ActivityPermission_Write')
        criteria.activityPermission_visible = self.getKey('ActivityPermission_Visible')
        self.put(criteria)

    def saveCondition(self,sheetId):
        condition=self.getStaticModel('Condition', sheetId)
        if (condition is None):
            condition=ConditionModel(key_name=sheetId)
        condition.sheetName=self.getValue('SheetName')
        condition.operator=self.getValue('Operator')
        if len(self.getKeyList('Formula.LHSCondition')) == 1:
            condition.lhsFormulaJson = self.constructFormulaJson(self.getKeyList('Formula.LHSCondition').pop())
        if len(self.getKeyList('Formula.RHSCondition')) == 1:
            condition.rhsFormulaJson = self.constructFormulaJson(self.getKeyList('Formula.RHSCondition').pop())
        condition.criteria=self.getKey('Criteria')
        condition.lhsValue = self.getValue('LHSValue')
        condition.rhsValue = self.getValue('RHSValue')
        self.put(condition)

    def saveLevelRowSpan(self,sheetId):
        levelRowSpan = self.getStaticModel('LevelRowSpan', sheetId)
        if(levelRowSpan is None):
            levelRowSpan = LevelRowSpanModel(key_name=sheetId)
        levelRowSpan.sheetName = self.getValue('SheetName')
        levelRowSpan.designation = self.getKey('Designation')
        levelRowSpan.designationList = self.getKeyList('LevelRowSpan.Designation')
        levelRowSpan.columnSpanned = self.getValue('ColumnSpanned')
        self.put(levelRowSpan)

    def saveButton(self,sheetId):
        button=self.getStaticModel('Button', sheetId)
        if (button is None):
            button=ButtonModel(key_name=sheetId)
        button.sheetName=self.getValue('SheetName')
        button.action=self.getValue('Action')
        button.goto=self.getValue('GoTo')
        button.index=float(self.getValue('Index') or 0)
        button.icon=self.getValue('Icon')
        button.size=float(self.getValue('Size') or 0)
        button.activitydefinition=self.getKey('ActivityDefinition')
        self.put(button)

    def saveActivityPermission(self,sheetId):
        activityPermission=self.getStaticModel('ActivityPermission', sheetId)
        if (activityPermission is None):
            activityPermission=ActivityPermissionModel(key_name=sheetId)
        activityPermission.sheetName=self.getValue('SheetName')
        activityPermission.activitydefinition=self.getKey('ActivityDefinition')
        activityPermission.gridCell=self.getKey('GridCell')
        activityPermission.read = float(self.getValue('Read') or 0)
        activityPermission.write = float(self.getValue('Write') or 0)
        activityPermission.visible = float(self.getValue('Visible') or 0)
        self.put(activityPermission)

    def saveRange(self,sheetId):
        range=self.getStaticModel('Range', sheetId)
        if (range is None):
            range = RangeModel(key_name=sheetId)
        range.sheetName=self.getValue('SheetName')
        range.application=self.getKey('Application')
        range.rangeValueList = self.getKeyList('Range.RangeValue')
        self.put(range)

    def saveRangeValue(self,sheetId):
        rangeValue=self.getStaticModel('RangeValue', sheetId)
        if (rangeValue is None):
            rangeValue=RangeValueModel(key_name=sheetId)
        rangeValue.sheetName=self.getValue('SheetName')
        rangeValue.range=self.getKey('Range')
        rangeValue.value=self.getValue('Value')
        self.put(rangeValue)

    def saveProperty(self,sheetId):
        property=self.getStaticModel('Property', sheetId)
        if (property is None):
            property=PropertyModel(key_name=sheetId)
        property.sheetName = self.getValue('SheetName')
        property.gridCell = self.getKey('GridCell')
        property.attributeName = self.getValue('AttributeName')
        property.staticValue = self.getValue('StaticValue')
        property.formulaValue = self.getValue('FormulaValue')
        self.put(property)

    def put(self,sheet):
        self.localCache[sheet.getSheetId()]=sheet

    def save(self, entityList):
        size = len(entityList)
        if size>0:
            if size > self.max_commit_objects:
                m = size % self.max_commit_objects
                if m > 0:
                    splitsize = (size/self.max_commit_objects)+1
                else:
                    splitsize = (size/self.max_commit_objects)
                splitList = split_seq(entityList, splitsize)
                for objList in splitList:
                    db.put(objList)
            else:
                db.put(entityList)


class Serializer:
    def getJsonString(self,session,rootObj,isDeep=True):
        return DeepSerialize(session,rootObj,isDeep)

    def export(self,session,rootObj):
        return export(session,rootObj)

    def getSpecifiedJsonString(self,session,rootObj,gridView):
        return specifiedSerialize(session,rootObj,gridView)

    def serializeObject(self,obj):
        return jsonWrite(obj)

