indexing
	description: "The FILE protocol"
	status: "See note at end of class"
	date: "$Date$"
	revision: "$Revision$"

class interface
	FILE_PROTOCOL

create 

	make (addr: like address)
			-- Create protocol.
			-- (from DATA_RESOURCE)
		require -- from DATA_RESOURCE
			address_exists: addr /= void
		ensure -- from DATA_RESOURCE
			address_set: address = addr

feature -- Access

	address: FILE_URL
			-- Associated address

	hash_code: INTEGER
			-- Hash function
			-- (from DATA_RESOURCE)
		ensure -- from HASHABLE
			good_hash_value: Result >= 0

	last_packet: STRING
			-- Last packet read
			-- (from DATA_RESOURCE)

	location: STRING
			-- Location of resource
			-- (from DATA_RESOURCE)
		require -- from DATA_RESOURCE
			address_exists: address /= void

	mode: INTEGER
			-- Current mode
			-- (from DATA_RESOURCE)

	port: INTEGER
			-- Port used by service
			-- (from DATA_RESOURCE)

	service: STRING
			-- Name of service
			-- (from DATA_RESOURCE)
	
feature -- Measurement

	bytes_transferred: INTEGER
			-- Number of transferred bytes

	count: INTEGER
			-- Size of data resource

	last_packet_size: INTEGER
			-- Size of last packet

	read_buffer_size: INTEGER
			-- Size of read buffer
	
feature -- Comparison

	is_equal (other: like Current): BOOLEAN
			-- Is resource equal to other?
			-- (from DATA_RESOURCE)
		require -- from ANY
			other_not_void: other /= void
		ensure -- from ANY
			symmetric: Result implies other.is_equal (Current)
			consistent: standard_is_equal (other) implies Result
	
feature -- Status report

	address_exists: BOOLEAN
			-- Does address exist?

	error: BOOLEAN
			-- Has an error occurred?
			-- (from DATA_RESOURCE)

	error_code: INTEGER
			-- Code of error
			-- (from DATA_RESOURCE)

	error_text (code: INTEGER): STRING
			-- Textual description of error
			-- (from DATA_RESOURCE_ERROR_CONSTANTS)
		require -- from DATA_RESOURCE_ERROR_CONSTANTS
			positive_code: code > 0

	has_packet: BOOLEAN
			-- Is there a packet available in last_packet?
			-- (from DATA_RESOURCE)

	Is_count_valid: BOOLEAN is True
			-- Is value in count valid? (Answer: yes)

	is_hashable: BOOLEAN
			-- Are objects of current type hashable?
			-- (from DATA_RESOURCE)
		ensure -- from HASHABLE
			ok_if_not_default: Result implies (Current /= default)

	Is_local: BOOLEAN is True
			-- Is protocol not networked? (Answer: yes)

	is_mode_set: BOOLEAN
			-- Has resource mode been set?
			-- (from DATA_RESOURCE)

	is_open: BOOLEAN
			-- Is resource open?

	is_packet_pending: BOOLEAN
			-- Can another packet currently be read out?

	is_proxy_supported: BOOLEAN
			-- Is proxy supported by resource?
			-- (from DATA_RESOURCE)

	is_readable: BOOLEAN
			-- Is it possible to open in read mode currently?
		ensure -- from DATA_RESOURCE
			mode_unchanged: mode = old mode

	is_writable: BOOLEAN
			-- Is it possible to open in write mode currently?
		ensure -- from DATA_RESOURCE
			mode_unchanged: mode = old mode

	read_mode: BOOLEAN
			-- Is read mode set?

	Supports_multiple_transactions: BOOLEAN is False
			-- Does resource support multiple tranactions per connection?
			-- (Answer: no)

	timeout: INTEGER
			-- Connection timeout
			-- (from DATA_RESOURCE)

	transfer_initiated: BOOLEAN
			-- Has transfer being initiated.
			-- (from DATA_RESOURCE)

	valid_mode (n: INTEGER): BOOLEAN
			-- Is mode n valid?

	write_mode: BOOLEAN
			-- Is write mode set?
	
feature -- Status setting

	close
			-- Close.
		require -- from DATA_RESOURCE
			open: is_open
		ensure -- from DATA_RESOURCE
			closed: not is_open
			mode_unchanged: mode = old mode
			no_packet_available: not (has_packet and is_packet_pending)

	initiate_transfer
			-- Initiate transfer.
		require -- from DATA_RESOURCE
			no_error_occurred: not error
			mode_set: is_mode_set
			open: is_open
			not_initiated: not transfer_initiated
		ensure -- from DATA_RESOURCE
			failure_means_error: not transfer_initiated implies error

	open
			-- Open file resource.
		require -- from DATA_RESOURCE
			no_error_occurred: not error
			mode_set: is_mode_set
		ensure -- from DATA_RESOURCE
			no_packet_available: not (has_packet and is_packet_pending)
			initiated_flag_reset: not transfer_initiated
			failure_means_error: not is_open implies error
		ensure then
			counter_reset: bytes_transferred = 0

	reset_error
			-- Reset error.
			-- (from DATA_RESOURCE)
		ensure -- from DATA_RESOURCE
			error_reset: not error

	reset_overwrite_mode
			-- Switch on file overwrite mode on.

	reset_proxy
			-- Reset proxy information.
			-- (from DATA_RESOURCE)
		ensure -- from DATA_RESOURCE
			proxy_reset: not address.is_proxy_used

	reuse_connection (other: DATA_RESOURCE)
			-- Reuse connection of other.
		require -- from DATA_RESOURCE
			other_exists: other /= void
			same_type: same_type (other)
			supports_multiple_transactions: supports_multiple_transactions and other.supports_multiple_transactions
			other_opened: other.is_open

	set_overwrite_mode
			-- Switch on file overwrite mode on.

	set_password (pw: STRING)
			-- Set password to pw.
			-- (from DATA_RESOURCE)
		require -- from DATA_RESOURCE
			password_accepted: address.is_password_accepted
			non_empty_password: pw /= void and then not pw.is_empty

	set_port (port_no: INTEGER)
			-- Set port number to port_no.
			-- (from DATA_RESOURCE)
		require -- from DATA_RESOURCE
			closed: not is_open
			non_negative_port_number: port_no >= 0
		ensure -- from DATA_RESOURCE
			port_set: port = port_no

	set_proxy (host: STRING; port_no: INTEGER)
			-- Set proxy host to host and port to port_no.
			-- (from DATA_RESOURCE)
		require -- from DATA_RESOURCE
			proxy_supported: is_proxy_supported
			closed: not is_open
			non_empty_host: host /= void and then not host.is_empty
			host_ok: address.proxy_host_ok (host)
			non_negative_port: port_no >= 0
		ensure -- from DATA_RESOURCE
			proxy_set: address.is_proxy_used

	set_proxy_information (pi: PROXY_INFORMATION)
			-- Set proxy information to pi.
			-- (from DATA_RESOURCE)
		require -- from DATA_RESOURCE
			proxy_supported: is_proxy_supported
		ensure -- from DATA_RESOURCE
			proxy_set: address.is_proxy_used

	set_read_buffer_size (n: INTEGER)
			-- Set size of read buffer.
		require -- from DATA_RESOURCE
			size_positive: n > 0
		ensure -- from DATA_RESOURCE
			buffer_size_set: read_buffer_size = n
		ensure then
			buffer_size_correct: buffer.area.count = read_buffer_size

	set_read_mode
			-- Set read mode.
		ensure -- from DATA_RESOURCE
			read_mode_set: read_mode

	set_timeout (n: INTEGER)
			-- Set connection timeout to n.
			-- (from DATA_RESOURCE)
		require -- from DATA_RESOURCE
			non_negative: n >= 0
		ensure -- from DATA_RESOURCE
			timeout_set: timeout = n

	set_username (un: STRING)
			-- Set username to un.
			-- (from DATA_RESOURCE)
		require -- from DATA_RESOURCE
			username_accepted: address.has_username
			non_empty_username: un /= void and then not un.is_empty

	set_write_mode
			-- Set write mode.
		ensure -- from DATA_RESOURCE
			write_mode_set: write_mode
	
feature -- Removal

	dispose
			-- Clean up resource.
			-- (from DATA_RESOURCE)
	
feature -- Input

	read
			-- Read packet.
		require -- from DATA_RESOURCE
			no_error_occurred: not error
			open: is_open
			transfer_initated: transfer_initiated
			readable: is_readable
			positive_read_buffer_size: read_buffer_size > 0
			packet_pending: is_packet_pending
		ensure -- from DATA_RESOURCE
			packet_received: is_packet_pending implies last_packet_size > 0
			counter_correct: not error implies bytes_transferred = old bytes_transferred + last_packet_size
	
feature -- Output

	put (other: DATA_RESOURCE)
			-- Write out resource other.
		require -- from DATA_RESOURCE
			no_error_occurred: not (error and other.error)
			other_resource_exists: other /= void
			resources_open: is_open and other.is_open
			writable: is_writable
			transfer_initated: transfer_initiated
	
invariant

		-- from ANY
	reflexive_equality: standard_is_equal (Current)
	reflexive_conformance: conforms_to (Current)
		-- from DATA_RESOURCE
	address_assigned: address /= void
	timeout_non_negative: timeout >= 0
	packet_constraint: not (has_packet xor last_packet /= void)
	pending_constraint: is_packet_pending implies (is_open and is_readable and transfer_initiated)
	error_definition: error = (error_code /= 0)
	valid_count_constraint: count > 0 implies is_count_valid
	mode_constraint: is_mode_set = read_mode xor write_mode

end -- class FILE_PROTOCOL