note description: "Decoding of arbitrary objects graphs between sessions of programs containing the same types. It basically takes care of potential reordering of attributes from one system to the other." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date: 2020-05-19 14:29:33 +0000 (Tue, 19 May 2020) $" revision: "$Revision: 104259 $" class SED_INDEPENDENT_DESERIALIZER obsolete "Use SED_RECOVERABLE_DESERIALIZER instead." inherit SED_BASIC_DESERIALIZER redefine read_header, new_attribute_offset, read_persistent_field_count, clear_internal_data, is_transient_retrieval_required, is_store_settings_enabled end create make feature {NONE} -- Implementation: access attributes_mapping: detachable SPECIAL [detachable SPECIAL [INTEGER_32]] -- Mapping for each dynamic type id between old attribute location -- and new attribute location. new_attribute_offset (a_new_type_id, a_old_offset: INTEGER_32): INTEGER_32 -- Given attribute offset a_old_offset in the stored object whose dynamic type id -- is now a_new_type_id, retrieve new offset in a_new_type_id. do if attached attributes_mapping as l_map and then l_map.valid_index (a_new_type_id) and then attached l_map.item (a_new_type_id) as l_entry and then l_entry.valid_index (a_old_offset) then Result := l_entry.item (a_old_offset) end end feature {NONE} -- Status report is_transient_retrieval_required: BOOLEAN -- Do we need to retrieve transient attribute with their default value? -- This is necessary for Session/Basic storing where we expect the same -- object layout. do Result := False end is_store_settings_enabled: BOOLEAN -- Are settings stored? -- By default not for SED_INDEPENDENT_DESERIALIZER. do Result := False end feature {NONE} -- Implementation read_header (a_count: NATURAL_32) -- Read header which contains mapping between dynamic type and their -- string representation. local i, j, nb: INTEGER_32 l_deser: like deserializer l_reflector: like reflector l_table: like dynamic_type_table l_old_dtype, l_new_dtype: INTEGER_32 l_type_str: STRING_8 do l_reflector := reflector l_deser := deserializer read_settings nb := l_deser.read_compressed_natural_32.to_integer_32 create l_table.make_filled (0, nb) create attributes_mapping.make_filled (Void, nb) from j := 0 until j = 2 loop from i := 0 until i = nb loop l_old_dtype := l_deser.read_compressed_natural_32.to_integer_32 l_type_str := l_deser.read_string_8 l_new_dtype := l_reflector.dynamic_type_from_string (l_type_str) if l_new_dtype >= 0 then if not l_table.valid_index (l_old_dtype) then l_table := l_table.aliased_resized_area_with_default (0, (l_old_dtype + 1).max (l_table.count * 2)) end; l_table.put (l_new_dtype, l_old_dtype) else add_error (Error_factory.new_missing_type_error (l_type_str, l_type_str)) end i := i + 1 end if j = 0 then nb := l_deser.read_compressed_natural_32.to_integer_32 end j := j + 1 end dynamic_type_table := l_table from i := 0 nb := l_deser.read_compressed_natural_32.to_integer_32 until i = nb loop l_old_dtype := l_deser.read_compressed_natural_32.to_integer_32 if l_table.valid_index (l_old_dtype) then read_attributes (l_table.item (l_old_dtype)) else raise_fatal_error (Error_factory.new_internal_error ("Cannot read attributes data")) end i := i + 1 end read_object_table (a_count) end read_persistent_field_count (a_reflected_object: REFLECTED_OBJECT): INTEGER_32 -- Number of fields we are going to read from a_reflected_object in the the retrieved system. local l_dtype: INTEGER_32 do l_dtype := a_reflected_object.dynamic_type if attached attributes_mapping as l_map and then l_map.valid_index (l_dtype) and then attached l_map.item (l_dtype) as l_entry then Result := l_entry.count - 1 else raise_fatal_error (Error_factory.new_internal_error ("Cannot retrieve stored count")) end end read_attributes (a_dtype: INTEGER_32) -- Read attribute description for a_dtype where a_dtype is a dynamic type -- from the current system. require a_dtype_non_negative: a_dtype >= 0 attributes_mapping_not_void: attributes_mapping /= Void local l_deser: like deserializer l_map: like attributes_map l_mapping: SPECIAL [INTEGER_32] l_name: STRING_8 l_old_dtype, l_dtype: INTEGER_32 i, nb: INTEGER_32 a: like attributes_mapping l_attribute_type: INTEGER_32 do l_deser := deserializer nb := l_deser.read_compressed_natural_32.to_integer_32 if nb = reflector.persistent_field_count_of_type (a_dtype) then from i := 1 l_map := attributes_map (a_dtype) nb := nb + 1 create l_mapping.make_empty (nb); l_mapping.extend (0) until i = nb loop l_old_dtype := l_deser.read_compressed_natural_32.to_integer_32 l_dtype := new_dynamic_type_id (l_old_dtype) l_name := l_deser.read_string_8 if l_dtype >= 0 then if attached l_map.item (l_name) as l_item then l_attribute_type := l_item.dtype if l_attribute_type = l_dtype then l_mapping.extend (l_item.position) else add_error (Error_factory.new_attribute_mismatch (a_dtype, l_name, l_attribute_type, l_dtype)) end else add_error (Error_factory.new_missing_attribute_error (a_dtype, l_name)) end else add_error (Error_factory.new_unknown_attribute_type_error (a_dtype, l_name)) end i := i + 1 end if not has_error then a := attributes_mapping if a /= Void then if not a.valid_index (a_dtype) then a := a.aliased_resized_area_with_default (Void, (a_dtype + 1).max (a.count * 2)) attributes_mapping := a end; a.put (l_mapping, a_dtype) end end else add_error (Error_factory.new_attribute_count_mismatch (a_dtype, nb)) end end attributes_map (a_dtype: INTEGER_32): HASH_TABLE [TUPLE [position: INTEGER_32; dtype: INTEGER_32], STRING_8] -- Attribute map for dynamic type a_dtype which records -- position and dynamic type for a given attribute name. require a_dtype_non_negative: a_dtype >= 0 local l_reflector: like reflector i, nb: INTEGER_32 do l_reflector := reflector from i := 1 nb := l_reflector.field_count_of_type (a_dtype) create Result.make (nb) nb := nb + 1 until i = nb loop Result.put ([i, l_reflector.field_static_type_of_type (i, a_dtype)], l_reflector.field_name_of_type (i, a_dtype)) i := i + 1 end ensure attributes_map_not_void: Result /= Void end feature {NONE} -- Cleaning clear_internal_data -- Clear all allocated data do Precursor {SED_BASIC_DESERIALIZER} attributes_mapping := Void end note library: "EiffelBase: Library of reusable components for Eiffel." copyright: "Copyright (c) 1984-2020, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end -- class SED_INDEPENDENT_DESERIALIZER
Generated by ISE EiffelStudio