note description: "Class to write a feature call transition into Solr format" author: "" date: "$Date$" revision: "$Revision$" class SOLR_FEATURE_CALL_WRITER inherit SEM_TRANSITION_WRITER [SEM_FEATURE_CALL_TRANSITION] SOLR_QUERYABLE_WRITER [SEM_FEATURE_CALL_TRANSITION] SEM_UTILITY EPA_SHARED_EQUALITY_TESTERS create make_with_medium feature{NONE} -- Initialization make_with_medium (a_medium: like medium) -- Initialize `medium' with `a_medium'. do set_medium (a_medium) end feature -- Basic operations write (a_transition: like queryable) -- Write `a_transition' into `medium'. do queryable := a_transition queryable_dynamic_type_name_table := type_name_table (queryable.variable_dynamic_type_table) queryable_static_type_name_table := type_name_table (queryable.variable_static_type_table) create dynamic_change_meta.make (400) dynamic_change_meta.compare_objects create static_change_meta.make (400) static_change_meta.compare_objects medium.put_string (once "%N") append_basic_info append_contracts append_changes append_serialization append_exception medium.put_string (once "%N") end feature{NONE} -- Implementation queryable_static_type_name_table: like type_name_table -- Static type name table for variables in `queryable' queryable_dynamic_type_name_table: like type_name_table -- Dynamic type name table for variables in `queryable' append_basic_info -- Append basic information of `queryable' into `medium'. do append_queryable_type (queryable) append_class_and_feature (queryable) append_uuid append_library (queryable) append_feature_type (queryable) append_transition_status (queryable) -- append_variables (queryable.inputs.union (queryable.outputs), dynamic_variables_field, True, False, False) -- append_variables (queryable.inputs.union (queryable.outputs), variables_field, True, False, True) -- append_variables (queryable.inputs.union (queryable.outputs), variable_types_field, False, True, False) append_variables (queryable.variables, dynamic_variables_field, True, False, False) append_variables (queryable.variables, variables_field, True, False, True) append_variables (queryable.variables, variable_types_field, False, True, False) append_interface_variable_positions append_content append_hit_breakpoints (queryable) end append_interface_variable_positions -- Append position information for interface variables into `medium'. local l_arg_count: INTEGER l_vars: DS_HASH_SET [EPA_EXPRESSION] do -- For target variable. create l_vars.make (1) l_vars.set_equality_tester (expression_equality_tester) l_vars.force_last (queryable.reversed_variable_position.item (0)) append_interface_variable_positions_internal (l_vars, target_varaible_short) -- For result variable. if queryable.is_query then create l_vars.make (1) l_vars.set_equality_tester (expression_equality_tester) l_vars.force_last (queryable.reversed_variable_position.item (queryable.argument_count + 1)) append_interface_variable_positions_internal (l_vars, result_varaible_short) end -- For argument variables. if queryable.argument_count > 0 then create l_vars.make (queryable.argument_count) l_vars.set_equality_tester (expression_equality_tester) across 1 |..| queryable.argument_count as l_arg_indexes loop l_vars.force_last (queryable.reversed_variable_position.item (l_arg_indexes.item)) end append_interface_variable_positions_internal (l_vars, argument_variable_short) end -- For particular variables. if queryable.argument_count > 0 then across 1 |..| queryable.argument_count as l_arg_indexes loop create l_vars.make (queryable.argument_count) l_vars.set_equality_tester (expression_equality_tester) l_vars.force_last (queryable.reversed_variable_position.item (l_arg_indexes.item)) append_interface_variable_positions_internal (l_vars, one_argument_variable_short + "_" + l_arg_indexes.item.out) end end -- For operand variables (target + argument). if queryable.argument_count > 0 then create l_vars.make (queryable.argument_count + 1) l_vars.set_equality_tester (expression_equality_tester) across 0 |..| queryable.argument_count as l_arg_indexes loop l_vars.force_last (queryable.reversed_variable_position.item (l_arg_indexes.item)) end append_interface_variable_positions_internal (l_vars, operand_variable_short) end -- For interface variables (target + argument + result). if queryable.argument_count > 0 then create l_vars.make (queryable.argument_count + 2) l_vars.set_equality_tester (expression_equality_tester) across 0 |..| (queryable.interface_variable_count - 1) as l_arg_indexes loop l_vars.force_last (queryable.reversed_variable_position.item (l_arg_indexes.item)) end append_interface_variable_positions_internal (l_vars, interface_variable_short) end end append_interface_variable_positions_internal (a_vars: DS_HASH_SET [EPA_EXPRESSION]; a_category: STRING) -- Append position information for interface variables into `medium'. local l_dfield_value, l_sfield_value: STRING l_meta_field_value: STRING l_cursor: DS_HASH_SET_CURSOR [EPA_EXPRESSION] l_var_name: STRING l_var_position: INTEGER do create l_sfield_value.make (128) create l_dfield_value.make (128) create l_meta_field_value.make (256) from l_cursor := a_vars.new_cursor l_cursor.start until l_cursor.after loop l_var_name := l_cursor.item.text l_var_position := queryable.variable_position (l_cursor.item) l_sfield_value.append (queryable.static_type_name_table.item (l_var_name)) l_sfield_value.append_character (field_value_separator) l_dfield_value.append (queryable.dynamic_type_name_table.item (l_var_name)) l_dfield_value.append_character (field_value_separator) l_meta_field_value.append (l_var_position.out) l_meta_field_value.append_character (',') l_meta_field_value.append_boolean (True) l_meta_field_value.append_character (field_value_separator) l_cursor.forth end append_string_field (once "t_s_" + a_category, l_sfield_value) append_string_field (once "t_d_" + a_category, l_dfield_value) append_string_field (once "s_s_" + a_category, l_meta_field_value) append_string_field (once "s_d_" + a_category, l_meta_field_value) end append_contracts -- Append contracts from `queryable' into `medium'. local l_equations: like queryable.interface_equations.new_cursor l_expr: EPA_EXPRESSION l_tran: like queryable l_var_dtype_tbl: like type_name_table l_var_stype_tbl: like type_name_table l_type: INTEGER l_anonymous: STRING a_prefix: STRING l_equation: SEM_EQUATION l_boost: DOUBLE l_value_text: STRING l_value: EPA_EXPRESSION_VALUE l_prefix: STRING l_smeta: HASH_TABLE [DS_HASH_SET [STRING], STRING] l_dmeta: HASH_TABLE [DS_HASH_SET [STRING], STRING] l_body: STRING l_field_name: STRING l_list: LINKED_LIST [STRING] l_meta_value: STRING l_separator: STRING l_char: CHARACTER l_set: DS_HASH_SET_CURSOR [STRING] do l_tran := queryable l_var_dtype_tbl := queryable_dynamic_type_name_table l_var_stype_tbl := queryable_static_type_name_table l_separator := field_value_separator.out create l_smeta.make (400) l_smeta.compare_objects create l_dmeta.make (400) l_dmeta.compare_objects -- Iterate through all interface contracts from `queryable'. from if queryable.is_passing then l_equations := queryable.all_equations.new_cursor else l_equations := queryable.all_precondition_equations.new_cursor end l_equations.start until l_equations.after loop l_equation := l_equations.item l_expr := l_equation.expression l_value := l_equation.value l_value_text := l_value.text l_type := type_of_equation (l_equation.equation) l_boost := boost_value_for_equation (l_equation) if l_equation.is_precondition then l_prefix := precondition_prefix else l_prefix := postcondition_prefix end -- Only handle integer value and boolean values. if l_value.is_integer or l_value.is_boolean then -- Output anonymous format. l_anonymous := queryable.anonymous_expression_text (l_expr) append_field_with_data (field_name_for_equation (l_anonymous, l_equation.equation, anonymous_type_form, False, l_prefix), l_value_text, l_type, l_boost) -- Output dynamic type format. l_body := expression_with_replacements (l_expr, l_var_dtype_tbl, True) append_field_with_data ( field_name_for_equation ( l_body, l_equation.equation, dynamic_type_form, False, l_prefix), l_value_text, l_type, l_boost) l_field_name := field_name_for_equation (l_body, l_equation.equation, dynamic_type_form, True, l_prefix) l_meta_value := text_for_variable_indexes_and_value (l_anonymous, l_value_text) extend_string_into_list (l_smeta, l_meta_value, l_field_name) -- Output static type format. l_body := expression_with_replacements (l_expr, l_var_stype_tbl, True) append_field_with_data ( field_name_for_equation ( l_body, l_equation.equation, static_type_form, False, l_prefix), l_value_text, l_type, l_boost) l_field_name := field_name_for_equation (l_body, l_equation.equation, static_type_form, True, l_prefix) extend_string_into_list (l_dmeta, l_meta_value, l_field_name) end l_equations.forth end across <> as l_metas loop across l_metas.item as l_items loop create l_value_text.make (256) from l_set := l_items.item.new_cursor l_set.start until l_set.after loop l_value_text.append (l_set.item) l_set.forth end append_field_with_data (l_items.key, l_value_text, ir_string_value_type, l_boost) end end end append_content -- Append content of `queryable' to `medium'. do append_string_field (content_field, queryable.content) end append_changes -- Append state-changes of `queryable' to `medium'. local l_change_calculator: EPA_EXPRESSION_CHANGE_CALCULATOR l_dynamic_change: DS_HASH_TABLE [LIST [EPA_EXPRESSION_CHANGE], EPA_EXPRESSION] l_static_change: DS_HASH_TABLE [LIST [EPA_EXPRESSION_CHANGE], EPA_EXPRESSION] l_type: INTEGER l_set: DS_HASH_SET_CURSOR [STRING] l_value_text: STRING do if queryable.is_passing then create l_change_calculator.make l_static_change := l_change_calculator.change_set (queryable.written_preconditions, queryable.written_postconditions) append_change_set (l_static_change, default_boost_value * 2.0) l_dynamic_change := l_change_calculator.change_set (queryable.preconditions, queryable.postconditions) append_change_set (l_dynamic_change, default_boost_value) l_type := ir_string_value_type across <> as l_metas loop across l_metas.item as l_items loop create l_value_text.make (256) from l_set := l_items.item.new_cursor l_set.start until l_set.after loop l_value_text.append (l_set.item) l_set.forth end append_field_with_data (l_items.key, l_value_text, l_type, default_boost_value) end end end end append_change_set (a_set: DS_HASH_TABLE [LIST [EPA_EXPRESSION_CHANGE], EPA_EXPRESSION]; a_boost_value: DOUBLE) -- Append change set `a_set' with `a_boost_value' into `medium'. local l_expr: EPA_EXPRESSION l_cursor: DS_HASH_TABLE_CURSOR [LIST [EPA_EXPRESSION_CHANGE], EPA_EXPRESSION] do from l_cursor := a_set.new_cursor l_cursor.start until l_cursor.after loop l_cursor.item.do_all (agent append_change (?, a_boost_value)) l_cursor.forth end end append_change (a_change: EPA_EXPRESSION_CHANGE; a_boost_value: DOUBLE) -- Append `a_change' into `medium'. local l_values: EPA_EXPRESSION_CHANGE_VALUE_SET l_value: EPA_EXPRESSION l_equations: like queryable.interface_equations.new_cursor l_expr: EPA_EXPRESSION l_tran: like queryable l_var_dtype_tbl: like type_name_table l_var_stype_tbl: like type_name_table l_type: INTEGER l_anonymous: STRING a_prefix: STRING l_equation: SEM_EQUATION l_boost: DOUBLE l_value_text: STRING l_body: STRING l_field_name: STRING l_meta_value: STRING l_meta_value2: STRING l_bool_text: STRING l_bool_type: TYPE_A do if not a_change.values.is_empty then l_var_dtype_tbl := queryable_dynamic_type_name_table l_var_stype_tbl := queryable_static_type_name_table l_expr := a_change.expression if l_expr.is_integer or l_expr.is_boolean then l_value_text := a_change.values.first.text l_type := type_of_expression (l_expr) -- Output anonymous format. l_anonymous := queryable.anonymous_expression_text (a_change.expression) append_field_with_data (field_name_for_change (l_anonymous, a_change, anonymous_type_form, False, False), l_value_text, l_type, a_boost_value) append_field_with_data (field_name_for_change (l_anonymous, a_change, anonymous_type_form, False, True), once "True", ir_boolean_value_type, a_boost_value) -- Output dynamic type format. l_body := expression_with_replacements (l_expr, l_var_dtype_tbl, True) append_field_with_data ( field_name_for_change (l_body, a_change, dynamic_type_form, False, False), l_value_text, l_type, l_boost) append_field_with_data ( field_name_for_change (l_body, a_change, dynamic_type_form, False, True), once "True", ir_boolean_value_type, l_boost) l_field_name := field_name_for_change (l_body, a_change, dynamic_type_form, True, False) l_meta_value := text_for_variable_indexes_and_value (l_anonymous, l_value_text) extend_string_into_list (dynamic_change_meta, l_meta_value, l_field_name) l_field_name := field_name_for_change (l_body, a_change, dynamic_type_form, True, True) l_meta_value2 := text_for_variable_indexes_and_value (l_anonymous, once "True") extend_string_into_list (dynamic_change_meta, l_meta_value2, l_field_name) -- Output static type format. l_body := expression_with_replacements (l_expr, l_var_stype_tbl, True) append_field_with_data ( field_name_for_change (l_body, a_change, static_type_form, False, False), l_value_text, l_type, l_boost) append_field_with_data ( field_name_for_change (l_body, a_change, static_type_form, False, True), once "True", ir_boolean_value_type, l_boost) l_field_name := field_name_for_change (l_body, a_change, static_type_form, True, False) extend_string_into_list (static_change_meta, l_meta_value, l_field_name) l_field_name := field_name_for_change (l_body, a_change, static_type_form, True, True) extend_string_into_list (static_change_meta, l_meta_value2, l_field_name) end end end append_serialization -- Append object serialization data into `medium'. do if pre_state_serialization /= Void and then pre_state_object_info /= Void then append_string_field (pre_serialization_field, pre_state_serialization) append_string_field (pre_object_info_field, pre_state_object_info) end end feature{NONE} -- Implementation dynamic_change_meta: HASH_TABLE [DS_HASH_SET [STRING], STRING] -- Meta data for dynamic change -- Key is Typed expression, value is all anonymous expressions conforming to that typed expression static_change_meta: HASH_TABLE [DS_HASH_SET [STRING], STRING] -- Meta data for dynamic change -- Key is Typed expression, value is all anonymous expressions conforming to that typed expression field_name_for_change (a_name: STRING; a_change: EPA_EXPRESSION_CHANGE; a_format_type: INTEGER; a_meta: BOOLEAN; a_only_change: BOOLEAN): STRING -- Field_name for `a_change' -- `a_anonymous' indicates if the field is a field for anonymous property. do create Result.make (a_name.count + 32) -- Append type prefix. if a_meta then Result.append (string_prefix) elseif a_only_change then Result.append (boolean_prefix) else if a_change.expression.type.is_integer then Result.append (integer_prefix) else Result.append (boolean_prefix) end end Result.append (format_type_prefix (a_format_Type)) if a_only_change then Result.append (change_prefix) else if a_change.is_relative then Result.append (by_change_prefix) else Result.append (to_change_prefix) end end Result.append (encoded_field_string (a_name)) end boost_value_for_equation (a_equation: SEM_EQUATION): DOUBLE -- Boost value for `a_equation' do if a_equation.is_human_written then Result := default_boost_value * 2.0 else Result := default_boost_value end end end