commit f7217dcdffe4d0fc4711c30a59da1f76064cc40a
Author: Marc Dequènes (Duck) <Duck@DuckCorp.org>
Date:   Sat Jul 25 00:24:44 2009 +0200

    [evol] move display options out of object management into the display functions, and display binary field presence

diff --git a/TODO b/TODO
index 96370f4..826f1b9 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,2 @@
-- display sort order
-- display familly information (optional)
-- binary fields: display presence and (later) allow download/upload to/from file
\ No newline at end of file
+- display familly information (preliminary work done for debug mode done, but object type should be recognized and displayed properly)
+- binary fields: allow download/upload to/from file
\ No newline at end of file
diff --git a/bin/shadowwalker b/bin/shadowwalker
index 89fdbe2..c85d4a6 100755
--- a/bin/shadowwalker
+++ b/bin/shadowwalker
@@ -145,6 +145,7 @@ cmd.set_execution_block do |args|
     exit 2
   end
 
+  $program_options[:skip_binary] = true
   Display.display_item(item, $program_options)
 end
 cmdparser.add_command(cmd)
@@ -202,7 +203,7 @@ cmd.set_execution_block do |args|
 
   item_hdl = args.shift
   begin
-    item = obj_klass.find(item_hdl, :attributes => ["*",])
+    item = obj_klass.find(item_hdl)
   rescue ActiveLdap::EntryNotFound
     STDERR.puts "No such item '#{obj_hdl}/#{item_hdl}'"
     exit 2
@@ -214,9 +215,6 @@ cmd.set_execution_block do |args|
     key = $1
     op = $2
     val = $3
-    puts "key: #{key}"
-    puts "op: #{op}"
-    puts "val: #{val}"
 
     if key.nil?
       STDERR.puts "Syntax error in modification parameters: invalid field name" 
@@ -311,7 +309,6 @@ cmd.set_execution_block do |args|
 
   if modification_done
     puts "Modified attributes:"
-    p item.modified_attributes
     begin
       item.save!
     rescue ActiveLdap::OperationNotPermitted => e
@@ -333,8 +330,3 @@ end
 cmdparser.add_command(cmd)
 
 cmdparser.parse
-
-# ActiveLdap bugs:
-# - fetching operational attributes in an object used for modification cause
-#   collect_modified_attributes() to catch them by mistake and triggers an
-#   ActiveLdap::LdapError::ConstraintViolation exception
diff --git a/lib/ldap_shadows/display_utils.rb b/lib/ldap_shadows/display_utils.rb
index 1c7f3b4..5415383 100644
--- a/lib/ldap_shadows/display_utils.rb
+++ b/lib/ldap_shadows/display_utils.rb
@@ -51,9 +51,19 @@ module LdapShadows
   module Display
     def self.display_fields(attr_data, options = {})
       attr_data.each_pair do |key, val|
+        next if attr_data[:expert] and options[:expert]
+
         field_name = Translator.translate_field_name(key)
-        field_name += " [#{key}]" if options[:handles]
-        puts field_name + ": " + (val.is_a?(Array) ? val.sort.collect{|v| v.to_s }.join(", ") : val.to_s)
+
+        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
 
@@ -78,7 +88,7 @@ module LdapShadows
           puts "#{rel}: " + item.send(rel).collect{|g| g.name }.join(", ")
         end
       else
-        obj_info, obj_aspects = item.organized_data(:expert => options[:expert], :skip_binary => true)
+        obj_info, obj_aspects = item.organized_data
 
         display_fields(obj_info, options)
 
diff --git a/lib/ldap_shadows/object.rb b/lib/ldap_shadows/object.rb
index 210e4c3..b455f00 100755
--- a/lib/ldap_shadows/object.rb
+++ b/lib/ldap_shadows/object.rb
@@ -162,14 +162,11 @@ module LdapShadows
       self.relations_info[rel.to_sym]
     end
 
-    def organized_data(options = {})
-      options.symbolize_keys!
-      options[:expert] ||= false;
-      options[:skip_binary] ||= false;
+    def organized_data
+      expert_attributes = (self.class.presentation[:expert_attributes] || []) + OPERATIONAL_ATTRIBUTES
 
       ignored_attrs = self.mapper.get_global_config[:hidden_attributes] || []
       ignored_attrs += self.class.presentation[:hidden_attributes] || []
-      ignored_attrs += (self.class.presentation[:expert_attributes] || []) unless options[:expert]
       attr_list = self.attributes.keys - ignored_attrs
 
       aspects = self.aspects
@@ -184,7 +181,7 @@ module LdapShadows
           taken_attr_list = aspect_data[:presentation][:associated_attributes] & (attr_list + ignored_attrs)
           unless taken_attr_list.empty?
             obj_aspects[aspect] ||= {}
-            obj_aspects[aspect].merge!(fetch_attributes_data(taken_attr_list, options))
+            obj_aspects[aspect].merge!(fetch_attributes_data(taken_attr_list, expert_attributes))
             attr_list -= taken_attr_list
           end
         end
@@ -193,7 +190,7 @@ module LdapShadows
           taken_rel_list = aspect_data[:presentation][:associated_relations] & rel_list
           unless taken_rel_list.empty?
             obj_aspects[aspect] ||= {}
-            obj_aspects[aspect].merge!(fetch_relations_data(taken_rel_list, options))
+            obj_aspects[aspect].merge!(fetch_relations_data(taken_rel_list, expert_attributes))
             rel_list -= taken_rel_list
           end
         end
@@ -210,16 +207,15 @@ module LdapShadows
         end
         taken_attr_list += objectclasses_attr_list(self.required_classes + (self.class.presentation[:optional_classes] || []))
       end
-      taken_attr_list += OPERATIONAL_ATTRIBUTES if options[:expert]
       taken_attr_list = taken_attr_list.uniq & attr_list
-      obj_info = fetch_attributes_data(taken_attr_list, options)
+      obj_info = fetch_attributes_data(taken_attr_list, expert_attributes)
       attr_list -= taken_attr_list
 
       # manage general relations
       if self.class.presentation[:associated_relations]
         taken_rel_list = self.class.presentation[:associated_relations] & rel_list
         unless taken_rel_list.empty?
-          obj_info.merge!(fetch_relations_data(taken_rel_list, options))
+          obj_info.merge!(fetch_relations_data(taken_rel_list, expert_attributes))
           rel_list -= taken_rel_list
         end
       end
@@ -231,7 +227,7 @@ module LdapShadows
 
           taken_attr_list = (objectclasses_attr_list(aspect_data[:mapping][:classes]) & attr_list)
           obj_aspects[aspect] ||= {}
-          obj_aspects[aspect].merge!(fetch_attributes_data(taken_attr_list, options))
+          obj_aspects[aspect].merge!(fetch_attributes_data(taken_attr_list, expert_attributes))
           attr_list -= taken_attr_list
 
           break if attr_list.empty?
@@ -275,15 +271,35 @@ module LdapShadows
 
     protected
 
-    def fetch_attributes_data(attr_list, options = {})
-      attr_data = self.attributes.select {|key, val| attr_list.include?(key) and not (options[:skip_binary] and ActiveLdap::Base.schema.attribute(key).binary?) }
-      Hash[attr_data]
+    def fetch_attributes_data(attr_list, expert_attributes)
+      attr_data = self.attributes.collect do |key, val|
+        if attr_list.include?(key)
+          [key, {
+             :value => val,
+             :multiple => (val.is_a?(Array) ? val.size : 1),
+             :expert => expert_attributes.include?(key),
+             :binary => ActiveLdap::Base.schema.attribute(key).binary?
+           }]
+        else
+          nil
+        end
+      end
+      Hash[attr_data.compact]
     end
 
-    def fetch_relations_data(rel_list, options = {})
+    def fetch_relations_data(rel_list, expert_attributes)
       rel_data = rel_list.collect do |rel|
         data = self.send(rel).collect{|g| g.name }
-        data.empty? ? nil : ["rel:" + rel, data]
+        if data.empty?
+          nil
+        else
+          ["rel:" + rel, {
+             :value => data,
+             :multiple => (data.size > 1),
+             :expert => expert_attributes.include?("rel:" + rel),
+             :binary => false
+           }]
+        end
       end
       Hash[rel_data.compact]
     end
