note
	description: "Notion of event type"
	documenatiton: "[
					Usage and architecture described in the article 
					'Event Library: an object-oriented library for even-driven design',
					by Volkan Arslan, Piotr Nienaltowski, and Karine Arnout.
					]"
	date: "$Date: 2003/01/31"
	revision: "$Revision: 1.0"
	authors: "Volkan Arslan, Alexey Kolesnichenko"
	institute: "Chair of Software Engineering, ETH Zurich, Switzerland"

class
	EVENT_TYPE [ EVENT_DATA -> TUPLE]

inherit ANY
redefine
	default_create
end
feature {NONE} -- Initialization

	default_create
		do
			create actions_list.make
			actions_list.compare_objects
		end

feature -- Element change

	subscribe (an_action: separate PROCEDURE [ANY, EVENT_DATA])
			-- Add `an_action' to the subscription list.		
		require
			an_action_not_void: an_action /= Void
			an_action_not_already_subscribed: not has (an_action)
		do
			actions_list.extend (an_action)
		ensure
			an_action_subscribed: actions_list.count = old actions_list.count + 1 and has (an_action)
			index_at_same_position: actions_list.index = old actions_list.index
		end

	unsubscribe (an_action: separate PROCEDURE [ANY, EVENT_DATA])
			-- Remove `an_action' from the subscription list.
		require
			an_action_not_void: an_action /= Void
			an_action_already_subscribed: has (an_action)
		local
			pos: INTEGER
		do
			pos := actions_list.index
			actions_list.start
			actions_list.search (an_action)
			actions_list.remove
			actions_list.go_i_th (pos)
		ensure
			an_action_unsubscribed: actions_list.count = old actions_list.count - 1 and not has (an_action)
			index_at_same_position: actions_list.index = old actions_list.index
		end

feature -- Publication

	publish (arguments: EVENT_DATA)
			-- Publish all not suspended actions from the subscription list.
		require
			arguments_not_void: arguments /= Void
		do
			if not is_suspended then

				across actions_list as iterator
				loop
					call_async (iterator.item, arguments)
				end
			end
		end

feature{NONE}
	call_async(delegate: separate PROCEDURE [ANY, EVENT_DATA]; data : EVENT_DATA)
	do
		delegate.call(data)
	end
feature -- Status report

	is_suspended: BOOLEAN
			-- Is the publication of all actions from the subscription list suspended?
			-- (Answer: no by default.)			

	has(a_item: separate PROCEDURE [ANY, EVENT_DATA]) : BOOLEAN
	do
		Result := actions_list.has (a_item)
	end
feature -- Status settings

	suspend_subscription
			-- Ignore the call of all actions from the subscription list,
			-- until feature restore_subscription is called.
		do
			is_suspended := True
		ensure
			subscription_suspended: is_suspended
		end

	restore_subscription
			-- Consider again the call of all actions from the subscription list,
			-- until feature suspend_subscription is called.
		do
			is_suspended := False
		ensure
			subscription_not_suspended: not is_suspended
		end

feature {NONE}
	actions_list : LINKED_LIST[separate PROCEDURE [ANY, EVENT_DATA]]
end -- class EVENT_TYPE
