from SystemInterface import Static
from Interface import Version, Application, SheetMetadata, RowMetadata, ColumnMetadata, CellMetadata
from Interface import Formula, BaseNode, Node, Task, ActivityDefinition, Branch, InputportMetadata, OutputportMetadata
from Interface import SubProcess, Level, MenuGroup, LayoutView, LayoutRow, LayoutColumn, LayoutCell,LevelRowSpan
from Interface import SearchDefinition, Header, Hierarchy, Section, GridView, GridRow, GridColumn, GridCell, Style, RowSpan,TableStyle,Criteria,Condition,Button
from Interface import ActivityPermission,Range,RangeValue,Property,Folder,ShortCut
from orangescape.model.engine.exception.Error import MetadataError
from orangescape.model.engine.exception.ErrorMessage import Server1007,Server1006, Server2003
from orangescape.model.engine.engineconstants import WORKFLOW
from util.ServerUtil import _get_class
from orangescape.model.server.util.metadatautil import constructDescendantNodeList
from pickleUtil import unpickle
import appconfig as config

""" Non-SL specific package import handled globally here instead of importing inside every methods """
if config.env!=config.SL:
    import os

def getModule(sheetId):
    replaceSheetId = sheetId.replace('-', '_')
    if config.env==config.SL:
        return _get_class(replaceSheetId+"."+replaceSheetId)
    else:
        return _get_class("orangescape.model.server.metamodel."+replaceSheetId+"."+replaceSheetId)

class StaticModel(Static):

    def __init__(self, dictionary, app):
        self.__dict__ = dictionary
        self.application = app

    def getValue(self,cellName):
        if cellName.__contains__("."):
            if self.__dict__.get(cellName) is None:
                return {}
        return self.__dict__.get(cellName)

    def getSheetMetadataName(self):
        return self.getValue('SheetMetadataName')

    def getSheetId(self):
        return self.getValue('SheetId')

    def getSheetName(self):
        return self.getValue('SheetName')

    def get(self, cellName,sheetId = None):
        idDict = self.getValue(cellName)
        if idDict and len(idDict)>0:
            id = idDict.keys().pop()
            return self.getObject(id, sheetId)

    def getObject(self,id,sheetId = None):
        if sheetId:
            return self.application.getObject(id,sheetId);
        return self.application.getObject(id);

    def getList(self,attrName):
        idDict = self.getValue(attrName)
        if idDict:
            return [self.getObject(id) for id in idDict]
        return []

    def getCrossCellObject(self,idDict):
        if idDict and len(idDict)>0:
            id = idDict.keys().pop()
            displayName = idDict.values().pop()
            if displayName.__contains__("-"):
                refSheetId = displayName[:displayName.rfind("-")]
                return self.getObject(id,refSheetId)
            return self.getObject(id)

class ApplicationModel(Application,StaticModel):
    def __init__(self,context, formMapping, actionMapping):
        StaticModel.__init__(self, context[context["root"]],self)
        self.context = context
        self.metadataCache = dict()
        #load app into metadata cache
        self.metadataCache[self.getSheetId()] = self

        self.sheetMetadataDict = dict()
        sheets = self.__dict__.get('Application.SheetMetadata')
        for key in sheets:
            self.sheetMetadataDict[sheets[key]] = key
        self.register(context);
        self.formMapping = formMapping
        self.actionMapping = actionMapping

    def register(self, context):
        for key in context:
            value = context[key]
            if key != "root" and value['SheetMetadataName'] != 'Application':
                clsName = value['SheetMetadataName']+"Model"
                if config.env==config.SL:
                    obj = _get_class("Metadata."+clsName)(value, self)
                else:
                    obj = _get_class("orangescape.model.server.Metadata."+clsName)(value, self)
                self.metadataCache[key] = obj

    def getMetadataCache(self,id):
        return self.metadataCache.get(id)

    def getObject(self, id, sheetId = None):
        if sheetId:
            if not self.metadataCache.__contains__(id):
                if config.env==config.SL:
                    application_path=""
                else:
                    application_path=os.path.join(os.path.dirname(__file__).split('model')[0],'application')
                if config.pickle:
                    metadataDict=unpickle(application_path,sheetId+'.pck')
                    self.register(metadataDict)
                else:
                    self.register(_get_class("orangescape.application."+sheetId+"."+sheetId))
#                    self.register(_get_class("orangescape.tests.functional.server.test."+sheetId+"."+sheetId))
                return self.getObject(id);
        return self.getMetadataCache(id);

    def getApplicationName(self):
        return self.getValue('SheetName')

    def getVersion(self):
        return self.get('Version')

    def getLevelList(self):
        return self.getList('Application.Level')

    def getVersionList(self):
        return self.getList('Application.Version')

    def getStyleList(self):
        return self.getList('Application.Style')

    def getTableStyleList(self):
        return self.getList('Application.TableStyle')

    def getRangeList(self):
        return self.getList('Application.Range')

    def getSheetMetadataList(self):
#        idDict = self.getValue('Application.SheetMetadata')
#        return [self.getObject(id,id) for id in idDict]
        return self.getValue('Application.SheetMetadata')

    def getFolderList(self):
        return self.getList('Application.Folder')

    def getSheetMetadataDict(self):
        return self.sheetMetadataDict

    def getSheetMetadata(self, name):
        if self.getSheetMetadataDict().__contains__(name):
            sheetId = self.getSheetMetadataDict().get(name)
            return self.getObject(sheetId,sheetId)
        raise MetadataError , Server1007 % (name, self.getApplicationName())

    def getSheetMetadataById(self, idVal):
        return self.getObject(idVal,idVal)

    def getAppRoles(self):
        return self.getValue('AppRoles')

    def setFormMapping(self, formMapping):
        self.formMapping = formMapping

    def setActionMapping(self, actionMapping):
        self.actionMapping = actionMapping

    def getFormMapping(self):
        return self.formMapping

    def getActionMapping(self):
        return self.actionMapping

class VersionModel(Version,StaticModel):
    def getVersionNumber(self):
        return self.getValue('VersionNumber')

    def getApplicationList(self):
        return self.getList('Version.Application')

class SheetMetadataModel(SheetMetadata,StaticModel):

    def __init__(self,dictionary,app):
        StaticModel.__init__(self, dictionary, app)
        self.publicCellMetadataDict = dict()
        self.constructPublicCellMetadataDict()
        self.branchDict = dict()
        self.constructBranchDict()

    def getSheetMetadataName(self):
        return self.getValue('SheetName')

    def isSystemModel(self):
        return self.getValue('SystemModel')

    def getApplication(self):
        return self.application

    def getCellMetadataList(self):
        return self.getList('SheetMetadata.CellMetadata')

    def getProtectedCellMetadataList(self):
        return self.getList('ProtectedSheetMetadata.CellMetadata')

    def constructPublicCellMetadataDict(self):
        cellMetadataDict = dict()
        for key,value in self.getValue('SheetMetadata.CellMetadata').iteritems():
            if value.__contains__(self.getSheetId()):
                cellMetadataDict[value[value.rfind("-")+1:]] = key
            else:
                cellMetadataDict[value] = key
        self.publicCellMetadataDict=cellMetadataDict

    def getPublicCellMetadataDict(self):
        return self.publicCellMetadataDict

    def getPublicCellMetadata(self, name):
        if self.getPublicCellMetadataDict().__contains__(name):
            return self.getObject(self.getPublicCellMetadataDict().get(name))
        raise MetadataError , Server1006 % (name, self.getSheetMetadataName())

    def getCellMetadataById(self, idVal):
        return self.getObject(idVal)

    def getRowMetadataList(self):
        return self.getList('SheetMetadata.RowMetadata')

    def getColumnMetadataList(self):
        return self.getList('SheetMetadata.ColumnMetadata')

    def getOneToManyList(self):
        oneToManyList = list()
        cellDict = self.getValue('ReferredSheetMetadata.CellMetadata')
        #getting RefCell
        for key in cellDict:
            displayName = cellDict[key]
            refSheetId = displayName[:displayName.rfind("-")]
            oneToManyList.append(self.getObject(key,refSheetId))
        return oneToManyList

    def getManyToOneList(self):
        manyToOneList = list()
        for cell in self.getCellMetadataList():
            if cell.getReferredSheetMetadata():
                manyToOneList.append(cell)
        return manyToOneList

    def getSectionList(self):
        return self.getList('SheetMetadata.Section')

    def getGridViewList(self):
        return self.getValue('SheetMetadata.GridView')

    def getQGridViewList(self):
        return self.getValue('QSheetMetadata.GridView')

    def getBranchList(self):
        branchList = self.getList('SheetMetadata.Branch')
        branchList.sort(lambda x, y: cmp(x.getValue('SequenceNo'), y.getValue('SequenceNo')))
        return branchList

    def constructBranchDict(self):
        for key,value in self.getValue('SheetMetadata.Branch').iteritems():
            self.branchDict[value]=key

    def getBranchDict(self):
        return self.branchDict

    def getBranch(self, name):
        if self.getBranchDict().__contains__(name):
            return self.getBranchById(self.getBranchDict().get(name))
        raise MetadataError , Server2003 % (name, self.getSheetMetadataName())

    def getBranchById(self,branchId):
        return self.getObject(branchId)

    def getWorkFlowRoot(self):
        branchList = [branch for branch in self.getBranchList() if branch.getProcessType()==WORKFLOW]
        if len(branchList)>0:
            return branchList.pop()
        return None

    def getActivityDefinitionById(self,actDefId):
        return self.getObject(actDefId)

    def getFolder(self):
        return self.get('Folder')

    def isPublic(self):
        return self.getValue('IsPublic')

    def getPublicName(self):
        return self.getValue('PublicName') or self.getSheetName()

    def getShortCutList(self):
        return self.getList('SheetMetadata.ShortCut')

    def getStartActivity(self):
        workFlowRootbranch = self.getWorkFlowRoot()
        if workFlowRootbranch:
            actList = workFlowRootbranch.getActivityDefinitionList()
            if len(actList) > 0:
                return actList[0]
        return None

    def isMonitorEnabled(self):
        return not self.getValue('DisableProcessInstance')

    def getSearchDefinitionList(self):
        return self.getList('SheetMetadata.SearchDefinition')

    def getSearchDefinitionById(self, idVal):
        return self.getObject(idVal)

    def getMetadataVersion(self):
        return  self.getValue('MetadataVersion')

    def isTrash(self):
        return  self.getValue('IsTrash')

class RowMetadataModel(RowMetadata, StaticModel):

    def getRowNumber(self):
        return self.getValue('RowNumber')

    def getRowHeight(self):
        return self.getValue('RowHeight')

    def getStyle(self):
        return self.get('Style')

    def getSheetMetadata(self):
        return self.get('SheetMetadata')

    def getCellMetadataList(self):
        return [self.getObject(cellId) for cellId in self.getValue('RowMetadata.CellMetadata') if self.getObject(cellId)]

    def getPreviousRef(self):
        return self.get('RowMetadata')

class ColumnMetadataModel(ColumnMetadata, StaticModel):

    def getColumnName(self):
        return self.getValue('ColumnName')

    def getColumnNumber(self):
        return self.getValue('ColumnNumber')

    def getColumnWidth(self):
        return self.getValue('ColumnWidth')

    def getSheetMetadata(self):
        return self.get('SheetMetadata')

    def getCellMetadataList(self):
        return [self.getObject(cellId) for cellId in self.getValue('ColumnMetadata.CellMetadata') if self.getObject(cellId)]

    def getPreviousRef(self):
        return self.get('ColumnMetadata')

class CellMetadataModel(CellMetadata, StaticModel):
    descendantNodeList = None
    nodeList = None

    def getCellName(self):
       return self.getValue('CellName')

    def getCellDisplayName(self):
       return self.getValue('CellDisplayName')

    def getCellType(self):
        return self.getValue('CellType')

    def getWidgetType(self):
        return self.getValue('WidgetType')

    def getStyle(self):
        return self.get('Style')

    def getRowSpanned(self):
        return self.getValue('RowSpanned')

    def getColumnSpanned(self):
        return self.getValue('ColumnSpanned')

    def getDefaultValue(self):
        return self.getValue('DefaultValue')

    def getCellValue(self):
        return self.getValue('CellValue')

    def isCascade(self):
        if self.getValue('Cascade') is not None:
            if type(self.getValue('Cascade'))==str or type(self.getValue('Cascade'))==unicode:
                return float(self.getValue('Cascade'))
        return self.getValue('Cascade')

    def getRowMetadata(self):
        return self.get('RowMetadata')

    def getColumnMetadata(self):
        return self.get('ColumnMetadata')

    def getSheetMetadata(self):
        return self.get('SheetMetadata')

    def getReferredSheetMetadata(self):
        #getting RefCell
        refCellDict = self.getValue('ReferredSheetMetadata')
        if refCellDict and len(refCellDict)>0:
            refSheetId = refCellDict.keys()[0]
            return self.getObject(refSheetId,refSheetId)
        return None

    def getFormulaList(self):
        return self.getList('CellMetadata.Formula')

    def isNamedCell(self):
        return self.getValue('CellName') is not None

    def isReferenceCell(self):
        return self.getValue('ReferredSheetMetadata') is not None and len(self.getValue('ReferredSheetMetadata'))>0

    def isFormula(self):
        return len(self.getValue('CellMetadata.Formula'))>0

    def getRowSpan(self):
        return self.get('RowSpan')

    def getRowSpanList(self):
        return self.getList('CellMetadata.RowSpan')

    def getColumnNumber(self):
        return self.getValue('ColumnNumber')

    def getRowNumber(self):
        return self.getValue('RowNumber')

    def getHeaderList(self):
        return self.getList('CellMetadata.Header')

    def isHidden(self):
        return self.getValue('Hidden')

    def isHeader(self):
        return self.getValue('Header')

    def getSearchDefinitionList(self):
        return self.getList('CellMetadata.SearchDefinition')

    def getFormat(self):
        return self.getValue('OutputFormat')

    def getCategory(self):
        return self.getValue('OutputCategory')

    def getFinalFormat(self):
        return self.getValue('FinalFormat')

    def getFinalCategory(self):
        return self.getValue('FinalCategory')

    def getIsFormulaError(self):
        return self.getValue('FormulaError') > 0

    def getOutputportMetadataList(self):
        return self.getList('CellMetadata.OutPutportMetadata')

    def isStr(self):
        return self.getValue('IsStr')

    def getDescendentNodeList(self):
        if self.descendantNodeList is None:
            self.descendantNodeList = constructDescendantNodeList(self.getNodeList())
        return self.descendantNodeList

    def getNodeList(self):
        if self.nodeList is None:
            self.nodeList = self.constructNodeList()
        return self.nodeList

    def constructNodeList(self):
        nodeList = list()
        cellDict = self.getValue('CellMetadata.Node')
        for key in cellDict:
            refSheetId = cellDict[key]
            isSync = None
            if refSheetId.__contains__("-"):
                idSyncList = refSheetId.split("-")
                refSheetId = idSyncList[0]
                isSync = idSyncList[1]
            if refSheetId:
                if refSheetId == self.getRowMetadata().getSheetMetadata().getSheetId():
                    nodeList.append(self.getObject(key))
                elif refSheetId != 'NonCellFormula' and isSync != 'False':
                    nodeList.append(self.getObject(key,refSheetId))
        return nodeList

    def isSystemCell(self):
        return self.getRowNumber()<0.0 or self.getColumnNumber()<0.0

    def getOutputFormat(self):
        return self.getValue('OutputFormat')

    def getInputFormat(self):
        return self.getValue('FinalFormat')

    def getCellFloatValue(self):
        return self.getValue('CellFloatValue')

    def getTextLength(self):
        return self.getValue('TextLength')

class FormulaModel(Formula, StaticModel):

    def getSheetId(self):
        return self.getValue('SheetId')

    def getSheetName(self):
        return self.getValue('SheetName')

    def getNodeList(self):
        return self.getList('Formula.Node')

    def getCellMetadata(self):
        return self.get('CellMetadata')

    def getActivityDefinition(self):
        return self.get('ActivityDefinition')

    def getBranch(self):
        return self.get('Branch')

    def getInputportMetadata(self):
        return self.get('InputportMetadata')

    def isError(self):
        return self.getValue('Error') > 0

class NodeModel(Node, StaticModel):
    def getSheetId(self):
        return self.getValue('SheetId')

    def getSheetName(self):
        return self.getValue('SheetName')

    def isString(self):
        return self.getValue('IsStr')

    def getNodeType(self):
        return self.getValue('NodeType')

    def getFormula(self):
        return self.get('Formula')

    def getCellMetadata(self):
        if self.getNodeType() == "3dCellReference":
            #getting RefCell
            refCellDict = self.getValue('CellMetadata')
            if refCellDict and len(refCellDict)>0:
                refSheetId = self.getValue('ReferredSheetId')
                return self.getObject(refCellDict.keys()[0],refSheetId)
            return None
        else:
            return self.get('CellMetadata')

    def getNode(self):
        return self.get('Node')

    def isRootNode(self):
        return self.getValue('Formula') is not None

    def getNodeList(self):
        nodeList = self.getList('Node.Node')
        nodeList.sort(lambda x, y: cmp(x.getValue('ArgNo'), y.getValue('ArgNo')))
        return nodeList

    def getArgNo(self):
        return self.getValue('ArgNo')

    def getNodeValue(self):
        return self.getValue('Value')

    def isPublicRef(self):
        return self.getValue('IsPublicRef')

    def isNodeParenthesised(self):
        return self.getValue('IsParenthesised')

    def getLeadingWS(self):
        return self.getValue('LeadingWS')

    def getTrailingWS(self):
        return self.getValue('TrailingWS')

    def isError(self):
        return self.getValue('Error') > 0

    def getNodeFloatValue(self):
        return self.getValue('NodeFloatValue')

    def isSyntacticSugar(self):
        return self.getValue('IsSyntacticSugar')

class ActivityDefinitionModel(ActivityDefinition, StaticModel):

    def getActivityDefinitionName(self):
        return self.getValue('SheetName')

    def getSequenceNo(self):
        return self.getValue('SequenceNo')

    def getTaskStatus(self):
        return self.getValue('TaskStatus')

    def getFormulaList(self):
        return self.getList('ActivityDefinition.Formula')

    def getBranchList(self):
        branchList = self.getList('ActivityDefinition.Branch')
        branchList.sort(lambda x, y: cmp(x.getValue('SequenceNo'), y.getValue('SequenceNo')))
        return branchList

    def getButtonList(self):
        return self.getList('ActivityDefinition.Button')

    def getSearchDefinitionList(self):
        return self.getList('ActivityDefinition.SearchDefinition')

    def getBranch(self):
        return self.get('Branch')

    def getGridView(self):
        return self.get('GridView')

    def containsFormula(self):
        return len(self.getValue('ActivityDefinition.Formula'))>0 and len(self.getValue('ActivityDefinition.Formula').keys()[0])>0

    def getNodeType(self):
        return self.getValue('NodeType')

    def getAppRole(self):
        return self.getValue('AppRole')

    def isStatic(self):
        return self.getValue('Static')!=0

    def getCellMetadata(self):
        return self.get('CellMetadata')

    def getAssignedFor(self):
        return self.getValue('AssignedFor')

    def getGoTo(self):
        return self.get('GoTo')

    def getRoot(self):
        return self.getValue('Root')

    def getInputportMetadataList(self):
        inputPortList = self.getList('ActivityDefinition.InputportMetadata')
        return inputPortList

    def getOutputportMetadataList(self):
        outputPortList = self.getList('ActivityDefinition.OutputportMetadata')
        return outputPortList

    def getOutputHierarchyList(self):
        return self.getList('OutputActivityDefinition.Hierarchy')

    def getProcessType(self):
        return self.getValue('ProcessType')

    def getAllowedFormulaList(self):
        return self.getValue('AllowedFormulaList')

    def containsAllowedFormula(self):
        return len(self.getValue('AllowedFormulaList'))>0

    def isContinueOnError(self):
        return self.getValue('ContinueOnError')!=0

    def getFinalInboxGridView(self):
        gridViewDict = self.getValue('FinalInboxGridView')
        if gridViewDict and len(gridViewDict)>0:
            gridViewNameList = gridViewDict.values()
            return gridViewNameList.pop()

    def getFinalEditorGridView(self):
        gridViewDict = self.getValue('FinalEditorGridView')
        if gridViewDict and len(gridViewDict)>0:
            gridViewNameList = gridViewDict.values()
            return gridViewNameList.pop()

    def getFinalEditorForm(self):
        return self.getValue('FinalEditorForm')

    def getFinalInboxForm(self):
        return self.getValue('FinalInboxForm')

    def getHierarchyList(self):
        return self.getList('InputActivityDefinition.Hierarchy')

    def getOutputtHierarchyList(self):
        return self.getList('OutputActivityDefinition.Hierarchy')

    def getBelongingSheetId(self):
        return self.getValue('BelongingSheetId')

    def getAssignedTo(self):
        return self.getValue('AssignedTo')

    def getActivityTenant(self):
        return self.getValue('ActivityTenant')

    def getActivityTenantFormulaList(self):
        return self.getList('ActivityTenantFormula.Formula')

    def containsActivityTenantFormula(self):
        return len(self.getValue('ActivityTenantFormula.Formula'))>0 and len(self.getValue('ActivityTenantFormula.Formula').keys()[0])>0

class BranchModel(Branch, StaticModel):

    def getBranchName(self):
        return self.getValue('SheetName')

    def getProcessType(self):
        return self.getValue('ProcessType')

    def getSequenceNo(self):
        return self.getValue('SequenceNo')

    def getFormulaList(self):
        return self.getList('Branch.Formula')

    def getActivityDefinitionList(self):
        activityDefList = self.getList('Branch.ActivityDefinition')
        activityDefList.sort(lambda x, y: cmp(x.getValue('SequenceNo'), y.getValue('SequenceNo')))
        return activityDefList

    def getActivityDefinition(self):
        return self.get('ActivityDefinition')

    def containsFormula(self):
        return len(self.getValue('Branch.Formula'))>0

    def getRoot(self):
        return self.getValue('Root')

    def getSheetMetadata(self):
        return self.get('SheetMetadata')

    def getNodeType(self):
        return self.getValue('NodeType')

class InputportMetadataModel(InputportMetadata, StaticModel):

    def getStringValue(self):
        return self.getValue('StringValue')

    def getFloatValue(self):
        return self.getValue('FloatValue')

    def isStr(self):
        return self.getValue('IsStr')

    def getSequenceNo(self):
        return self.getValue('SequenceNo')

    def getActivityDefinition(self):
        return self.get('ActivityDefinition')

    def getCellMetadata(self):
        idDict = self.getValue('CellMetadata')
        #getting RefCell
        return self.getCrossCellObject(idDict)

    def getFormulaList(self):
        return self.getList('InputportMetadata.Formula')

    def containsFormula(self):
        return len(self.getValue('InputportMetadata.Formula'))>0

    def getParamName(self):
        return self.getValue('ParamName')

    def getHierarchy(self):
        return self.get('Hierarchy')

    def getBranch(self):
        return self.get('Branch')

    def getActivityDefinitionRef(self):
        return self.get('ActivityDefinitionRef')

class OutputportMetadataModel(OutputportMetadata, StaticModel):
    def getCellMetadata(self):
        idDict = self.getValue('CellMetadata')
        #getting RefCell
        return self.getCrossCellObject(idDict)

    def getSequenceNo(self):
        return self.getValue('SequenceNo')

    def getActivityDefinition(self):
        return self.get('ActivityDefinition')

    def getParamName(self):
        return self.getValue('ParamName')

    def getHierarchy(self):
        return self.get('Hierarchy')

class SearchDefinitionModel(SearchDefinition, StaticModel):

    def getSearchDefinitionName(self):
        return self.getValue('SheetName')

    def getActivityDefinition(self):
        return self.get('ActivityDefinition')

    def getCriteriaList(self):
        return self.getList('SearchDefinition.Criteria')

    def getItemsPerPage(self):
        return self.getValue('ItemsPerPage')

    def isDefault(self):
        return self.getValue('Default')

    def getTableStyle(self):
        return self.get('TableStyle')

    def getCellMetadata(self):
        return self.get('CellMetadata')

    def getDisplayCell(self):
        idDict = self.getValue('DisplayCell')
        #getting RefCell
        return self.getCrossCellObject(idDict)

    def isNotAllowNone(self):
        return self.getValue('DontAllowNone')

    def isDescending(self):
        return self.getValue('IsDescending')

    def getParentReferenceCell(self):
        idDict = self.getValue('ParentReferenceCell')
        #getting RefCell
        return self.getCrossCellObject(idDict)

    def getReferredSheetMetadata(self):
        refSearchDict = self.getValue('ReferredSheetMetadata')
        if refSearchDict and len(refSearchDict)>0:
            refSheetId = refSearchDict.keys()[0]
            return self.getObject(refSheetId,refSheetId)
        return None

    def getSearchReferenceCell(self):
        idDict = self.getValue('SearchReferenceCell')
        #getting RefCell
        return self.getCrossCellObject(idDict)

    def getSheetMetadata(self):
        return self.get('SheetMetadata')

    def getFormulaList(self):
        return self.getList('SearchDefinition.Formula')

    def containsFormula(self):
        return len(self.getValue('SearchDefinition.Formula'))>0 and len(self.getValue('SearchDefinition.Formula').keys()[0])>0

    def getFinalInboxGridView(self):
        gridViewDict = self.getValue('FinalInboxGridView')
        if gridViewDict and len(gridViewDict)>0:
            gridViewNameList = gridViewDict.values()
            return gridViewNameList.pop()

    def getFinalInboxForm(self):
        return self.getValue('FinalInboxForm')

    def getFinalEditorGridView(self):
        gridViewDict = self.getValue('FinalEditorGridView')
        if gridViewDict and len(gridViewDict)>0:
            gridViewNameList = gridViewDict.values()
            return gridViewNameList.pop()

    def getFinalEditorForm(self):
        return self.getValue('FinalEditorForm')

class HeaderModel(Header, StaticModel):

    def getHeaderName(self):
        return self.getValue('SheetName')

    def getIndex(self):
        return self.getValue('Index')

    def getCellMetadata(self):
        return self.get('CellMetadata')

    def getOrderBy(self):
        return self.getValue('OrderBy')

    def getHierarchy(self):
        return self.get('Hierarchy')

    def getWidth(self):
        return self.getValue('Width')

class HierarchyModel(Hierarchy, StaticModel):

    def getReferenceCell(self):
        idDict = self.getValue('ReferenceCell')
        return self.getCrossCellObject(idDict)

    def getHierarchyList(self):
        return self.getList('Hierarchy.Hierarchy')

    def getHeaderList(self):
        return self.getList('Hierarchy.Header')

    def getActivityDefinition(self):
        return self.get('InputActivityDefinition')

    def getOutputActivityDefinition(self):
        return self.get('OutputActivityDefinition')

    def getNodeName(self):
        return self.getValue('NodeName')

    def getInputportMetadataList(self):
        return self.getList('Hierarchy.InputportMetadata')

    def getOutputportMetadataList(self):
        return self.getList('Hierarchy.OutputportMetadata')

    def getHierarchy(self):
        return self.get('Hierarchy')

class SectionModel(Section, StaticModel):

    def getSectionName(self):
        return self.getValue('SheetName')

    def getFrom(self):
        return self.get('CellMetadata')

    def getTo(self):
        return self.get('CellMetadata')

    def getSheetMetadata(self):
        return self.get('SheetMetadata')

class GridViewModel(GridView, StaticModel):

    def getGridViewName(self):
        return self.getValue('SheetName')

    def getSheetMetadata(self):
        return self.get('SheetMetadata')

    def getGridCell(self):
        return self.get('GridCell')

    def getGridRowList(self):
        return self.getList('GridView.GridRow')

    def getGridColumnList(self):
        return self.getList('GridView.GridColumn')

    def getJSTLString(self):
        return getJSTLString_GridView(self, 'json')

    def isDefault(self):
        return self.getValue('Default')

    def getProperty(self):
        return self.getValue('Property')

    def getGridViewHeight(self):
        return self.getValue('GridViewHeight')

    def getGridViewWidth(self):
        return self.getValue('GridViewWidth')

class GridRowModel(GridRow, StaticModel):

    def getRowNumber(self):
        return self.getValue('RowNumber')

    def getRowHeight(self):
        return self.getValue('RowHeight')

    def getStyle(self):
        return self.get('Style')

    def getReferenceCellMetadata(self):
        return self.get('CellMetadata')

    def getGridView(self):
        return self.get('GridView')

    def getGridCellList(self):
        return self.getList('GridRow.GridCell')

    def getFinalHeight(self):
        return self.getValue('FinalHeight')

class GridColumnModel(GridColumn, StaticModel):

    def getColumnNumber(self):
        return self.getValue('ColumnNumber')

    def getColumnWidth(self):
        return self.getValue('ColumnWidth')

    def getReferenceCellMetadata(self):
        return self.get('CellMetadata')

    def getGridView(self):
        return self.get('GridView')

    def getGridCellList(self):
        return self.getList('GridColumn.GridCell')

    def getFinalWidth(self):
        return self.getValue('FinalWidth')

class GridCellModel(GridCell, StaticModel):

    def getStyle(self):
        return self.get('Style')

    def getRowSpanned(self):
        return self.getValue('RowSpanned')

    def getColumnSpanned(self):
        return self.getValue('ColumnSpanned')

    def getCellValue(self):
        return self.getValue('CellValue')

    def getGridRow(self):
        return self.get('GridRow')

    def getGridColumn(self):
        return self.get('GridColumn')

    def getSection(self):
        return self.get('Section')

    def getCellMetadata(self):
        return self.get('CellMetadata')

    def getGridViewList(self):
        return self.getList('GridCell.GridView')

    def getJSTLString(self, sheetMetadataId, jsonName):
        if self.getCellMetadata():
            cellMetdata = self.getCellMetadata()
            startRowNumber = cellMetdata.getRowMetadata().getRowNumber()
            startColumnNumber = cellMetdata.getColumnMetadata().getColumnNumber()
            return getJSTLString_CellMetadata(startRowNumber, startColumnNumber, sheetMetadataId, jsonName)
        elif self.getSection():
            section = self.getSection()
            startCell = section.getFrom()
            endCell = section.getTo()
            startRowNumber = startCell.getRowMetadata().getRowNumber()
            endRowNumber = endCell.getRowMetadata().getRowNumber()
            startColumnNumber = startCell.getColumnMetadata().getColumnNumber()
            endColumnNumber = endCell.getColumnMetadata().getColumnNumber()
            return getJSTLString_Section(startRowNumber, endRowNumber, startColumnNumber, endColumnNumber, sheetMetadataId, jsonName)
        elif len(self.getGridViewList())>0:
            refGridView = self.getGridViewList().pop()
            return getJSTLString_GridView(refGridView, jsonName)
        elif self.getCellValue():
            return getJSTLString_CellValue(self)
        else:
            return ""

    def getGridRowSpan(self):
        return self.get('GridRowSpan')

    def getGridRowSpanList(self):
        return self.getList('GridCell.GridRowSpan')

    def getColumnNumber(self):
        return self.getValue('ColumnNumber')

    def getRowNumber(self):
        return self.getValue('RowNumber')

    def isHidden(self):
        return self.getValue('Hidden')

    def getWidgetType(self):
        return self.getValue('WidgetType')

    def getActivityPermissionList(self):
        return self.getList('GridCell.ActivityPermission')

    def getGridViewHeight(self):
        return self.getValue('GridViewHeight')

    def getGridViewWidth(self):
         return self.getValue('GridViewWidth')

    def getCriteriaList(self):
        return self.getList('GridCell.Criteria')

    def getPropertyList(self):
        return self.getList('GridCell.Property')

    def getHintMessage(self):
        return self.getValue('HintMessage')

    def getErrorMessage(self):
        return self.getValue('ErrorMessage')

    def isRead(self):
        return self.getValue('Read')

    def isWrite(self):
        return self.getValue('Write')

    def isVisible(self):
        return self.getValue('Visible')

class StyleModel(Style, StaticModel):

    def getStyleName(self):
        return self.getValue('SheetName')

    def getApplication(self):
        return self.application

    def getFontFamily(self):
        return self.getValue('FontFamily')

    def getFontWeight(self):
        return self.getValue('FontWeight')

    def getFontSize(self):
        return self.getValue('FontSize')

    def getFontStyle(self):
        return self.getValue('FontStyle')

    def getColor(self):
        return self.getValue('Color')

    def getTextAlign(self):
        return self.getValue('TextAlign')

    def getTextDecoration(self):
        return self.getValue('TextDecoration')

    def getBorderTop(self):
        return self.getValue('BorderTop')

    def getBorderBottom(self):
        return self.getValue('BorderBottom')

    def getBorderLeft(self):
        return self.getValue('BorderLeft')

    def getBorderRight(self):

        return self.getValue('BorderRight')

    def getBorderColor(self):
        return self.getValue('BorderColor')

    def getBorderStyle(self):
        return self.getValue('BorderStyle')

    def getTextIndent(self):
        return self.getValue('TextIndent')

    def getTextTransform(self):
        return self.getValue('TextTransform')

    def getBackgroundColor(self):
        return self.getValue('BackgroundColor')

class LevelModel(Level, StaticModel):

    def getLevelName(self):
        return self.getValue('SheetName')

    def getRowNumber(self):
        return self.getValue('RowNumber')

    def getRowHeight(self):
        return self.getValue('RowHeight')

    def getApplication(self):
        return self.application

    def getActivityDefinitionList(self):
        return self.getList('Level.ActivityDefinition')

class RowSpanModel(RowSpan, StaticModel):

    def getCellMetadata(self):
        return self.get('CellMetadata')

    def getCellMetadataList(self):
        return self.getList('RowSpan.CellMetadata')

    def getColumnSpanned(self):
        return self.getValue('ColumnSpanned')

class GridRowSpanModel(RowSpan, StaticModel):

    def getGridCell(self):
        return self.get('GridCell')

    def getGridCellList(self):
        return self.getList('GridRowSpan.GridCell')

    def getGridColumnSpanned(self):
        return self.getValue('GridColumnSpanned')

class TableStyleModel(TableStyle,StaticModel):

    def getTableStyleName(self):
        return self.getValue('SheetName')

    def getApplication(self):
        return self.application

    def getCategory(self):
        return  self.getValue('Category')

    def getFirstRowBGColor(self):
        return self.getValue('FirstRowBGColor')

    def getRowFontStyle(self):
        return self.getValue('RowFontStyle')

    def getRowFontWeight(self):
        return self.getValue('RowFontWeight')

    def getRowFontSize(self):
        return self.getValue('RowFontSize')

    def getRowFontFace(self):
        return self.getValue('RowFontFace')

    def getSecondRowBGColor(self):
        return self.getValue('SecondRowBGColor')

    def getHeaderBGColor(self):
        return self.getValue('HeaderBGColor')

    def getHeaderFontColor(self):
        return self.getValue('HeaderFontColor')

    def getHeaderFontStyle(self):
        return self.getValue('HeaderFontStyle')

    def getHeaderFontWeight(self):
        return self.getValue('HeaderFontWeight')

    def getHeaderFontSize(self):
        return self.getValue('HeaderFontSize')

    def getHeaderFontFace(self):
        return self.getValue('HeaderFontFace')

class CriteriaModel(Criteria,StaticModel):

    def getCriteria(self):
        return self.get('Criteria')

    def getCriteriaList(self):
        criteriaList = self.getList('Criteria.Criteria')
        criteriaList.sort(lambda x, y: cmp(x.getValue('CreatedAt'), y.getValue('CreatedAt')))
        return criteriaList

    def getConditionList(self):
        return self.getList('Criteria.Condition')

    def isAndOper(self):
        #used in jstl serialization
        return self.getValue('AndOper')

    def isOrOper(self):
        #used in search execution
        return self.getValue('OrOper')

    def getSearchDefinition(self):
        return self.get('SearchDefinition')

    def getGridCell(self):
        return self.get('GridCell')

    def getGridCell_Read(self):
        return self.get('GridCell')

    def getGridCell_Write(self):
        return self.get(GirdCellModel,'GirdCell')

    def getGridCell_Visible(self):
        return self.get('GridCell')

    def getActivityPermission_Read(self):
        return self.get('ActivityPermission')

    def getActivityPermission_Write(self):
        return self.get('ActivityPermission')

    def getActivityPermission_Visible(self):
        return self.get('ActivityPermission')

class ConditionModel(Condition,StaticModel):

    def getCriteria(self):
        return self.get('Criteria')

    def getLHSFormulaList(self):
        return self.getList('LHSCondition.Formula')

    def getRHSFormulaList(self):
        return self.getList('RHSCondition.Formula')

    def getOperator(self):
        return self.getValue('Operator')

    def getLHSValue(self):
        return self.getValue('LHSValue')

    def getRHSValue(self):
         return self.getValue('RHSValue')

    def getLHSCellMetadata(self):
        return self.get('LHSCellMetadata')

    def getRHSReferenceCellMetadata(self):
        idDict = self.getValue('RHSReferenceCellMetadata')
        #getting RefCell
        return self.getCrossCellObject(idDict)

    def getRHSParentReferenceCellMetadata(self):
        idDict = self.getValue('RHSParentReferenceCellMetadata')
        #getting RefCell
        return self.getCrossCellObject(idDict)

    def getRHSCellMetadata(self):
        idDict = self.getValue('RHSReferenceCellMetadata')
        refSheetId = None
        if idDict and len(idDict)>0:
            displayName = idDict.values().pop()
            if displayName.__contains__("-"):
                refSheetId = displayName[:displayName.rfind("-")]

        cellIdDict = self.getValue('RHSCellMetadata')
        if cellIdDict and len(cellIdDict)>0:
            cellId = cellIdDict.keys().pop()
            return self.getObject(cellId,refSheetId)

    def getRHSParamType(self):
        return self.getValue('RHSParamType')

    def getSearchDefinition(self):
        return self.get('SearchDefinition')

    def getSearchDefinitionList(self):
        return self.getList('Condition.SearchDefinition')

class LevelRowSpanModel(LevelRowSpan, StaticModel):

    def getColumnSpanned(self):
        return self.getValue('ColumnSpanned')

class ButtonModel(Button, StaticModel):

    def getAction(self):
        return self.getValue('Action')

    def getIcon(self):
         return self.getValue('Icon')

    def getSize(self):
        return self.getValue('Size')

    def getGoTo(self):
        return self.getValue('Goto')

    def getIndex(self):
        return self.getValue('Index')

    def getActivityDefinition(self):
        return self.get('ActivityDefinition')

class ActivityPermissionModel(ActivityPermission,StaticModel):

    def getGridCell(self):
        return self.get('GridCell')

    def getActivityDefinition(self):
        return self.get('ActivityDefinition')

    def isRead(self):
        return self.getValue('Read')

    def isWrite(self):
        return self.getValue('Write')

    def isVisible(self):
        return self.getValue('Visible')

class PropertyModel(Property,StaticModel):

    def getGridCell(self):
        return self.get('GridCell')

    def getAttributeName(self):
        return self.getValue('AttributeName')

    def getStaticValue(self):
        return self.getValue('StaticValue')

    def getFormulaValue(self):
        return self.getValue('FormulaValue')

class RangeModel(Range,StaticModel):

    def getApplication(self):
        return self.application

    def getRangeList(self):
        return self.getList('Range.RangeValue')

class RangeValueModel(RangeValue,StaticModel):

    def getRangeValue(self):
       return self.getValue('Value')

    def getRange(self):
        return self.get('Range')

class CustomStyleModel(StaticModel):
    pass

class FolderModel(Folder,StaticModel):
    def getFolderList(self):
       return self.getList('Folder.Folder')

    def getSheetMetadataList(self):
       return self.getValue('Folder.SheetMetadata')

    def getFolder(self):
        return self.get('Folder')

    def getShortCutList(self):
        return self.getList('Folder.ShortCut')

class ShortCutModel(ShortCut,StaticModel):
    def getFolder(self):
         return self.get('Folder')

    def getSheetMetadata(self):
         return self.get('SheetMetadata')

    def getGridView(self):
        gridViewNameList = self.getValue('GridView').values()
        if len(gridViewNameList) > 0:
            return gridViewNameList.pop()

    def getBranch(self):
        return self.get('Branch')