XdmfCoreReader.cpp 5.69 KB
Newer Older
1 2 3
// Kenneth Leiter
// Xdmf Smart Pointer Test

4
#include <libxml/xpointer.h>
5
#include <libxml/xmlreader.h>
6
#include <map>
7
#include <sstream>
8 9 10
#include "XdmfCoreItemFactory.hpp"
#include "XdmfCoreReader.hpp"
#include "XdmfItem.hpp"
11
#include "XdmfSystemUtils.hpp"
12 13 14 15 16 17 18 19

/**
 * PIMPL
 */
class XdmfCoreReader::XdmfCoreReaderImpl {

public:

20 21
	XdmfCoreReaderImpl(const boost::shared_ptr<const XdmfCoreItemFactory> itemFactory, const XdmfCoreReader * const coreReader) :
		mCoreReader(coreReader),
22 23 24 25 26 27 28 29
		mItemFactory(itemFactory)
	{
	};

	~XdmfCoreReaderImpl()
	{
	};

30 31
	void closeFile()
	{
32
		mXPathMap.clear();
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
		xmlXPathFreeContext(mXPathContext);
		xmlFreeDoc(mDocument);
		xmlCleanupParser();
	}

	void openFile(const std::string & filePath)
	{
		mXMLDir = XdmfSystemUtils::getRealPath(filePath);
		size_t index = mXMLDir.find_last_of("/\\");
		if(index != std::string::npos)
		{
		    mXMLDir = mXMLDir.substr(0, index + 1);
		}

		mDocument = xmlReadFile(filePath.c_str(), NULL, 0);

		if(mDocument == NULL)
		{
			assert(false);
		}

		mXPathContext = xmlXPtrNewContext(mDocument, NULL, NULL);
55
		mXPathMap.clear();
56 57
	}

58 59 60
	/**
	 * Constructs XdmfItems for all nodes in currNode's tree.  XdmfItems are constructed by recursively calling this function for all children of currNode.
	 */
61
	std::vector<boost::shared_ptr<XdmfItem> > read(xmlNodePtr currNode)
62 63 64 65 66 67 68
	{
		std::vector<boost::shared_ptr<XdmfItem> > myItems;

		while(currNode != NULL)
		{
			if(currNode->type == XML_ELEMENT_NODE)
			{
69
				xmlChar * xpointer = NULL;
70
				if(xmlStrcmp(currNode->name, (xmlChar*)"include") == 0)
71
				{
72
					// Deal with proper reading of XIncludes
73 74 75 76 77 78 79 80 81
					xmlAttrPtr currAttribute = currNode->properties;
					while(currAttribute != NULL)
					{
						if(xmlStrcmp(currAttribute->name, (xmlChar*)"xpointer") == 0)
						{
							xpointer = currAttribute->children->content;
							break;
						}
					}
82
					if(xpointer)
83
					{
84 85 86
						xmlXPathObjectPtr xPathObject = xmlXPtrEval(xpointer, mXPathContext);
						if(xPathObject && xPathObject->nodesetval)
						{
87
							for(int i=0; i<xPathObject->nodesetval->nodeNr; ++i)
88 89 90 91 92
							{
								this->readSingleNode(xPathObject->nodesetval->nodeTab[i], myItems);
							}
						}
						xmlXPathFreeObject(xPathObject);
93
					}
94 95 96
				}
				else
				{
97
					// Normal reading
98
					this->readSingleNode(currNode, myItems);
99 100
				}
			}
101 102 103 104 105 106
			currNode = currNode->next;
		}
		return myItems;
	}

	/**
107
	 * Reads a single xmlNode into an XdmfItem object in memory.  The constructed XdmfItem is added to myItems and an entry is added mapping the xmlNodePtr to the new XdmfItem in the mXPathMap.
108
	 */
109
	void readSingleNode(const xmlNodePtr currNode, std::vector<boost::shared_ptr<XdmfItem> > & myItems)
110
	{
111 112
		std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> >::const_iterator iter = mXPathMap.find(currNode);
		if(iter != mXPathMap.end())
113 114 115 116 117 118 119
		{
			myItems.push_back(iter->second);
		}
		else
		{
			std::map<std::string, std::string> itemProperties;
			if(currNode->children != NULL)
120
			{   
121 122 123
                xmlChar *content = xmlNodeGetContent(currNode);
                itemProperties["Content"] = (char*)content;
                xmlFree(content);
124
				itemProperties["XMLDir"] = mXMLDir;
125
			}
126 127 128 129 130
			xmlAttrPtr currAttribute = currNode->properties;
			while(currAttribute != NULL)
			{
				itemProperties[(const char *)currAttribute->name] = (const char *)currAttribute->children->content;
				currAttribute = currAttribute->next;
131
			}
132

133
			std::vector<boost::shared_ptr<XdmfItem> > childItems = this->read(currNode->children);
134
			boost::shared_ptr<XdmfItem> newItem = mItemFactory->createItem((const char *)currNode->name, itemProperties, childItems);
135 136 137 138
			if(newItem == NULL)
			{
				assert(false);
			}
139

140
			newItem->populateItem(itemProperties, childItems, mCoreReader);
141
			myItems.push_back(newItem);
142 143 144 145 146 147 148 149 150
			mXPathMap[currNode] = newItem;
		}
	}

	void readPathObjects(const std::string & xPath, std::vector<boost::shared_ptr<XdmfItem> > & myItems)
	{
		xmlXPathObjectPtr xPathObject = xmlXPathEvalExpression((xmlChar*)xPath.c_str(), mXPathContext);
		if(xPathObject && xPathObject->nodesetval)
		{
151
			for(int i=0; i<xPathObject->nodesetval->nodeNr; ++i)
152 153 154
			{
				this->readSingleNode(xPathObject->nodesetval->nodeTab[i], myItems);
			}
155
		}
156
		xmlXPathFreeObject(xPathObject);
157 158
	}

159
	xmlDocPtr mDocument;
160
	const XdmfCoreReader * const mCoreReader;
161
	const boost::shared_ptr<const XdmfCoreItemFactory> mItemFactory;
162 163
	std::string mXMLDir;
	xmlXPathContextPtr mXPathContext;
164
	std::map<xmlNodePtr, boost::shared_ptr<XdmfItem> > mXPathMap;
165 166
};

167
XdmfCoreReader::XdmfCoreReader(const boost::shared_ptr<const XdmfCoreItemFactory> itemFactory) :
168
	mImpl(new XdmfCoreReaderImpl(itemFactory, this))
169 170 171 172 173 174 175 176
{
}

XdmfCoreReader::~XdmfCoreReader()
{
	delete mImpl;
}

177
std::vector<boost::shared_ptr<XdmfItem> > XdmfCoreReader::readItems(const std::string & filePath) const
178
{
179 180
	mImpl->openFile(filePath);
	const xmlNodePtr currNode = xmlDocGetRootElement(mImpl->mDocument);
181
	const std::vector<boost::shared_ptr<XdmfItem> > toReturn = mImpl->read(currNode->children);
182
	mImpl->closeFile();
183 184 185 186 187 188 189 190 191
	return toReturn;
}

boost::shared_ptr<XdmfItem> XdmfCoreReader::read(const std::string & filePath) const
{
	const std::vector<boost::shared_ptr<XdmfItem> > toReturn = readItems(filePath);
	if (toReturn.size() == 0)
		return(boost::shared_ptr<XdmfItem>());
	return(toReturn[0]);
192
}
193 194 195

std::vector<boost::shared_ptr<XdmfItem> > XdmfCoreReader::read(const std::string & filePath, const std::string & xPath) const
{
196
	mImpl->openFile(filePath);
197
	std::vector<boost::shared_ptr<XdmfItem> > toReturn = this->readPathObjects(xPath);
198
	mImpl->closeFile();
199 200
	return toReturn;
}
201 202 203 204 205 206 207 208

std::vector<boost::shared_ptr<XdmfItem> > XdmfCoreReader::readPathObjects(const std::string & xPath) const
{
	std::vector<boost::shared_ptr<XdmfItem> > toReturn;
	mImpl->readPathObjects(xPath, toReturn);
	return toReturn;
}