From 7927c3da2eb04f6969af7afc6cfc5a83ade89565 Mon Sep 17 00:00:00 2001
From: florent <florent@laas.fr>
Date: Thu, 21 Oct 2010 17:55:44 +0200
Subject: [PATCH] Implement command

	  * include/CMakeLists.txt,
	  * include/dynamic-graph/command.h: new,
	* include/dynamic-graph/entity.h,
	* include/dynamic-graph/parameter.h: new,
	* include/dynamic-graph/value.h: new,
	* src/command/command.cpp: new,
	* src/command/value.cpp: new,
	* src/dgraph/entity.cpp.
---
 include/CMakeLists.txt            |  4 ++
 include/dynamic-graph/command.h   | 63 +++++++++++++++++++++++
 include/dynamic-graph/entity.h    | 13 +++++
 include/dynamic-graph/parameter.h | 18 +++++++
 include/dynamic-graph/value.h     | 83 +++++++++++++++++++++++++++++++
 src/command/command.cpp           | 75 ++++++++++++++++++++++++++++
 src/command/value.cpp             | 75 ++++++++++++++++++++++++++++
 src/dgraph/entity.cpp             | 24 +++++++++
 8 files changed, 355 insertions(+)
 create mode 100644 include/dynamic-graph/command.h
 create mode 100644 include/dynamic-graph/parameter.h
 create mode 100644 include/dynamic-graph/value.h
 create mode 100644 src/command/command.cpp
 create mode 100644 src/command/value.cpp

diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index 008cc9f..0ac0e40 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -65,6 +65,10 @@ all-signals.h
 
 tracer.h
 tracer-real-time.h
+
+command.h
+value.h
+parameter.h
 )
 
 # Recreate correct path for the headers
diff --git a/include/dynamic-graph/command.h b/include/dynamic-graph/command.h
new file mode 100644
index 0000000..3f0d02f
--- /dev/null
+++ b/include/dynamic-graph/command.h
@@ -0,0 +1,63 @@
+//
+// Copyright 2010 CNRS
+//
+// Author: Florent Lamiraux
+//
+// This file is part of dynamic-graph.
+// dynamic-graph is free software: you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+// dynamic-graph is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Lesser General Public License for more details.  You should
+// have received a copy of the GNU Lesser General Public License along
+// with dynamic-graph.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef DYNAMIC_GRAPH_COMMAND_H
+#define DYNAMIC_GRAPH_COMMAND_H
+
+#include <vector>
+#include "dynamic-graph/value.h"
+#include "dynamic-graph/dynamic-graph-api.h"
+
+namespace dynamicgraph {
+  class Entity;
+  namespace command {
+    /// Abstract class for entity commands
+    ///
+    /// This class provide a mean to control entities from external python script.
+    /// A command has several parameters (dynamicgraph::parameter) that can take
+    /// various types of values (dynamicgraph::Value).
+
+    class DYNAMICGRAPH_EXPORT Command
+    {
+    public:
+      virtual ~Command();
+      /// Store the owner entity and a vector of value types
+      /// \param entity reference to Entity owning this command.
+      /// \param valueTypes vector specifying the number and types of parameters
+      Command(Entity& entity, const std::vector<Value::Type>& valueTypes);
+      /// Return the value type of all parameters
+      const std::vector<Value::Type>& valueTypes() const;
+      /// Set parameter values
+      void setParameterValues(const std::vector<Value>& values);
+      /// Get parameter values
+      const std::vector<Value> getParameterValues();
+      /// Execute the command after checking parameters
+      Value execute();
+      /// Get a reference to the Entity owning this command
+      Entity& owner();
+    protected:
+      /// Specific action performed by the command
+      virtual Value doExecute() = 0;
+    private:
+      Entity& owner_;
+      std::vector<Value::Type> valueTypeVector_;
+      std::vector<Value> valueVector_;
+    };
+  } // namespace command
+} // namespace dynamicgraph
+
+#endif //DYNAMIC_GRAPH_COMMAND_H
diff --git a/include/dynamic-graph/entity.h b/include/dynamic-graph/entity.h
index 2a215e0..c1c5f4d 100644
--- a/include/dynamic-graph/entity.h
+++ b/include/dynamic-graph/entity.h
@@ -41,6 +41,10 @@
 
 /* NAMESPACE */
 namespace dynamicgraph {
+  // Forward declaration
+  namespace command {
+    class Command;
+  };
 
 /* --------------------------------------------------------------------- */
 /* --- CLASS ----------------------------------------------------------- */
@@ -97,6 +101,15 @@ class DYNAMIC_GRAPH_DLLAPI Entity
   virtual void test2( SignalBase<int>* ) { return ; }
 
   virtual const std::string& getCommandList( void ) const;
+  /// Return the list of command objects
+  virtual std::map<const std::string, command::Command*>
+    getNewStyleCommandMap();
+ protected:
+  /// Add a command to Entity
+  virtual void addCommand(const std::string& name,
+			  command::Command* command);
+ private:
+  std::map<const std::string, command::Command*> commandMap;
 };
 
 DYNAMIC_GRAPH_DLLAPI std::ostream& operator<< (std::ostream& os, const dynamicgraph::Entity& ent );
diff --git a/include/dynamic-graph/parameter.h b/include/dynamic-graph/parameter.h
new file mode 100644
index 0000000..719aa08
--- /dev/null
+++ b/include/dynamic-graph/parameter.h
@@ -0,0 +1,18 @@
+#ifndef DYNAMIC_GRAPH_PARAMETER_H
+#define DYNAMIC_GRAPH_PARAMETER_H
+
+#include <boost/static_assert.hpp>
+#include "dynamicgraph/exception-abstract.h"
+
+namespace dynamicgraph {
+  namespace command {
+    class Parameter {
+    public:
+      Parameter(Value::Type valueType) : valueType_(valueType) {}
+      /// Return value type of parameter
+      Value::Type valueType() { return valueType_;}
+    private:
+      Value::Type valueType_;
+    }; // class Parameter
+  } // namespace command
+} //namespace dynamicgraph
diff --git a/include/dynamic-graph/value.h b/include/dynamic-graph/value.h
new file mode 100644
index 0000000..6e151de
--- /dev/null
+++ b/include/dynamic-graph/value.h
@@ -0,0 +1,83 @@
+//
+// Copyright 2010 CNRS
+//
+// Author: Florent Lamiraux
+//
+// This file is part of dynamic-graph.
+// dynamic-graph is free software: you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+// dynamic-graph is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Lesser General Public License for more details.  You should
+// have received a copy of the GNU Lesser General Public License along
+// with dynamic-graph.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef DYNAMIC_GRAPH_VALUE_H
+#define DYNAMIC_GRAPH_VALUE_H
+
+#include <iostream>
+#include <string>
+#include <cassert>
+#include <typeinfo>
+#include "dynamic-graph/dynamic-graph-api.h"
+
+namespace dynamicgraph {
+  namespace command {
+    class DYNAMICGRAPH_EXPORT Value {
+    public:
+      enum Type {
+	NONE,
+	INT,
+	DOUBLE,
+	STRING,
+	NB_TYPES
+      };
+      /// template constructor
+      template <class T> Value(const T& value);
+      /// Copy constructor
+      Value(const Value& value);
+      // Construct an empty value (None)
+      Value();
+      /// Return the type of the value
+      Type type() const;
+
+      /// Return the value if it is a double and throw otherwise
+      const double& doubleValue () const;
+      /// Return the value if it is a int and throw otherwise
+      const int& intValue () const;
+      /// Return the value if it is a string and throw otherwise
+      const std::string& stringValue () const;
+      /// Return the name of the type
+      static std::string typeName(Type type);
+    private:
+      Type type_;
+      const void* value_;
+    };
+
+    // Template constructors
+    template <> Value::Value(const int& value)
+    {
+      value_ = &value;
+      type_ = INT;
+    }
+    template <> Value::Value(const double& value)
+    {
+      value_ = &value;
+      type_ = DOUBLE;
+    }
+    template <> Value::Value(const std::string& value)
+    {
+      value_ = &value;
+      type_ = STRING;
+    }
+    template <class T> Value::Value(const T& value)
+    {
+      assert(false);
+    }
+  } // namespace command
+} //namespace dynamicgraph
+
+#endif //DYNAMIC_GRAPH_VALUE_H
diff --git a/src/command/command.cpp b/src/command/command.cpp
new file mode 100644
index 0000000..e0c1745
--- /dev/null
+++ b/src/command/command.cpp
@@ -0,0 +1,75 @@
+//
+// Copyright 2010 CNRS
+//
+// Author: Florent Lamiraux
+//
+// This file is part of dynamic-graph.
+// dynamic-graph is free software: you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+// dynamic-graph is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Lesser General Public License for more details.  You should
+// have received a copy of the GNU Lesser General Public License along
+// with dynamic-graph.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <sstream>
+#include "dynamic-graph/command.h"
+#include "dynamic-graph/exception-abstract.h"
+
+namespace dynamicgraph {
+  namespace command {
+
+    Command::~Command() {}
+    Command::Command(Entity& entity,
+		     const std::vector<Value::Type>& valueTypes) : 
+      owner_(entity), valueTypeVector_(valueTypes)
+    {
+    }
+
+    const std::vector<Value::Type>& Command::valueTypes() const
+    {
+      return valueTypeVector_;
+    }
+
+    void Command::setParameterValues(const std::vector<Value>& values)
+    {
+      unsigned int size = values.size();
+      const std::vector<Value::Type>& paramTypes = valueTypes();
+      // Check that number of parameters is correct
+      if (values.size() != paramTypes.size()) {
+	throw ExceptionAbstract(ExceptionAbstract::ABSTRACT,
+				"wrong number of parameters");
+      }
+      // Check that each parameter is of correct type
+      for (unsigned int iParam=0; iParam < values.size(); iParam++) {
+	if (values[iParam].type() != paramTypes[iParam]) {
+	  std::stringstream ss;
+	  ss << "argument " << iParam << "is of wrong type: "
+	     << Value::typeName(paramTypes[iParam]) << " expected, got "
+	     << Value::typeName(values[iParam].type());
+	  throw ExceptionAbstract(ExceptionAbstract::TOOLS, ss.str());
+	}
+      }
+      // Copy vector of values in private part
+      valueVector_ = values;
+    }
+
+    const std::vector<Value> Command::getParameterValues()
+    {
+      return valueVector_;
+    }
+
+    Value Command::execute()
+    { 
+      return doExecute();
+    }
+
+    Entity& Command::owner()
+    {
+      return owner_;
+    }
+  } // namespace command
+} //namespace dynamicgraph
diff --git a/src/command/value.cpp b/src/command/value.cpp
new file mode 100644
index 0000000..06fd51d
--- /dev/null
+++ b/src/command/value.cpp
@@ -0,0 +1,75 @@
+//
+// Copyright 2010 CNRS
+//
+// Author: Florent Lamiraux
+//
+// This file is part of dynamic-graph.
+// dynamic-graph is free software: you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public License
+// as published by the Free Software Foundation, either version 3 of
+// the License, or (at your option) any later version.
+// dynamic-graph is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Lesser General Public License for more details.  You should
+// have received a copy of the GNU Lesser General Public License along
+// with dynamic-graph.  If not, see <http://www.gnu.org/licenses/>.
+
+#include "dynamic-graph/value.h"
+#include "dynamic-graph/exception-abstract.h"
+
+namespace dynamicgraph {
+  namespace command {
+
+    Value::Value(const Value& value) : type_(value.type_),
+				       value_(value.value_)
+    {
+    }
+
+    Value::Value() : type_(NONE), value_(NULL)
+    {
+    }
+
+    Value::Type Value::type() const
+    {
+      return type_;
+    }
+
+    const double& Value::doubleValue () const 
+    {
+      if (type_ == DOUBLE)
+	return *(static_cast<const double*>(value_));
+      throw ExceptionAbstract(ExceptionAbstract::TOOLS,
+			      "value is not a double");
+    }
+
+    const int& Value::intValue () const
+    {
+      if (type_ == INT)
+	return *(static_cast<const int*>(value_));
+      throw ExceptionAbstract(ExceptionAbstract::TOOLS,
+			      "value is not an int");
+    }
+    
+    const std::string& Value::stringValue () const
+    {
+      if (type_ == STRING)
+	return *(static_cast<const std::string*>(value_));
+      throw ExceptionAbstract(ExceptionAbstract::TOOLS,
+			      "value is not an string");
+    }
+    
+    std::string Value::typeName(Type type)
+    {
+      switch (type) {
+      case INT:
+	return std::string("int");
+      case DOUBLE:
+	return std::string("double");
+      case STRING:
+	return std::string("string");
+      }
+      return std::string("unknown");
+    }
+  } // namespace command
+} //namespace dynamicgraph
diff --git a/src/dgraph/entity.cpp b/src/dgraph/entity.cpp
index 02764fa..b71fdc6 100644
--- a/src/dgraph/entity.cpp
+++ b/src/dgraph/entity.cpp
@@ -23,6 +23,7 @@
 #include <dynamic-graph/pool.h>
 #include <dynamic-graph/pool.h>
 #include <dynamic-graph/debug.h>
+#include <dynamic-graph/command.h>
 
 /*! System includes */
 #include <stdlib.h>
@@ -31,6 +32,7 @@
 
 using namespace std;
 using namespace dynamicgraph;
+using dynamicgraph::command::Command;
 
 const std::string Entity::CLASS_NAME = "Entity";
 
@@ -70,6 +72,10 @@ Entity::
 {
   dgDEBUG(25) << "# In (" << name << " { " << endl;
   entityDeregistration();
+  for (std::map<const std::string, Command*>::iterator it =
+	 commandMap.begin(); it != commandMap.end(); it++) {
+    delete it->second;
+  }
   dgDEBUGOUT(25);
 }
 
@@ -267,3 +273,21 @@ commandLine( const std::string& cmdLine,std::istringstream& cmdArgs,std::ostream
     }
 
 }
+
+void Entity::
+addCommand(const std::string& inName, Command* command)
+{
+  if (commandMap.count(inName) != 0) {
+    DG_THROW ExceptionFactory(ExceptionFactory::OBJECT_CONFLICT,
+			      "Command " + inName + 
+			      " already registered in Entity.");
+  }
+  std::pair<const std::string, Command*> item(inName, command);
+  commandMap.insert(item);
+}
+
+std::map<const std::string, Command*> Entity::
+getNewStyleCommandMap()
+{
+  return commandMap;
+}
-- 
GitLab