commit 1c89625f86dc33b7cff7f63ceb1e73da27eeb073
Author: Marc Dequènes (Duck) <Duck@DuckCorp.org>
Date:   Sat Aug 14 21:33:24 2010 +0200

    [evol] work on cyborg server protocol and API #5 (refs #31)

diff --git a/bin/mapmaker b/bin/mapmaker
index 44bda84..5dfebd9 100755
--- a/bin/mapmaker
+++ b/bin/mapmaker
@@ -48,7 +48,7 @@ module CyborgHood
       include SimpleServer
 
       def interface
-        MapMakerInterface
+        MapMakerInterface.instance
       end
     end
 
diff --git a/lib/cyborghood/cyborg/interface.rb b/lib/cyborghood/cyborg/interface.rb
index 5164e2a..40fa7cc 100644
--- a/lib/cyborghood/cyborg/interface.rb
+++ b/lib/cyborghood/cyborg/interface.rb
@@ -26,37 +26,27 @@ module CyborgHood
       base.extend(ClassMethods)
     end
 
-    module ClassMethods
-      def decompose_command(cmd)
-        object, method = cmd.split('.', 2)
-
-        if method
-          begin
-            klass = object.split('::').inject(self) {|scope, const_name| scope.const_get(const_name)}
-          rescue
-            return
-          end
+    def find_node_action(node_name)
+      next_node_name, other_nodes_names = node_name.split('.', 2)
+
+      next_node_klass = api_klasses[next_node_name]
+      if next_node_klass.nil?
+        if api_methods.include? next_node_name
+          next_node_method = self.method(next_node_name)
+          return next_node_method if other_nodes_names.nil?
+          next_node = next_node_method.call
         else
-          if object.index("::")
-            return
-          else
-            klass = self
-            method = cmd
-          end
+          return
         end
-
-        [klass, method]
+      else
+        next_node = next_node_klass.instance
+        return next_node.method('api_nodes') if other_nodes_names.nil?
       end
 
-      def has_node?(cmd)
-        klass, method = self.decompose_command(cmd)
-        return false if klass.nil?
-        return true if method.nil?
-
-        inst = klass.instance
-        inst.api_methods.include?(method)
-      end
+      next_node.find_node_action(other_nodes_names)
+    end
 
+    module ClassMethods
       attr_accessor :exported_methods
       attr_accessor :auto_export_public_instance_methods
 
@@ -74,11 +64,12 @@ module CyborgHood
       self.class.auto_export_public_instance_methods = true
     end
 
-    def api_modules
-      @modules ||= self.class.constants.select do |c|
+    def api_klasses
+      list = self.class.constants.collect do |c|
         cc = self.class.const_get(c)
-        cc.class == Class and cc.ancestors.include? CyborgServerInterface
-      end
+        (cc.class == Class and cc.ancestors.include? CyborgServerInterface) ? [c, cc] : nil
+      end.compact
+      Hash[list]
     end
 
     def api_methods
@@ -87,16 +78,14 @@ module CyborgHood
       methods & self.methods
     end
 
+    def api_nodes
+      (api_klasses.keys + api_methods).sort
+    end
+
     # preliminary incoming message handling
     def call(cmd, data)
-      klass, method = self.class.decompose_command(cmd)
-      return "551 unknown object" if klass.nil?
-
-      inst = klass.instance
-
-      unless inst.api_methods.include?(method)
-        return "551 this object has no such method"
-      end
+      action = find_node_action(cmd)
+      return "551 unknown node" if action.nil?
 
       if data.nil?
         formated_data = []
@@ -104,7 +93,7 @@ module CyborgHood
         begin
           formated_data = YAML.load(data) unless data.nil?
         rescue
-          return "552 unreadable data for arguments"
+          return "552 unreadable YAML data for arguments"
         end
 
         return "552 wrong format for arguments" unless formated_data.is_a? Array
@@ -112,9 +101,9 @@ module CyborgHood
 
       begin
         # preliminary outgoing message handling
-        inst.send(method, *formated_data).to_yaml
+        action.call(*formated_data).to_yaml
       rescue
-        return "550 method call failed"
+        return "550 method call failed: " + $!
       end
     end
   end
diff --git a/lib/cyborghood/cyborg/server.rb b/lib/cyborghood/cyborg/server.rb
index 42ddfb1..c63e1a8 100644
--- a/lib/cyborghood/cyborg/server.rb
+++ b/lib/cyborghood/cyborg/server.rb
@@ -129,7 +129,7 @@ module CyborgHood
 
           if flags.index '?'
             send_line "250+ ok"
-            send_line({'exists?' => @interface.has_node?(cmd)}.to_yaml)
+            send_line({'exists?' => @interface.find_node_action(cmd)}.to_yaml)
             return
           end
 
@@ -144,7 +144,7 @@ module CyborgHood
 
     def receive_command(cmd, data = nil)
       logger.debug "Executing command '#{cmd}' [#{identifier}]"
-      send_line @interface.instance.call(cmd, data)
+      send_line @interface.call(cmd, data)
     end
 
     def receive_error(msg)
@@ -215,7 +215,7 @@ module CyborgHood
     end
 
     def interface
-      EmptyInterface
+      EmptyInterface.instance
     end
   end
 end
