From 0615f413c9274a998b0a85c2ddc3ec89ded84d8a Mon Sep 17 00:00:00 2001
From: Thomas Fischer <thomas.fischer@ufz.de>
Date: Tue, 18 Nov 2014 13:19:06 +0100
Subject: [PATCH] [ML] Move property implementation to separate file.

---
 MeshLib/Mesh.cpp                 |   6 +-
 MeshLib/Mesh.h                   |  71 +----------------
 MeshLib/Properties.h             | 130 +++++++++++++++++++++++++++++++
 Tests/MeshLib/MeshProperties.cpp |   4 +-
 4 files changed, 140 insertions(+), 71 deletions(-)
 create mode 100644 MeshLib/Properties.h

diff --git a/MeshLib/Mesh.cpp b/MeshLib/Mesh.cpp
index 9fd14af9d8c..3a881b17446 100644
--- a/MeshLib/Mesh.cpp
+++ b/MeshLib/Mesh.cpp
@@ -34,7 +34,8 @@ Mesh::Mesh(const std::string &name,
 	  _edge_length(std::numeric_limits<double>::max(), 0),
 	  _node_distance(std::numeric_limits<double>::max(), 0),
 	  _name(name), _nodes(nodes), _elements(elements),
-	  _n_base_nodes(n_base_nodes==0 ? nodes.size() : n_base_nodes)
+	  _n_base_nodes(n_base_nodes==0 ? nodes.size() : n_base_nodes),
+	  _properties(*this)
 {
 	assert(n_base_nodes <= nodes.size());
 	this->resetNodeIDs();
@@ -54,7 +55,8 @@ Mesh::Mesh(const Mesh &mesh)
 	  _edge_length(mesh._edge_length.first, mesh._edge_length.second),
 	  _node_distance(mesh._node_distance.first, mesh._node_distance.second),
 	  _name(mesh.getName()), _nodes(mesh.getNNodes()), _elements(mesh.getNElements()),
-	  _n_base_nodes(mesh.getNBaseNodes())
+	  _n_base_nodes(mesh.getNBaseNodes()),
+	  _properties(*this)
 {
 	const std::vector<Node*> nodes (mesh.getNodes());
 	const size_t nNodes (nodes.size());
diff --git a/MeshLib/Mesh.h b/MeshLib/Mesh.h
index 1766c680c16..b0da85d7213 100644
--- a/MeshLib/Mesh.h
+++ b/MeshLib/Mesh.h
@@ -28,7 +28,7 @@
 #include "BaseLib/Counter.h"
 
 #include "MeshEnums.h"
-#include "Location.h"
+#include "Properties.h"
 
 namespace MeshLib
 {
@@ -127,49 +127,8 @@ public:
 	/// Return true if the mesh has any nonlinear nodes
 	bool isNonlinear() const { return (getNNodes() != getNBaseNodes()); }
 
-	/// Method to get a vector of property values.
-	template <typename T>
-	boost::optional<std::vector<T> const&>
-	getProperty(std::string const& name) const
-	{
-		PropertyKeyType property_key(name, MeshItemType::Cell);
-		std::map<PropertyKeyType, boost::any>::const_iterator it(
-			_properties.find(property_key)
-		);
-		if (it != _properties.end()) {
-			try {
-				boost::any_cast<std::vector<T> const&>(it->second);
-				return boost::any_cast<std::vector<T> const&>(it->second);
-			} catch (boost::bad_any_cast const&) {
-				ERR("A property with the desired data type is not available.");
-				return boost::optional<std::vector<T> const&>();
-			}
-		} else {
-			return boost::optional<std::vector<T> const&>();
-		}
-	}
-
-	/// Method to store a vector of property values assigned to a property name.
-	/// Since the implementation makes no assumption about the number of data
-	/// items stored within the vector, it is possible either to use a small
-	/// number of properties where each particular property can be assigned to
-	/// several mesh items. In contrast to this it is possible to have a
-	/// separate value for each mesh item.
-	/// The user has to ensure the correct usage of the vector later on.
-	template <typename T>
-	void addProperty(std::string const& name, std::vector<T> const& property)
-	{
-		PropertyKeyType property_key(name, MeshItemType::Cell);
-		std::map<PropertyKeyType, boost::any>::const_iterator it(
-			_properties.find(property_key)
-		);
-		if (it != _properties.end()) {
-			WARN("A property of the name \"%s\" already assigned to the mesh.",
-				name.c_str());
-			return;
-		}
-		_properties[property_key] = boost::any(property);
-	}
+	MeshLib::Properties & getProperties() { return _properties; }
+	MeshLib::Properties const& getProperties() const { return _properties; }
 
 protected:
 	/// Set the minimum and maximum length over the edges of the mesh.
@@ -210,29 +169,7 @@ protected:
 	std::vector<Node*> _nodes;
 	std::vector<Element*> _elements;
 	std::size_t _n_base_nodes;
-
-	struct PropertyKeyType
-	{
-		PropertyKeyType(std::string const& n, MeshItemType t)
-			: name(n), mesh_item_type(t)
-		{}
-
-		std::string name;
-		MeshItemType mesh_item_type;
-
-		bool operator<(PropertyKeyType const& other) const
-		{
-			if (name.compare(other.name) == 0) {
-				return mesh_item_type < other.mesh_item_type;
-			}
-			return name.compare(other.name) < 0 ? true : false;
-		}
-	};
-
-	/// A mapping from property's name to the stored object of any type.
-	/// See addProperty() and getProperty() documentation.
-	std::map<PropertyKeyType, boost::any> _properties;
-
+	Properties _properties;
 }; /* class */
 
 } /* namespace */
diff --git a/MeshLib/Properties.h b/MeshLib/Properties.h
new file mode 100644
index 00000000000..c1fa9e09a8c
--- /dev/null
+++ b/MeshLib/Properties.h
@@ -0,0 +1,130 @@
+/**
+ * \file
+ * \brief  Definition of the class Properties that implements a container of
+ *         properties.
+ *
+ * \copyright
+ * Copyright (c) 2012-2014, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#ifndef PROPERTIES_H_
+#define PROPERTIES_H_
+
+#include <cstdlib>
+#include <string>
+#include <vector>
+#include <map>
+
+#include <boost/any.hpp>
+#include <boost/optional.hpp>
+
+#include "logog/include/logog.hpp"
+
+#include "Location.h"
+
+namespace MeshLib
+{
+// forward declaration
+class Mesh;
+
+/// Properties associated to mesh items (nodes or elements).
+class Properties
+{
+public:
+	explicit Properties(MeshLib::Mesh const& mesh)
+		: _mesh(mesh)
+	{}
+
+	/// Method to get a vector of property values.
+	template <typename T>
+	boost::optional<std::vector<T> const&>
+	getProperty(std::string const& name) const
+	{
+		PropertyKeyType property_key(name, MeshItemType::Cell);
+		std::map<PropertyKeyType, boost::any>::const_iterator it(
+			_properties.find(property_key)
+		);
+		if (it != _properties.end()) {
+			try {
+				boost::any_cast<std::vector<T> const&>(it->second);
+				return boost::any_cast<std::vector<T> const&>(it->second);
+			} catch (boost::bad_any_cast const&) {
+				ERR("A property with the desired data type is not available.");
+				return boost::optional<std::vector<T> const&>();
+			}
+		} else {
+			return boost::optional<std::vector<T> const&>();
+		}
+	}
+
+	/// Method to store a vector of property values assigned to a property name.
+	/// Since the implementation makes no assumption about the number of data
+	/// items stored within the vector, it is possible either to use a small
+	/// number of properties where each particular property can be assigned to
+	/// several mesh items. In contrast to this it is possible to have a
+	/// separate value for each mesh item.
+	/// The user has to ensure the correct usage of the vector later on.
+	template <typename T>
+	void addProperty(std::string const& name, std::vector<T> const& property)
+	{
+		PropertyKeyType property_key(name, MeshItemType::Cell);
+		std::map<PropertyKeyType, boost::any>::const_iterator it(
+			_properties.find(property_key)
+		);
+		if (it != _properties.end()) {
+			WARN("A property of the name \"%s\" already assigned to the mesh.",
+				name.c_str());
+			return;
+		}
+		_properties[property_key] = boost::any(property);
+	}
+
+	void removeProperty(std::string const& name,
+		MeshItemType mesh_item_type = MeshItemType::Cell)
+	{
+		PropertyKeyType property_key(name, mesh_item_type);
+		std::map<PropertyKeyType, boost::any>::const_iterator it(
+			_properties.find(property_key)
+		);
+		if (it == _properties.end()) {
+			WARN("A property of the name \"%s\" does not exist.",
+				name.c_str());
+			return;
+		}
+		_properties.erase(it);
+	}
+
+private:
+	struct PropertyKeyType
+	{
+		PropertyKeyType(std::string const& n, MeshItemType t)
+			: name(n), mesh_item_type(t)
+		{}
+
+		std::string name;
+		MeshItemType mesh_item_type;
+
+		bool operator<(PropertyKeyType const& other) const
+		{
+			if (name.compare(other.name) == 0) {
+				return mesh_item_type < other.mesh_item_type;
+			}
+			return name.compare(other.name) < 0 ? true : false;
+		}
+	};
+
+	/// Mesh object the properties are assigned to.
+	MeshLib::Mesh const& _mesh;
+	/// A mapping from property's name to the stored object of any type.
+	/// See addProperty() and getProperty() documentation.
+	std::map<PropertyKeyType, boost::any> _properties;
+}; // end class
+
+} // end namespace MeshLib
+
+#endif
+
diff --git a/Tests/MeshLib/MeshProperties.cpp b/Tests/MeshLib/MeshProperties.cpp
index 834597d3654..4d92c9e86e4 100644
--- a/Tests/MeshLib/MeshProperties.cpp
+++ b/Tests/MeshLib/MeshProperties.cpp
@@ -41,10 +41,10 @@ TEST_F(MeshLibMeshProperties, AddDoubleProperties)
 
 	std::string const& prop_name("FirstTestProperty");
 	// add a vector with property values to the mesh
-	mesh->addProperty(prop_name, double_properties);
+	mesh->getProperties().addProperty(prop_name, double_properties);
 
 	boost::optional<std::vector<double> const&>
-		double_properties_cpy(mesh->getProperty<double>(prop_name));
+		double_properties_cpy(mesh->getProperties().getProperty<double>(prop_name));
 
 	for (std::size_t k(0); k<size; k++) {
 		ASSERT_EQ(double_properties[k], (*double_properties_cpy)[k]);
-- 
GitLab