# = to_s Style # #-- # Ruby version 1.8 # # == Authors # * Yomei Komiya # # == Copyright # 2008 the original author or authors. # # == License # Apache License 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #++ # == Version # SVN: $Id: to_s_style.rb 75 2008-10-12 10:35:52Z whitestar $ # # == Since # File available since Release 0.8.0 require 'commons/lang/class_utils' require 'commons/lang/object_utils' require 'commons/lang/system_utils' module Commons module Lang module Builder class ToSStyle attr_accessor \ :use_class_name, :use_short_className, :use_identity_hash_code, :use_field_names, :default_full_detail, :array_content_detail, :array_start, :array_end, :array_separator, :content_start, :content_end, :field_name_value_separator, :field_separator, :field_separator_at_start, :field_separator_at_end, :nil_text, :size_start_text, :size_end_text, :summary_object_start_text, :summary_object_end_text attr_reader :registry protected \ :registry, :use_class_name, :use_short_className, :use_identity_hash_code, :use_field_names, :default_full_detail, :array_content_detail, :array_start, :array_end, :array_separator, :content_start, :content_end, :field_name_value_separator, :field_separator, :field_separator_at_start, :field_separator_at_end, :nil_text, :size_start_text, :size_end_text, :summary_object_start_text, :summary_object_end_text def initialize super() @registry = Hash.new # Whether to use the field names, the default is true. @use_field_names = true # Whether to use the class name, the default is true. @use_class_name = true # Whether to use short class names, the default is false. @use_short_className = false # Whether to use the identity hash code, the default is true. @use_identity_hash_code = true # The content start '{'. @content_start = '{' # The content end '}'. @content_end = '}' # The field name value separator '='. @field_name_value_separator = '=' # Whether the field separator should be added before any other fields. @field_separator_at_start = false # Whether the field separator should be added after any other fields. @field_separator_at_end = false # The field separator ','. @field_separator = ',' # The array start '['. @array_start = '[' # The array separator ','. @array_separator = ',' # The detail for array content. @array_content_detail = true # The array end ']'. @array_end = ']' # The value to use when fullDetail is nil, # the default value is true. @default_full_detail = true # The nil text '<nil>'. @nil_text = '' # The summary size text start '= 0 && pos2 >= 0 data = to_s[pos1 ... pos2] if @field_separator_at_start remove_last_field_separator(buffer) end buffer.concat(data) append_field_separator(buffer) end end end def append_start(buffer, object) if object != nil append_class_name(buffer, object) append_identity_hash_code(buffer, object) append_content_start(buffer) if @field_separator_at_start append_field_separator(buffer) end end end def append_end(buffer, object) if @field_separator_at_end == false remove_last_field_separator(buffer) end append_content_end(buffer) end def remove_last_field_separator(buffer) len = buffer.length sep_len = @field_separator.length if len > 0 && sep_len > 0 && len >= sep_len match = true (0 ... sep_len).each {|i| if buffer[len - 1 - i] != @field_separator[sep_len - 1 - i] match = false break end } if match buffer[len - sep_len .. -1] = '' end end end protected :remove_last_field_separator #-- ------------------------------------------------------------------------------ #++ def append(buffer, field_name, value, full_detail) append_field_start(buffer, field_name) if value == nil append_nil_text(buffer, field_name) else append_internal(buffer, field_name, value, full_detail) end append_field_end(buffer, field_name) end def append_internal(buffer, field_name, value, detail) if registered?(value) append_cyclic_object(buffer, field_name, value) return end register(value) begin case value when Hash if detail append_hash_detail(buffer, field_name, value) else append_summary_size(buffer, field_name, value.size) end when Array if detail # We do not use Array#to_s append_array_detail(buffer, field_name, value) else append_summary_size(buffer, field_name, value.size) end else if detail append_detail(buffer, field_name, value) else append_summary(buffer, field_name, value) end end ensure unregister(value) end end protected :append_internal def append_cyclic_object(buffer, field_name, value) ObjectUtils.append_identity_to_s(buffer, value) buffer.concat('...') end protected :append_cyclic_object def append_summary(buffer, field_name, value) buffer.concat(@summary_object_start_text) buffer.concat(get_short_class_name(value.class)) buffer.concat(@summary_object_end_text) end protected :append_summary def append_detail(buffer, field_name, value) buffer.concat(value.to_s) end protected :append_detail #-- ------------------------------------------------------------------------------ #++ def append_hash_detail(buffer, field_name, hash) buffer.concat(@array_start) i = 0 hash.each_pair {|key, value| if i > 0 buffer.concat(@array_separator) end if value == nil append_nil_text(buffer, field_name) else buffer.concat(key.to_s + '=>') append_internal(buffer, field_name, value, @array_content_detail) end i += 1 } buffer.concat(@array_end) end protected :append_hash_detail def append_array_detail(buffer, field_name, array) buffer.concat(@array_start) array.each_index {|i| item = array[i] if i > 0 buffer.concat(@array_separator) end if item == nil append_nil_text(buffer, field_name) else append_internal(buffer, field_name, item, @array_content_detail) end } buffer.concat(@array_end) end protected :append_array_detail #-- ------------------------------------------------------------------------------ #++ def append_class_name(buffer, object) if @use_class_name && object != nil if @use_short_className buffer.concat(get_short_class_name(object.class)) else buffer.concat(object.class.name) end end end protected :append_class_name def append_identity_hash_code(buffer, object) if @use_identity_hash_code && object != nil buffer.concat(':') buffer.concat('0x' + object.__id__.to_s(16)) end end protected :append_identity_hash_code def append_content_start(buffer) buffer.concat(@content_start) end protected :append_content_start def append_content_end(buffer) buffer.concat(@content_end) end protected :append_content_end def append_nil_text(buffer, field_name) buffer.concat(@nil_text) end protected :append_nil_text def append_field_separator(buffer) buffer.concat(@field_separator) end protected :append_field_separator def append_field_start(buffer, field_name) if @use_field_names && field_name != nil buffer.concat(field_name) buffer.concat(@field_name_value_separator) end end protected :append_field_start def append_field_end(buffer, field_name) append_field_separator(buffer) end protected :append_field_end def append_summary_size(buffer, field_name, size) buffer.concat(@size_start_text) buffer.concat(size.to_s) buffer.concat(@size_end_text) end protected :append_summary_size def get_short_class_name(clazz) return ClassUtils.get_short_class_name(clazz) end protected :get_short_class_name #-- ------------------------------------------------------------------------------ #++ class DefaultToSStyle < ToSStyle def initialize super() end def read_resolve return ToSStyle::DEFAULT_STYLE end private :read_resolve end # ToSStyle that does not print out the field names. class NoFieldNameToSStyle < ToSStyle def initialize super() self.use_field_names = false end def read_resolve return ToSStyle::NO_FIELD_NAMES_STYLE end private :read_resolve end # ToSStyle that prints out the short # class name and no identity hashcode. class ShortPrefixToSStyle < ToSStyle def initialize super() self.use_short_className = true self.use_identity_hash_code = false end def read_resolve return ToSStyle::SHORT_PREFIX_STYLE end private :read_resolve end # ToSStyle that does not print out the # classname, identity hashcode, content start or field name. class SimpleToSStyle < ToSStyle def initialize super() self.use_class_name = false self.use_identity_hash_code = false self.use_field_names = false self.content_start = '' self.content_end = '' end def read_resolve return ToSStyle::SIMPLE_STYLE end private :read_resolve end # ToSStyle that outputs on multiple lines. class MultiLineToSStyle < ToSStyle def initialize super() self.content_start = '{' self.field_separator = SystemUtils.line_separator + ' ' self.field_separator_at_start = true self.content_end = SystemUtils.line_separator + '}' end def read_resolve return ToSStyle::MULTI_LINE_STYLE end private :read_resolve end DEFAULT_STYLE = DefaultToSStyle.new MULTI_LINE_STYLE = MultiLineToSStyle.new NO_FIELD_NAMES_STYLE = NoFieldNameToSStyle.new SHORT_PREFIX_STYLE = ShortPrefixToSStyle.new SIMPLE_STYLE = SimpleToSStyle.new end end end end