import logging
from json import write
import urllib

def urlEncode(val):
    return urllib.quote(val)

def urlDecode(val):
    return urllib.unquote(val)

class JstlGenerator:
    def __init__(self, session):
        self.session = session
        self.isQueueGridView = False
        self.macroTable = dict()

        self.JSTL = ""
        self.actionMappingTable = dict()
        self.formSerializeTable = dict()
        self.importMappingTable = dict()
        self.styleMapping = dict()
        self.validationMapping = dict()

        self.SheetMetadata = self.session.getApplication().getSheetMetadata('SheetMetadata')
        self.GridView = self.session.getApplication().getSheetMetadata('GridView')
        self.GridRow = self.session.getApplication().getSheetMetadata('GridRow')
        self.GridColumn = self.session.getApplication().getSheetMetadata('GridColumn')
        self.GridCell = self.session.getApplication().getSheetMetadata('GridCell')
        self.RowMetadata = self.session.getApplication().getSheetMetadata('RowMetadata')
        self.CellMetadata = self.session.getApplication().getSheetMetadata('CellMetadata')
        self.Formula = self.session.getApplication().getSheetMetadata('Formula')
        self.ActivityPermission = self.session.getApplication().getSheetMetadata('ActivityPermission')
        self.Criteria = self.session.getApplication().getSheetMetadata('Criteria')
        self.Condition = self.session.getApplication().getSheetMetadata('Condition')
        self.Section = self.session.getApplication().getSheetMetadata('Section')
        self.Branch = self.session.getApplication().getSheetMetadata('Branch')
        self.Node = self.session.getApplication().getSheetMetadata('Node')
        self.Property = self.session.getApplication().getSheetMetadata('Property')
        self.Range = self.session.getApplication().getSheetMetadata('Range')
        self.RangeValue = self.session.getApplication().getSheetMetadata('RangeValue')
        self.ValidationGrid = self.session.getApplication().getSheetMetadata('ValidationGrid')
        self.ExcludeValidationGrid = self.session.getApplication().getSheetMetadata('ExcludeValidationGrid')
        self.IncludeValidationGrid = self.session.getApplication().getSheetMetadata('IncludeValidationGrid')
        self.Validation = self.session.getApplication().getSheetMetadata('Validation')
        self.ActivityDefinition = self.session.getApplication().getSheetMetadata('ActivityDefinition')
        self.SearchDefinition = self.session.getApplication().getSheetMetadata('SearchDefinition')
        self.Style = self.session.getApplication().getSheetMetadata('Style')

#   The following method added to solve the same problem in runtime (this.getEncodedValue in orangescape.controller.js)
    def encodeValue(self, value):
        if type(value) is str:
            value = value.replace("'","&apos;")
            value = value.replace('"',"&quot;")
            return value
        return value

    def build(self, gridView):
        self.rootGrid = gridView
        strBuffer = list()

        if gridView.getValue("QSheetMetadata") is not None:
            self.isQueueGridView = True
        rootTable = {'ManyToOne':{},'OneToMany':{}}
        self.getJstlTable(gridView, rootTable);

        strBuffer.append("<style>\n")
        for style in self.styleMapping:
            strBuffer.append("."+style+"{")
            propDict = self.styleMapping[style]
            for prop in propDict:
                strBuffer.append(prop+":"+propDict[prop]+";")
            strBuffer.append("}\n")
        strBuffer.append("</style>\n")

        if len(self.validationMapping) > 0:
            strBuffer.append("{eval}\n")
            for validation in self.validationMapping:
                strBuffer.append(validation)
                strBuffer.append(" = ")
                strBuffer.append(self.validationMapping[validation])
                strBuffer.append(";\n")
            strBuffer.append("{/eval}\n")

        strBuffer.append("{macro getPermBasedStyle(permission, cl, readonlyCl)}\n")
        strBuffer.append("{if permission == 1} readonly ${readonlyCl}\n")
        strBuffer.append("{else} ${cl}\n")
        strBuffer.append("{/if}\n")
        strBuffer.append("{/macro}\n")

        for gridViewId in self.macroTable:
            strBuffer.append(self.macroTable.get(gridViewId))
        strBuffer.append("\n${" + self.getMacroName(gridView) + "(getRoot(), 2, '')}")

        self.JSTL = ''.join(strBuffer)
        #formmapping creation
        self.formSerializeTable['root'] = rootTable

    def getMacroName(self, gridView):
        sheetmeta = self.session.get(gridView.getValue('SheetMetadata'),self.SheetMetadata)
        return sheetmeta.getSheetName() + "_" + gridView.getSheetId()

    def getJstlTable(self, gv, rootTable, isCascadePerm=False):
        strBuffer = list()
        if not self.macroTable.__contains__(gv.getSheetId()):
            strBuffer.append("{macro "+self.getMacroName( gv)+"(inst, permit, refUrl)}\n")
            strBuffer.append("{var instance = inst}\n")
            strBuffer.append("{var relationUrl = refUrl}\n")
            strBuffer.append("{var permission = permit}\n")

            strBuffer.append("<table id='"+gv.getSheetId()+"' cellpadding=0 cellspacing=0  style='border-collapse:collapse'")
            if self.rootGrid.getValue('Property') == 'AutoWidth':
                strBuffer.append(" width='100%' ")
            strBuffer.append(">\n")

            sheetmeta = self.session.get(gv.getValue('SheetMetadata'),self.SheetMetadata)
            gridRow_gridView_refCell = self.GridRow.getPublicCellMetadata('GridView')
            gridRowList = self.session.getList(gv,gridRow_gridView_refCell)
            gridRowList.sort(lambda x, y: cmp(x.getValue('RowNumber'), y.getValue('RowNumber')))
            for grow in gridRowList:
                if grow.getValue('CellMetadata'):
                    #has reference cell
                    refcell = self.session.get(grow.getValue('CellMetadata'), self.CellMetadata)
                    refcellsheetmeta = self.session.get(refcell.getValue('SheetMetadata'),self.SheetMetadata)
                    refcellrefsheetmeta = self.session.get(refcell.getValue('ReferredSheetMetadata'),self.SheetMetadata)
                    if(refcellsheetmeta.getSheetId() == sheetmeta.getSheetId() and refcellrefsheetmeta.getSheetId() != refcellsheetmeta.getSheetId()):
                        #many-to-one reference cell
                        manyToOneTable = rootTable['ManyToOne']
                        if manyToOneTable.get(refcell.getSheetId()) is None:
                            manyToOneTable[refcell.getSheetId()] = {'ManyToOne':{},'OneToMany':{}}
                        strBuffer.append("{var instance = inst.get('"+refcell.getValue('CellName')+"')}\n")
                        strBuffer.append("{if instance}\n")
                        strBuffer.append("{var relationUrl = refUrl+\"/"+refcell.getValue('CellName')+"/"+refcellrefsheetmeta.getSheetName()+"/\"+instance.getValue('SheetId')}\n")
                        strBuffer.append(self.getJstlRow(gv, grow, manyToOneTable[refcell.getSheetId()], isCascadePerm))
                        strBuffer.append("{/if}\n")
                    else:
                        #one-to-many reference cell
                        oneToManyTable = rootTable['OneToMany']
                        if oneToManyTable.get(refcell.getSheetId()+"."+refcellsheetmeta.getSheetName()) is None:
                            oneToManyTable[refcell.getSheetId()+"."+refcellsheetmeta.getSheetName()] = {'ManyToOne':{},'OneToMany':{}}
                        childListStr = ""
                        if not self.isQueueGridView:
                            orderByCellName = 'CreatedAt'
                            if grow.getValue('OrderByCell'):
                                orderByCell = self.session.get(grow.getValue('OrderByCell'),self.CellMetadata)
                                orderByCellName = orderByCell.getValue('CellName')
                            isDesc = "false"
                            if grow.getValue('IsDescending'):
                                isDesc = "true"
                            childListStr = "inst.getList('"+refcell.getValue('CellName')+"','"+refcellsheetmeta.getSheetName()+"','"+orderByCellName+"',"+isDesc+")"
                        else:
                            childListStr = "inst.getList('"+refcell.getValue('CellName')+"','"+refcellsheetmeta.getSheetName()+"')"
                        strBuffer.append("{for instance in "+childListStr+"}\n")
                        strBuffer.append("{var relationUrl = refUrl+\"/"+refcell.getValue('CellName')+"/"+refcellsheetmeta.getSheetName()+"/\"+instance.getValue('SheetId')}\n")
                        strBuffer.append(self.getJstlRow(gv, grow, oneToManyTable[refcell.getSheetId()+"."+refcellsheetmeta.getSheetName()], isCascadePerm))
                        strBuffer.append("{/for}\n")
                    strBuffer.append("{var instance = inst}\n")
                    strBuffer.append("{var relationUrl = refUrl}\n")
                else:
                    strBuffer.append(self.getJstlRow(gv, grow, rootTable, isCascadePerm))

            strBuffer.append("</table>\n")
            strBuffer.append("{/macro}\n")
            self.macroTable[gv.getSheetId()] = ''.join(strBuffer);

    def getJstlRow(self, gv, grow, serializeTable, isCascadePerm):
        strBuffer = list()
        rowStyleName = ""
        if grow.getValue('Style'):
            rowStyleName = self.getStyleName(grow.getValue('Style'))
        elif grow.getValue('GlobalStyle'):
            rowStyleName = grow.getValue('GlobalStyle')

        alternateRowStyleName = ""
        if grow.getValue('AlternateStyle') :
            alternateRowStyleName = self.getStyleName(grow.getValue('AlternateStyle'))
        elif grow.getValue('AlternateGlobalStyle') :
            alternateRowStyleName = grow.getValue('AlternateGlobalStyle')

        strBuffer.append("<tr")
        if len(alternateRowStyleName) > 0 and len(rowStyleName) > 0:
            strBuffer.append(" class = {if (parseInt(instance_index)+1) % 2 ==0}"+ alternateRowStyleName +" {else}"+ rowStyleName +"{/if}")
        elif len(alternateRowStyleName) > 0:
            strBuffer.append(" class = {if (parseInt(instance_index)+1) % 2 ==0}"+ alternateRowStyleName +"{/if}")
        elif len(rowStyleName):
            strBuffer.append(" class = "+rowStyleName)
        strBuffer.append(">\n")

        gridCell_gridRow_refCell = self.GridCell.getPublicCellMetadata('GridRow')
        gridCellList = self.session.getList(grow,gridCell_gridRow_refCell)
        gridCellList.sort(lambda x, y: cmp(x.getValue('ColumnNumber'), y.getValue('ColumnNumber')))
        for gcell in gridCellList:
            if(gcell.getValue('Hidden') != 1):
                overrideCascadePerm = isCascadePerm
                condPermJstl = self.getDefaultConditionPermissionJstl(gcell)
                actPerm_gridCell_refCell = self.ActivityPermission.getPublicCellMetadata('GridCell')
                permissionList = self.session.getList(gcell, actPerm_gridCell_refCell);
                if(gcell.getValue('PermissionType') is not None or len(condPermJstl) > 0 or len(permissionList) > 0):
                    overrideCascadePerm = True
                #to avoid getting var permission = permit before every td
                if overrideCascadePerm and strBuffer[len(strBuffer)-1] != "{var permission = permit}\n":
                    strBuffer.append("{var permission = permit}\n")

                if(gcell.getValue('PermissionType') is not None or len(condPermJstl) > 0):
                    strBuffer.append(self.getPermissionJstl(gcell.getValue('PermissionType'), condPermJstl))

                if(len(permissionList) > 0):
                    strBuffer.append("{if 'equal' == 'not equal'}\n")
                    for actperm in permissionList:
                        act = self.session.get(actperm.getValue('ActivityDefinition'),self.ActivityDefinition)
                        condPermJstl = self.getActivityConditionPermissionJstl(actperm)
                        if(actperm.getValue('PermissionType') is not None or len(condPermJstl) > 0):
                            strBuffer.append("{elseif '"+act.getSheetId()+"' == activityDefinitionId}\n")
                            strBuffer.append(self.getPermissionJstl(actperm.getValue('PermissionType'), condPermJstl))
                    strBuffer.append("{/if}\n")

                strBuffer.append("<td")
                if gcell.getValue('ColumnSpanned'):
                    strBuffer.append(" colspan="+str(int(gcell.getValue('ColumnSpanned'))))
                if gcell.getValue('RowSpanned'):
                    strBuffer.append(" rowspan="+str(int(gcell.getValue('RowSpanned'))))

                sysClassName =  ""
                if not self.hasGridView(gcell):
                    sysClassName = self.getSystemClass(gcell.getValue('FinalHeight'), gcell.getValue('FinalWidth'))
                    sysClassName += self.getAlignStyleName(gcell)
                else:
                    strBuffer.append(self.getAlignAttribute(gcell))

                appliedClassName = ""
                #if(not gcell.getValue('CellMetadata') and  not gcell.getValue('Branch')):
                if gcell.getValue('WidgetType') is None:
                    appliedClassName = self.getJSTLClass(gcell)

                if overrideCascadePerm == True:
                    strBuffer.append(" {if permission > 0.5}")
                    strBuffer.append(" class='"+sysClassName+" ${getPermBasedStyle(permission, '"+appliedClassName+"', '"+self.getReadOnlyStyle(gcell)+"')}'")
                    strBuffer.append(">\n")
                    strBuffer.append(self.getJstlCell(gv, gcell, serializeTable, overrideCascadePerm)+"\n")
                    strBuffer.append("{else}")
                    strBuffer.append(">")
                    strBuffer.append("{/if}\n")
                else:
                    strBuffer.append(" class='"+sysClassName+" "+appliedClassName+"'")
                    strBuffer.append(">\n")
                    strBuffer.append(self.getJstlCell(gv, gcell, serializeTable, overrideCascadePerm)+"\n")

                strBuffer.append("</td>\n")
                #since we are avoiding getting var permission = permit before every td, should not affect the permission of next td
                if overrideCascadePerm:
                    strBuffer.append("{var permission = permit}\n")
        strBuffer.append("</tr>\n")
        return ''.join(strBuffer)

    def getJstlCell(self, gv, gcell, serializeTable, isCascadePerm):
        strBuffer = list()
        customProperty = "data-id='${instance.getValue(\"SheetId\")}'"
        if gcell.getValue('WidgetType') and gcell.getValue('CellMetadata'):
            cellmeta = self.session.get(gcell.getValue('CellMetadata'),self.CellMetadata)
            if gcell.getValue('Command') == 'create' or gcell.getValue('Command') == 'createupdate':
                customProperty += " data-path='${refCreateUrl}'"
                customProperty += self.isSend(gcell, True)
                refcell = self.session.get(gcell.getValue('CellMetadata'),self.CellMetadata)
                refcellsheetmeta = self.session.get(refcell.getValue('SheetMetadata'),self.SheetMetadata)
                #via many to one refcell - creation of parent
                if(gcell.getValue('Command') == 'createupdate'):
                    refcellsheetmeta = self.session.get(refcell.getValue('ReferredSheetMetadata'),self.SheetMetadata)
                    strBuffer.append("{var refCreateUrl = \"/"+refcell.getValue("CellName")+"\"}\n")
                else:
                    strBuffer.append("{var refCreateUrl = \"/"+refcell.getValue("CellName")+"/"+refcellsheetmeta.getSheetName()+"\"}\n")
                widget = str(gcell.getValue('WidgetType'))
                className = self.getJSTLClass(gcell)
                if gcell.getValue('WidgetType') == 'button':
                    strBuffer.append("<input type='button' id='add_"+refcell.getValue("CellName")+"' value='"+self.encodeValue(self.getPropertyValue(gcell,'Caption'))+"' class='"+widget+" "+className+"' "+customProperty+" {if permission==1} disabled {/if}")
                    strBuffer.append(" onclick='${id}.create(this)'/>")
                else:
                    strBuffer.append("<a href='javascript:void(0);' id='add_"+refcell.getValue("CellName")+"' "+customProperty+" onclick=\"{if permission!=1}${id}.create(this){/if}\">")
                    strBuffer.append("<img class='"+widget+" "+className+"' src='"+self.getPropertyValue(gcell,'src')+"'/>")
                    strBuffer.append("</a>")
            elif gcell.getValue('Command') == 'import':
                customProperty += " data-path='${refImportUrl}'"
                refcell = self.session.get(gcell.getValue('CellMetadata'),self.CellMetadata)
                refcellsheetmeta = self.session.get(refcell.getValue('SheetMetadata'),self.SheetMetadata)
                strBuffer.append("{var refImportUrl = \"/"+refcell.getValue("CellName")+"/"+refcellsheetmeta.getSheetId()+"\"}\n")
                strBuffer.append("<input type='file' id='"+gcell.getSheetId()+"' name='uploadedfile' "+customProperty+" onchange='${id}.csvimport(this)' {if permission==1} disabled {/if}/>")
                self.importMappingTable[gcell.getSheetId()] = self.getImportPropertyDict(gcell)
            elif(gcell.getValue('WidgetType') == 'button' or gcell.getValue('WidgetType') == 'image' or gcell.getValue('WidgetType') == 'checkboxparamcopy'):
                targetCellName=None
                rhsCellMetadata = self.getPropertyValue(gcell,'Value','RHSCellMetadata')
                if rhsCellMetadata and len(rhsCellMetadata) > 0:
                    targetCellName=self.session.get(rhsCellMetadata,self.CellMetadata).getValue('CellName')

                cellName = cellmeta.getValue('CellName')
                paramType = self.getPropertyValue(gcell,'Value','ParamType')
                widget = str(gcell.getValue('WidgetType'))
                caption = self.encodeValue(self.getPropertyValue(gcell,'Caption'))
                className = self.getJSTLClass(gcell)

                if targetCellName is not None:
                    if paramType == "Cell":
                        strBuffer.append("{var insValue=instance.getValue('"+cellName+"')}\n")
                        strBuffer.append("{var finalValue=instance.getValue('"+targetCellName+"')}\n")
                    elif paramType == 'ContextFrom':
                        strBuffer.append("{var insValue=instance.getValue('"+cellName+"')}\n")
                        strBuffer.append("{var finalValue=getRoot().getValue('"+targetCellName+"')}\n")
                    elif paramType == 'ContextTo':
                        strBuffer.append("{var insValue=getRoot().getValue('"+targetCellName+"')}\n")
                        strBuffer.append("{var finalValue=instance.getValue('"+cellName+"')}\n")
                        cellName = targetCellName
                        customProperty = "data-id='${getRoot().getValue(\"SheetId\")}'"
                else:
                    strBuffer.append("{var insValue=instance.getValue('"+cellName+"')}\n")
                    strBuffer.append("{var finalValue='"+self.getPropertyValue(gcell,'Value')+"'}\n")

                customProperty += self.isCellSend(gcell, cellmeta)
                if widget == "button":
                    strBuffer.append("<input type='button' id='"+caption+"' class='"+widget+" "+className+"' name='"+caption+"' value='"+caption+"' "+customProperty+" {if permission==1} disabled {/if}")
                    strBuffer.append("onclick = \"${id}.update(this,{'"+cellName+"':'${finalValue}'});\"/>")
                elif widget == "image":
                    strBuffer.append("<a href='javascript:void(0);' id='"+cellName+"' "+customProperty+" onclick=\"{if permission!=1}${id}.update(this, {'"+cellName+"':'${finalValue}'});{/if}\">")
                    strBuffer.append("<img class='"+widget+" "+className+"' src='"+self.getPropertyValue(gcell,'src')+"'/>")
                    strBuffer.append("</a>")
                elif widget == "checkboxparamcopy":
                    strBuffer.append("<input type = 'checkbox' id='"+cellName+"' class='"+widget+" "+className+"' "+customProperty+" {if finalValue==insValue} checked {/if} onclick = \"${id}.updateCheckboxParamCopy(this,'"+cellName+"','${finalValue}');\" {if permission==1} disabled {/if} />")
            else:
                widget = gcell.getValue('WidgetType')
                className = self.getJSTLClass(gcell)
                strBuffer.append(self.getWidgetStr(cellmeta, widget, className, gcell))
        else:
            gridView_gridCell_refCell = self.GridView.getPublicCellMetadata('GridCell')
            nestedGridViewList = self.session.getList(gcell,gridView_gridCell_refCell)
            if(gcell.getValue('GridView')):
                publicGrid = self.session.get(gcell.getValue('GridView'),self.GridView)
                self.getJstlTable(publicGrid, serializeTable, isCascadePerm);
                strBuffer.append("\n${"+self.getMacroName(publicGrid)+"(instance, permission, relationUrl)}\n")
            elif len(nestedGridViewList) > 0:
                for nestedGrid in nestedGridViewList:
                    self.getJstlTable(nestedGrid, serializeTable, isCascadePerm);
                    strBuffer.append("\n${"+self.getMacroName(nestedGrid)+"(instance, permission, relationUrl)}\n")
            elif(gcell.getValue('Section')):
                section = self.session.get(gcell.getValue('Section'),self.Section)
                strBuffer.append(self.getJstlSection(section))
            elif(gcell.getValue('Branch')):
                caption = self.encodeValue(self.getPropertyValue(gcell,'Caption'))
                branch = self.session.get(gcell.getValue('Branch'),self.Branch)
                widget = str(gcell.getValue('WidgetType'))
                className = self.getJSTLClass(gcell)
                if len(caption) <= 0:
                    caption = self.encodeValue(branch.getSheetName())

                status = self.getPropertyValue(gcell,'Status')
                target = self.getPropertyValue(gcell,'Target')
                if target == "URL":
                    target = self.getPropertyValue(gcell,'Target','ValueDescription')
                validate = self.getPropertyValue(gcell,'Validate')

                customProperty += self.isSend(gcell, True)

                if status:
                    customProperty += " data-status='"+status+"'"
                if target:
                    customProperty += " data-target='"+target+"'"

                if validate == 'Yes':
                    customProperty += " data-validate='true'"
                    excludeContainerJsonStr = self.getExcludeContainerDict(gcell)
                    if excludeContainerJsonStr:
                        customProperty += " data-exclude='"+excludeContainerJsonStr+"'"

                if gcell.getValue('WidgetType') == 'button':
                    strBuffer.append("<input type='button' id='"+branch.getSheetName()+"_"+caption+"' name='"+branch.getSheetName()+"' value='"+caption+"' class='"+widget+" "+className+"' "+customProperty+" {if permission==1} disabled {/if} ")
                    strBuffer.append("onclick = \"${id}.invoke(this)\"/>")
                else:
                    strBuffer.append("<a href='javascript:void(0);' id='"+branch.getSheetName()+"_"+caption+"' name='"+branch.getSheetName()+"' value='"+caption+"' "+customProperty+" onclick=\"{if permission!=1}${id}.invoke(this);{/if}\">")
                    strBuffer.append("<img class='"+widget+" "+className+"' src='"+self.getPropertyValue(gcell,'src')+"' />")
                    strBuffer.append("</a>")

                self.actionMappingTable[branch.getSheetName()+"~"+caption] = branch.getSheetId()
            elif(gcell.getValue('GotoBranch')):
                className = self.getJSTLClass(gcell)
                formName = ''
                if gcell.getValue('GotoGridView'):
                    gridView = self.session.get(gcell.getValue('GotoGridView'),self.GridView)
                    formName = gridView.getValue('SheetName')
                branch = self.session.get(gcell.getValue('GotoBranch'), self.Branch)
                statusCellName = "Status"
                if branch.getValue('NodeType') != 'Workflow':
                    statusCellName = branch.getSheetId()+"_Status"
                strBuffer.append("<img src='"+self.getPropertyValue(gcell,'src')+"' id="+formName+" class='image "+className+"' {if permission!=1} onclick=\"window.open('${getGotoLinkUrl(instance, '"+statusCellName+"','"+formName+"')}','_self')\"{/if}/>")
            elif(gcell.getValue('Command') == 'save'):
                widget = str(gcell.getValue('WidgetType'))
                className = self.getJSTLClass(gcell)
                status = self.getPropertyValue(gcell,'Status')
                target = self.getPropertyValue(gcell,'Target')
                if target == "URL":
                    target = self.getPropertyValue(gcell,'Target','ValueDescription')
                validate = self.getPropertyValue(gcell,'Validate')

                customProperty += self.isSend(gcell, True)

                if status:
                    customProperty += " data-status='"+status+"'"
                if target:
                    customProperty += " data-target='"+target+"'"

                if validate == 'Yes':
                    customProperty += " data-validate='true'"
                    excludeContainerJsonStr = self.getExcludeContainerDict(gcell)
                    if excludeContainerJsonStr:
                        customProperty += " data-excludeContainer='"+excludeContainerJsonStr+"'"

                if gcell.getValue('WidgetType') == 'button':
                    strBuffer.append("<input type='button' id='save_${instance.getValue(\"SheetId\")}' value='"+self.encodeValue(self.getPropertyValue(gcell,'Caption'))+"' class='"+widget+" "+className+"' "+customProperty+" {if permission==1} disabled {/if}")
                    strBuffer.append(" onclick='${id}.save(this)'/>")
                else:
                    strBuffer.append("<a href='javascript:void(0);' id='save_${instance.getValue(\"SheetId\")}' "+customProperty+" onclick=\"{if permission!=1}${id}.save(this);{/if}\">")
                    strBuffer.append("<img class='"+widget+" "+className+"' src='"+self.getPropertyValue(gcell,'src')+"' />")
                    strBuffer.append("</a>")
            elif(gcell.getValue('Command') == 'delete'):
                customProperty += " data-path='${relationUrl}'"
                customProperty += self.isSend(gcell, True)
                widget = str(gcell.getValue('WidgetType'))
                className = self.getJSTLClass(gcell)
                if gcell.getValue('WidgetType') == 'button':
                    strBuffer.append("<input type='button' id='delete' value='"+self.encodeValue(self.getPropertyValue(gcell,'Caption'))+"' class='"+widget+" "+className+"' "+customProperty+" {if permission==1} disabled {/if}")
                    strBuffer.append(" onclick='${id}.remove(this)'/>")
                else:
                    strBuffer.append("<a href='javascript:void(0);' id='delete' "+customProperty+" onclick=\"{if permission!=1}${id}.remove(this){/if}\">")
                    strBuffer.append("<img class='"+widget+" "+className+"' src='"+self.getPropertyValue(gcell,'src')+"' {if permission==1} disabled {/if}/>")
                    strBuffer.append("</a>")
            elif(gcell.getValue('Command') == 'attachment'):
                strBuffer.append("{if instance.getValue('Attachment')}\n")
                strBuffer.append("<a href='${getAttachmentUrl(instance)}/attachment' id='attach' target='_blank' title='Download [${instance.getValue('Attachment')}]'>${instance.getValue('Attachment')}</a>\n")
                strBuffer.append("{elseif selectedAttachment==instance.getValue('SheetId')}\n")
                strBuffer.append("<input type='file' id='attach_${instance.getValue(\"SheetId\")}' name='uploadedfile' "+customProperty+" onchange='${id}.updateAttach(this)'/>")
                strBuffer.append("{else}\n")
                strBuffer.append("<a href='javascript:void(0);' id='attach' title='Attach a file' {if permission != 1}onclick=\"${id}.setSelectedAttachment('${instance.getValue('SheetId')}')\"{/if}>[Attach]</a>\n")
                strBuffer.append("{/if}\n")
            elif(gcell.getValue('Command') == 'reattach'):
                strBuffer.append("{if instance.getValue('Attachment')}\n")
                strBuffer.append("{if (selectedAttachment==instance.getValue('SheetId'))}\n")
                strBuffer.append("<input type='file' id='reattach' name='uploadedfile' "+customProperty+" onchange='${id}.updateAttach(this)'/>\n")
                strBuffer.append("{else}\n")
                strBuffer.append("<a href='javascript:void(0);' id='reattach' onclick=\"${id}.setSelectedAttachment('${instance.getValue('SheetId')}')\">[ReAttach]</a>\n")
                strBuffer.append("{/if}\n")
                strBuffer.append("{/if}\n")
            elif(gcell.getValue('Command') == 'removeAttach'):
                strBuffer.append("{if instance.getValue('Attachment')}\n")
                strBuffer.append("<a href='javascript:void(0);' id='removeattach' title='Remove Attachment' "+customProperty+" onclick=\"${id}.removeAttach(this)\">[Remove]</a>\n")
                strBuffer.append("{/if}\n")
            elif gcell.getValue('CellValue'):
                strBuffer.append(gcell.getValue('CellValue'))
            else:
                strBuffer.append("")
        return ''.join(strBuffer)

    def getWidgetStr(self, cellmeta, widget, className, gcell=None):
        strBuffer = list()
        customProperty = "data-id='${instance.getValue(\"SheetId\")}'"
        format = self.getCellFormat(cellmeta)
        cellName = cellmeta.getValue('CellName')
        category = "Number" #"Category002"
        if format.__contains__('dd'):
            category = "Date" #"Category005"
            #because jquery ui datepicker supports only space AM/PM
            format = format.replace("mma", "mm a")
        elif format.__contains__('hh:') or format.__contains__('HH:') or format.__contains__('h:'):
            category = "Time" #"Category006"
            #to follow consistent begaviour for
            format = format.replace("sa", "s a")
        elif format == 'Boolean' or format=='Yes/No' or format=='True/False':
            category = "Boolean" #"Category011"
        elif not format.__contains__('#'):
            category = "Text" #"Category010"

        #since we need validation attribute only for checked 'option button' we seperated validation attribute form custom property and added this new property called validationProperty.
        validationProperty = ""
        #adding format part of widget
        customProperty += " data-format='"+format+"'"

        if gcell is not None:
            #for textbox submit on dependancy is removed
            if widget == "textbox":
                customProperty += self.isSend(gcell)
            else:
                customProperty += self.isCellSend(gcell, cellmeta)

            if cellmeta.getValue('TextLength'):
                maxlength = str(cellmeta.getValue('TextLength'))
                customProperty += " maxlength = "+maxlength
            if cellmeta.getValue('RegExp'):
                pattern = urlDecode(cellmeta.getValue('RegExp'))
                validationProperty += " pattern = '"+pattern+"'"

            validation_gridCell_refCell = self.Validation.getPublicCellMetadata('GridCell')
            validationList = self.session.getList(gcell, validation_gridCell_refCell)
            validationList.sort(lambda x, y: cmp(x.getValue('CreatedAt'), y.getValue('CreatedAt')))
            validationTypeMapping = dict()
            for validation in validationList:
                errorType = validation.getValue('ErrorType')
                if errorType:
                    validtionFuncStr = self.getValidationJstl(gcell, widget, format, validation)
                    self.validationMapping["validation_"+validation.getSheetId()] = validtionFuncStr

                    errorType = validation.getValue('ErrorType')
                    if validationTypeMapping.__contains__(errorType):
                        validationTypeMapping[errorType] += ", validation_"+validation.getSheetId()
                    else:
                        validationTypeMapping[errorType] = "validation_"+validation.getSheetId()
                if validation.getValue('InputMessage'):
                    customProperty += " title ="+self.getValidationValue(validation,'InputMessage')

            for val in validationTypeMapping:
                if val == "Stop":
                    validationProperty += " data-error = '["+validationTypeMapping[val]+"]'"
                elif val == 'Warning':
                    validationProperty += " data-warning = '["+validationTypeMapping[val]+"]'"
                elif val == 'Information':
                    validationProperty += " data-info = '["+validationTypeMapping[val]+"]'"
            if len(validationProperty) > 0:
                if gcell.getValue('ValidationOnReadOnly'):
                    validationProperty = " {if permission >=1}" + validationProperty + " {/if}"
                else:
                    validationProperty = " {if permission>1 }" + validationProperty + " {/if}"
        customProperty += " data-actualValue = '${actualValue}'"
        strBuffer.append("{var actualValue = instance.getValue('"+cellName+"')}\n")
        strBuffer.append("{var dispValue = instance.getDisplayValue('"+cellName+"','"+format+"','"+category+"')}\n")
        if widget == 'label' or widget == 'hidden':
            strBuffer.append("<div id='"+cellName+"' class='"+widget+" "+className+ "' name='"+cellName+"' "+customProperty+validationProperty+" value='{if dispValue==0 || dispValue==\"\"}${dispValue|h}{else}${getEncodedValue(dispValue)}{/if}' >")
            strBuffer.append("{if dispValue==0 || dispValue==\"\"}${dispValue|h}{else}${getEncodedValue(dispValue)}{/if}")
            strBuffer.append("</div>")
        elif widget == 'textbox' :
            strBuffer.append("<input ")
            if format == "Password":
                strBuffer.append("type='password' id='"+cellName+"'")
            elif category == "Date":
                widget = widget+" calendar"
                if format.__contains__('hh:') or format.__contains__('HH:') or format.__contains__('h:'):
                    strBuffer.append("type='text' id='"+cellName+"_${instance.getValue(\"SheetId\")}' data-type='datetime' ")
                else:
                    strBuffer.append("type='text' id='"+cellName+"_${instance.getValue(\"SheetId\")}' data-type='date'")
            else:
                strBuffer.append("type='text' id='"+cellName+"'")
            strBuffer.append(" class='"+self.getAlignStyleName(gcell)+" "+widget+" "+className+"' name='"+cellName+"' "+customProperty+validationProperty+" {if permission==1} disabled {/if} value='{if dispValue==0 || dispValue==\"\"}${dispValue|h}{else}${getEncodedValue(dispValue)}{/if}' onchange='${id}.update(this)'/>")
        elif widget == 'combobox':
            advanceSearchFormName = self.getAdvanceSearchFormName(cellmeta)
            if advanceSearchFormName:
                strBuffer.append("<table cellspacing=0 cellpadding=0 width='100%' height='100%'>\n<tr>\n<td height='100%'>\n")
            strBuffer.append("<input type='text' id='"+cellName+"' name='"+cellName+"' class='"+widget+" "+className+"' "+customProperty+validationProperty+" {if permission==1} disabled {/if} ")
            rangeValList = self.getRangeValueList(cellmeta)
            if rangeValList:
                staticListValue = list()
                staticListValue.append("{'label':'None','idval':''}")
                for rangeValue in rangeValList:
                    if len(staticListValue) > 0:
                        staticListValue.append(",")
                    staticListValue.append("{'label':'")
                    staticListValue.append(rangeValue)
                    staticListValue.append("',")
                    staticListValue.append("'idval':'")
                    staticListValue.append(rangeValue)
                    staticListValue.append("'}")
                strBuffer.append("value='{if actualValue == \"\"}None{else}${getEncodedValue(dispValue)}{/if}' data-staticlist=\"["+"".join(staticListValue)+"]\" onclick='${id}.showList(this)'")
            elif category == 'Boolean':
                if  format=='Yes/No':
                    strBuffer.append("value='${getEncodedValue(dispValue)}' data-staticlist=\"[{'label':'Yes','idval':1.0},{'label':'No','idval':0.0}]\" onclick='${id}.showList(this)'")
                elif format=='True/False':
                    strBuffer.append("value='${getEncodedValue(dispValue)}' data-staticlist=\"[{'label':'True','idval':1.0},{'label':'False','idval':0.0}]\" onclick='${id}.showList(this)'")
            elif self.isDependancyRef(cellmeta):
                strBuffer.append("value='{if actualValue == \"\"}None{else}${getEncodedValue(dispValue)}{/if}' data-depandancylist onclick='${id}.showList(this)'")
            else:
                strBuffer.append("value='{if actualValue == \"\"}None{else}${getEncodedValue(dispValue)}{/if}' onclick='${id}.dynamicSearch(this)'")
            strBuffer.append("/>")

            if advanceSearchFormName:
                strBuffer.append("</td>\n")
                strBuffer.append("<td style='width: 16px'>\n")
                strBuffer.append("<img src='/runtime/images/advance_search.png' onclick=\"window.open('${getAdvanceSearchUrl(\'"+cellmeta.getValue('CellName')+"\',relationUrl)}?mimetype=text/html&form="+advanceSearchFormName+"&theme=off','AdvanceSearch','width=500,height=300,resizable=yes,scrollbars=yes')\"\n")
                strBuffer.append("</td>\n</tr>\n</table>\n")

        elif widget == 'optionbutton':
            rangeValList = self.getRangeValueList(cellmeta)
            if rangeValList:
                strBuffer.append("<table cellspacing='0' cellpadding='0' class='autowidth'>\n")
                strBuffer.append("<tr>\n")
                for rangeValue in rangeValList:
                    strBuffer.append("<td>")
                    strBuffer.append("<input type='radio' id='"+cellName+"' name='"+cellName+"_${instance.getValue(\"SheetId\")}' class='"+widget+" "+className+"' "+customProperty+" {if permission==1} disabled {/if}")
                    strBuffer.append(" value='${getEncodedValue('"+rangeValue+"')}' {if actualValue == '"+rangeValue+"'}"+validationProperty+" checked{/if} onclick=\"${id}.update(this, {'"+cellName+"': this.value})\">")
                    strBuffer.append(rangeValue)
                    strBuffer.append("</input>\n")
                    strBuffer.append("</td>\n")
                strBuffer.append("</tr>\n")
                strBuffer.append("</table>\n")
            elif  format == 'Boolean' or format=='Yes/No' or format=='True/False':
                strBuffer.append("<input type = 'radio' id='"+cellName+"' name='"+cellName+"_${instance.getValue(\"SheetId\")}' class='"+widget+" "+className+"' "+customProperty+" {if permission==1} disabled {/if}")
                strBuffer.append(" value='1' {if actualValue==1}"+validationProperty+" checked {/if} onclick=\"${id}.update(this, {'"+cellName+"': parseValue(this.value, '"+format+"')})\">")
                if format == 'Boolean' or format=='Yes/No':
                    strBuffer.append("Yes")
                else:
                    strBuffer.append("True")
                strBuffer.append("</input>\n")

                strBuffer.append("<input type = 'radio' id='"+cellName+"' name='"+cellName+"_${instance.getValue(\"SheetId\")}' class='"+widget+" "+className+"' "+customProperty+" {if permission==1} disabled {/if}")
                strBuffer.append(" value='0' {if actualValue!=1}"+validationProperty+" checked {/if} onclick=\"${id}.update(this, {'"+cellName+"': parseValue(this.value, '"+format+"')})\">")
                if format == 'Boolean' or format=='Yes/No':
                    strBuffer.append("No")
                else:
                    strBuffer.append("False")
                strBuffer.append("</input>\n")
        elif widget == 'checkbox':
            if  format == 'Boolean' or format=='Yes/No' or format=='True/False':
                strBuffer.append("<input type = 'checkbox' id='"+cellName+"' name='"+cellName+"' class='"+widget+" "+className+"' "+customProperty+validationProperty+" {if permission==1} disabled {/if}")
                strBuffer.append(" value='${actualValue}' {if actualValue==1} checked {/if} onclick=\"${id}.update(this, {'"+cellName+"': parseValue(this.checked)})\"/>")
        elif widget == 'textarea':
            strBuffer.append("<textarea id='"+cellName+"' name='"+cellName+"' class='"+self.getAlignStyleName(gcell)+" "+widget+" "+className+"' "+customProperty+validationProperty+" {if permission==1} disabled {/if}")
            strBuffer.append(" onchange='${id}.update(this)'>")
            strBuffer.append("${actualValue}")
            strBuffer.append("</textarea>")
        else:
            strBuffer.append("${actualValue}")
        return ''.join(strBuffer)

    def getJstlSection(self,section):
        strBuffer = list()
        strBuffer.append("<table border=0 cellpadding=0 cellspacing=0>\n")
        shmd = self.session.get(section.getValue("SheetMetadata"),self.SheetMetadata)
        sheet_row_refCell = self.RowMetadata.getPublicCellMetadata('SheetMetadata')
        row_cell_refCell = self.CellMetadata.getPublicCellMetadata('RowMetadata')
        srows = self.session.getList(shmd, sheet_row_refCell)
        srows.sort(lambda x, y: cmp(x.getValue('RowNumber'), y.getValue('RowNumber')))
        sfrom = self.session.get(section.getValue("From"),self.CellMetadata)
        sto = self.session.get(section.getValue("To"),self.CellMetadata)
        for srow in srows:
            if(srow.getValue('RowNumber') >= sfrom.getValue('RowNumber') and srow.getValue('RowNumber') <= sto.getValue('RowNumber')):
                strBuffer.append("<tr>\n")
                scells = self.session.getList(srow, row_cell_refCell)
                scells.sort(lambda x, y: cmp(x.getValue('ColumnNumber'), y.getValue('ColumnNumber')))
                for scell in scells:
                    if(scell.getValue('ColumnNumber') >= sfrom.getValue('ColumnNumber') and scell.getValue('ColumnNumber') <= sto.getValue('ColumnNumber')):
                        strBuffer.append("<td")
                        if(scell.getValue('ColumnSpanned')):
                            strBuffer.append(" colspan="+str(int(scell.getValue('ColumnSpanned'))))
                        if(scell.getValue('RowSpanned')):
                            strBuffer.append(" rowspan="+str(int(scell.getValue('RowSpanned'))))


                        sysClassName = self.getSystemClass(scell.getValue('FinalHeight'), scell.getValue('FinalWidth'))
                        stylestr = ""
                        if scell.getValue("Style"):
                            stylestr += " "+self.getStyleName(scell.getValue("Style"))
                        elif scell.getValue('GlobalStyle'):
                            stylestr += " "+scell.getValue('GlobalStyle')
                        widget = "";
                        if(scell.getValue('CellName')):
                            strBuffer.append(" class='"+sysClassName+"'>\n")
                            formula_cell_refCell = self.Formula.getPublicCellMetadata('CellMetadata')
                            formulaList = self.session.getList(scell, formula_cell_refCell)
                            if(len(formulaList) > 0):
                                widget = "label";
                            elif(scell.getValue("ReferredSheetMetadata")):
                                widget = "combobox";
                            else:
                                widget = "textbox";
#                            searchDefList = self.session.getList(scell,self.SearchDefinition.getPublicCellMetadata("CellMetadata"))
#                            advanceSearchId = ""
#                            if len(searchDefList) > 0:
#                                searchDef = searchDefList.pop()
#                                if searchDef.getValue('GridView'):
#                                    advanceSearchId = searchDef.getValue('GridView')
#                            textlength = 0
#                            if scell.getValue('TextLength'):
#                                textlength=scell.getValue('TextLength')
                            strBuffer.append(self.getWidgetStr(scell, widget, stylestr))
                        else:
                            strBuffer.append(" class='"+sysClassName+" "+stylestr+"'")
                            strBuffer.append(">\n")
                            if(scell.getValue('CellValue')):
                                cellValue = scell.getValue('CellValue')
                                if isinstance(cellValue,str) or isinstance(cellValue,unicode):
                                    strBuffer.append(cellValue)
                                else:
                                    strBuffer.append(str(cellValue))
                        strBuffer.append("</td>\n")
                strBuffer.append("</tr>\n")
        strBuffer.append("</table>\n")
        return ''.join(strBuffer)


# ****************************************************  criteria serialization methods ******************************************************

    def getExcludeContainerDict(self, gCell):
        strBuffer = list()
        excludeValidationGrid_gridCell_refCell = self.ExcludeValidationGrid.getPublicCellMetadata('GridCell')
        includeValidationGrid_excludeValidationGrid_refCell = self.IncludeValidationGrid.getPublicCellMetadata('ExcludeValidationGrid')
        excludeValidationList = self.session.getList(gCell, excludeValidationGrid_gridCell_refCell)
        if len(excludeValidationList) > 0:
            strBuffer.append('{"exclude-block":{')
            excludeValidationList.sort(lambda x, y: cmp(x.getValue('CreatedAt'), y.getValue('CreatedAt')))
            for excludeValidation in excludeValidationList:
                strBuffer.append(write(excludeValidation.getValue('GridView')))
                strBuffer.append(":{")
                includeValidationList = self.session.getList(excludeValidation, includeValidationGrid_excludeValidationGrid_refCell)
                if len(includeValidationList) > 0:
                    strBuffer.append('"include-block":{')
                    for includeValidation in includeValidationList:
                        strBuffer.append(write(includeValidation.getValue('GridView')))
                        strBuffer.append(":{}")
                        strBuffer.append(",")
                    strBuffer.pop()
                    strBuffer.append("}")
                strBuffer.append("}")
                strBuffer.append(",")
            strBuffer.pop()
            strBuffer.append("}}")
            return ''.join(strBuffer)

    def getSystemClass(self, finalHeight, finalWidth):
        height=width="0"
        if finalHeight:
            height = str(int(float(finalHeight)))
        if finalWidth:
            width= str(int(float(finalWidth)))
        if not self.styleMapping.__contains__("h"+height):
            propDict = dict()
            propDict['height'] = height+"px"
            self.styleMapping["h"+height] = propDict
        if not self.styleMapping.__contains__("w"+width):
            propDict = dict()
            propDict['width'] = width+"px"
            propDict['min-width'] = width+"px"
            self.styleMapping["w"+width] = propDict
        return "h"+height+" w"+width

    def getValidationJstl(self, gcell, widget, format, validation):
        strBuffer = list()
        strBuffer.append("function(elem, value, controller){\n")
        #when criteria in validation
        strBuffer.append("var instance = new DataObject(id, $(elem).attr('data-id'))\n")
        strBuffer.append("var errorMsg = "+self.getValidationValue(validation,'ErrorMessage')+"\n")
        if format != "Text" or widget == 'combobox':
            strBuffer.append("value = $(elem).attr('data-actualValue')\n")
        criteria_validation_refCell = self.Criteria.getPublicCellMetadata('Validation_When')
        validationCriteriaList = self.session.getList(validation,criteria_validation_refCell)
        if len(validationCriteriaList) > 0:
            strBuffer.append("var performValidation=false\n")
            criteriaCondStr = self.constructCriteria(validationCriteriaList[0])
            if(len(criteriaCondStr) > 0):
                strBuffer.append("if (")
                strBuffer.append(criteriaCondStr)
                strBuffer.append("){\n")
                strBuffer.append("performValidation = true\n")
                strBuffer.append("}\n")
        if len(validationCriteriaList):
            strBuffer.append("if (performValidation){\n")
        if validation.getValue('Criteria') == 'Text' or validation.getValue('Criteria') == 'Text_length':
            strBuffer.append("var validationLhsValue=value\n")
        else:
            strBuffer.append("var validationLhsValue=0 \n")
            strBuffer.append("if(value != null && value != \"\"){\n")
            strBuffer.append("validationLhsValue=parseFloat(value)\n")
            strBuffer.append("}\n")
        if validation.getValue('Criteria')  == 'Text_length':
            strBuffer.append("if (validationLhsValue != null){\n")
            strBuffer.append("validationLhsValue = validationLhsValue.length\n")
            strBuffer.append("}\n")
        if(validation.getValue('ParamType') is None or validation.getValue('ParamType') == "Value"):
            if validation.getValue('Operator') == 'between' or validation.getValue('Operator') == 'not_between':
                strBuffer.append("var validationMinimumValue = "+self.getValidationValue(validation,'Minimum')+"\n")
                strBuffer.append("var validationMaximumValue = "+self.getValidationValue(validation,'Maximum')+"\n")
            elif(validation.getValue('Criteria') == 'Text'):
                strBuffer.append("var validationRhsValue = "+self.getValidationValue(validation,'TextValue')+"\n")
            else:
                strBuffer.append("var validationRhsValue = "+self.getValidationValue(validation,'Value')+"\n")
        else:
            if validation.getValue('Operator') == 'between' or validation.getValue('Operator') == 'not_between':
                strBuffer.append("var validationMinimumValue = "+self.getValidationCellName(validation,'MinimumCellMetadata')+"\n")
                strBuffer.append("var validationMaximumValue = "+self.getValidationCellName(validation,'MaximumCellMetadata')+"\n")
            else:
                strBuffer.append("var validationRhsValue = "+self.getValidationCellName(validation,'ValueCellMetadata')+"\n")
        if validation.getValue('Operator') == 'between':
            strBuffer.append("if (validationLhsValue < validationMinimumValue || validationLhsValue > validationMaximumValue){\n")
            strBuffer.append("return errorMsg\n")
            strBuffer.append("}\n")
        elif validation.getValue('Operator') == 'not_between':
            strBuffer.append("if (validationLhsValue >= validationMinimumValue || validationLhsValue <= validationMaximumValue){\n")
            strBuffer.append("return errorMsg\n")
            strBuffer.append("}\n")
        elif validation.getValue('Operator') == 'equal_to':
            strBuffer.append("if (validationLhsValue != validationRhsValue){\n")
            strBuffer.append("return errorMsg\n")
            strBuffer.append("}\n")
        elif validation.getValue('Operator') == 'not_equal_to':
            strBuffer.append("if (validationLhsValue == validationRhsValue){\n")
            strBuffer.append("return errorMsg\n")
            strBuffer.append("}\n")
        elif validation.getValue('Operator') == 'greater_than':
            strBuffer.append("if (validationLhsValue <= validationRhsValue){\n")
            strBuffer.append("return errorMsg\n")
            strBuffer.append("}\n")
        elif validation.getValue('Operator') == 'less_than':
            strBuffer.append("if (validationLhsValue >= validationRhsValue){\n")
            strBuffer.append("return errorMsg\n")
            strBuffer.append("}\n")
        elif validation.getValue('Operator') == 'greater_than_or_equal_to':
            strBuffer.append("if (validationLhsValue < validationRhsValue){\n")
            strBuffer.append("return errorMsg\n")
            strBuffer.append("}\n")
        elif validation.getValue('Operator') == 'less_than_or_equal_to':
            strBuffer.append("if (validationLhsValue > validationRhsValue){\n")
            strBuffer.append("return errorMsg\n")
            strBuffer.append("}\n")

        if len(validationCriteriaList):
            strBuffer.append("}\n")
        strBuffer.append("}")
        return ''.join(strBuffer)

    def getDefaultConditionPermissionJstl(self, gcell):
        strBuffer = list()
        crieria_gridCell_visible = self.Criteria.getPublicCellMetadata('GridCell_Visible')
        crieria_gridCell_read = self.Criteria.getPublicCellMetadata('GridCell_Read')
        crieria_gridCell_write = self.Criteria.getPublicCellMetadata('GridCell_Write')

        visibleCriteriaList = self.session.getList(gcell,crieria_gridCell_visible)
        readCriteriaList = self.session.getList(gcell,crieria_gridCell_read)
        writeCriteriaList = self.session.getList(gcell,crieria_gridCell_write)

        if(len(visibleCriteriaList) > 0):
            strBuffer.append(self.constructConditionBasedPermission(visibleCriteriaList[0], 0.5))
        if(len(readCriteriaList) > 0):
            strBuffer.append(self.constructConditionBasedPermission(readCriteriaList[0], 1))
        if(len(writeCriteriaList) > 0):
            strBuffer.append(self.constructConditionBasedPermission(writeCriteriaList[0], 2))
        return ''.join(strBuffer)

    def getActivityConditionPermissionJstl(self, actperm):
        strBuffer = list()
        crieria_actPerm_visible = self.Criteria.getPublicCellMetadata('ActivityPermission_Visible')
        crieria_actPerm_read = self.Criteria.getPublicCellMetadata('ActivityPermission_Read')
        crieria_actPerm_write = self.Criteria.getPublicCellMetadata('ActivityPermission_Write')

        visibleCriteriaList = self.session.getList(actperm,crieria_actPerm_visible)
        readCriteriaList = self.session.getList(actperm,crieria_actPerm_read)
        writeCriteriaList = self.session.getList(actperm,crieria_actPerm_write)

        if(len(visibleCriteriaList) > 0):
            strBuffer.append(self.constructConditionBasedPermission(visibleCriteriaList[0], 0.5))
        if(len(readCriteriaList) > 0):
            strBuffer.append(self.constructConditionBasedPermission(readCriteriaList[0], 1))
        if(len(writeCriteriaList) > 0):
            strBuffer.append(self.constructConditionBasedPermission(writeCriteriaList[0], 2))
        return ''.join(strBuffer)

    def constructConditionBasedPermission(self,criteria,permissionType):
        criteriaCondStr = self.constructCriteria(criteria)
        strBuffer = list()
        if(len(criteriaCondStr) > 0):
            strBuffer.append("{elseif ")
            strBuffer.append(criteriaCondStr)
            strBuffer.append("}\n")
            strBuffer.append("{var permission = "+str(permissionType)+"}\n")
        return ''.join(strBuffer)

    def constructCriteria(self,criteria):
        strBuffer = list()
        strBuffer.append(self.constructCondition(criteria))
        criteria_criteria_refCell = self.Criteria.getPublicCellMetadata('Criteria')
        criteriaList = self.session.getList(criteria,criteria_criteria_refCell)
        for childCriteria in criteriaList:
            if criteria.getValue('AndOper'):
                strBuffer.append("&&")
            else:
                strBuffer.append("||")
            strBuffer.append(" ( ")
            strBuffer.append(self.constructCriteria(childCriteria))
            strBuffer.append(" ) ")
        return ''.join(strBuffer)

    def constructCondition(self, criteria):
        strBuffer = list()
        cond_criteria_refCell = self.Condition.getPublicCellMetadata('Criteria')
        conditionList = self.session.getList(criteria,cond_criteria_refCell)
        n = len(conditionList)
        for condition in conditionList:
            cellType=None
            if(n != len(conditionList)):
                if criteria.getValue('AndOper'):
                    strBuffer.append(" &&")
                else:
                    strBuffer.append(" ||")
            n = n - 1
            if condition.getValue('LHSCellMetadata'):
                lhsCellMetadata = self.session.get(condition.getValue('LHSCellMetadata'),self.CellMetadata)
                strBuffer.append(" instance.getValue('"+ str(lhsCellMetadata.getValue('CellName'))+"') ")
                cellType=lhsCellMetadata.getValue('IsStr')
            else:
                strBuffer.append(" '' ")
            strBuffer.append(condition.getValue('Operator'))
            if condition.getValue('RHSParamType') == 'Cell':
                if condition.getValue('RHSCellMetadata'):
                    rhsCellMetadata = self.session.get(condition.getValue('RHSCellMetadata'),self.CellMetadata)
                    strBuffer.append(" instance.getValue('"+rhsCellMetadata.getValue('CellName')+"') ")
                else:
                    strBuffer.append(" '' ")
            elif condition.getValue('RHSParamType') == 'PrivateCell':
                if condition.getValue('RHSPrivateCellMetadata'):
                    rhsCellMetadata = self.session.get(condition.getValue('RHSPrivateCellMetadata'),self.CellMetadata)
                    strBuffer.append(" instance.getValue('"+rhsCellMetadata.getValue('CellDisplayName')+"') ")
                else:
                    strBuffer.append(" '' ")
            else:
                if condition.getValue('RHSValue'):
                    rhsValue=condition.getValue('RHSValue')
                    if cellType and int(cellType)==1 :
                        if (rhsValue[0]=='"' and rhsValue[len(rhsValue)-1]=='"') or (rhsValue[0]=="'" and rhsValue[len(rhsValue)-1]=="'") :
                            strBuffer.append(rhsValue)
                        else:
                            strBuffer.append("'"+rhsValue+"'")
                    else:
                        strBuffer.append(rhsValue)
                else:
                    strBuffer.append(" '' ")
        return ''.join(strBuffer)

    def getPermissionJstl(self,permissionType,condPermJstl):
        strBuffer = list()
        strBuffer.append("{if 'equal' == 'not equal'}\n")
        if len(condPermJstl)>0:
            strBuffer.append(condPermJstl)
        if permissionType is not None:
            strBuffer.append("{else}")
            strBuffer.append("{var permission = "+str(permissionType)+"}\n")
        strBuffer.append("{/if}\n")
        return ''.join(strBuffer)

# ************************************************************** helper methods *************************************************************
    def getValidationValue(self, validation,propertyName):
        if validation.getValue(propertyName) is not None:
            return write(validation.getValue(propertyName))
        elif propertyName == 'Value' or propertyName == 'Minimum' or propertyName == 'Maximum':
            return "0"
        else:
            return "null"

    def getValidationCellName(self, validation,propertyName):
        if validation.getValue(propertyName):
            cellMetadata = self.session.get(validation.getValue(propertyName),self.CellMetadata)
            return "instance.getValue('"+cellMetadata.getValue('CellName')+"')"
        else:
            return "null"

    def getReadOnlyStyle(self, gcell):
        if gcell.getValue('ReadOnlyStyle'):
            return self.getStyleName(gcell.getValue('ReadOnlyStyle'))
        elif gcell.getValue('ReadOnlyGlobalStyle'):
            return gcell.getValue('ReadOnlyGlobalStyle')
        else:
            return self.getJSTLClass(gcell)

    def getJSTLClass(self, gcell):
        if gcell.getValue('Style'):
            return self.getStyleName(gcell.getValue('Style'))
        elif gcell.getValue('GlobalStyle'):
            return gcell.getValue('GlobalStyle')

        if gcell.getValue('CellMetadata'):
            cellmeta = self.session.get(gcell.getValue('CellMetadata'),self.CellMetadata)
            if cellmeta.getValue('Style'):
                return self.getStyleName(cellmeta.getValue('Style'))
            elif cellmeta.getValue('GlobalStyle'):
                return cellmeta.getValue('GlobalStyle')
        return ""

    def getStyleName(self, styleId):
        if styleId:
            return  self.session.get(styleId, self.Style).getSheetName().replace(" ","_") or ""
        return ""

    def getAlignStyleName(self, gcell):
        #this will be used if the gcell doesn't contain table, and in textbox and textarea widget
        alignStr = ""
        if gcell and gcell.getValue('VAlign'):
            alignStr += " v"+gcell.getValue('VAlign')
        if gcell and gcell.getValue('HAlign'):
            alignStr += " h"+gcell.getValue('HAlign')
        return alignStr

    def getAlignAttribute(self, gcell):
        #this will be used if the cell contains table
        alignStr = ""
        if gcell.getValue('VAlign'):
            alignStr += " valign='"+gcell.getValue('VAlign')+"'"
        if gcell.getValue('HAlign'):
            alignStr += " align='"+gcell.getValue('HAlign')+"'"
        return alignStr

    def isSend(self, gcell, default=False):
        if gcell.getValue('ForceUpdate') == 2:
            return ""
        elif gcell.getValue('ForceUpdate') == 1 or default:
            return " data-send='true' "
        return ""

    def isCellSend(self, gcell, cellmeta):
        node_cell_refCell = self.Node.getPublicCellMetadata('CellMetadata')
        nodeList = self.session.getList(cellmeta,node_cell_refCell)
        if len(nodeList) > 0:
            return self.isSend(gcell, True)
        return self.isSend(gcell, False)

    def getRangeValueList(self,cellmeta):
        if(cellmeta.getValue('Range')):
            range = self.session.get(cellmeta.getValue('Range'),self.Range)
            rangeValue_range_refCell = self.RangeValue.getPublicCellMetadata('Range')
            rangeValList = self.session.getList(range,rangeValue_range_refCell)
            rangeValList.sort(lambda x, y: cmp(x.getValue('CreatedAt'), y.getValue('CreatedAt')))
            return [rangeValue.getValue('Value') for rangeValue in rangeValList]

    def isDependancyRef(self, cellMeta):
        search_cell_refCell = self.SearchDefinition.getPublicCellMetadata('CellMetadata')
        searchList = self.session.getList(cellMeta, search_cell_refCell)
        if len(searchList) > 0:
            searchDef = searchList.pop()
            parentRefCell = searchDef.getValue('ParentReferenceCell')
            searchRefCell = searchDef.getValue('SearchReferenceCell')
            if parentRefCell and searchRefCell:
                return True
        return False


    def getPropertyValue(self, gcell, attrName, paramName='StaticValue'):
        prop_gridCell_refCell = self.Property.getPublicCellMetadata('GridCell')
        propertyList = self.session.getList(gcell,prop_gridCell_refCell)
        for property in propertyList:
            if(property.getValue('AttributeName') == attrName):
                return property.getValue(paramName) or ""
        return ''

    def hasGridView(self,gcell):
        if gcell.getValue('GridView'):
            return True;
        else:
            gridView_gridCell_refCell = self.GridView.getPublicCellMetadata('GridCell')
            gridViewList = self.session.getList(gcell,gridView_gridCell_refCell)
            if len(gridViewList) > 0:
                return True
        return False

    def getCellFormat(self, cellmeta):
        format = "#,###"
        if cellmeta.getValue('FinalFormat'):
            format = cellmeta.getValue('FinalFormat')
        return str(format)

    def getImportPropertyDict(self,gcell):
        prop_gridCell_refCell = self.Property.getPublicCellMetadata('GridCell')
        propertyList = self.session.getList(gcell,prop_gridCell_refCell)
        importDict = dict()
        for property in propertyList:
            if property.getValue('AttributeName') == 'import':
                if property.getValue('LHSCellMetadata'):
                    propertyDict = dict()
                    if property.getValue('StaticValue'):
                        propertyDict['CSVColumn'] = property.getValue('StaticValue')
                    if property.getValue('IsNatural'):
                        propertyDict['IsNaturalKey'] = property.getValue('IsNatural')
                    if property.getValue('Category'):
                        propertyDict['Category'] = property.getValue('Category')
                    if property.getValue('Format'):
                        propertyDict['Format'] = property.getValue('Format')
                    if property.getValue('RHSCellMetadata'):
                        propertyDict['OneToManyReference'] = property.getValue('RHSCellMetadata')
                    importDict[property.getValue('LHSCellMetadata')] = propertyDict
        return importDict

    def getAdvanceSearchFormName(self,cellMeta):
        cell_search_refCell = self.SearchDefinition.getPublicCellMetadata('CellMetadata')
        searchDefList = self.session.getList(cellMeta,cell_search_refCell)
        if len(searchDefList) > 0:
            searchDef = searchDefList.pop()
            if searchDef.getValue('GridView'):
                gridView = self.session.get(searchDef.getValue('GridView'), self.GridView)
                return gridView.getValue("SheetName")
