## @file
# This file is used to define class objects of INF file [Packages] section. 
# It will consumed by InfParser. 
#
# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials are licensed and made available 
# under the terms and conditions of the BSD License which accompanies this 
# distribution. The full text of the license may be found at 
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

'''
InfPackageObject
'''

from Logger import StringTable as ST
from Logger import ToolError
import Logger.Log as Logger
from Library import GlobalData 

from Library.Misc import Sdict
from Library.ParserValidate import IsValidPath
from Library.ExpressionValidate import IsValidFeatureFlagExp 

class InfPackageItem():
    def __init__(self, 
                 PackageName = '',
                 FeatureFlagExp = '',
                 HelpString = ''):
        self.PackageName    = PackageName
        self.FeatureFlagExp = FeatureFlagExp
        self.HelpString     = HelpString
        self.SupArchList    = []
        
    def SetPackageName(self, PackageName):
        self.PackageName = PackageName
    def GetPackageName(self):
        return self.PackageName
    
    def SetFeatureFlagExp(self, FeatureFlagExp):
        self.FeatureFlagExp = FeatureFlagExp
    def GetFeatureFlagExp(self):
        return self.FeatureFlagExp
    
    def SetHelpString(self, HelpString):
        self.HelpString = HelpString
    def GetHelpString(self):
        return self.HelpString
    
    def SetSupArchList(self, SupArchList):
        self.SupArchList = SupArchList
    def GetSupArchList(self):
        return self.SupArchList

            
## INF package section
#
#
#
class InfPackageObject():
    def __init__(self):
        self.Packages = Sdict()
        #
        # Macro defined in this section should be only used in this section.
        #
        self.Macros         = {}
    
    def SetPackages(self, PackageData, Arch = None):
        IsValidFileFlag = False
        SupArchList     = []
        for ArchItem in Arch:
            #
            # Validate Arch
            #            
            if (ArchItem == '' or ArchItem == None):
                ArchItem = 'COMMON'
            SupArchList.append(ArchItem)       
        
        for PackageItem in PackageData:
            PackageItemObj = InfPackageItem()
            HelpStringObj = PackageItem[1]
            CurrentLineOfPackItem = PackageItem[2]
            PackageItem = PackageItem[0]
            if HelpStringObj != None:
                HelpString = HelpStringObj.HeaderComments + HelpStringObj.TailComments
                PackageItemObj.SetHelpString(HelpString)                  
            if len(PackageItem) >= 1:
                #
                # Validate file exist/format.
                #
                if IsValidPath(PackageItem[0], ''):
                    IsValidFileFlag = True
                elif IsValidPath(PackageItem[0], GlobalData.gINF_MODULE_DIR):
                    IsValidFileFlag = True           
                elif IsValidPath(PackageItem[0], GlobalData.gWORKSPACE):
                    IsValidFileFlag = True
                else:
                    Logger.Error("InfParser", 
                                 ToolError.FORMAT_INVALID,
                                 ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(PackageItem[0]),
                                 File=CurrentLineOfPackItem[2], 
                                 Line=CurrentLineOfPackItem[1], 
                                 ExtraData=CurrentLineOfPackItem[0])
                    return False
                if IsValidFileFlag:                   
                    PackageItemObj.SetPackageName(PackageItem[0])
            if len(PackageItem) == 2:
                #
                # Validate Feature Flag Express
                #
                if PackageItem[1].strip() == '':
                    Logger.Error("InfParser", 
                                 ToolError.FORMAT_INVALID, 
                                 ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING,
                                 File=CurrentLineOfPackItem[2], 
                                 Line=CurrentLineOfPackItem[1], 
                                 ExtraData=CurrentLineOfPackItem[0])
                #
                # Validate FFE    
                #
                FeatureFlagRtv = IsValidFeatureFlagExp(PackageItem[1].strip())
                if not FeatureFlagRtv[0]:
                    Logger.Error("InfParser", 
                                 ToolError.FORMAT_INVALID,
                                 ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[1]),
                                 File=CurrentLineOfPackItem[2], 
                                 Line=CurrentLineOfPackItem[1], 
                                 ExtraData=CurrentLineOfPackItem[0])
                      
                PackageItemObj.SetFeatureFlagExp(PackageItem[1].strip())
            
            if len(PackageItem) > 2:
                #
                # Invalid format of Package statement 
                #
                Logger.Error("InfParser", 
                             ToolError.FORMAT_INVALID, 
                             ST.ERR_INF_PARSER_PACKAGE_SECTION_CONTENT_ERROR,
                             File=CurrentLineOfPackItem[2], 
                             Line=CurrentLineOfPackItem[1], 
                             ExtraData=CurrentLineOfPackItem[0])
            PackageItemObj.SetSupArchList(SupArchList)
            
            #
            # Determine package file name duplicate. Follow below rule:
            #
            # A package filename must not be duplicated within a [Packages] 
            # section. Package filenames may appear in multiple architectural 
            # [Packages] sections. A package filename listed in an 
            # architectural [Packages] section must not be listed in the common
            # architectural [Packages] section.
            # 
            # NOTE: This check will not report error now.
            #             
            for Item in self.Packages:
                if Item.GetPackageName() == PackageItemObj.GetPackageName():
                    ItemSupArchList = Item.GetSupArchList()
                    for ItemArch in ItemSupArchList:
                        for PackageItemObjArch in SupArchList:
                            if ItemArch == PackageItemObjArch:
                                #
                                # ST.ERR_INF_PARSER_ITEM_DUPLICATE
                                #
                                pass
                            if ItemArch.upper() == 'COMMON' or PackageItemObjArch.upper() == 'COMMON':
                                #
                                # ST.ERR_INF_PARSER_ITEM_DUPLICATE_COMMON
                                #
                                pass
                                            
            if self.Packages.has_key((PackageItemObj)):   
                PackageList = self.Packages[PackageItemObj]
                PackageList.append(PackageItemObj)
                self.Packages[PackageItemObj] = PackageList
            else:
                PackageList = []
                PackageList.append(PackageItemObj)
                self.Packages[PackageItemObj] = PackageList
        
        return True
    
    def GetPackages(self, Arch = None):
        if Arch == None:
            return self.Packages