commit 9821799643b84c1515f3c342036686bd3a266f73
Author: Marc Dequènes (Duck) <Duck@DuckCorp.org>
Date:   Thu Jun 24 00:46:23 2010 +0200

    [evol] switched to a higher activeldap library (closes #27)

diff --git a/conf/ldap_shadows/shadows/MilkyPond/aspects/fs.conf b/conf/ldap_shadows/shadows/MilkyPond/aspects/fs.conf
index 749cedb..92c5af6 100644
--- a/conf/ldap_shadows/shadows/MilkyPond/aspects/fs.conf
+++ b/conf/ldap_shadows/shadows/MilkyPond/aspects/fs.conf
@@ -12,7 +12,7 @@ relations:
     type: belongs_to
     object: group
     many: uniqueMember
-    foreign_key: dn
+    primary_key: dn
 plugin:
   min_uid: 10000
   max_uid: 65535
diff --git a/conf/ldap_shadows/shadows/MilkyPond/objects/group.conf b/conf/ldap_shadows/shadows/MilkyPond/objects/group.conf
index b10f739..8eebef3 100644
--- a/conf/ldap_shadows/shadows/MilkyPond/objects/group.conf
+++ b/conf/ldap_shadows/shadows/MilkyPond/objects/group.conf
@@ -13,12 +13,12 @@ relations:
     type: belongs_to
     object: individual
     many: gidNumber
-    foreign_key: gidNumber
+    primary_key: gidNumber
   botsPrimaryMembers:
     type: belongs_to
     object: bot
     many: gidNumber
-    foreign_key: gidNumber
+    primary_key: gidNumber
   individualsSecondaryMembers:
     type: has_many
     object: individual
diff --git a/data/ldap_shadows/schema/aspect.yaml b/data/ldap_shadows/schema/aspect.yaml
index d52d836..10bfba2 100644
--- a/data/ldap_shadows/schema/aspect.yaml
+++ b/data/ldap_shadows/schema/aspect.yaml
@@ -33,7 +33,7 @@ mapping:
         mapping:
           "type": {type: str, required: true, enum: [belongs_to, has_many]}
           "object": {type: str, required: true}
-          "foreign_key": {type: str, required: true}
+          "foreign_key": {type: str}
           "many": {type: str}
           "primary_key": {type: str}
   "plugin":
diff --git a/data/ldap_shadows/schema/object.yaml b/data/ldap_shadows/schema/object.yaml
index f3ee200..727351b 100644
--- a/data/ldap_shadows/schema/object.yaml
+++ b/data/ldap_shadows/schema/object.yaml
@@ -43,7 +43,7 @@ mapping:
         mapping:
           "type": {type: str, required: true, enum: [belongs_to, has_many]}
           "object": {type: str, required: true}
-          "foreign_key": {type: str, required: true}
+          "foreign_key": {type: str}
           "many": {type: str}
           "primary_key": {type: str}
   "plugin":
diff --git a/lib/ldap_shadows/activeldap_fixes.rb b/lib/ldap_shadows/activeldap_fixes.rb
index ef9d196..47419a7 100644
--- a/lib/ldap_shadows/activeldap_fixes.rb
+++ b/lib/ldap_shadows/activeldap_fixes.rb
@@ -17,105 +17,6 @@
 #++
 
 module ActiveLdap
-  # patch for activeldap#26824
-  class Schema
-    class Attribute
-      # operational?
-      #
-      # Returns true if an attribute is operational
-      # USAGE contains directoryOperation
-      # Duck: new method
-      def operational?
-        @operational
-      end
-
-      def collect_info
-        @description = attribute("DESC")[0]
-        @super_attribute = attribute("SUP")[0]
-        if @super_attribute
-          @super_attribute = @schema.attribute(@super_attribute)
-          @super_attribute = nil if @super_attribute.id.nil?
-        end
-        @read_only = attribute('NO-USER-MODIFICATION')[0] == 'TRUE'
-        @single_value = attribute('SINGLE-VALUE')[0] == 'TRUE'
-        @syntax = attribute("SYNTAX")[0]
-        @syntax = @schema.ldap_syntax(@syntax) if @syntax
-        if @syntax
-          @binary_required = @syntax.binary_transfer_required?
-          @binary = (@binary_required or !@syntax.human_readable?)
-          @derived_syntax = @syntax
-        else
-          @binary_required = false
-          @binary = false
-          @derived_syntax = nil
-          @derived_syntax = @super_attribute.syntax if @super_attribute
-        end
-        # Duck: newly collected data
-        @operational = attribute("USAGE").include?("directoryOperation")
-      end
-    end
-  end
-
-  class Base
-    # temporary method until active_ldap is fixed: return a DN object (see activeldap#23932)
-    def dn_obj
-      ActiveLdap::DistinguishedName.parse(self.dn)
-    end
-
-    # temporary method until active_ldap is fixed: return a DN object (see activeldap#23932)
-    def self.base_obj
-      ActiveLdap::DistinguishedName.parse(self.base)
-    end
-
-    # patch for activeldap#26745
-    def collect_modified_attributes(ldap_data, data)
-      attributes = []
-      # Now that all the options will be treated as unique attributes
-      # we can see what's changed and add anything that is brand-spankin'
-      # new.
-      ldap_data.each do |k, v|
-        next if schema.attribute(k).read_only?
-
-        value = data[k] || []
-
-        next if v == value
-
-        x = value
-        value = self.class.remove_blank_value(value) || []
-        next if v == value
-
-        # Create mod entries
-        if self.class.blank_value?(value)
-          # Since some types do not have equality matching rules,
-          # delete doesn't work
-          # Replacing with nothing is equivalent.
-          if !data.has_key?(k) and schema.attribute(k).binary_required?
-            value = [{'binary' => []}]
-          end
-        else
-          # Ditched delete then replace because attribs with no equality
-          # match rules will fails
-        end
-        attributes.push([:replace, k, value])
-      end
-      data.each do |k, v|
-        value = v || []
-        next if ldap_data.has_key?(k)
-
-        value = self.class.remove_blank_value(value) || []
-        next if self.class.blank_value?(value)
-
-
-        # Detect subtypes and account for them
-        # REPLACE will function like ADD, but doesn't hit EQUALITY problems
-        # TODO: Added equality(attr) to Schema
-        attributes.push([:replace, k, value])
-      end
-
-      attributes
-    end
-  end
-
   module Validations
     # unfinished workaround for activeldap#26720 (not sure it would work in all cases)
     def validate_required_ldap_values
diff --git a/lib/ldap_shadows/elements/object.rb b/lib/ldap_shadows/elements/object.rb
index 46b6907..dc076fa 100644
--- a/lib/ldap_shadows/elements/object.rb
+++ b/lib/ldap_shadows/elements/object.rb
@@ -46,7 +46,7 @@ module Elements
     end
 
     def handle
-      name = self[dn_attribute] || self.attributes[dn_attribute] || self.dn
+      name = self[dn_attribute] || self.attributes[dn_attribute] || self.dn.to_s
       name = name.first if name.is_a? Array
       name.strip
     end
@@ -82,9 +82,11 @@ module Elements
         end
         rel[:class_name] = foreign_klass.to_s
 
+	rel_attr_val = rel[:foreign_key]
         case rel[:type]
         when 'belongs_to'
           belongs_to field_name, rel.reject {|key, val| not ActiveLdap::Associations::ClassMethods::VALID_BELONGS_TO_OPTIONS.include?(key) }
+	  rel_attr_val = rel[:primary_key] if rel[:many] and rel[:primary_key]
         when 'has_many'
           has_many field_name, rel.reject {|key, val| not ActiveLdap::Associations::ClassMethods::VALID_HAS_MANY_OPTIONS.include?(key) }
         else
@@ -93,7 +95,7 @@ module Elements
 
         object_relations_info[field_name] = {
           :foreign_klass => foreign_klass,
-          :single_value => ActiveLdap::Base.schema.attribute(rel[:foreign_key]).single_value?,
+          :single_value => ActiveLdap::Base.schema.attribute(rel_attr_val).single_value?,
           :read_only => rel[:read_only] || false
         }
       end
@@ -111,7 +113,7 @@ module Elements
       attr_list.unshift(name_attribute) unless name_attribute.nil?
       attr_list.each do |attr|
         if attr == 'dn'
-          return self.dn
+          return self.dn.to_s
         elsif self.attribute_present?(attr)
           val = self.send(attr, true)
           return val[0].strip
@@ -168,7 +170,7 @@ module Elements
 
       expert_attributes = self.class.parameters[:presentation][:expert_attributes]
       admin_attributes = attr_list.select do |attr|
-        ActiveLdap::Base.schema.attribute(attr).operational?
+        ActiveLdap::Base.schema.attribute(attr).directory_operation?
       end
 
       rel_list = self.possible_relations
@@ -426,7 +428,7 @@ module Elements
       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
+        self.base = parent_item.dn - parent_item.class.base
       else
         raise PreProcessingError, _("Moving items is not yet implemented")
       end
@@ -573,7 +575,7 @@ module Elements
 
           begin
             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
+            self.base = parent_item.dn - parent_item.class.base
           rescue
             raise PreProcessingError, _("Cannot create the item: bad default parent for this kind of object: %s") % $!
           end
diff --git a/lib/ldap_shadows/lang_additions.rb b/lib/ldap_shadows/lang_additions.rb
index 9880516..b31a008 100644
--- a/lib/ldap_shadows/lang_additions.rb
+++ b/lib/ldap_shadows/lang_additions.rb
@@ -27,21 +27,13 @@ end
 
 # for ActiveLDAP
 module ActiveLdap
-  class DistinguishedName
-    def shift
-      @rdns.shift
-    end
-  end
-
   class Base
     def family_parent_dn
-      pdn = self.dn_obj.dup
-      pdn.shift
-      pdn
+      self.dn.parent
     end
 
     def family_parent
-      ActiveLdap::Base.find(:first, :base => self.family_parent_dn.to_s, :scope => :base)
+      ActiveLdap::Base.find(:first, :base => self.family_parent_dn, :scope => :base)
     end
 
     def family_children
@@ -53,7 +45,7 @@ module ActiveLdap
     end
 
     def family_siblings
-      ActiveLdap::Base.find(:all, :base => self.family_parent_dn.to_s, :scope => :one).select{|obj| obj.dn != self.dn }
+      ActiveLdap::Base.find(:all, :base => self.family_parent_dn, :scope => :one).select{|obj| obj.dn != self.dn }
     end
 
     def family_siblings_dn
diff --git a/lib/ldap_shadows/manipulation_helper.rb b/lib/ldap_shadows/manipulation_helper.rb
index b5d65c8..1189bf9 100644
--- a/lib/ldap_shadows/manipulation_helper.rb
+++ b/lib/ldap_shadows/manipulation_helper.rb
@@ -41,9 +41,9 @@ module LdapShadows
     def self.items_find_from_strings(shadow, str_list)
       ldap_search_objects = "(objectClass=*)"
       ldap_search_aspects = ""
-      ldap_search_fields = []
-      ldap_search_where = []
-      ldap_search_exclude = []
+      ldap_search_fields = Set.new
+      ldap_search_where =Set.new
+      ldap_search_exclude =Set.new
       str_list.each do |str|
         unless str =~ /^([a-zA-Z]*(?::[a-zA-Z]+)?)(=|~=)(.*)$/
           raise SyntaxError, _("search parameter '%s' is invalid") % str
@@ -73,32 +73,32 @@ module LdapShadows
           when 'parents'
             val.split(",").each do |parent_fh|
               parent = find_item_by_full_handle(shadow, parent_fh)
-              ldap_search_where << [parent.dn.to_s, :one]
+              ldap_search_where << [parent.dn, :one]
             end
           when 'siblings'
             val.split(",").each do |sibling_fh|
               sibling = find_item_by_full_handle(shadow, sibling_fh)
-              ldap_search_where << [sibling.family_parent_dn.to_s, :one]
-              ldap_search_exclude << sibling.dn.to_s
+              ldap_search_where << [sibling.family_parent_dn, :one]
+              ldap_search_exclude << sibling.dn
             end
           when 'children'
             val.split(",").each do |child_fh|
               child = find_item_by_full_handle(shadow, child_fh)
-              ldap_search_where << [child.family_parent_dn.to_s, :base]
+              ldap_search_where << [child.family_parent_dn, :base]
             end
           when 'ancestors'
             val.split(",").each do |parent_fh|
               parent = find_item_by_full_handle(shadow, parent_fh)
-              ldap_search_where << [parent.dn.to_s, :sub]
-              ldap_search_exclude << parent.dn.to_s
+              ldap_search_where << [parent.dn, :sub]
+              ldap_search_exclude << parent.dn
             end
           when 'successors'
             val.split(",").each do |child_fh|
               child = find_item_by_full_handle(shadow, child_fh)
-              dn = child.dn_obj.dup
-              while dn.to_s != ActiveLdap::Base.base.to_s
+              dn = child.dn.dup
+              while dn != ActiveLdap::Base.base
                 dn.shift
-                ldap_search_where << [dn.to_s, :base]
+                ldap_search_where << [dn, :base]
               end
             end
           else
@@ -108,17 +108,17 @@ module LdapShadows
           raise PreProcessingError, _("Unknown type '%s' for field '%s'") % [type, field]
         end
       end
-      ldap_search_string = "(&" + ldap_search_objects + ldap_search_aspects + ldap_search_fields.join + ")"
+      ldap_search_string = "(&" + ldap_search_objects + ldap_search_aspects + ldap_search_fields.to_a.join + ")"
 
       if ldap_search_where.empty?
-        ldap_search_where << [ActiveLdap::Base.base.to_s, :sub]
+        ldap_search_where << [ActiveLdap::Base.base, :sub]
       end
-      res = []
+      res = Set.new
       ldap_search_where.each do |where|
         res += ActiveLdap::Base.find(:all, :base => where[0], :scope => where[1], :filter => ldap_search_string, :attributes => ["objectClass"])
       end
 
-      res.uniq.select {|item| not ldap_search_exclude.include?(item.dn.to_s) }
+      return res.select {|item| not ldap_search_exclude.include?(item.dn) }
     end
 
     def self.find_raw_item_object(shadow, raw_item)
@@ -153,9 +153,9 @@ module LdapShadows
           return {:full_handle => item.full_handle, :name => name, :item => item, :object => obj_klass, :is_root => is_root}
         end
 
-        item_fake_hdl = raw_item.dn
+        item_fake_hdl = raw_item.dn.to_s
       else
-        item_fake_hdl = dn || "???"
+        item_fake_hdl = dn.to_s || "???"
       end
 
       {:full_handle => nil, :name => "unknown/#{item_fake_hdl}", :is_root => is_root}
@@ -164,7 +164,7 @@ module LdapShadows
     def self.interpret_field_value(shadow, syntax, val)
       case syntax
       when "1.3.6.1.4.1.1466.115.121.1.12"
-        raw_item = ActiveLdap::Base.find(:first, :base => val.to_s, :scope => :base)
+        raw_item = ActiveLdap::Base.find(:first, :base => val, :scope => :base)
         LdapShadows::Manipulation.raw_item_info(shadow, raw_item, val.to_s)[:full_handle]
       else
         val
@@ -180,7 +180,7 @@ module LdapShadows
 
     def self.find_item_by_full_handle(shadow, full_handle, with_admin_fields = false)
       if full_handle == "root"
-        raw_item_dn = ActiveLdap::Base.base.to_s
+        raw_item_dn = ActiveLdap::Base.base
         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?
diff --git a/lib/ldap_shadows/shadow.rb b/lib/ldap_shadows/shadow.rb
index 738a49b..427db3e 100644
--- a/lib/ldap_shadows/shadow.rb
+++ b/lib/ldap_shadows/shadow.rb
@@ -104,7 +104,7 @@ module LdapShadows
       item_list = {}
       if all_objects
         ActiveLdap::Base.find(:all, :base => search_base, :scope => :sub, :attributes => ['']).each do |item|
-           item_list[ActiveLdap::DistinguishedName.parse(item.dn)]= item
+           item_list[item.dn]= item
         end
       else
         self.get_config[:presentation][:tree_objects].each do |obj_hdl|
@@ -114,7 +114,7 @@ module LdapShadows
           end
 
           obj_klass.find(:all, :base => search_base, :scope => :sub).each do |item|
-            item_list[item.dn_obj] = item
+            item_list[item.dn] = item
           end
         end
       end
@@ -122,7 +122,7 @@ module LdapShadows
       raw_tree = {}
       tree = {}
 
-      base_dn = ActiveLdap::DistinguishedName.parse(ActiveLdap::Base.base)
+      base_dn = ActiveLdap::Base.base
       dn_list = item_list.keys
 
       dn_list.each do |dn|
@@ -138,7 +138,7 @@ module LdapShadows
             current_dn = ActiveLdap::DistinguishedName.parse(current_dn_parts.join(","))
             current_item = item_list[current_dn]
             if current_item.nil?
-              current_item = ActiveLdap::Base.find(:first, :base => current_dn.to_s, :scope => :base, :attributes => [''])
+              current_item = ActiveLdap::Base.find(:first, :base => current_dn, :scope => :base, :attributes => [''])
               item_list[current_dn] = current_item
             end
             p_item = LdapShadows::Manipulation.raw_item_info(self, item_list[current_dn])[:name]
@@ -160,7 +160,7 @@ module LdapShadows
       if raw
         res = {base_dn.to_s => raw_tree}
       else
-        base_obj = ActiveLdap::Base.find(:first, :base => base_dn.to_s, :scope => :base, :attributes => [''])
+        base_obj = ActiveLdap::Base.find(:first, :base => base_dn, :scope => :base, :attributes => [''])
         res = {LdapShadows::Manipulation.raw_item_info(self, base_obj)[:name] => tree}
       end
 
