commit 7414a658751edfa655cedee01a9304ce19c8fc38
Author: Marc Dequènes (Duck) <Duck@DuckCorp.org>
Date:   Tue Nov 10 09:36:49 2009 +0100

    [evol] better parent definition for new items (not tested yet)

diff --git a/bin/shadowwalker b/bin/shadowwalker
index 33d26d6..136bb53 100755
--- a/bin/shadowwalker
+++ b/bin/shadowwalker
@@ -340,7 +340,7 @@ class ModifyCommand < Command
 
     self.short_desc = "Modify attributes of an item"
     self.usages_params = [
-                          "<item-full-handle> (<field>|<relation>|:aspects)(=|+=|-=)<value> [(<field>|<relation>|:aspects)(=|+=|-=)<value>] ..."
+                          "<item-full-handle> (<field>|<relation>|:aspects)(=|+=|-=)<value> [(<field>|<relation>|:aspects|:parent)(=|+=|-=)<value>] ..."
                          ]
   end
 
@@ -396,7 +396,7 @@ class CreateCommand < Command
 
     self.short_desc = "Create an item"
     self.usages_params = [
-                          "<new-item-full-handle> <parent-item-full-handle> [<field>=<value>] ..."
+                          "<new-item-full-handle> <parent-item-full-handle> [<field>=<value>|<relation>|:aspects|:parent)(=|+=|-=)<value>] ..."
                          ]
   end
 
@@ -404,24 +404,13 @@ class CreateCommand < Command
     super
 
     obj_klass, item_hdl = params_shift_item_handle_full_handle(args, false)
-    loc_obj_klass, loc_item = params_shift_item_handle_full_handle(args, true, "parent full-handle")
-
-    # TODO: move this in LdapShadows::Manipulation
-    p_hdl_restr = obj_klass.parameters[:mapping][:parent_handle_restrictions]
-    unless p_hdl_restr.nil? or loc_item.full_handle =~ Regexp.new(p_hdl_restr)
-      raise PreProcessingError, _("This parent can't raise such a child (handle restrictions)")
-    end
-    p_dn_restr = obj_klass.parameters[:mapping][:parent_dn_restrictions]
-    unless p_dn_restr.nil? or loc_item.dn =~ Regexp.new(p_dn_restr)
-      raise PreProcessingError, _("This parent can't raise such a child (DN restrictions)")
-    end
-
     item = obj_klass.new(item_hdl)
-    item.base = loc_item.dn_obj - obj_klass.base_obj
 
     modification_done = LdapShadows::Manipulation.item_modify_from_strings(item, args)
 
-    #item.save!
+    # TODO: use default parent for such object if defined (-> predefined hook)
+    # TODO: detect if parent specified and allowed (-> predefined hook)
+    item.save!
     puts "Creation done."
   end
 end
diff --git a/lib/ldap_shadows/elements/object.rb b/lib/ldap_shadows/elements/object.rb
index cc23663..12450b2 100755
--- a/lib/ldap_shadows/elements/object.rb
+++ b/lib/ldap_shadows/elements/object.rb
@@ -238,6 +238,8 @@ module Elements
         case field
         when 'aspects'
           modify_aspects(op, val)
+        when 'parent'
+          modify_parent(op, val)
         else
           raise PreProcessingError, _("Unknown core field '%s'") % field
         end
@@ -396,6 +398,42 @@ module Elements
       true
     end
 
+    def modify_parent(op, parent_full_handle)
+      case op
+      when '+=', '-='
+        raise PreProcessingError, _("This operator is not possible for parent")
+      else
+        raise SyntaxError, _("Unknown operator '%s'") % op
+      end
+
+      # TODO: provide such facilities elsewhere
+      raise SyntaxError, _("Bad handle '%s' for parent") % name unless parent_full_handle =~ /^([a-zA-Z]+)\/(.+)$/
+      parent_obj_hdl = $1.downcase.singularize
+      parent_item_hdl = $2
+      parent_obj_klass = self.class.shadow.get_object(parent_obj_hdl)
+      raise PreProcessingError, _("No such object '%s'") % parent_obj_hdl if parent_obj_klass.nil?
+      begin
+        parent_item = parent_obj_klass.find(parent_item_hdl, :attributes => attr_list)
+      rescue ActiveLdap::EntryNotFound
+        raise PreProcessingError, _("No such item '%s/%s'") % [parent_obj_klass.handle, parent_item_hdl]
+      end
+
+      p_hdl_restr = self.class.parameters[:mapping][:parent_handle_restrictions]
+      unless p_hdl_restr.nil? or parent_full_handle =~ Regexp.new(p_hdl_restr)
+        raise PreProcessingError, _("This parent can't raise such a child (handle restrictions)")
+      end
+      p_dn_restr = self.class.parameters[:mapping][:parent_dn_restrictions]
+      unless p_dn_restr.nil? or parent_item.dn =~ Regexp.new(p_dn_restr)
+        raise PreProcessingError, _("This parent can't raise such a child (DN restrictions)")
+      end
+
+      if self.new_entry?
+        self.base = parent_item.dn_obj - parent_obj_klass.base_obj
+      else
+        raise PreProcessingError, _("Moving items is not yet implemented")
+      end
+    end
+
     def add_aspect(aspect_name)
       return unless self.class.possible_aspects.include?(aspect_name)
 
