apicompatanamdw/compatanalysercmd/headeranalyser/src/PlatformData.cpp
changeset 0 638b9c697799
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apicompatanamdw/compatanalysercmd/headeranalyser/src/PlatformData.cpp	Tue Jan 12 14:52:39 2010 +0530
@@ -0,0 +1,1401 @@
+/*
+* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  
+*
+*/
+
+
+#include "CmdGlobals.h"
+#ifdef __WIN__
+#pragma warning(disable:4786)
+#endif
+
+#include <vector>
+#include <algorithm>
+#include "PlatformData.h"
+#include "XMLUtils.h"
+#include "XMLStringConst.h"
+#include "Utils.h"
+#include "BBCFileUtils.h"
+#include "HAException.h"
+
+
+const char* XML_FILE_ID_ATTRIBUTE = "id";
+
+/**
+ * Generic utility function, which checks whether the given object is
+ * in the vector.
+ */
+template <typename C>
+inline bool IsObjectInVector(const vector<C>& v, const C& o)
+{ 
+    return std::find(v.begin(), v.end(), o) != v.end();
+}
+
+// Convert to proper dir-separator
+string& FixPathString(string& str)
+{
+    string::size_type dirSepInd = str.find_first_of("\\/");
+    if( dirSepInd != string::npos && str.at(dirSepInd) != DIR_SEPARATOR )
+    {        
+        replaceChar(str, str.at(dirSepInd), DIR_SEPARATOR);
+    }
+    return str;
+}
+
+/**
+ *
+ */
+ComponentFile::ComponentFile()
+:
+iComponent(0)
+{}
+
+/**
+ *
+ */
+ComponentFile::ComponentFile(const string& ID, Component* comp)
+: 
+iID(ID),
+iComponent(comp)
+{ }
+
+/**
+ *
+ */
+ComponentFile::ComponentFile(const ComponentFile &rhs)
+:
+iID(rhs.ID()),
+iName(rhs.FileName()),
+iPath(rhs.Path()),
+iComponent(rhs.GetComponent())
+{ }
+
+/**
+ *
+ */
+ComponentFile::~ComponentFile()
+{ }
+
+/**
+ *
+ */
+const string& ComponentFile::ID() const
+{
+    return iID;
+}
+
+/**
+ *
+ */
+const string& ComponentFile::FileName() const
+{
+    return iName;
+}
+
+/**
+ *
+ */
+const string& ComponentFile::Path() const
+{
+    return iPath;
+}
+
+/**
+ *
+ */
+void ComponentFile::SetID(const string& ID)
+{
+    iID = ID;
+}
+
+/**
+ *
+ */
+void ComponentFile::SetFileName(const string& name)
+{
+    iName = name;
+}
+
+/**
+ *
+ */
+void ComponentFile::SetPath(const string& path)
+{
+    iPath = path;
+}
+
+/**
+ *
+ */
+Component* ComponentFile::GetComponent() const
+{
+    return iComponent;
+}
+
+/**
+ *
+ */
+void ComponentFile::SetComponent(Component* comp)
+{
+    iComponent = comp;
+}
+
+/**
+ *
+ */
+string ComponentFile::ForcedInclude()
+{
+return iForcedInclude;
+}
+
+pair<string,string>& ComponentFile::APIinfo()
+{
+    return iApiInfo;
+}
+
+/**
+ *
+ */
+const ComponentFile& ComponentFile::operator= (const ComponentFile& rhs)
+{
+    if( &rhs != this )
+    {
+        iID = rhs.ID();
+        iName = rhs.FileName();
+        iPath = rhs.Path();
+        iComponent = rhs.GetComponent();
+    }
+    return *this;
+}
+
+/**
+ *
+ */
+bool ComponentFile::operator== (const ComponentFile& rhs) const
+{
+    return  iID == rhs.ID() &&
+//            iName == rhs.iName &&
+//            iPath == rhs.iPath &&
+            iComponent == iComponent;
+}
+
+/**
+ *
+ */
+void ComponentFile::ProcessAttributes(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* node)
+{
+    // Read "fileid"-attribute:
+    const XMLCh* fileIdAttr = GetAttribute(node, XML_FILE_ID_ATTRIBUTE);
+    if( fileIdAttr )
+    {
+        string str(toString(fileIdAttr));
+        iID = FixPathString(toLower(str));        
+    }
+}
+
+/**
+ * Reads child elements from the parsed XML (DOM) data. This baseclass implementation
+ * processes the "filename", "relativepath" and "include" elements, which are common 
+ * to all component files.
+ */
+bool ComponentFile::ProcessChildElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* node, PlatformData* platform)
+{    
+    if( node->getNodeType() != DOMNode::ELEMENT_NODE )
+        return false;
+
+    bool properChild = false;
+
+    const XMLCh* elementtype = node->getNodeName();
+    if( elementtype )
+    {
+        string elemtypeStr(toString(elementtype));
+
+		//Handle the API info.
+		if( elemtypeStr == PLATFORM_ELEMENT_API_NAME )
+        {
+			XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* apiNode = (DOMElement*)node;
+			char* apiname = _X( apiNode->getAttribute( _X( "name" ) ) );
+			char* apiCategory = _X( apiNode->getAttribute( _X( "category" ) ) );
+
+			iApiInfo.first = apiname;
+			iApiInfo.second = apiCategory;
+
+			_XX(apiname);
+			_XX(apiCategory);
+        }
+        if( elemtypeStr == PLATFORM_ELEMENT_INCLUDE )
+        {
+            // Handle include element
+            const XMLCh* nodeVal = node->getTextContent();
+            if( nodeVal )
+            {
+                string tempStr(toString(nodeVal));
+                iIncludes.push_back(FixPathString(toLower(tempStr)));
+                properChild = true;
+            }
+        }
+        else if( elemtypeStr == PLATFORM_ELEMENT_INCLUDEPATH )
+        {
+            // Include paths:
+            const XMLCh* nodeVal = node->getTextContent();
+            if( nodeVal )
+            {
+                string tempStr(toString(nodeVal));
+                iIncludePaths.push_back(FixPathString(toLower(tempStr)));                
+                properChild = true;
+            }
+        }
+        else if( elemtypeStr == PLATFORM_ELEMENT_FORCEDINCLUDE )
+        {
+            // Forced Include:
+            const XMLCh* nodeVal = node->getTextContent();
+            if( nodeVal )
+            {
+                iForcedInclude=toString(nodeVal);
+                properChild = true;
+            }
+        }
+    }
+    return properChild;
+}
+
+/**
+ *
+ */
+const vector<string>& ComponentFile::IncludePaths() const
+{
+    return iIncludePaths;
+}
+
+/**
+ *
+ */
+void ComponentFile::AddIncludePath(const string& incPath)
+{
+    if( IsObjectInVector<string>(iIncludePaths, incPath) == false )
+        iIncludePaths.push_back(incPath);
+}
+
+const vector<string>& ComponentFile::Includes() const
+{
+    return iIncludes;
+}
+
+void ComponentFile::AddInclude(const string& incHdr)
+{
+    if( IsObjectInVector<string>(iIncludes, incHdr) == false )
+        iIncludes.push_back(incHdr);
+}
+
+void ComponentFile::SetIncludes(const vector<string>& incs)
+{
+    iIncludes = incs;
+}
+
+ParsedElement::ParsedElement()
+{}
+
+ParsedElement::~ParsedElement()
+{}
+
+/**
+ * Initializes the element using parsed XML (DOM) data. This method initiates
+ * attribute processing, child element processing and adds the element to
+ * the platform data object.
+ */
+bool ParsedElement::Initialize(DOMNode* node, PlatformData* platform)
+{
+    if( node == 0 || platform == 0 )
+        return false;
+
+    iRootDir = platform->GetRootDir();
+
+    // Read and process attributes of xml-element:
+    ProcessAttributes(node);
+                
+    // Process child elements:
+    DOMNodeList* childNodes = node->getChildNodes();
+    XMLSize_t childListLen = 0;
+    if( childNodes )
+    {
+        childListLen = childNodes->getLength();
+        for( XMLSize_t cI = 0; cI < childListLen; ++cI )
+        {
+            DOMNode* childNode = childNodes->item(cI);
+            if( childNode )
+            {                
+                ProcessChildElement(childNode, platform);                
+            }
+        }
+    }
+
+    // Add this element to a proper container of the platform data object:
+    return AddToPlatform(platform);
+}
+
+/**
+ *
+ */
+Project::Project()
+{}
+
+/**
+ *
+ */
+Project::Project(const string& prjID, Component* comp) 
+: ComponentFile(prjID, comp)
+{ }
+ 
+/**
+ *
+ */
+Project::~Project()
+{ }
+
+/**
+ * Adds this project element to platform's project list.
+ */
+bool Project::AddToPlatform(PlatformData* platform)
+{
+    return platform->AddProject(this);
+}
+
+/**
+ * Processes the given child element. Project can have following
+ * child elements:
+ *  - includepath
+ *  - source
+ */
+bool Project::ProcessChildElement(DOMNode* child, PlatformData* platform)
+{   
+    if( ComponentFile::ProcessChildElement(child, platform) == true )
+        return true;
+
+    bool properChild = false;
+    const XMLCh* childtype = child->getNodeName();
+    if( childtype )
+    {
+        string childtypeStr(toString(childtype));
+        const XMLCh* nodeVal = child->getTextContent();
+        if( nodeVal )
+        {                        
+            if( childtypeStr == PLATFORM_ELEMENT_SOURCE )
+            {
+                Source* srcObj = new Source();
+                if( srcObj->Initialize(child, platform) )
+                {
+                    iSourceObjs.push_back(srcObj);
+                    properChild = true;
+                }
+                else
+                    delete srcObj;
+            }
+        }
+    }
+    return properChild;
+}
+
+/**
+ * 
+ */
+const FileList& Project::Sources() const
+{
+    return iSourceObjs;
+}
+
+/**
+ * 
+ */
+string Project::PrettyPrint(int indentSpaces) const
+{
+    string ret;
+    for( int i = 0; i < indentSpaces; ++i )
+    {
+        ret += " ";
+    }
+    ret += string("Project ID: ") + iID + "\n";
+    for( int i = 0; i < indentSpaces; ++i )
+    {
+        ret += " ";
+    }
+    ret += "Sources:\n";
+    for( FileList::const_iterator s = iSourceObjs.begin(); s != iSourceObjs.end(); ++s )
+    {
+        ret += (*s)->PrettyPrint(indentSpaces+2);
+    }
+    return ret;
+}
+
+/**
+ * Header
+ */
+Header::Header()
+:
+iCachedIncludes(0),
+iCachedIncludePaths(0),
+iCachedForcedInclude("")
+{}
+/**
+ * 
+ */
+Header::Header(const string& hdrID, Component* comp) 
+: 
+ComponentFile(hdrID, comp),
+iCachedIncludes(0),
+iCachedIncludePaths(0),
+iCachedForcedInclude("")
+{ }
+
+/**
+ * 
+ */
+Header::~Header()
+{ 
+    delete iCachedIncludes;
+    delete iCachedIncludePaths;
+}
+
+/**
+ * 
+ */
+Header::STATUS Header::Status() const
+{
+    return iStatus;
+}
+
+/**
+ * 
+ */
+void Header::SetStatus(Header::STATUS s)
+{
+    iStatus = s;
+}
+
+/**
+ * 
+ */
+bool Header::AddToPlatform(PlatformData* platform)
+{
+    return platform->AddHeader(this);
+}
+
+/**
+ *
+ */
+string Header::PrettyPrint(int indentSpaces) const
+{
+    string ret;
+    for( int i = 0; i < indentSpaces; ++i )
+    {
+        ret += " ";
+    }
+    ret += string("Header ID: ") + iID + "\n";
+
+    return ret;
+}
+
+void Header::ProcessAttributes(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* node)
+{
+    /**
+     * Header element uses absolute path as a key, since that way it is easier
+     * to map this element to the filenames used in Analyser. Absolute path
+     * is calculated merging the root directories given in parameters (i.e BASELINEDIR
+     * and CURRENTDIR).
+     */
+    const XMLCh* fileIdAttr = GetAttribute(node, XML_FILE_ID_ATTRIBUTE);
+    if( fileIdAttr )
+    {
+        string tempStr(toString(fileIdAttr));
+        FixPathString(toLower(tempStr));
+        // Merge root and element directories.
+        // START -- Support for multiple header directories --
+        list<pair<string, bool> > fullID = BBCFileUtils::MergeDirs(iRootDir, tempStr);
+        list<pair<string, bool> >::iterator fulliterbegin = fullID.begin();
+        for(; fulliterbegin != fullID.end(); fulliterbegin++)
+        {
+          if( fulliterbegin->second )
+          {
+            iID = fulliterbegin->first;
+          }
+        }
+        // END -- Support for multiple header directories --
+    }
+}
+
+/**
+ * When IncludesForHeader() method of PlatformData is called, PlatformData
+ * retrieves the additional include directives from all the sources in the 
+ * component and caches the include directives to Header object, so next 
+ * time the retrival is faster. 
+ */
+
+/**
+ * 
+ */
+const vector<string>* Header::CachedIncludes() const
+{
+    return iCachedIncludes;
+}
+
+/**
+ * 
+ */
+void Header::SetCachedIncludes(vector<string>* incs)
+{
+    if( iCachedIncludes )
+        delete iCachedIncludes;
+    iCachedIncludes = incs;
+}
+
+/**
+ * When IncludesPathsForHeader() method of PlatformData is called, PlatformData
+ * retrieves the include paths from all the projects in the component and 
+ * caches the include paths to Header object, so next time the retrival is
+ * faster.
+ */
+
+/**
+ *
+ */
+const vector<string>* Header::CachedIncludePaths() const
+{
+    return iCachedIncludePaths;
+}
+
+/**
+ *
+ */
+void Header::SetCachedIncludePaths(vector<string>* incPaths)
+{
+    if( iCachedIncludePaths )
+        delete iCachedIncludePaths;
+    iCachedIncludePaths = incPaths;
+}
+
+
+/**
+ * When IncludesForHeader() method of PlatformData is called, PlatformData
+ * retrieves the additional forced include directive from the component
+ * and caches the forced include directive to Header object, so next 
+ * time the retrival is faster. 
+ */
+
+/**
+ * 
+ */
+string Header::CachedForcedInclude() const
+{
+    return iCachedForcedInclude;
+}
+
+string Header::CachedSource() const
+{
+	return iCacheSrcObj;
+}
+
+/**
+ * 
+ */
+void Header::SetCachedForcedInclude(string finc)
+{
+    iCachedForcedInclude = finc;
+}
+
+void Header::SetCachedSourceFile (string srcObj)
+{
+	iCacheSrcObj = srcObj;
+}
+/**
+ * Source
+ */
+Source::Source()
+{}
+
+/**
+ * 
+ */
+Source::Source(const string& srcID, Component* comp) 
+: ComponentFile(srcID, comp)
+{ }
+
+/**
+ * 
+ */
+Source::~Source()
+{ }
+
+/**
+ * 
+ */
+bool Source::AddToPlatform(PlatformData* platform)
+{
+    return platform->AddSource(this);
+}
+
+/**
+ *
+ */
+string Source::PrettyPrint(int indentSpaces) const
+{
+    string ret;
+    for( int i = 0; i < indentSpaces; ++i )
+    {
+        ret += " ";
+    }
+    ret += string("Source ID: ") + iID + "\n";
+    for( int i = 0; i < indentSpaces; ++i )
+    {
+        ret += " ";
+    }
+    ret += "Include directives:\n";
+    for( vector<string>::const_iterator inc = iIncludes.begin(); inc != iIncludes.end(); ++inc )
+    {
+        for( int i = 0; i < indentSpaces+2; ++i )
+        {
+            ret += " ";
+        }
+        ret += *inc + "\n";
+    }
+
+    return ret;
+}
+
+/**
+ * Component
+ */
+Component::Component()
+{ }
+
+/**
+ *
+ */
+Component::Component(const string& compID, Component* comp)
+: 
+ComponentFile(compID, comp)
+{ }
+
+/**
+ *
+ */
+Component::~Component()
+{ }
+   
+/**
+ *
+ */
+const FileList& Component::Headers() const
+{
+    return iHeaders;
+}
+
+/**
+ *
+ */
+FileList& Component::Headers()
+{
+    return iHeaders;
+}
+
+/**
+ *
+ */
+const FileList& Component::Projects() const
+{
+    return iProjects;
+}
+
+/**
+ *
+ */
+FileList& Component::Projects()
+{
+    return iProjects;
+}
+
+/**
+ *
+ */
+void Component::AddHeader(ComponentFile* hdr)
+{ 
+    if( IsObjectInVector<ComponentFile*>(iHeaders, hdr) == false )
+    {
+        iHeaders.push_back(hdr);
+    }
+}
+
+/**
+ *
+ */
+void Component::AddProject(ComponentFile* prj)
+{ 
+    if( IsObjectInVector<ComponentFile*>(iProjects, prj) == false )
+    {
+        iProjects.push_back(prj);
+    }
+}
+
+/**
+ * Processes child elements. Component can have following child elements:
+ *  - Header
+ *  - Project reference
+ */
+bool Component::ProcessChildElement(DOMNode* child, PlatformData* platform)
+{   
+    if( ComponentFile::ProcessChildElement(child, platform) == true )
+        return true;
+
+    bool properChild = false;
+    const XMLCh* childtype = child->getNodeName();
+    if( childtype )
+    {
+        string childtypeStr(toString(childtype));
+        if( childtypeStr == PLATFORM_ELEMENT_HEADER )
+        {            
+            Header* hdr = new Header();
+			string headerID(this->ID());
+            if( hdr->Initialize(child, platform) )
+			{
+				if(headerID == PLATFORM_IGNORED_COMPONENT )
+					hdr->SetStatus(Header::HDR_STATUS_IGNORE);
+
+				XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* hdrNode = (DOMElement*)child;
+				char* headername = _X( hdrNode->getAttribute( _X( "id" ) ) );
+				string header (headername);
+				header = FixPathString(toLower(header)); 
+				int loc = header.find_last_of(DIR_SEPARATOR);
+				if(loc != -1 )
+				{
+					// store header file name and path from header id tag only.
+					hdr->SetFileName(header.substr(loc+1,string::npos));
+					hdr->SetPath(header.substr(0,loc));
+				}
+				_XX(headername);
+
+				hdr->SetComponent(this);
+				iHeaders.push_back(hdr);
+				properChild = true;
+			}
+            else
+            {                
+                delete hdr;                
+            }
+        }
+        else if( childtypeStr == PLATFORM_ELEMENT_PROJECT )
+        {            
+            Project* prj = new Project();
+            if (prj->Initialize(child, platform) )
+            {
+                prj->SetComponent(this);
+                iProjects.push_back(prj);
+                properChild = true;
+            }
+            else
+            {
+                delete prj;
+            }
+        }       
+    }
+    return properChild;
+}
+
+/**
+ *
+ */
+bool Component::AddToPlatform(PlatformData* platform)
+{
+    return platform->AddComponent(this);
+}
+
+/**
+ *
+ */
+string Component::PrettyPrint(int indentSpaces) const
+{
+    string ret;
+    for( int i = 0; i < indentSpaces; ++i )
+    {
+        ret += " ";
+    }
+    ret += string("Component ID: ") + iID + "\n";
+    for( int i = 0; i < indentSpaces; ++i )
+    {
+        ret += " ";
+    }
+    ret += "Headers:\n";
+    for( FileList::const_iterator h = iHeaders.begin(); h != iHeaders.end(); ++h )
+    {        
+        ret += (*h)->PrettyPrint(indentSpaces+2);
+    }
+
+    for( int i = 0; i < indentSpaces; ++i )
+    {
+        ret += " ";
+    }
+    ret += "Projects\n";
+
+    for( FileList::const_iterator p = iProjects.begin(); p != iProjects.end(); ++p )
+    {
+        ret += (*p)->PrettyPrint(indentSpaces+2);
+    }
+
+    return ret;
+}
+
+/**
+ * PlatformData contains all the elements defined in the platrofm input file.
+ * It parses the XML-file and populates the internal containers. It also
+ * has different kind of methods for retrieving the data and the associations
+ * between elements.
+ */
+PlatformData::PlatformData(const string& pfVersion, const string& rootDir)
+:
+iDOMParser(0),
+iDOMDoc(0),
+iDOMRootElement(0),
+iPfVersion(pfVersion),
+iRootDir(rootDir)
+{ }
+
+/**
+ *
+ */
+PlatformData::~PlatformData()
+{
+    if (iDOMParser != NULL)
+    {
+        iDOMParser->resetDocumentPool();
+        iDOMParser->release();
+        iDOMParser = NULL;
+    }
+
+    CFileMap::iterator i;
+
+    for( i = iHeadersById.begin(); i != iHeadersById.end(); ++i )
+    {
+        delete i->second;
+    }
+
+    for( i = iProjectsById.begin(); i != iProjectsById.end(); ++i )
+    {
+        delete i->second;
+    }
+
+    for( i = iSourcesById.begin(); i != iSourcesById.end(); ++i )
+    {
+        delete i->second;
+    }
+
+    for( ComponentList::iterator ic = iCList.begin(); ic != iCList.end(); ++ic )
+    {
+        delete ic->second;
+    }
+}
+
+/**
+ *
+ */
+void PlatformData::Initialize(const string& dataFileName)
+{
+    // First read and parse the XML-file:
+    int ret = 0;
+    if (iDOMParser != NULL) 
+    {
+        iDOMParser->resetDocumentPool();
+        iDOMParser->release();
+        iDOMParser = 0;
+    }
+    cout << "Parsing platform data for " << iPfVersion << "...";
+    try {
+        ret = ParseXMLFile(dataFileName, iDOMParser, iDOMDoc, iDOMRootElement);
+    }
+    catch (HAException&)
+    {
+        cout.flush();
+        cerr.flush();
+        cerr << "Failed!" << endl;
+        if( iDOMParser )
+        {
+            iDOMParser->resetDocumentPool();
+            iDOMParser->release();
+            iDOMParser = 0;
+        }
+        throw;
+    }
+    cout << "Done." << endl;
+
+    // Then traverse the DOM tree and populate the containers:
+    cout << "Initializing platform data for " << iPfVersion << "...";
+    try {
+        InitializeElements();
+    }
+    catch( HAException& )
+    {
+        cerr << "Failed." << endl;
+        iDOMParser->resetDocumentPool();
+        iDOMParser->release();
+        iDOMParser = 0;
+        throw;
+    }
+    cout << "Done." << endl;
+    iDOMParser->resetDocumentPool();
+    iDOMParser->release();
+    iDOMParser = 0;    
+    cout << "Platform " << iPfVersion << " successfully initialized from platform " << iVersionStr << " data!"  << endl << endl;
+}
+
+/**
+ *
+ */
+bool PlatformData::AddComponent(Component* comp)
+{
+    return iCList.insert(make_pair<string, Component*>( comp->ID(), comp )).second;
+}
+
+/**
+ *
+ */
+bool PlatformData::AddProject(Project* prj)
+{
+    if( iProjectsById.insert(make_pair<string, ComponentFile*>(prj->ID(), prj)).second == false )
+        return false;
+
+    return true;
+}
+
+/**
+ *
+ */
+bool PlatformData::AddSource(Source* src)
+{
+    if( iSourcesById.insert(make_pair<string, ComponentFile*>(src->ID(), src)).second == false )
+        return false;
+
+    return true;
+}
+
+/**
+ *
+ */
+bool PlatformData::AddHeader(Header* hdr)
+{
+    if( iHeadersById.insert(make_pair<string, ComponentFile*>(hdr->ID(), hdr)).second == false )
+        return false;
+        
+    return true;
+}
+
+/**
+ * Factory method for creating element objects.
+ */
+ParsedElement* PlatformData::CreateElement( XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* node )
+{
+    const string elementType( toString( node->getNodeName() ));
+    ParsedElement* elem = 0;
+
+    if( elementType == PLATFORM_ELEMENT_COMPONENT )
+    {
+        elem = new Component();
+    }                
+    else if( elementType == PLATFORM_ELEMENT_PROJECT )
+    {
+        elem = new Project();            
+    }        
+    else if( elementType == PLATFORM_ELEMENT_SOURCE )
+    {
+        elem = new Source();            
+    }
+
+    return elem;
+}
+
+/**
+ * Traverses through the DOM-tree and builds element objects.
+ */
+void PlatformData::InitializeElements()
+{
+    if( iDOMDoc == 0 || iDOMRootElement == 0)
+        throw HAException(string("Platform ") + string(iPfVersion) + string(" initialization failed.\n"));
+    DOMNodeIterator* domIter = iDOMDoc->createNodeIterator(iDOMRootElement, DOMNodeFilter::SHOW_ELEMENT, NULL, true);
+    if( domIter == 0 )
+        throw HAException(string("Platform ") + string(iPfVersion) + string(" initialization failed.\n"));
+    DOMNode* root = domIter->getRoot();
+    if( root )
+    {
+        const XMLCh* platformVersion = GetAttribute(root, KXMLPlatformVersion);
+        if( platformVersion )
+            iVersionStr = toString(platformVersion);
+    }
+    DOMNode* nodeIter = 0;
+    ParsedElement* elem = 0;
+    while( (nodeIter = domIter->nextNode()) != 0 )
+    {
+        elem = CreateElement(nodeIter);
+        if( elem && elem->Initialize(nodeIter, this) == false )
+        {
+            delete elem;            
+        }
+    }
+
+    domIter->release();
+}
+
+/**
+ * 
+ */
+const CFileMap& PlatformData::HeadersById() const
+{
+    return iHeadersById;
+}
+
+/**
+ * 
+ */
+const CFileMap& PlatformData::ProjectsById() const
+{
+    return iProjectsById;
+}
+
+/**
+ * 
+ */
+CFileMap& PlatformData::ProjectsById()
+{
+    return iProjectsById;
+}
+
+/**
+ * 
+ */
+const CFileMap& PlatformData::SourcesById() const
+{
+    return iSourcesById;
+}
+
+/**
+ * Finds include paths defined in the projects belonging to the 
+ * same component than the header.
+ */
+const vector<string>& PlatformData::IncludePathsForHeader(const string& headerID)
+{
+    CFileMap::const_iterator hdrIter = iHeadersById.find(headerID);
+    if( hdrIter != iHeadersById.end() )
+    {
+        Header* hdrObj = dynamic_cast<Header*>(hdrIter->second);
+        if( hdrObj )
+            return IncludePathsForHeader(hdrObj);
+    }
+
+    return iDummyStringVector;
+}
+
+/**
+ * Finds include paths defined in the projects belonging to the 
+ * same component than the header.
+ */
+const vector<string>& PlatformData::IncludePathsForHeader(Header* hdrObj)
+{
+    if( hdrObj == 0 )
+        return iDummyStringVector;
+
+    // First try to find includes from the cache:
+    const vector<string>* cached = hdrObj->CachedIncludePaths();
+    if( cached )
+    {
+        return *cached;
+    }
+    
+    auto_ptr<vector<string> > newVector(new vector<string>());        
+    Component* comp = 0;
+
+    if( (comp = hdrObj->GetComponent()) != 0 )
+    {
+        // First insert the include paths defined in component level:
+        newVector->insert(newVector->end(), comp->IncludePaths().begin(),  comp->IncludePaths().end());
+
+        const FileList& prjs = comp->Projects();
+        for( FileList::const_iterator prj = prjs.begin(); prj != prjs.end(); ++prj )
+        {
+            Project* prjObj = dynamic_cast<Project*>(*prj);
+            if( prjObj )
+            {
+                const vector<string>& iPaths = prjObj->IncludePaths();
+                vector<string>::const_iterator ip = iPaths.begin();
+
+                for( ; ip != iPaths.end(); ++ip )
+                {
+                    if( !IsObjectInVector(*newVector, *ip) )
+                    {
+                        newVector->push_back(*ip);
+                    }
+                }
+            }
+        }
+    }
+
+    const vector<string>& hdrIncs = hdrObj->IncludePaths();
+    for( vector<string>::const_iterator i = hdrIncs.begin(); i != hdrIncs.end(); ++i )
+    {
+        if( !IsObjectInVector(*newVector, *i) )
+        {
+            newVector->push_back(*i);
+        }
+    }
+
+    // variable to track whether project has been found
+    bool found = false;
+    // Find a project in the platform data which includes the header under analysis and
+    // add all paths in the mmp file as dependencies before compilation. 
+    for( CFileMap::const_iterator pIter = iProjectsById.begin(); pIter != iProjectsById.end() && !found; ++pIter )
+    {
+        //First iterate over projects
+        Project* prj = dynamic_cast<Project*>(pIter->second);
+        const FileList& src = prj->Sources();
+        FileList::const_iterator sIter = src.begin();
+        for(;sIter != src.end() && !found; ++sIter)
+        {
+            // then search each source include in individual projects
+            Source* so = dynamic_cast<Source*>(*sIter);
+            const vector<string>& inc = so->Includes();
+            vector<string>::const_iterator iIter = inc.begin();
+            for(;iIter != inc.end() && !found; ++iIter)
+            {
+                string::size_type dirEnd = (*iIter).find_last_of('/\\');
+                // IF header found
+                if( (dirEnd == string::npos && *iIter == hdrObj->FileName()) ||
+                    (dirEnd != string::npos && string((*iIter).begin()+dirEnd+1, (*iIter).end()) == hdrObj->FileName()))
+                {
+                    const vector<string>& tmp = prj->IncludePaths();
+					if( IsObjectInVector<string>(tmp, hdrObj->Path()) )
+					{
+						vector<string>::const_iterator str = tmp.begin();
+						for(;str != prj->IncludePaths().end(); ++str)
+						{
+							// only include paths which are not already present
+							if( !IsObjectInVector<string>(*newVector, *str) )
+							{
+								newVector->insert(newVector->end(), *str);
+								found = true;
+							}
+						}
+					}
+                }
+            }
+        }
+    }
+    hdrObj->SetCachedIncludePaths(newVector.release());
+    return *(hdrObj->CachedIncludePaths());
+}
+
+/**
+ * Finds include directives used with this header when the header
+ * is compiled. Algorithm finds the <code>Header</code> object using 
+ * the given ID and then calls overloaded <code>IncludesForHeader</code> 
+ * using the <code>Header</code> object.
+ */
+const vector<string>& PlatformData::IncludesForHeader( const string& headerID )
+{
+    CFileMap::const_iterator hdrIter = iHeadersById.find(headerID);
+    if( hdrIter != iHeadersById.end() )
+    {
+        Header* hObj = dynamic_cast<Header*>(hdrIter->second);
+        if( hObj )
+            return IncludesForHeader(hObj);
+    }
+    return iDummyStringVector;
+}
+
+void PlatformData::IncludesFromSource(const Header* hObj, const Source* srcObj, vector<string>& includes) const
+{
+    const vector<string>& includeDirectives = srcObj->Includes();
+    vector<string>::const_iterator inc = includeDirectives.begin();
+    for( ; inc != includeDirectives.end(); ++inc )
+    {
+        string::size_type dirEnd = (*inc).find_last_of("/\\");
+
+        if( (dirEnd == string::npos && *inc == hObj->FileName()) ||
+            (dirEnd != string::npos && string(inc->begin()+dirEnd+1, inc->end()) == hObj->FileName()))
+        {
+            // The header was found. Take all the preceding include directives:
+            for( vector<string>::const_iterator tempIt = includeDirectives.begin(); tempIt != inc; ++tempIt)
+            {
+                if( IsObjectInVector(includes, *tempIt) == false )
+                {                            
+                    includes.push_back(*tempIt);
+                }        
+            }
+            break;
+        }
+    }
+}
+
+/**
+ * Finds include directives used with this header when the header
+ * is compiled. Algorithm find first all the projects belonging
+ * to the same component than the given <code>Header</code> object.
+ * Then it finds all the source files belonging to the projects.
+ * Then it scans the source files and if a source file includes
+ * this header, all the preceding include directives in that source
+ * file are inserted to the result vector.
+ *
+ * An example:
+ *
+ * Header, id: epoc32/include/hdr1.h, belongs to component c, which
+ * contains one project p.mmp. Project p.mmp contains two source files:
+ * s1.cpp and s2.cpp. Source s1.cpp includes hdrX.h, hdrY.h and hdr1.h 
+ * (in that order). Source s2.cpp does not include the hdr1.h at all.
+ * The returned headers in above example would be hdrX.h and hdrY.h.
+ */
+const vector<string>& PlatformData::IncludesForHeader(Header* hObj, Header* baseHObj)
+{
+	string tempSpurceObj;
+    if( hObj == 0 )
+        return iDummyStringVector;
+
+    if( hObj->CachedIncludes() != 0 )
+        return *(hObj->CachedIncludes());
+
+           
+    // Start build new include list:
+    auto_ptr<vector<string> > newVector(new vector<string>());        
+    Component* comp = 0;
+
+    if( (comp = hObj->GetComponent()) != 0 )
+    {
+        //set the forced header for this header
+        hObj->SetCachedForcedInclude(comp->ForcedInclude());
+        // Insert include directives defined in component level:
+        newVector->insert(newVector->end(), comp->Includes().begin(), comp->Includes().end());
+
+        // Then find all the sources that are including this header and get all the preceding include
+        // directives from the sources. The shortest list will do.
+
+        const FileList& projects = comp->Projects(); // All the projects in this component
+        FileList::const_iterator fIter = projects.begin();
+
+        // Get needed source files from the projects of this component:
+        FileList srcObjs;
+        for( ; fIter != projects.end(); ++fIter )
+        {
+            Project* prj = dynamic_cast<Project*>(*fIter);        
+            if( prj )
+            {                    
+                srcObjs.insert(srcObjs.end(), prj->Sources().begin(), prj->Sources().end());
+            }
+        }
+
+        // Next we investigate the include directives of each source file
+        // and get all the headers that are included before the given 
+        // header file.
+        auto_ptr<vector<string> > includesFromSrc(0);
+        for( FileList::iterator src = srcObjs.begin(); src != srcObjs.end(); ++src )
+        {
+            Source* srcObj = dynamic_cast<Source*>(*src);        
+            if( srcObj == 0 )
+                continue;
+
+            const vector<string>& includeDirectives = srcObj->Includes();
+            vector<string>::const_iterator inc = includeDirectives.begin();
+            auto_ptr<vector<string> > tmpIncludes(new vector<string>());
+           
+            IncludesFromSource(hObj, srcObj, *tmpIncludes);
+            if( includesFromSrc.get() == 0 ||
+                (tmpIncludes->size() > 0 && (tmpIncludes->size() < includesFromSrc->size() || includesFromSrc->size()==0) ))
+            {
+				tempSpurceObj = srcObj->ID();
+                includesFromSrc = tmpIncludes; // Get the smallest possible set of additional includes.
+            }
+        }
+        if( includesFromSrc.get() )
+        {
+            newVector->insert(newVector->end(), includesFromSrc->begin(), includesFromSrc->end());
+        }
+    }
+
+    if( newVector->size() == 0 )
+    {
+        // No includes found. Let's try to find some source from other components. First one will do...
+        for( CFileMap::const_iterator s = iSourcesById.begin(); s != iSourcesById.end(); ++s )
+        {
+            auto_ptr<vector<string> > tmpIncludes(new vector<string>());
+            Source* sO = dynamic_cast<Source*>(s->second);
+            if( sO )
+            {
+                IncludesFromSource(hObj, sO, *tmpIncludes);
+                if( tmpIncludes->size() > 0 )
+				{
+					string curSrc;
+					string baseSrc;
+					if ( baseHObj != NULL) // IncludesForHeader() is called for current sdk
+					{
+						string::size_type loc = sO->ID().find_last_of('/\\');
+						if(loc != string::npos )
+							curSrc = sO->ID().substr(loc+1 , string::npos);
+						loc = string::npos;
+						loc = baseHObj->CachedSource().find_last_of('/\\');
+						if(loc != string::npos)
+							baseSrc = baseHObj->CachedSource().substr(loc+1, string::npos);
+					}
+					// If the header is of baseline sdk or the current headers source file name is same as baseline's source file,
+					// In both of these cases , the dependent headers will be taken from platform data file
+					if(baseHObj == NULL || (baseSrc.size() > 0 && baseSrc == curSrc) )
+					{
+						newVector->insert(newVector->end(), tmpIncludes->begin(), tmpIncludes->end());
+					}
+					else // as current header's source file is not same as basiline's, so baseline's cacheinclude will be taken for current header too.
+					{
+						newVector->insert(newVector->end(), baseHObj->CachedIncludes()->begin(), baseHObj->CachedIncludes()->end());
+					}
+					break;
+				}
+            }
+        }
+    }    
+    hObj->SetCachedIncludes(newVector.release());
+	if(baseHObj == NULL) // IncludesForHeader() is called for baseline sdk, so get the source file name in cache
+	{
+		hObj->SetCachedSourceFile(tempSpurceObj);
+	}
+    return *(hObj->CachedIncludes());
+}
+/**
+ *
+ */
+string PlatformData::PrettyPrint() const
+{
+    string ret("PLATFORM version: ");
+    ret += iVersionStr + "\n";
+   
+    for( ComponentList::const_iterator c = iCList.begin(); c != iCList.end(); ++c )
+    {
+        ret += c->second->PrettyPrint();
+    }
+    return ret;
+}
+
+/**
+ *
+ */
+const ComponentList& PlatformData::Components() const
+{
+    return iCList;
+}
+
+/**
+ *
+ */
+const string& PlatformData::GetRootDir() const
+{
+    return iRootDir;
+}