XdmfCoreReader.cpp 5.34 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
				itemProperties["Content"] = (const char *)currNode->children->content;
122
				itemProperties["XMLDir"] = mXMLDir;
123
			}
124

125 126 127 128 129
			xmlAttrPtr currAttribute = currNode->properties;
			while(currAttribute != NULL)
			{
				itemProperties[(const char *)currAttribute->name] = (const char *)currAttribute->children->content;
				currAttribute = currAttribute->next;
130
			}
131
			std::vector<boost::shared_ptr<XdmfItem> > childItems = this->read(currNode->children);
132
			boost::shared_ptr<XdmfItem> newItem = mItemFactory->createItem((const char *)currNode->name, itemProperties, childItems);
133 134 135 136
			if(newItem == NULL)
			{
				assert(false);
			}
137
			newItem->populateItem(itemProperties, childItems, mCoreReader);
138
			myItems.push_back(newItem);
139 140 141 142 143 144 145 146 147
			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)
		{
148
			for(int i=0; i<xPathObject->nodesetval->nodeNr; ++i)
149 150 151
			{
				this->readSingleNode(xPathObject->nodesetval->nodeTab[i], myItems);
			}
152
		}
153
		xmlXPathFreeObject(xPathObject);
154 155
	}

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

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

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

boost::shared_ptr<XdmfItem> XdmfCoreReader::read(const std::string & filePath) const
{
176 177
	mImpl->openFile(filePath);
	const xmlNodePtr currNode = xmlDocGetRootElement(mImpl->mDocument);
178
	const std::vector<boost::shared_ptr<XdmfItem> > toReturn = mImpl->read(currNode->children);
179
	mImpl->closeFile();
180 181
	return toReturn[0];
}
182 183 184

std::vector<boost::shared_ptr<XdmfItem> > XdmfCoreReader::read(const std::string & filePath, const std::string & xPath) const
{
185
	mImpl->openFile(filePath);
186
	std::vector<boost::shared_ptr<XdmfItem> > toReturn = this->readPathObjects(xPath);
187
	mImpl->closeFile();
188 189
	return toReturn;
}
190 191 192 193 194 195 196 197

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;
}