commit 2bd92292f8692c53b98ab68897904f9eb244ca01
Author: Marc Dequènes (Duck) <Duck@DuckCorp.org>
Date:   Sun Oct 25 19:22:14 2009 +0100

    [cleanup] moved helper things out of LdapObject in Manipulation and began sweeping dust

diff --git a/TODO b/TODO
index 1b4889a..5c665fa 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,4 @@
+- ensure removing an aspect also remove reverse-depends
 - improve configuration:
   * allow global relations to share them among objects ???
 - select parent at creation with :parent if present, or use
diff --git a/bin/shadowwalker b/bin/shadowwalker
index 5b73b30..9a7390a 100755
--- a/bin/shadowwalker
+++ b/bin/shadowwalker
@@ -25,7 +25,8 @@ $: << File.join(File.dirname(__FILE__), "..", "lib")
 locale = ENV['LANGUAGE'] || ENV['LC_ALL'] || ENV['LC_MESSAGES'] || ENV['LANG']
 
 require 'ldap_shadows'
-require 'ldap_shadows/display_utils'
+require 'ldap_shadows/display_helper'
+require 'ldap_shadows/manipulation_helper'
 require 'cmdparse2'
 
 include LdapShadows
@@ -344,11 +345,7 @@ class ModifyCommand < Command
 
     obj_klass, item = params_shift_item_handle_full_handle(args)
 
-    modification_done = false
-    args.each do |mod_info|
-      mod_done = item.item_modify_from_string(mod_info)
-      modification_done ||= mod_done
-    end
+    modification_done = LdapShadows::Manipulation.item_modify_from_strings(item, args)
 
     if modification_done
       item.save!
@@ -408,12 +405,7 @@ class CreateCommand < Command
     item = obj_klass.new(item_hdl)
     item.base = loc_item.dn_obj - obj_klass.base_obj
 
-
-    modification_done = false
-    args.each do |mod_info|
-      mod_done = item.item_modify_from_string(mod_info)
-      modification_done ||= mod_done
-    end
+    modification_done = LdapShadows::Manipulation.item_modify_from_strings(item, args)
 
     item.save!
     puts "Creation done."
@@ -436,11 +428,11 @@ class SearchCommand < Command
 
     raise SyntaxError, _("no search arguments") if args.empty?
 
-    res = Elements::LdapObject.items_find_from_strings($shadow, args)
+    res = LdapShadows::Manipulation.items_find_from_strings($shadow, args)
     unless res.empty?
       display_lines = []
       res.each do |raw_item|
-        display_lines << Elements::LdapObject.raw_item_info($shadow, raw_item)[:name]
+        display_lines << LdapShadows::Manipulation.raw_item_info($shadow, raw_item)[:name]
       end
       puts display_lines.join("\n")
     end
diff --git a/lib/ldap_shadows/display_helper.rb b/lib/ldap_shadows/display_helper.rb
new file mode 100644
index 0000000..51dad27
--- /dev/null
+++ b/lib/ldap_shadows/display_helper.rb
@@ -0,0 +1,144 @@
+#--
+# LdapShadows, a Medium-level LDAP Access Library and Tool.
+# Copyright (c) 2009 Marc Dequènes (Duck) <Duck@DuckCorp.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#++
+
+require 'active_support'
+
+
+module LdapShadows
+  module Translator
+    I18n.default_locale = :en
+
+    def self.translate_object_name(obj_hdl)
+      I18n.t(obj_hdl, :scope => 'objects', :default => "Object '#{obj_hdl}'")
+    end
+
+    def self.translate_field_name(field_name)
+      if field_name.index(":")
+        type, key = field_name.split(":")
+        case type
+        when 'rel'
+          I18n.t(key, :scope => 'relations', :default => field_name)
+        else
+          raise "Cannot translate unknown data key type"
+        end
+      else
+        att = ActiveLdap::Base.schema.attribute(field_name)
+        I18n.t(att.human_attribute_name, :scope => 'attribute_types', :default => att.human_attribute_description)
+      end
+    end
+
+    def self.translate_aspect_name(aspect_name)
+      I18n.t(aspect_name, :scope => 'aspects', :default => "Aspect '#{aspect_name}'")
+    end
+  end
+
+  module Display
+    def self.display_fields(attr_data, options = {})
+      attr_data.each_pair do |key, val|
+        next if val[:expert] and not options[:expert]
+        next if val[:admin] and not options[:admin]
+
+        field_name = Translator.translate_field_name(key)
+
+        str = field_name
+        str += " [#{key}]" if options[:handles]
+        if val[:binary] and options[:skip_binary]
+          str += " -> #{val[:value].size} file(s) available"
+        else
+          str += ": " + (val[:multiple] ? val[:value].sort.collect{|v| v.to_s }.join(", ") : val[:value].to_s)
+        end
+
+        puts str
+      end
+    end
+
+    def self.display_item(item, options = {})
+      obj_human_name = Translator.translate_object_name(item.class.handle)
+      name = item.human_name
+      name += " [#{item.full_handle}]" if options[:handles]
+      puts "=== #{obj_human_name}: #{name} ==="
+
+      if options[:debug]
+        puts item.to_s
+        puts "--- Detected Info ---"
+        puts "aspects: " + item.aspects.sort.join(", ")
+
+        puts "--- Relations ---"
+        item.relations.each do |rel|
+          rel_data = item.send(rel)
+          if rel_data.is_a? Enumerable
+            next if rel_data.empty?
+            rel_value = rel_data.collect{|g| g.name }.join(", ")
+          else
+            # the exists? method also ensure the object is loaded
+            next unless rel_data.exists?
+            rel_value = rel_data.name
+          end
+          puts "#{rel}: " + rel_value
+        end
+
+        if options[:show_family_members]
+          puts "--- Family ---"
+          puts "parent: " + item.family_parent_dn.to_s
+          puts "siblings: " + item.family_siblings_dn.join(", ")
+          puts "children: " + item.family_children_dn.join(", ")
+        end
+      else
+        obj_info, obj_aspects = item.organized_data
+
+        display_fields(obj_info, options)
+
+        obj_aspects.each_pair do |aspect_name, aspect_data|
+          name = Translator.translate_aspect_name(aspect_name)
+          name += " [#{aspect_name}]" if options[:handles]
+          puts "--- #{name} ---"
+          display_fields(aspect_data, options)
+        end
+
+        if options[:show_family_members]
+          puts "--- Family ---"
+          puts "parent: " + item.class.raw_item_info(item.class.shadow, item.family_parent)[:name]
+          puts "siblings: " + item.family_siblings.collect{|raw_item| item.class.raw_item_info(item.class.shadow, raw_item)[:name] }.join(", ")
+          puts "children: " + item.family_children.collect{|raw_item| item.class.raw_item_info(item.class.shadow, raw_item)[:name] }.join(", ")
+        end
+      end
+    end
+
+    def self.display_item_list(title, item_list, options)
+      puts "=== #{title} (#{item_list.size}) ==="
+      item_list.each do |item|
+        str = item.human_name
+        str += " [#{item.full_handle}]" if options[:handles]
+        str += ": #{item.human_description}" unless item.human_description.empty?
+        puts str
+      end
+    end
+
+    def self.display_hash_tree(tree, level)
+      tree.keys.sort.each do |key|
+        str = ""
+        str += " " + "|    " * (level -1) + "+-- " if level > 0
+        str += "<#{key}>"
+        puts str
+
+        display_hash_tree(tree[key], level + 1) if tree[key]
+      end
+    end
+  end
+end
+
diff --git a/lib/ldap_shadows/display_utils.rb b/lib/ldap_shadows/display_utils.rb
deleted file mode 100644
index 51dad27..0000000
--- a/lib/ldap_shadows/display_utils.rb
+++ /dev/null
@@ -1,144 +0,0 @@
-#--
-# LdapShadows, a Medium-level LDAP Access Library and Tool.
-# Copyright (c) 2009 Marc Dequènes (Duck) <Duck@DuckCorp.org>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-#++
-
-require 'active_support'
-
-
-module LdapShadows
-  module Translator
-    I18n.default_locale = :en
-
-    def self.translate_object_name(obj_hdl)
-      I18n.t(obj_hdl, :scope => 'objects', :default => "Object '#{obj_hdl}'")
-    end
-
-    def self.translate_field_name(field_name)
-      if field_name.index(":")
-        type, key = field_name.split(":")
-        case type
-        when 'rel'
-          I18n.t(key, :scope => 'relations', :default => field_name)
-        else
-          raise "Cannot translate unknown data key type"
-        end
-      else
-        att = ActiveLdap::Base.schema.attribute(field_name)
-        I18n.t(att.human_attribute_name, :scope => 'attribute_types', :default => att.human_attribute_description)
-      end
-    end
-
-    def self.translate_aspect_name(aspect_name)
-      I18n.t(aspect_name, :scope => 'aspects', :default => "Aspect '#{aspect_name}'")
-    end
-  end
-
-  module Display
-    def self.display_fields(attr_data, options = {})
-      attr_data.each_pair do |key, val|
-        next if val[:expert] and not options[:expert]
-        next if val[:admin] and not options[:admin]
-
-        field_name = Translator.translate_field_name(key)
-
-        str = field_name
-        str += " [#{key}]" if options[:handles]
-        if val[:binary] and options[:skip_binary]
-          str += " -> #{val[:value].size} file(s) available"
-        else
-          str += ": " + (val[:multiple] ? val[:value].sort.collect{|v| v.to_s }.join(", ") : val[:value].to_s)
-        end
-
-        puts str
-      end
-    end
-
-    def self.display_item(item, options = {})
-      obj_human_name = Translator.translate_object_name(item.class.handle)
-      name = item.human_name
-      name += " [#{item.full_handle}]" if options[:handles]
-      puts "=== #{obj_human_name}: #{name} ==="
-
-      if options[:debug]
-        puts item.to_s
-        puts "--- Detected Info ---"
-        puts "aspects: " + item.aspects.sort.join(", ")
-
-        puts "--- Relations ---"
-        item.relations.each do |rel|
-          rel_data = item.send(rel)
-          if rel_data.is_a? Enumerable
-            next if rel_data.empty?
-            rel_value = rel_data.collect{|g| g.name }.join(", ")
-          else
-            # the exists? method also ensure the object is loaded
-            next unless rel_data.exists?
-            rel_value = rel_data.name
-          end
-          puts "#{rel}: " + rel_value
-        end
-
-        if options[:show_family_members]
-          puts "--- Family ---"
-          puts "parent: " + item.family_parent_dn.to_s
-          puts "siblings: " + item.family_siblings_dn.join(", ")
-          puts "children: " + item.family_children_dn.join(", ")
-        end
-      else
-        obj_info, obj_aspects = item.organized_data
-
-        display_fields(obj_info, options)
-
-        obj_aspects.each_pair do |aspect_name, aspect_data|
-          name = Translator.translate_aspect_name(aspect_name)
-          name += " [#{aspect_name}]" if options[:handles]
-          puts "--- #{name} ---"
-          display_fields(aspect_data, options)
-        end
-
-        if options[:show_family_members]
-          puts "--- Family ---"
-          puts "parent: " + item.class.raw_item_info(item.class.shadow, item.family_parent)[:name]
-          puts "siblings: " + item.family_siblings.collect{|raw_item| item.class.raw_item_info(item.class.shadow, raw_item)[:name] }.join(", ")
-          puts "children: " + item.family_children.collect{|raw_item| item.class.raw_item_info(item.class.shadow, raw_item)[:name] }.join(", ")
-        end
-      end
-    end
-
-    def self.display_item_list(title, item_list, options)
-      puts "=== #{title} (#{item_list.size}) ==="
-      item_list.each do |item|
-        str = item.human_name
-        str += " [#{item.full_handle}]" if options[:handles]
-        str += ": #{item.human_description}" unless item.human_description.empty?
-        puts str
-      end
-    end
-
-    def self.display_hash_tree(tree, level)
-      tree.keys.sort.each do |key|
-        str = ""
-        str += " " + "|    " * (level -1) + "+-- " if level > 0
-        str += "<#{key}>"
-        puts str
-
-        display_hash_tree(tree[key], level + 1) if tree[key]
-      end
-    end
-  end
-end
-
diff --git a/lib/ldap_shadows/elements/object.rb b/lib/ldap_shadows/elements/object.rb
index e99fa49..e91ceef 100755
--- a/lib/ldap_shadows/elements/object.rb
+++ b/lib/ldap_shadows/elements/object.rb
@@ -221,18 +221,7 @@ module Elements
       [obj_info, obj_aspects]
     end
 
-    def item_modify_from_string(str)
-      unless str =~ /^([a-zA-Z]*(?::[a-zA-Z]+)?)(=|\+=|-=)(.*)$/
-        raise SyntaxError, _("modification parameter '%s' is invalid") % str
-      end
-      key = $1
-      op = $2
-      val = $3
-
-      item_modify(key, op, val)
-    end
-
-    def item_modify(key, op, val)
+    def modify(key, op, val)
       if key.index(":")
         type, field = key.split(":")
       else
@@ -242,13 +231,13 @@ module Elements
 
       case type
       when nil
-        item_modify_field(key, op, val)
+        modify_field(key, op, val)
       when 'rel'
-        item_modify_relation(field, op, val)
+        modify_relation(field, op, val)
       when ''
         case field
         when 'aspects'
-          item_modify_aspects(op, val)
+          modify_aspects(op, val)
         else
           raise PreProcessingError, _("Unknown core field '%s'") % field
         end
@@ -257,7 +246,7 @@ module Elements
       end
     end
 
-    def item_modify_field(field, op, val)
+    def modify_field(field, op, val)
       unless self.has_field?(field)
         raise PreProcessingError, _("No such field '%s' in object '%s'") % [field, self.class.handle]
       end
@@ -311,12 +300,12 @@ module Elements
       true
     end
 
-    def item_modify_relation(rel, op, val)
+    def modify_relation(rel, op, val)
       unless self.relations.include?(rel)
         raise PreProcessingError, _("No such relation '%s' for object '%s'") % [rel, self.class.handle]
       end
 
-      rel_info = self.class.relations_info[rel]
+      rel_info = self.class.relations_info[rel.to_sym]
       if rel_info[:read_only]
         raise PreProcessingError, _("The relation '%s' cannot be modified (read only)") % rel
       end
@@ -365,7 +354,7 @@ module Elements
       true
     end
 
-    def item_modify_aspects(op, aspect_name)
+    def modify_aspects(op, aspect_name)
       unless self.class.possible_aspects.include?(aspect_name)
         raise PreProcessingError, _("No such aspect '%s' for object '%s'") % [aspect_name, self.class.handle]
       end
@@ -375,14 +364,14 @@ module Elements
         raise PreProcessingError, _("The equality operator is not possible for aspects")
 
       when '+='
-        return false if self.aspects.keys.include?(aspect)
+        return false if self.aspects.keys.include?(aspect_name)
 
-        self.add_aspect(aspect)
+        self.add_aspect(aspect_name)
 
       when '-='
-        return false unless self.aspects.keys.include?(aspect)
+        return false unless self.aspects.keys.include?(aspect_name)
 
-        self.remove_aspect(aspect)
+        self.remove_aspect(aspect_name)
 
       else
         raise SyntaxError, _("Unknown operator '%s'") % op
@@ -391,131 +380,6 @@ module Elements
       true
     end
 
-    def self.items_find_from_strings(shadow, str_list)
-      ldap_search_objects = "(objectClass=*)"
-      ldap_search_aspects = ""
-      ldap_search_fields = []
-      str_list.each do |str|
-        unless str =~ /^([a-zA-Z]*(?::[a-zA-Z]+)?)(=|~=)(.*)$/
-          raise SyntaxError, _("search parameter '%s' is invalid") % str
-        end
-        key = $1
-        op = $2
-        val = $3
-
-        if key.index(":")
-          type, field = key.split(":")
-        else
-          type = nil
-          field = key
-        end
-
-        case type
-        when nil
-          ldap_search_fields << ldap_search_string_field(field, op, val)
-        when 'rel'
-          raise PreProcessingError, _("Searching relations is not implemented yet")
-        when ''
-          case field
-          when 'objects'
-            ldap_search_objects = ldap_search_string_objects(shadow, field, op, val)
-          when 'aspects'
-            ldap_search_aspects = ldap_search_string_aspects(shadow, field, op, val)
-          else
-            raise PreProcessingError, _("Unknown core field '%s'") % field
-          end
-        else
-          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 + ")"
-
-      LdapObject.find(:all, :scope => :sub, :filter => ldap_search_string, :attributes => ["objectClass"])
-    end
-
-    def self.ldap_search_string_field(field, op, val)
-      esc_val = self.connection.escape_filter_value(val)
-      case op
-      when "="
-        "(#{field}=#{esc_val})"
-
-      when "~="
-        raise PreProcessingError, _("Searching with regex is not implemented yet")
-
-      else
-        raise SyntaxError, _("Unknown operator '%s'") % op
-      end
-    end
-
-    def self.ldap_search_string_objects(shadow, field, op, val_list)
-      ldap_search_parts = val_list.split(",").collect do |val|
-        obj_hdl = val.downcase.singularize
-        obj_klass = shadow.get_object(obj_hdl)
-        raise PreProcessingError, _("No such object '%s'") % val if obj_klass.nil?
-
-        ldap_classes = obj_klass.required_classes
-
-        case op
-        when "="
-          "(&" + ldap_classes.collect{|cl| "(objectClass=#{cl})" }.join + ")"
-
-        when "~="
-          raise PreProcessingError, _("Searching with regex is not possible with objects")
-
-        else
-          raise SyntaxError, _("Unknown operator '%s'") % op
-        end
-      end
-      "(|" + ldap_search_parts.join + ")"
-    end
-
-    def self.ldap_search_string_aspects(shadow, field, op, val_list)
-      ldap_search_parts = val_list.split(",").collect do |val|
-        aspect = shadow.get_aspect(val)
-        raise PreProcessingError, _("No such aspect '%s'") % val if aspect.nil?
-
-        ldap_classes = aspect.parameters[:mapping][:classes]
-
-        case op
-        when "="
-          "(&" + ldap_classes.collect{|cl| "(objectClass=#{cl})" }.join + ")"
-
-        when "~="
-          raise PreProcessingError, _("Searching with regex is not possible with aspects")
-
-        else
-          raise SyntaxError, _("Unknown operator '%s'") % op
-        end
-      end
-      "(&" + ldap_search_parts.join + ")"
-    end
-
-    def self.find_raw_item_object(shadow, raw_item)
-      # easy case
-      base_obj_klass = LdapShadows::Elements::LdapObject
-      if raw_item.class != base_obj_klass and raw_item.class.ancestors.include?(base_obj_klass)
-        return raw_item.class.handle
-      end
-
-      shadow.objects.each do |obj_hdl|
-        obj_klass = shadow.get_object(obj_hdl)
-        ldap_classes = obj_klass.required_classes
-        return obj_hdl if raw_item.classes & ldap_classes == ldap_classes
-      end
-      nil
-    end
-
-    def self.raw_item_info(shadow, raw_item)
-      obj_hdl = self.find_raw_item_object(shadow, raw_item)
-      if obj_hdl
-        obj_klass = shadow.get_object(obj_hdl)
-        item = obj_klass.new(raw_item.dn)
-        {:name => item.full_handle, :item => item, :object => obj_klass}
-      else
-        {:name => "unknown/#{raw_item.dn}"}
-      end
-    end
-
     def add_aspect(aspect_name)
       return unless self.class.possible_aspects.include?(aspect_name)
 
diff --git a/lib/ldap_shadows/manipulation_helper.rb b/lib/ldap_shadows/manipulation_helper.rb
new file mode 100644
index 0000000..08b7795
--- /dev/null
+++ b/lib/ldap_shadows/manipulation_helper.rb
@@ -0,0 +1,168 @@
+#--
+# LdapShadows, a Medium-level LDAP Access Library and Tool.
+# Copyright (c) 2009 Marc Dequènes (Duck) <Duck@DuckCorp.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#++
+
+
+module LdapShadows
+  module Manipulation
+    def self.item_modify_from_strings(item, str_list)
+      str_list = [str_list] unless str_list.is_a? Array
+
+      modification_done = false
+      str_list.each do |str|
+        unless str =~ /^([a-zA-Z]*(?::[a-zA-Z]+)?)(=|\+=|-=)(.*)$/
+          raise SyntaxError, _("modification parameter '%s' is invalid") % str
+        end
+        key = $1
+        op = $2
+        val = $3
+
+        mod_done = item.modify(key, op, val)
+        modification_done ||= mod_done
+      end
+
+      modification_done
+    end
+
+    def self.items_find_from_strings(shadow, str_list)
+      ldap_search_objects = "(objectClass=*)"
+      ldap_search_aspects = ""
+      ldap_search_fields = []
+      str_list.each do |str|
+        unless str =~ /^([a-zA-Z]*(?::[a-zA-Z]+)?)(=|~=)(.*)$/
+          raise SyntaxError, _("search parameter '%s' is invalid") % str
+        end
+        key = $1
+        op = $2
+        val = $3
+
+        if key.index(":")
+          type, field = key.split(":")
+        else
+          type = nil
+          field = key
+        end
+
+        case type
+        when nil
+          ldap_search_fields << ldap_search_string_field(field, op, val)
+        when 'rel'
+          raise PreProcessingError, _("Searching relations is not implemented yet")
+        when ''
+          case field
+          when 'objects'
+            ldap_search_objects = ldap_search_string_objects(shadow, field, op, val)
+          when 'aspects'
+            ldap_search_aspects = ldap_search_string_aspects(shadow, field, op, val)
+          else
+            raise PreProcessingError, _("Unknown core field '%s'") % field
+          end
+        else
+          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 + ")"
+
+      ActiveLdap::Base.find(:all, :scope => :sub, :filter => ldap_search_string, :attributes => ["objectClass"])
+    end
+
+    def self.find_raw_item_object(shadow, raw_item)
+      # easy case
+      base_obj_klass = LdapShadows::Elements::LdapObject
+      if raw_item.class != base_obj_klass and raw_item.class.ancestors.include?(base_obj_klass)
+        return raw_item.class.handle
+      end
+
+      shadow.objects.each do |obj_hdl|
+        obj_klass = shadow.get_object(obj_hdl)
+        ldap_classes = obj_klass.required_classes
+        return obj_hdl if raw_item.classes & ldap_classes == ldap_classes
+      end
+      nil
+    end
+
+    def self.raw_item_info(shadow, raw_item)
+      obj_hdl = self.find_raw_item_object(shadow, raw_item)
+      if obj_hdl
+        obj_klass = shadow.get_object(obj_hdl)
+        item = obj_klass.new(raw_item.dn)
+        {:name => item.full_handle, :item => item, :object => obj_klass}
+      else
+        {:name => "unknown/#{raw_item.dn}"}
+      end
+    end
+
+    protected
+
+    def self.ldap_search_string_field(field, op, val)
+      esc_val = ActiveLdap::Base.connection.escape_filter_value(val)
+      case op
+      when "="
+        "(#{field}=#{esc_val})"
+
+      when "~="
+        raise PreProcessingError, _("Searching with regex is not implemented yet")
+
+      else
+        raise SyntaxError, _("Unknown operator '%s'") % op
+      end
+    end
+
+    def self.ldap_search_string_objects(shadow, field, op, val_list)
+      ldap_search_parts = val_list.split(",").collect do |val|
+        obj_hdl = val.downcase.singularize
+        obj_klass = shadow.get_object(obj_hdl)
+        raise PreProcessingError, _("No such object '%s'") % val if obj_klass.nil?
+
+        ldap_classes = obj_klass.required_classes
+
+        case op
+        when "="
+          "(&" + ldap_classes.collect{|cl| "(objectClass=#{cl})" }.join + ")"
+
+        when "~="
+          raise PreProcessingError, _("Searching with regex is not possible with objects")
+
+        else
+          raise SyntaxError, _("Unknown operator '%s'") % op
+        end
+      end
+      "(|" + ldap_search_parts.join + ")"
+    end
+
+    def self.ldap_search_string_aspects(shadow, field, op, val_list)
+      ldap_search_parts = val_list.split(",").collect do |val|
+        aspect = shadow.get_aspect(val)
+        raise PreProcessingError, _("No such aspect '%s'") % val if aspect.nil?
+
+        ldap_classes = aspect.parameters[:mapping][:classes]
+
+        case op
+        when "="
+          "(&" + ldap_classes.collect{|cl| "(objectClass=#{cl})" }.join + ")"
+
+        when "~="
+          raise PreProcessingError, _("Searching with regex is not possible with aspects")
+
+        else
+          raise SyntaxError, _("Unknown operator '%s'") % op
+        end
+      end
+      "(&" + ldap_search_parts.join + ")"
+    end
+  end
+end
diff --git a/lib/ldap_shadows/shadow.rb b/lib/ldap_shadows/shadow.rb
index b94d80b..11df13c 100755
--- a/lib/ldap_shadows/shadow.rb
+++ b/lib/ldap_shadows/shadow.rb
@@ -103,10 +103,6 @@ module LdapShadows
     def tree(search_base, raw = false, all_objects = false)
       item_list = {}
       if all_objects
-        # does not work well...
-        #Elements::LdapObject.find(:all, :base => search_base, :scope => :sub, :attributes => ['']).each do |item|
-        #  item_list[item.dn_obj] = item
-        #end
         ActiveLdap::Base.find(:all, :base => search_base, :scope => :sub, :attributes => ['']).each do |item|
            item_list[ActiveLdap::DistinguishedName.parse(item.dn)]= item
         end
@@ -126,7 +122,7 @@ module LdapShadows
       raw_tree = {}
       tree = {}
 
-      base_dn = ActiveLdap::DistinguishedName.parse(Elements::LdapObject.base)
+      base_dn = ActiveLdap::DistinguishedName.parse(ActiveLdap::Base.base)
       dn_list = item_list.keys
 
       dn_list.each do |dn|
@@ -145,7 +141,7 @@ module LdapShadows
               current_item = ActiveLdap::Base.find(:first, :base => current_dn.to_s, :scope => :base, :attributes => [''])
               item_list[current_dn] = current_item
             end
-            p_item = Elements::LdapObject.raw_item_info(self, item_list[current_dn])[:name]
+            p_item = LdapShadows::Manipulation.raw_item_info(self, item_list[current_dn])[:name]
           end
 
           unless p_raw_tree.has_key?(p_dn)
@@ -165,7 +161,7 @@ module LdapShadows
         res = {base_dn.to_s => raw_tree}
       else
         base_obj = ActiveLdap::Base.find(:first, :base => base_dn.to_s, :scope => :base, :attributes => [''])
-        res = {Elements::LdapObject.raw_item_info(self, base_obj)[:name] => tree}
+        res = {LdapShadows::Manipulation.raw_item_info(self, base_obj)[:name] => tree}
       end
 
       res
