commit 020c18fef17a781c2687cf73c9fcf02865432fb0
Author: Marc Dequènes (Duck) <Duck@DuckCorp.org>
Date:   Fri Nov 13 01:24:47 2009 +0100

    [fix/cleanup] handle the 'root' element better (even if ActiveLdap seems not to behave properly with the root DSA)

diff --git a/TODO b/TODO
index c3c81c8..12f2ded 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,4 @@
-- ensure creating/modifying the root DSA object is possible (using the "root" handle" ?)
+- debug root DSA manipulation (show/modify does not reflect the current values)
 - improve configuration:
   * allow global relations to share them among objects ???
 - move (relocate) an item
diff --git a/bin/shadowwalker b/bin/shadowwalker
index e1e210d..bdecb1f 100755
--- a/bin/shadowwalker
+++ b/bin/shadowwalker
@@ -26,7 +26,6 @@ locale = ENV['LANGUAGE'] || ENV['LC_ALL'] || ENV['LC_MESSAGES'] || ENV['LANG']
 
 require 'ldap_shadows'
 require 'ldap_shadows/display_helper'
-require 'ldap_shadows/manipulation_helper'
 require 'cmdparse2'
 
 include LdapShadows
@@ -94,17 +93,16 @@ class Command < CmdParse::Command
     raise SyntaxError, _("no %s given") % name if args.empty?
 
     full_handle = args.shift
-    m = LdapShadows::Elements::LdapObject.looks_like_full_handle?(full_handle)
+    m = LdapShadows::Manipulation.looks_like_full_handle?(full_handle)
     raise SyntaxError, _("bad %s") % name unless m
-    obj_hdl = m[1].downcase
+    obj_hdl = m[1]
     item_hdl = m[2]
 
-    split_args = [obj_hdl, item_hdl]
-    obj_klass = params_shift_object_handle(split_args)
     if fetch_item
-      item = params_shift_item_handle(obj_klass, split_args)
-      [obj_klass, item]
+      item = LdapShadows::Manipulation.find_item_by_full_handle($shadow, full_handle)
+      [item.class, item]
     else
+      obj_klass = params_shift_object_handle([obj_hdl])
       [obj_klass, item_hdl]
     end
   end
diff --git a/lib/ldap_shadows/elements/object.rb b/lib/ldap_shadows/elements/object.rb
index 82f8afe..a38d7f7 100755
--- a/lib/ldap_shadows/elements/object.rb
+++ b/lib/ldap_shadows/elements/object.rb
@@ -17,12 +17,15 @@
 #++
 
 
+require 'ldap_shadows/manipulation_helper'
+
+
 module LdapShadows
 module Elements
   class LdapObject < ActiveLdap::Base
     include LdapElement
 
-    FULL_HANDLE_PATTERN = /^([a-zA-Z_]+)\/(.+)$/
+    FULL_HANDLE_PATTERN = /^(?:root|([a-zA-Z_]+)\/(.+))$/
 
     attr_reader :parent_changed
 
@@ -52,11 +55,6 @@ module Elements
       "#{self.class.handle}/#{self.handle}"
     end
 
-    def self.looks_like_full_handle?(full_handle)
-      full_handle =~ FULL_HANDLE_PATTERN
-      $~
-    end
-
     def self.cast
       super
 
@@ -423,7 +421,10 @@ module Elements
         raise SyntaxError, _("Unknown operator '%s'") % op
       end
 
-      parent_item = self.class.find_by_full_handle(parent_full_handle)
+      unless Manipulation.looks_like_full_handle?(parent_full_handle)
+        raise PreProcessingError, _("Parent for the item is not a full handle")
+      end
+      parent_item = Manipulation.find_item_by_full_handle(self.class.shadow, parent_full_handle)
 
       if self.new_entry?
         self.base = parent_item.dn_obj - parent_item.class.base_obj
@@ -435,34 +436,6 @@ module Elements
       @latest_parent_full_handle = parent_full_handle
     end
 
-    def self.find_by_full_handle(full_handle)
-      if full_handle == "root" and LdapShadows.const_defined?('Manipulation')
-        raw_item_dn = ActiveLdap::Base.base.to_s
-        raw_item = ActiveLdap::Base.find(:first, :base => raw_item_dn, :scope => :base)
-        info = LdapShadows::Manipulation.raw_item_info(self.shadow, raw_item, raw_item_dn)
-        if info.nil?
-          raise PreProcessingError, _("No such item 'root'")
-        elsif info[:object].nil?
-          raise PreProcessingError, _("Root item found, but no corresponding object defined")
-        else
-          full_handle = info[:full_handle]
-        end
-      end
-
-      raise SyntaxError, _("Bad handle '%s'") % full_handle unless full_handle =~ FULL_HANDLE_PATTERN
-      obj_hdl = $1.downcase.singularize
-      item_hdl = $2
-
-      obj_klass = self.shadow.get_object(obj_hdl)
-      raise PreProcessingError, _("No such object '%s'") % obj_hdl if obj_klass.nil?
-
-      begin
-        obj_klass.find(item_hdl, :attributes => [""])
-      rescue ActiveLdap::EntryNotFound
-        raise PreProcessingError, _("No such item '%s/%s'") % [obj_klass.handle, item_hdl]
-      end
-    end
-
     def add_aspect(aspect_name)
       return unless self.class.possible_aspects.include?(aspect_name)
 
@@ -590,8 +563,12 @@ module Elements
       if self.new_entry? and not self.parent_changed
         parent_full_handle = self.class.parameters[:mapping][:default_parent]
         if parent_full_handle
+          unless Manipulation.looks_like_full_handle?(parent_full_handle)
+            raise PreProcessingError, _("Default parent for the item is not a full handle")
+          end
+
           begin
-            parent_item = self.class.find_by_full_handle(parent_full_handle)
+            parent_item = Manipulation.find_item_by_full_handle(self.class.shadow, parent_full_handle)
             self.base = parent_item.dn_obj - parent_item.class.base_obj
           rescue
             raise PreProcessingError, _("Cannot create the item: bad default parent for this kind of object: %s") % $!
diff --git a/lib/ldap_shadows/manipulation_helper.rb b/lib/ldap_shadows/manipulation_helper.rb
index d2c84a1..a8467b1 100644
--- a/lib/ldap_shadows/manipulation_helper.rb
+++ b/lib/ldap_shadows/manipulation_helper.rb
@@ -130,6 +130,42 @@ module LdapShadows
       end
     end
 
+    def self.looks_like_full_handle?(full_handle)
+      full_handle =~ LdapShadows::Elements::LdapObject::FULL_HANDLE_PATTERN
+      res = $~
+      res = res.to_a if res
+      res
+    end
+
+    def self.find_item_by_full_handle(shadow, full_handle)
+      if full_handle == "root"
+        raw_item_dn = ActiveLdap::Base.base.to_s
+        raw_item = ActiveLdap::Base.find(:first, :base => raw_item_dn, :scope => :base)
+        info = raw_item_info(shadow, raw_item, raw_item_dn)
+        if info.nil?
+          raise PreProcessingError, _("No such item 'root'")
+        elsif info[:object].nil?
+          raise PreProcessingError, _("Root item found, but no corresponding object defined")
+        else
+          full_handle = info[:full_handle]
+        end
+      end
+
+      m = looks_like_full_handle?(full_handle)
+      raise SyntaxError, _("Bad handle '%s'") % full_handle unless m
+      obj_hdl = m[1].downcase.singularize
+      item_hdl = m[2]
+
+      obj_klass = shadow.get_object(obj_hdl)
+      raise PreProcessingError, _("No such object '%s'") % obj_hdl if obj_klass.nil?
+
+      begin
+        obj_klass.find(item_hdl, :attributes => [""])
+      rescue ActiveLdap::EntryNotFound
+        raise PreProcessingError, _("No such item '%s/%s'") % [obj_klass.handle, item_hdl]
+      end
+    end
+
     protected
 
     def self.ldap_search_string_field(field, op, val)
