indexing description: "Represents a discovery response message" license: "MIT license (see ../../license.txt)" author: "Beat Strasser " date: "$Date$" revision: "$Revision$" class P2P_DISCOVERY_RESPONSE inherit P2P_XML_CACHE redefine document, validate, initialize end P2P_CREATORS_SHARED undefine out end create make_with_response, make_with_peer_advertisement, make_from_query, make_from_element, parse_from_string feature {NONE} -- Initialization make_with_response (a_type: like type; a_responses_list: DS_LIST [P2P_ADVERTISEMENT]) is -- Create new discovery response message require Type_valid: a_type >= {P2P_DISCOVERY_SERVICE}.type_peer and a_type <= {P2P_DISCOVERY_SERVICE}.type_general List_valid: a_responses_list /= Void and a_responses_list.count > 0 do initialize set_type (a_type) add_responses (a_responses_list) is_valid := True ensure Type_set: type = a_type end make_with_peer_advertisement (a_peer_advertisement: like peer_advertisement) is -- Create new discovery response message with a peer advertisement only require Advertisement_valid: a_peer_advertisement /= Void and a_peer_advertisement.is_valid do initialize set_type ({P2P_DISCOVERY_SERVICE}.type_peer) set_peer_advertisement (a_peer_advertisement) is_valid := True ensure Type_set: type = {P2P_DISCOVERY_SERVICE}.type_peer Advertisement_set: peer_advertisement = a_peer_advertisement end make_from_query (a_query: P2P_DISCOVERY_QUERY; a_responses_list: DS_LIST [P2P_ADVERTISEMENT]) is -- Create new response to given `a_query' require Query_valid: a_query /= Void and a_query.is_valid Responses_valid: a_responses_list /= Void and a_responses_list.count > 0 do initialize set_type (a_query.type) if a_query.key /= Void and a_query.value /= Void then set_restriction (a_query.key, a_query.value) end add_responses (a_responses_list) is_valid := True ensure Type_set: type = a_query.type Key_set: key = a_query.key Value_set: value = a_query.value end feature -- Access type: INTEGER key: STRING value: STRING peer_advertisement: P2P_PEER_ADVERTISEMENT responses: DS_LIST [P2P_ADVERTISEMENT] count: INTEGER is -- Number of responses do if responses.count = 0 and peer_advertisement /= Void and type = {P2P_DISCOVERY_SERVICE}.type_peer then Result := 1 else Result := responses.count end end match (an_element_name, an_element_value: STRING): BOOLEAN is -- Is given element's value equal with `an_element_value'? do if element_type.is_equal (an_element_name) then Result := does_element_match (type, an_element_value) elseif element_key.is_equal (an_element_name) then Result := does_element_match (key, an_element_value) elseif element_value.is_equal (an_element_name) then Result := does_element_match (value, an_element_value) end end all_peer_advertisements: DS_LIST [P2P_PEER_ADVERTISEMENT] is -- All responses incl peer advertisement require Type_is_peer: type = {P2P_DISCOVERY_SERVICE}.type_peer local peer_adv: P2P_PEER_ADVERTISEMENT do create {DS_ARRAYED_LIST [P2P_PEER_ADVERTISEMENT]} Result.make (responses.count + 1) if peer_advertisement /= Void then Result.put_last (peer_advertisement) end from responses.start until responses.after loop peer_adv ?= responses.item_for_iteration if peer_adv /= Void then Result.put_last (peer_adv) end responses.forth end ensure Result_set: Result /= Void end feature -- Element change set_type (a_type: like type) is -- Set response's advertisement type require Type_valid: a_type >= {P2P_DISCOVERY_SERVICE}.type_peer and a_type <= {P2P_DISCOVERY_SERVICE}.type_general do type := a_type renew_document ensure Type_set: type = a_type end set_restriction (a_key: like key; a_value: like value) is -- Set key and value require Key_valid: a_key /= Void Value_valid: a_value /= Void do key := a_key value := a_value renew_document ensure Key_set: key.is_equal (a_key) Value_set: value.is_equal (a_value) end set_peer_advertisement (an_adv: like peer_advertisement) is -- Set peer advertisement require Advertisement_valid: an_adv /= Void and an_adv.is_valid do peer_advertisement := an_adv renew_document ensure Advertisement_set: peer_advertisement.is_equal (an_adv) end add_response (an_adv: P2P_ADVERTISEMENT) is -- Add response require Advertisement_valid: an_adv /= Void and an_adv.is_valid do if not responses.has (an_adv) then responses.put_last (an_adv) renew_document end ensure Advertisement_added: responses.has (an_adv) end add_responses (a_list: DS_LIST [P2P_ADVERTISEMENT]) is -- Add responses from `a_list' require List_valid: a_list /= Void do from a_list.start until a_list.after loop if a_list.item_for_iteration.is_valid and not responses.has (a_list.item_for_iteration) then responses.put_last (a_list.item_for_iteration) renew_document end a_list.forth end end feature -- Output document: P2P_XML_DOCUMENT is -- Create XML document local cached: BOOLEAN do cached := cached_document /= Void -- create document Result := Precursor if not cached then -- Element Type Result.create_root_child_element (element_type, Result.namespace_empty) Result.create_content (Result.last_element, type.out) -- Element Count Result.create_root_child_element (element_count, Result.namespace_empty) Result.create_content (Result.last_element, responses.count.out) if key /= Void and value /= Void then -- Element Attr Result.create_root_child_element (element_key, Result.namespace_empty) Result.create_content (Result.last_element, key) -- Element Value Result.create_root_child_element (element_value, Result.namespace_empty) Result.create_content (Result.last_element, value) end -- Element PeerAdv if peer_advertisement /= Void then Result.create_root_child_element (element_peer_advertisement, Result.namespace_empty) Result.create_content (Result.last_element, peer_advertisement.out) end -- Element Response from responses.start until responses.after loop Result.create_root_child_element (element_response, Result.namespace_empty) Result.last_element.add_unqualified_attribute (attribute_expiration, responses.item_for_iteration.expiration_time.out) Result.create_content (Result.last_element, responses.item_for_iteration.out) responses.forth end end end feature {NONE} -- Implementation Element_type: STRING is "Type" Element_count: STRING is "Count" Element_key: STRING is "Attr" Element_value: STRING is "Value" Element_peer_advertisement: STRING is "PeerAdv" Element_response: STRING is "Response" Attribute_expiration: STRING is "Expiration" root_element_name: STRING is "DiscoveryResponse" attribute_handler (root_attribute: XM_ATTRIBUTE) is -- No attributes do end element_handler (element: XM_ELEMENT) is -- Handle root child element of parsed advertisement local int_value: STRING unknown_adv: P2P_UNKNOWN_ADVERTISEMENT an_adv: P2P_ADVERTISEMENT attr_expiration: XM_ATTRIBUTE do if element_type.is_equal (element.name) then int_value := element_text (element) if int_value.is_integer then type := int_value.to_integer else type := -1 end elseif element_key.is_equal (element.name) then key := trimmed (element.text) elseif element_value.is_equal (element.name) then value := trimmed (element.text) elseif element_peer_advertisement.is_equal (element.name) then attr_expiration := element.attribute_by_name (attribute_expiration) if attr_expiration /= Void then int_value := trimmed (attr_expiration.value) end create peer_advertisement.parse_from_string (element_text (element)) if peer_advertisement.is_valid then -- set advertisements expiration and life time if int_value /= Void and int_value.is_integer_64 then peer_advertisement.set_expiration_time (int_value.to_integer_64) end peer_advertisement.set_lifetime_relative (peer_advertisement.expiration_time) else peer_advertisement := Void end elseif element_response.is_equal (element.name) then attr_expiration := element.attribute_by_name (attribute_expiration) if attr_expiration /= Void then int_value := trimmed (attr_expiration.value) end create unknown_adv.parse_from_string (element_text (element)) an_adv := xml_document_creator.advertisement_from_element (unknown_adv.document.document.root_element) if an_adv /= Void then -- set advertisements expiration and life time if int_value /= Void and int_value.is_integer_64 then an_adv.set_expiration_time (int_value.to_integer_64) end an_adv.set_lifetime_relative (an_adv.expiration_time) responses.put_last (an_adv) end end end validate is -- Validate message and set `is_valid' do is_valid := is_valid and type >= {P2P_DISCOVERY_SERVICE}.type_peer and type <= {P2P_DISCOVERY_SERVICE}.type_general and count > 0 and (key = Void implies value = Void) and (value = Void implies key = Void) end initialize is -- Initialize data structures local advertisement_tester: KL_EQUALITY_TESTER [P2P_ADVERTISEMENT] do create {DS_LINKED_LIST [P2P_ADVERTISEMENT]} responses.make create advertisement_tester responses.set_equality_tester (advertisement_tester) end end