note description: "EWG config file validator" copyright: "Copyright (c) 2004, Andreas Leitner and others" license: "Eiffel Forum License v2 (see forum.txt)" date: "$Date$" revision: "$Revision$" class EWG_CONFIG_VALIDATOR inherit EWG_CONFIG_ELEMENT_NAMES export {NONE} all end EWG_CONFIG_SHARED_WRAPPER_TYPE_NAMES export {NONE} all end EWG_CONFIG_SHARED_CONSTRUCT_TYPE_NAMES export {NONE} all end KL_IMPORTED_STRING_ROUTINES export {NONE} all end ANY create make feature {NONE} -- Initialization make (an_error_handler: like error_handler) -- Create new EWG config file validator. require an_error_handler_not_void: an_error_handler /= Void do error_handler := an_error_handler ensure error_handler_set: error_handler = an_error_handler end feature {ANY} -- Status report has_error: BOOLEAN -- Has an error been detected during the -- last validation procress? feature {ANY} -- Access error_handler: EWG_ERROR_HANDLER -- Error handler feature {ANY} -- Validation validate_config_system_doc (a_doc: XM_DOCUMENT; a_position_table: XM_POSITION_TABLE) -- Check whether `a_doc' is a valid XML EWG config system. -- Set `has_error' to `True' if not. require a_doc_not_void: a_doc /= Void a_position_table_not_void: a_position_table /= Void do has_error := False if STRING_.same_string (a_doc.root_element.name, config_system_element_name) then validate_config_system (a_doc.root_element, a_position_table) else has_error := True error_handler.report_wrong_config_root_element_error (config_system_element_name, a_position_table.item (a_doc.root_element)) end end feature {NONE} -- Validation validate_config_system (a_config_system: XM_ELEMENT; a_position_table: XM_POSITION_TABLE) -- Check whether `a_config_system' is a valid EWG config "ewg_config" element. -- Set `has_error' to `True' if not. require a_config_system_not_void: a_config_system /= Void a_config_system_is_config_system: STRING_.same_string (a_config_system.name, config_system_element_name) a_position_table_not_void: a_position_table /= Void local cs: DS_BILINEAR_CURSOR [XM_NODE] child: XM_ELEMENT do cs := a_config_system.new_cursor from cs.start until cs.after loop child ?= cs.item if child = Void then -- Not an element. Ignore. elseif STRING_.same_string (child.name, rule_list_element_name) then -- OK. validate_rule_list (child, a_position_table) else has_error := True error_handler.report_unknown_config_element_error (a_config_system, child, a_position_table.item (child)) end cs.forth end end validate_rule_list (a_rule_list: XM_ELEMENT; a_position_table: XM_POSITION_TABLE) -- Check whether `a_rule_list' is a valid EWG config "rule_list" element. -- Set `has_error' to `True' if not. require a_rule_list_not_void: a_rule_list /= Void a_rule_list_is_rule_list: STRING_.same_string (a_rule_list.name, rule_list_element_name) a_position_table_not_void: a_position_table /= Void local cs: DS_BILINEAR_CURSOR [XM_NODE] child: XM_ELEMENT do cs := a_rule_list.new_cursor from cs.start until cs.after loop child ?= cs.item if child = Void then -- Not an element. Ignore. elseif STRING_.same_string (child.name, rule_element_name) then -- OK. validate_rule (child, a_position_table) else has_error := True error_handler.report_unknown_config_element_error (a_rule_list, child, a_position_table.item (child)) end cs.forth end end validate_rule (a_rule: XM_ELEMENT; a_position_table: XM_POSITION_TABLE) -- Check whether `a_rule' is a valid EWG config "rule" element. -- Set `has_error' to `True' if not. require a_rule_not_void: a_rule /= Void a_rule_is_rule: STRING_.same_string (a_rule.name, rule_element_name) a_position_table_not_void: a_position_table /= Void local cs: DS_BILINEAR_CURSOR [XM_NODE] child: XM_ELEMENT match_clause_parsed: BOOLEAN construct_type_name: STRING construct_type_code: INTEGER do cs := a_rule.new_cursor cs.start from cs.start until cs.after loop child ?= cs.item if child = Void then -- Not an element. Ignore. elseif STRING_.same_string (child.name, match_element_name) then -- OK. validate_match (child, a_position_table) match_clause_parsed := True if attached child.element_by_name (type_element_name) as type and then attached type.attribute_by_name (name_attribute_name) as l_construct_type_name then construct_type_name := l_construct_type_name.value construct_type_code := construct_type_names.construct_type_code_from_name (construct_type_name) else construct_type_code := construct_type_names.any_code end elseif STRING_.same_string (child.name, wrapper_element_name) then if not match_clause_parsed then error_handler.report_unexpected_element_error (match_element_name, child, a_position_table.item (child)) else -- OK. validate_wrapper (child, a_position_table, construct_type_code) end elseif STRING_.same_string (child.name, function_element_name) then validate_function (child, a_position_table) elseif STRING_.same_string (child.name, function_element_address_name) then validate_function_address (child, a_position_table) else has_error := True error_handler.report_unknown_config_element_error (a_rule, child, a_position_table.item (child)) end cs.forth end end validate_match (a_match: XM_ELEMENT; a_position_table: XM_POSITION_TABLE) -- Check whether `a_match' is a valid EWG config "match" element. -- Set `has_error' to `True' if not. require a_match_not_void: a_match /= Void a_match_is_rule: STRING_.same_string (a_match.name, match_element_name) a_position_table_not_void: a_position_table /= Void local cs: DS_BILINEAR_CURSOR [XM_NODE] child: XM_ELEMENT do cs := a_match.new_cursor from cs.start until cs.after loop child ?= cs.item if child = Void then -- Not an element. Ignore. elseif STRING_.same_string (child.name, header_element_name) then -- OK. validate_header (child, a_position_table) elseif STRING_.same_string (child.name, identifier_element_name) then -- OK. validate_identifier (child, a_position_table) elseif STRING_.same_string (child.name, type_element_name) then -- OK. validate_match_type (child, a_position_table) else has_error := True error_handler.report_unknown_config_element_error (a_match, child, a_position_table.item (child)) end cs.forth end end validate_function (a_function: XM_ELEMENT; a_position_table: XM_POSITION_TABLE) -- Check whether `a_function' is a valid EWG config "function" element. -- Set `has_error' to `True' if not. require a_function_not_void: a_function /= Void a_function_is_rule: STRING_.same_string (a_function.name, function_element_name) a_position_table_not_void: a_position_table /= Void local cs: DS_BILINEAR_CURSOR [XM_NODE] child: XM_ELEMENT do if not a_function.has_attribute_by_name (name_attribute_name) then has_error := True error_handler.report_missing_config_attribute_error (a_function, name_attribute_name, a_position_table.item (a_function)) else -- create regexp.make -- regexp.compile (a_identifier.attribute_by_name (name_attribute_name).value) -- if not regexp.is_compiled then -- error_handler.report_illegal_regular_expression_in_attribute (a_identifier, -- name_attribute_name, -- a_position_table.item (a_identifier), -- regexp.error_message, -- regexp.error_position) -- end end cs := a_function.new_cursor from cs.start until cs.after loop child ?= cs.item if child = Void then -- Not an element. Ignore. else has_error := True error_handler.report_unknown_config_element_error (a_function, child, a_position_table.item (child)) end cs.forth end end validate_function_address (a_function_address: XM_ELEMENT; a_position_table: XM_POSITION_TABLE) -- Check whether `a_function_address' is a valid EWG config "function_address" element. -- Set `has_error' to `True' if not. require a_function_address_not_void: a_function_address /= Void a_function_address_is_rule: STRING_.same_string (a_function_address.name, function_element_address_name) a_position_table_not_void: a_position_table /= Void local cs: DS_BILINEAR_CURSOR [XM_NODE] child: XM_ELEMENT regexp: RX_PCRE_REGULAR_EXPRESSION do if not a_function_address.has_attribute_by_name (name_attribute_name) then has_error := True error_handler.report_missing_config_attribute_error (a_function_address, name_attribute_name, a_position_table.item (a_function_address)) else -- create regexp.make -- regexp.compile (a_identifier.attribute_by_name (name_attribute_name).value) -- if not regexp.is_compiled then -- error_handler.report_illegal_regular_expression_in_attribute (a_identifier, -- name_attribute_name, -- a_position_table.item (a_identifier), -- regexp.error_message, -- regexp.error_position) -- end end cs := a_function_address.new_cursor from cs.start until cs.after loop child ?= cs.item if child = Void then -- Not an element. Ignore. else has_error := True error_handler.report_unknown_config_element_error (a_function_address, child, a_position_table.item (child)) end cs.forth end end validate_wrapper (a_wrapper: XM_ELEMENT; a_position_table: XM_POSITION_TABLE; a_construct_type_code: INTEGER) -- Check whether `a_wrapper' is a valid EWG config "wrapper" element. -- Set `has_error' to `True' if not. require a_wrapper_not_void: a_wrapper /= Void a_wrapper_is_rule: STRING_.same_string (a_wrapper.name, wrapper_element_name) a_position_table_not_void: a_position_table /= Void valid_construct_type_code: construct_type_names.is_valid_construct_type_code (a_construct_type_code) local cs: DS_BILINEAR_CURSOR [XM_NODE] child: XM_ELEMENT do if attached a_wrapper.attribute_by_name (type_attribute_name) as l_type_attribute_name then if not wrapper_type_names.is_valid_wrapper_type_name (l_type_attribute_name.value) then has_error := True error_handler.report_unknown_config_wrapper_type_error (a_wrapper, a_position_table.item (a_wrapper)) end end if attached a_wrapper.attribute_by_name (type_attribute_name) as l_type_attribute_name then if not wrapper_type_names.is_valid_wrapper_type_name (l_type_attribute_name.value) then has_error := True error_handler.report_unknown_config_wrapper_type_error (a_wrapper, a_position_table.item (a_wrapper)) end else has_error := True error_handler.report_missing_config_attribute_error (a_wrapper, type_attribute_name, a_position_table.item (a_wrapper)) end cs := a_wrapper.new_cursor from cs.start until cs.after loop child ?= cs.item if child = Void then -- Not an element. Ignore. else if STRING_.same_string (child.name, class_name_element_name) and ( a_construct_type_code = construct_type_names.function_code or a_construct_type_code = construct_type_names.macro_code) then -- OK validate_class_name (child, a_position_table) elseif STRING_.same_string (child.name, callbacks_per_type_element_name) and a_construct_type_code = construct_type_names.callback_code then -- OK validate_callbacks_per_type (child, a_position_table) else has_error := True error_handler.report_unknown_config_element_error (a_wrapper, child, a_position_table.item (child)) end end cs.forth end end validate_header (a_header: XM_ELEMENT; a_position_table: XM_POSITION_TABLE) -- Check whether `a_header' is a valid EWG config "header" element. -- Set `has_error' to `True' if not. require a_header_not_void: a_header /= Void a_header_is_rule: STRING_.same_string (a_header.name, header_element_name) a_position_table_not_void: a_position_table /= Void local cs: DS_BILINEAR_CURSOR [XM_NODE] child: XM_ELEMENT regexp: RX_PCRE_REGULAR_EXPRESSION do if attached a_header.attribute_by_name (name_attribute_name) as l_name_attribute_name then create regexp.make regexp.compile (l_name_attribute_name.value) if not regexp.is_compiled then error_handler.report_illegal_regular_expression_in_attribute (a_header, name_attribute_name, a_position_table.item (a_header), regexp.error_message, regexp.error_position) end else has_error := True error_handler.report_missing_config_attribute_error (a_header, name_attribute_name, a_position_table.item (a_header)) end cs := a_header.new_cursor from cs.start until cs.after loop child ?= cs.item if child = Void then -- Not an element. Ignore. else has_error := True error_handler.report_unknown_config_element_error (a_header, child, a_position_table.item (child)) end cs.forth end end validate_identifier (a_identifier: XM_ELEMENT; a_position_table: XM_POSITION_TABLE) -- Check whether `a_identifier' is a valid EWG config "identifier" element. -- Set `has_error' to `True' if not. require a_identifier_not_void: a_identifier /= Void a_identifier_is_rule: STRING_.same_string (a_identifier.name, identifier_element_name) a_position_table_not_void: a_position_table /= Void local cs: DS_BILINEAR_CURSOR [XM_NODE] child: XM_ELEMENT regexp: RX_PCRE_REGULAR_EXPRESSION do if attached a_identifier.attribute_by_name (name_attribute_name) as l_name_attribute_name then create regexp.make regexp.compile (l_name_attribute_name.value) if not regexp.is_compiled then error_handler.report_illegal_regular_expression_in_attribute (a_identifier, name_attribute_name, a_position_table.item (a_identifier), regexp.error_message, regexp.error_position) end else has_error := True error_handler.report_missing_config_attribute_error (a_identifier, name_attribute_name, a_position_table.item (a_identifier)) end cs := a_identifier.new_cursor from cs.start until cs.after loop child ?= cs.item if child = Void then -- Not an element. Ignore. else has_error := True error_handler.report_unknown_config_element_error (a_identifier, child, a_position_table.item (child)) end cs.forth end end validate_match_type (a_type: XM_ELEMENT; a_position_table: XM_POSITION_TABLE) -- Check whether `a_type' is a valid EWG config "type" element. -- Set `has_error' to `True' if not. require a_type_not_void: a_type /= Void a_type_is_rule: STRING_.same_string (a_type.name, type_element_name) a_position_table_not_void: a_position_table /= Void local cs: DS_BILINEAR_CURSOR [XM_NODE] child: XM_ELEMENT name: STRING do if attached a_type.attribute_by_name (name_attribute_name) as l_name_attribute_name then name := l_name_attribute_name.value if not construct_type_names.is_valid_construct_type_name (name) then has_error := True error_handler.report_unknown_config_construct_type_error (a_type, a_position_table.item (a_type)) end else has_error := True error_handler.report_missing_config_attribute_error (a_type, name_attribute_name, a_position_table.item (a_type)) end cs := a_type.new_cursor from cs.start until cs.after loop child ?= cs.item if child = Void then -- Not an element. Ignore. else has_error := True error_handler.report_unknown_config_element_error (a_type, child, a_position_table.item (child)) end cs.forth end end validate_class_name (a_class_name: XM_ELEMENT; a_position_table: XM_POSITION_TABLE) -- Check whether `a_class_name' is a valid EWG config "class_name" element. -- Set `has_error' to `True' if not. require a_class_name_not_void: a_class_name /= Void a_class_name_is_class_name: STRING_.same_string (a_class_name.name, class_name_element_name) a_position_table_not_void: a_position_table /= Void local cs: DS_BILINEAR_CURSOR [XM_NODE] child: XM_ELEMENT name: STRING do if attached a_class_name.attribute_by_name (name_attribute_name) as l_name_attribute_name then name := l_name_attribute_name.value if name.count = 0 then has_error := True error_handler.report_invalid_class_name_error (a_class_name, a_position_table.item (a_class_name)) end else has_error := True error_handler.report_missing_config_attribute_error (a_class_name, name_attribute_name, a_position_table.item (a_class_name)) end cs := a_class_name.new_cursor from cs.start until cs.after loop child ?= cs.item if child = Void then -- Not an element. Ignore. else has_error := True error_handler.report_unknown_config_element_error (a_class_name, child, a_position_table.item (child)) end cs.forth end end validate_callbacks_per_type (a_callback: XM_ELEMENT; a_position_table: XM_POSITION_TABLE) -- Check whether `a_callback' is a valid EWG config "callbacks_per_type" element. -- Set `has_error' to `True' if not. require a_class_name_not_void: a_callback /= Void a_class_name_is_class_name: STRING_.same_string (a_callback.name, callbacks_per_type_element_name) a_position_table_not_void: a_position_table /= Void local cs: DS_BILINEAR_CURSOR [XM_NODE] child: XM_ELEMENT value: STRING do if attached a_callback.attribute_by_name (value_attribute_name) as l_value_attribute_name then value := l_value_attribute_name.value if not value.is_natural then has_error := True error_handler.report_invalid_class_name_error (a_callback, a_position_table.item (a_callback)) end else has_error := True error_handler.report_missing_config_attribute_error (a_callback, value_attribute_name, a_position_table.item (a_callback)) end cs := a_callback.new_cursor from cs.start until cs.after loop child ?= cs.item if child = Void then -- Not an element. Ignore. else has_error := True error_handler.report_unknown_config_element_error (a_callback, child, a_position_table.item (child)) end cs.forth end end invariant error_handler_not_void: error_handler /= Void end