From d0bd43fd8c54f11f4d9efb36c5cdfd8c41b24fc4 Mon Sep 17 00:00:00 2001
From: Christoph Lehmann <christoph.lehmann@ufz.de>
Date: Mon, 25 Jan 2016 13:59:46 +0100
Subject: [PATCH] [FIO] changed gml parser to new config tree -- 1st iteration

---
 FileIO/XmlIO/Boost/BoostXmlGmlInterface.cpp | 274 +++++++++-----------
 FileIO/XmlIO/Boost/BoostXmlGmlInterface.h   |  15 +-
 2 files changed, 124 insertions(+), 165 deletions(-)

diff --git a/FileIO/XmlIO/Boost/BoostXmlGmlInterface.cpp b/FileIO/XmlIO/Boost/BoostXmlGmlInterface.cpp
index 42f6ef63337..67849b85eff 100644
--- a/FileIO/XmlIO/Boost/BoostXmlGmlInterface.cpp
+++ b/FileIO/XmlIO/Boost/BoostXmlGmlInterface.cpp
@@ -25,6 +25,7 @@
 
 #include <logog/include/logog.hpp>
 
+#include "BaseLib/ConfigTreeUtil.h"
 #include "BaseLib/StringTools.h"
 #include "GeoLib/GEOObjects.h"
 #include "GeoLib/Point.h"
@@ -42,14 +43,10 @@ BoostXmlGmlInterface::BoostXmlGmlInterface(GeoLib::GEOObjects& geo_objs) :
 
 bool BoostXmlGmlInterface::readFile(const std::string &fname)
 {
-	std::ifstream in(fname.c_str());
-	if (!in)
-	{
-		ERR("BoostXmlGmlInterface::readFile(): Can't open xml-file %s.", fname.c_str());
-		return false;
-	}
-
-	std::string geo_name("[NN]");
+	auto doc = BaseLib::makeConfigTree(fname, true, "OpenGeoSysGLI");
+	doc->ignoreConfAttribute("xmlns:xsi");
+	doc->ignoreConfAttribute("xsi:noNamespaceSchemaLocation");
+	doc->ignoreConfAttribute("xmlns:ogs");
 
 	auto points = std::unique_ptr<std::vector<GeoLib::Point*>>(
 	    new std::vector<GeoLib::Point*>);
@@ -60,51 +57,42 @@ bool BoostXmlGmlInterface::readFile(const std::string &fname)
 
 	std::map<std::string, std::size_t>* pnt_names = new std::map<std::string, std::size_t>;
 	std::map<std::string, std::size_t>* ply_names = new std::map<std::string, std::size_t>;
-	std::map<std::string, std::size_t>* sfc_names  = new std::map<std::string, std::size_t>;
-
-	GeoLib::GEOObjects* geo_objects (&_geo_objects);
-
-	// build DOM tree
-    BaseLib::ConfigTree doc;
-	read_xml(in, doc, boost::property_tree::xml_parser::no_comments);
-
-	if (!isGmlFile(doc))
-		return false;
-
-    BaseLib::ConfigTree const & root_node = doc.get_child("OpenGeoSysGLI");
-	BOOST_FOREACH( BaseLib::ConfigTree::value_type const & node, root_node )
-	{
-		if (node.first.compare("name") == 0)
-		{
-			if (node.second.data().empty())
-			{
-				ERR("BoostXmlGmlInterface::readFile(): <name>-tag is empty.")
-				return false;
-			}
-			geo_name = node.second.data();
-		}
-		else if (node.first.compare("points") == 0)
-		{
-			readPoints(node.second, points.get(), pnt_names);
-			geo_objects->addPointVec(std::move(points), geo_name, pnt_names);
-		}
-		else if (node.first.compare("polylines") == 0)
-			readPolylines(node.second,
-			              polylines.get(),
-			              geo_objects->getPointVec(geo_name),
-			              geo_objects->getPointVecObj(geo_name)->getIDMap(),
-			              ply_names);
-		else if (node.first.compare("surfaces") == 0)
-			readSurfaces(node.second,
-			             surfaces.get(),
-			             geo_objects->getPointVec(geo_name),
-			             geo_objects->getPointVecObj(geo_name)->getIDMap(),
-			             sfc_names);
-	}
+	std::map<std::string, std::size_t>* sfc_names = new std::map<std::string, std::size_t>;
+
+	// GeoLib::GEOObjects* geo_objects (&_geo_objects);
+
+    auto geo_name = doc->getConfParam<std::string>("name");
+    if (geo_name.empty())
+    {
+        ERR("BoostXmlGmlInterface::readFile(): <name> tag is empty.")
+        std::abort();
+    }
+
+    for (auto st : doc->getConfSubtreeList("points"))
+    {
+        readPoints(st, points.get(), pnt_names);
+        _geo_objects.addPointVec(std::move(points), geo_name, pnt_names);
+    }
+    for (auto st : doc->getConfSubtreeList("polylines"))
+    {
+        readPolylines(st,
+                      polylines.get(),
+                      _geo_objects.getPointVec(geo_name),
+                      _geo_objects.getPointVecObj(geo_name)->getIDMap(),
+                      ply_names);
+    }
+    for (auto st : doc->getConfSubtreeList("surfaces"))
+    {
+        readSurfaces(st,
+                     surfaces.get(),
+                     _geo_objects.getPointVec(geo_name),
+                     _geo_objects.getPointVecObj(geo_name)->getIDMap(),
+                     sfc_names);
+    }
 
 	if (!polylines->empty())
 	{
-		geo_objects->addPolylineVec(std::move(polylines), geo_name, ply_names);
+		_geo_objects.addPolylineVec(std::move(polylines), geo_name, ply_names);
 	}
 	else
 	{
@@ -113,7 +101,7 @@ bool BoostXmlGmlInterface::readFile(const std::string &fname)
 
 	if (!surfaces->empty())
 	{
-		geo_objects->addSurfaceVec(std::move(surfaces), geo_name, sfc_names);
+		_geo_objects.addSurfaceVec(std::move(surfaces), geo_name, sfc_names);
 	}
 	else
 	{
@@ -123,32 +111,29 @@ bool BoostXmlGmlInterface::readFile(const std::string &fname)
 	return true;
 }
 
-void BoostXmlGmlInterface::readPoints(BaseLib::ConfigTree const& pointsRoot,
+void BoostXmlGmlInterface::readPoints(BaseLib::ConfigTreeNew const& pointsRoot,
 	                                  std::vector<GeoLib::Point*>* points,
 	                                  std::map<std::string, std::size_t>* &pnt_names )
 {
-	BOOST_FOREACH( BaseLib::ConfigTree::value_type const & point, pointsRoot )
+	for (auto const pt : pointsRoot.getConfParamList("point"))
 	{
-		if (point.first.compare("point") != 0)
-			continue;
-
-		unsigned p_id = static_cast<unsigned>(point.second.get("<xmlattr>.id", std::numeric_limits<unsigned>::max()));
-		double   p_x  = static_cast<double>  (point.second.get("<xmlattr>.x",  std::numeric_limits<double>::max()));
-		double   p_y  = static_cast<double>  (point.second.get("<xmlattr>.y",  std::numeric_limits<double>::max()));
-		double   p_z  = static_cast<double>  (point.second.get("<xmlattr>.z",  std::numeric_limits<double>::max()));
-		std::string p_name = point.second.get("<xmlattr>.name", "");
-
-		if ( p_id == std::numeric_limits<unsigned>::max() || p_x == std::numeric_limits<double>::max() ||
-		     p_y  == std::numeric_limits<double>::max()   || p_z == std::numeric_limits<double>::max() )
-			WARN("BoostXmlGmlInterface::readPoints(): Skipping point, attribute missing in <point> tag:\n%s",
-				BaseLib::propertyTreeToString(point.second).c_str())
-		else
-		{
-			_idx_map.insert (std::pair<std::size_t, std::size_t>(p_id, points->size()));
-			GeoLib::Point* p = new GeoLib::Point(p_x, p_y, p_z, p_id);
-			if (!p_name.empty())
-				pnt_names->insert( std::pair<std::string, std::size_t>(p_name, points->size()) );
-			points->push_back(p);
+		auto const p_id = pt.getConfAttribute<std::size_t>("id");
+		auto const p_x  = pt.getConfAttribute<double>("x");
+		auto const p_y  = pt.getConfAttribute<double>("y");
+		auto const p_z  = pt.getConfAttribute<double>("z");
+
+		auto const p_name = pt.getConfAttributeOptional<std::string>("name");
+
+		auto const p_size = points->size();
+		_idx_map[p_id] = p_size; // TODO: unique ids?
+		points->push_back(new GeoLib::Point(p_x, p_y, p_z, p_id));
+
+		if (p_name) {
+			if (p_name->empty()) {
+				ERR("Empty point name found in geometry file.");
+				std::abort();
+			}
+			(*pnt_names)[*p_name] = p_size; // TODO: unique names?
 		}
 	}
 
@@ -161,45 +146,43 @@ void BoostXmlGmlInterface::readPoints(BaseLib::ConfigTree const& pointsRoot,
 }
 
 void BoostXmlGmlInterface::readPolylines(
-    BaseLib::ConfigTree const& polylinesRoot,
+    BaseLib::ConfigTreeNew const& polylinesRoot,
     std::vector<GeoLib::Polyline*>* polylines,
     std::vector<GeoLib::Point*> const* points,
     const std::vector<std::size_t>& pnt_id_map,
     std::map<std::string, std::size_t>*& ply_names)
 {
-	BOOST_FOREACH( BaseLib::ConfigTree::value_type const & polyline, polylinesRoot )
+	for (auto const pl : polylinesRoot.getConfSubtreeList("polyline"))
 	{
-		if (polyline.first.compare("polyline") != 0)
-			continue;
-
-		if (static_cast<unsigned>(polyline.second.get("<xmlattr>.id", std::numeric_limits<unsigned>::max()) == std::numeric_limits<unsigned>::max()))
-			WARN("BoostXmlGmlInterface::readPolylines(): Skipping polyline, attribute \"id\" missing in <polyline> tag:\n%s",
-				BaseLib::propertyTreeToString(polyline.second).c_str())
-		else
-		{
-			polylines->push_back(new GeoLib::Polyline(*points));
-
-			std::string const p_name = polyline.second.get("<xmlattr>.name", "");
-			if (!p_name.empty()) {
-				std::map<std::string, std::size_t>::const_iterator it(
-					ply_names->find(p_name)
+		auto const id = pl.getConfAttribute<std::size_t>("id");
+		(void) id; // id not used
+
+		polylines->push_back(new GeoLib::Polyline(*points));
+
+		auto const p_name = pl.getConfAttributeOptional<std::string>("name");
+		if (p_name) {
+			if (p_name->empty()) {
+				ERR("Empty polyline name found in geometry file.");
+				std::abort();
+			}
+
+			// TODO change
+			// auto const inserted = ply_names->insert(std::make_pair(p_name, polylines->size()-1));
+			auto const it = ply_names->find(*p_name);
+			if (it == ply_names->end()) {
+				ply_names->insert(std::pair<std::string,std::size_t>(
+					*p_name, polylines->size()-1)
 				);
-				if (it == ply_names->end()) {
-					ply_names->insert(std::pair<std::string,std::size_t>(
-						p_name, polylines->size()-1)
-					);
-				} else {
-					WARN("Polyline \"%s\" exists already. The polyline will "
-						"be inserted without a name.\n%s",
-						p_name.c_str(),
-						BaseLib::propertyTreeToString(polyline.second).c_str());
-				}
+
+			} else {
+				WARN("Polyline \"%s\" exists already. The polyline will "
+					"be inserted without a name.\n%s",
+					p_name->c_str(), ""
+					/*BaseLib::propertyTreeToString(polyline.second).c_str()*/);
 			}
 
-			BOOST_FOREACH( BaseLib::ConfigTree::value_type const & pnt, polyline.second )
-			{
-				if (pnt.first.compare("pnt") == 0)
-					polylines->back()->addPoint(pnt_id_map[_idx_map[std::atoi(pnt.second.data().c_str())]]);
+			for (auto const pt : pl.getConfParamList<std::size_t>("pnt")) {
+				polylines->back()->addPoint(pnt_id_map[_idx_map[pt]]);
 			}
 		}
 	}
@@ -213,46 +196,35 @@ void BoostXmlGmlInterface::readPolylines(
 }
 
 void BoostXmlGmlInterface::readSurfaces(
-    BaseLib::ConfigTree const&  surfacesRoot,
+    BaseLib::ConfigTreeNew const&  surfacesRoot,
     std::vector<GeoLib::Surface*>* surfaces,
     std::vector<GeoLib::Point*> const* points,
     const std::vector<std::size_t>& pnt_id_map,
     std::map<std::string, std::size_t>*& sfc_names)
 {
-	BOOST_FOREACH( BaseLib::ConfigTree::value_type const & surface, surfacesRoot )
+	for (auto const& sfc : surfacesRoot.getConfSubtreeList("surface"))
 	{
-		if (surface.first.compare("surface") != 0)
-			continue;
-
-		if (static_cast<unsigned>(surface.second.get("<xmlattr>.id", std::numeric_limits<unsigned>::max()) == std::numeric_limits<unsigned>::max()))
-		{
-			WARN("BoostXmlGmlInterface::readSurfaces(): Skipping surface, attribute \"id\" missing in <surface> tag:\n%s",
-				BaseLib::propertyTreeToString(surface.second).c_str())
-			continue;
-		}
-
+		auto const id = sfc.getConfAttribute<std::size_t>("id");
+		(void) id; // id not used
 		surfaces->push_back(new GeoLib::Surface(*points));
 
-		std::string s_name = surface.second.get("<xmlattr>.name", "");
-		if (!s_name.empty())
-			sfc_names->insert(std::pair<std::string, std::size_t>(s_name, surfaces->size()-1));
-
-		BOOST_FOREACH( BaseLib::ConfigTree::value_type const & element, surface.second )
-		{
-			if (element.first.compare("element") != 0)
-				continue;
-
-			unsigned p1_attr = static_cast<unsigned>(element.second.get("<xmlattr>.p1", std::numeric_limits<unsigned>::max()));
-			unsigned p2_attr = static_cast<unsigned>(element.second.get("<xmlattr>.p2", std::numeric_limits<unsigned>::max()));
-			unsigned p3_attr = static_cast<unsigned>(element.second.get("<xmlattr>.p3", std::numeric_limits<unsigned>::max()));
-
-			if (p1_attr == std::numeric_limits<unsigned>::max() || p2_attr == std::numeric_limits<unsigned>::max() || p3_attr == std::numeric_limits<unsigned>::max())
-				WARN("BoostXmlGmlInterface::readSurfaces(): Skipping triangle, attribute missing in <element> tag:\n%s",
-					BaseLib::propertyTreeToString(element.second).c_str())
-			{
-				std::size_t p1 = pnt_id_map[_idx_map[p1_attr]];
-				std::size_t p2 = pnt_id_map[_idx_map[p2_attr]];
-				std::size_t p3 = pnt_id_map[_idx_map[p3_attr]];
+		auto const s_name = sfc.getConfAttributeOptional<std::string>("name");
+		if (s_name) {
+			if (s_name->empty()) {
+				ERR("Empty surface name found in geometry file.");
+				std::abort();
+			}
+
+			(*sfc_names)[*s_name] = surfaces->size()-1; // TODO unique names
+
+			for (auto const& element : sfc.getConfParamList("element")) {
+				auto const p1_attr = element.getConfAttribute<std::size_t>("p1");
+				auto const p2_attr = element.getConfAttribute<std::size_t>("p2");
+				auto const p3_attr = element.getConfAttribute<std::size_t>("p3");
+
+				auto const p1 = pnt_id_map[_idx_map[p1_attr]];
+				auto const p2 = pnt_id_map[_idx_map[p2_attr]];
+				auto const p3 = pnt_id_map[_idx_map[p3_attr]];
 				surfaces->back()->addTriangle(p1,p2,p3);
 			}
 		}
@@ -266,16 +238,6 @@ void BoostXmlGmlInterface::readSurfaces(
 	}
 }
 
-bool BoostXmlGmlInterface::isGmlFile(BaseLib::ConfigTree const& root) const
-{
-	if (!root.get_child_optional("OpenGeoSysGLI"))
-	{
-		ERR("BoostXmlGmlInterface::isGmlFile(): Not a GML file.");
-		return false;
-	}
-	return true;
-}
-
 bool BoostXmlGmlInterface::write()
 {
 	if (this->_exportName.empty()) {
@@ -303,19 +265,19 @@ bool BoostXmlGmlInterface::write()
 	}
 
 	// create a property tree for writing it to file
-	BaseLib::ConfigTree pt;
+	boost::property_tree::ptree pt;
 
 	// put header in property tree
 	pt.put("<xmlattr>.xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
 	pt.put("<xmlattr>.xsi:noNamespaceSchemaLocation",
 		"http://www.opengeosys.org/images/xsd/OpenGeoSysGLI.xsd");
 	pt.put("<xmlattr>.xmlns:ogs", "http://www.opengeosys.net");
-	BaseLib::ConfigTree &geometry_set = pt.add("OpenGeoSysGLI", "");
+	auto& geometry_set = pt.add("OpenGeoSysGLI", "");
 
 	geometry_set.add("name", _exportName);
-	BaseLib::ConfigTree & pnts_tag = geometry_set.add("points", "");
+	auto& pnts_tag = geometry_set.add("points", "");
 	for (std::size_t k(0); k<pnts->size(); k++) {
-		BaseLib::ConfigTree &pnt_tag = pnts_tag.add("point", "");
+		auto& pnt_tag = pnts_tag.add("point", "");
 		pnt_tag.put("<xmlattr>.id", k);
 		pnt_tag.put("<xmlattr>.x", (*((*pnts)[k]))[0]);
 		pnt_tag.put("<xmlattr>.y", (*((*pnts)[k]))[1]);
@@ -338,7 +300,7 @@ bool BoostXmlGmlInterface::write()
 }
 
 void BoostXmlGmlInterface::addSurfacesToPropertyTree(
-	BaseLib::ConfigTree & geometry_set)
+	boost::property_tree::ptree & geometry_set)
 {
 	GeoLib::SurfaceVec const*const sfc_vec(_geo_objects.getSurfaceVecObj(_exportName));
 	if (!sfc_vec) {
@@ -357,17 +319,17 @@ void BoostXmlGmlInterface::addSurfacesToPropertyTree(
 		return;
 	}
 
-	BaseLib::ConfigTree & surfaces_tag = geometry_set.add("surfaces", "");
+	auto& surfaces_tag = geometry_set.add("surfaces", "");
 	for (std::size_t i=0; i<surfaces->size(); ++i) {
 		GeoLib::Surface const*const surface((*surfaces)[i]);
 		std::string sfc_name("");
 		sfc_vec->getNameOfElement(surface, sfc_name);
-		BaseLib::ConfigTree &surface_tag = surfaces_tag.add("surface", "");
+		auto& surface_tag = surfaces_tag.add("surface", "");
 		surface_tag.put("<xmlattr>.id", i);
 		if (!sfc_name.empty())
 			surface_tag.put("<xmlattr>.name", sfc_name);
 		for (std::size_t j=0; j<surface->getNTriangles(); ++j) {
-			BaseLib::ConfigTree &element_tag = surface_tag.add("element", "");
+			auto& element_tag = surface_tag.add("element", "");
 			element_tag.put("<xmlattr>.p1", (*(*surface)[j])[0]);
 			element_tag.put("<xmlattr>.p2", (*(*surface)[j])[1]);
 			element_tag.put("<xmlattr>.p3", (*(*surface)[j])[2]);
@@ -376,7 +338,7 @@ void BoostXmlGmlInterface::addSurfacesToPropertyTree(
 }
 
 void BoostXmlGmlInterface::addPolylinesToPropertyTree(
-	BaseLib::ConfigTree & geometry_set)
+	boost::property_tree::ptree & geometry_set)
 {
 	GeoLib::PolylineVec const*const vec(_geo_objects.getPolylineVecObj(_exportName));
 	if (!vec) {
@@ -395,12 +357,12 @@ void BoostXmlGmlInterface::addPolylinesToPropertyTree(
 		return;
 	}
 
-	BaseLib::ConfigTree & polylines_tag = geometry_set.add("polylines", "");
+	auto& polylines_tag = geometry_set.add("polylines", "");
 	for (std::size_t i=0; i<polylines->size(); ++i) {
 		GeoLib::Polyline const*const polyline((*polylines)[i]);
 		std::string ply_name("");
 		vec->getNameOfElement(polyline, ply_name);
-		BaseLib::ConfigTree &polyline_tag = polylines_tag.add("polyline", "");
+		auto& polyline_tag = polylines_tag.add("polyline", "");
 		polyline_tag.put("<xmlattr>.id", i);
 		if (!ply_name.empty())
 			polyline_tag.put("<xmlattr>.name", ply_name);
diff --git a/FileIO/XmlIO/Boost/BoostXmlGmlInterface.h b/FileIO/XmlIO/Boost/BoostXmlGmlInterface.h
index 21b827c2a83..b76f164833f 100644
--- a/FileIO/XmlIO/Boost/BoostXmlGmlInterface.h
+++ b/FileIO/XmlIO/Boost/BoostXmlGmlInterface.h
@@ -20,7 +20,7 @@
 #include <vector>
 
 
-#include "BaseLib/ConfigTree.h"
+#include "BaseLib/ConfigTreeNew.h"
 #include "../XMLInterface.h"
 
 namespace GeoLib
@@ -50,29 +50,26 @@ protected:
 
 private:
 	/// Reads GeoLib::Point-objects from an xml-file
-	void readPoints    ( BaseLib::ConfigTree const& pointsRoot,
+	void readPoints    ( BaseLib::ConfigTreeNew const& pointsRoot,
 	                     std::vector<GeoLib::Point*>* points,
 	                     std::map<std::string, std::size_t>* &pnt_names );
 
 	/// Reads GeoLib::Polyline-objects from an xml-file
-	void readPolylines ( BaseLib::ConfigTree const& polylinesRoot,
+	void readPolylines ( BaseLib::ConfigTreeNew const& polylinesRoot,
 	                   std::vector<GeoLib::Polyline*>* polylines,
 	                   std::vector<GeoLib::Point*> const* points,
 	                   const std::vector<std::size_t>& pnt_id_map,
 	                   std::map<std::string, std::size_t>*& ply_names);
 
 	/// Reads GeoLib::Surface-objects from an xml-file
-	void readSurfaces  ( BaseLib::ConfigTree const& surfacesRoot,
+	void readSurfaces  ( BaseLib::ConfigTreeNew const& surfacesRoot,
 	                  std::vector<GeoLib::Surface*>* surfaces,
 	                  std::vector<GeoLib::Point*> const* points,
 	                  const std::vector<std::size_t>& pnt_id_map,
 	                  std::map<std::string, std::size_t>*& sfc_names);
 
-	void addSurfacesToPropertyTree(BaseLib::ConfigTree & pt);
-	void addPolylinesToPropertyTree(BaseLib::ConfigTree & geometry_set);
-
-	/// Check if the root node really specifies an GML file
-	bool isGmlFile( BaseLib::ConfigTree const& root) const;
+	void addSurfacesToPropertyTree(BaseLib::ConfigTreeNew::PTree & pt);
+	void addPolylinesToPropertyTree(BaseLib::ConfigTreeNew::PTree & geometry_set);
 
 	std::map<std::size_t, std::size_t> _idx_map;
 	GeoLib::GEOObjects &_geo_objects;
-- 
GitLab