indexing
	description: "implementation of IStorage interface"
	status: "See notice at end of class"
	date: "$Date$"
	revision: "$Revision$"

class interface
	ECOM_STORAGE

create 

	make_new_doc_file (filename: FILE_NAME; a_mode: INTEGER)
			-- Create new compound file with path filename
			-- and mode a_mode in file system.
			-- See class ECOM_STGM for mode values.
		require
			valid_filename: filename /= void
			valid_mode: is_valid_stgm (a_mode)
		ensure
			compound_file_created: exists

	make_temporary_doc_file (a_mode: INTEGER)
			-- Create temporary compound file with mode mode
			-- See class ECOM_STGM for a_mode values.
		require
			valid_mode: is_valid_stgm (a_mode)
		ensure
			compound_file_created: exists

	make_open_file (filename: FILE_NAME; a_mode: INTEGER)
			-- Open existing root compound file with path filename
			-- and mode mode in file system.
			-- excluding block pointed by exclude (can be default_pointer)
			-- See class ECOM_STGM for a_mode values.
		require
			valid_file: filename /= void and then is_compound_file (filename)
			valid_mode: is_valid_stgm (a_mode)
		ensure
			compound_file_open: exists

	make_from_other (other: ECOM_INTERFACE)
			-- Make from other Queriable.
			-- (from ECOM_QUERIABLE)
		require -- from ECOM_QUERIABLE
			non_void_other: other /= void
		ensure -- from ECOM_QUERIABLE
			valid_initializer: initializer /= default_pointer
			exists: exists

	make_from_pointer (cpp_obj: POINTER)
			-- Make from pointer
		require -- from ECOM_QUERIABLE
			non_default_pointer: a_pointer /= default_pointer
		ensure -- from ECOM_QUERIABLE
			valid_initializer: initializer /= default_pointer
			exists: exists

feature -- Access

	access_time: WEL_FILE_TIME
			-- Access time

	class_id: POINTER
			-- Class identifier

	creation_time: WEL_FILE_TIME
			-- Creation time

	element_access_time (a_name: STRING): WEL_FILE_TIME
			-- Access time of element a_name
		require
			non_void_name: a_name /= void
			valid_name: is_valid_name (a_name)
		ensure
			non_void_access_time: Result /= void

	element_creation_time (a_name: STRING): WEL_FILE_TIME
			-- Creation time of element a_name
		require
			non_void_name: a_name /= void
			valid_name: is_valid_name (a_name)
		ensure
			non_void_creation_time: Result /= void

	element_modification_time (a_name: STRING): WEL_FILE_TIME
			-- Modification time of element a_name
		require
			non_void_name: a_name /= void
			valid_name: is_valid_name (a_name)
		ensure
			non_void_modification_time: Result /= void

	elements: ECOM_ENUM_STATSTG
			-- Substorages and substreams enumerator
		ensure
			Result /= void

	exists: BOOLEAN
			-- Is wrapped structure initialized?
			-- (from ECOM_QUERIABLE)

	is_same_name (a_name: STRING): BOOLEAN
			-- is a_name equal to name of Current storage

	is_valid_name (a_name: STRING): BOOLEAN
			-- is object with name a_name
			-- part of Current storage
		require
			valid_name: a_name /= void

	is_valid_stat_flag (flag: INTEGER): BOOLEAN
			-- Is flag a valid stat flag?
			-- (from ECOM_STAT_FLAGS)

	is_valid_stgc (stgc: INTEGER): BOOLEAN
			-- Is stgc a valid storage commit mode flag?
			-- (from ECOM_STGC)

	is_valid_stgm (stgm: INTEGER): BOOLEAN
			-- Is stgm a valid storage mode flag?
			-- (from ECOM_STGM)

	is_valid_stgmove (stgmove: INTEGER): BOOLEAN
			-- Is stgmove a valid storage move flag?
			-- (from ECOM_STGMOVE)

	item: POINTER
			-- Pointer to COM object wrapper.
			-- (from ECOM_QUERIABLE)

	mode: INTEGER
			-- Access mode

	modification_time: WEL_FILE_TIME
			-- Modufication time

	name: STRING
			-- Name

	new_stream (a_name: STRING; a_mode: INTEGER): ECOM_STREAM
			-- Newly created stream with name a_name
			-- and mode a_mode nested within Current storage
			-- Opening the same stream more than once from the
			-- same storage is not supported.
			-- STGM_SHARE_EXCLUSIVE flag must be specified.
		require
			non_void_storage_name: a_name /= void
			valid_storage_name: not a_name.is_empty
			valid_mode: is_valid_stgm (a_mode)
		ensure
			non_void_stream: Result /= void
			valid_stream: Result.exists

	new_substorage (a_name: STRING; a_mode: INTEGER): ECOM_STORAGE
			-- Newly created storage with name a_name
			-- and mode a_mode
			-- nested within Current storage
		require
			non_void_storage_name: a_name /= void
			valid_storage_name: not a_name.is_empty
			valid_mode: is_valid_stgm (a_mode)
		ensure
			non_void_storage: Result /= void
			valid_storage: Result.exists

	retrieved_stream (a_name: STRING; a_mode: INTEGER): ECOM_STREAM
			-- Retrieved nested stream with name a_name
			-- and mode a_mode
			-- same storage is not supported.
			-- STGM_SHARE_EXCLUSIVE flag must be specified.
		require
			non_void_name: a_name /= void
			valid_name: is_valid_name (a_name)
			valid_mode: is_valid_stgm (a_mode)
		ensure
			non_void_stream: Result /= void
			valid_stream: Result.exists

	retrieved_substorage (a_name: STRING; a_mode: INTEGER): ECOM_STORAGE
			-- Retrieved storage with name a_name and mode a_mode
			-- nested within Current storage
			-- Opening the same storage object more than once from the same
			-- parent storage is not supported.
			-- STGM_SHARE_EXCLUSIVE flag must be specified.
		require
			non_void_name: a_name /= void
			valid_name: is_valid_name (a_name)
			valid_mode: is_valid_stgm (a_mode)
		ensure
			non_void_storage: Result /= void
			valid_storage: Result.exists

	root_storage: ECOM_ROOT_STORAGE
			-- IRootStorage interface

	statflag_default: INTEGER
			-- Indicate that this is not used for property
			-- (from ECOM_STAT_FLAGS)

	statflag_noname: INTEGER
			-- Indicate that this is not used for property
			-- (from ECOM_STAT_FLAGS)

	stgc_dangerouslycommitmerelytodiskcache: INTEGER
			-- EOLE_STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE commits the changes,
			-- but does not save them to the disk cache.
			-- (from ECOM_STGC)

	stgc_default: INTEGER
			-- OLE 2 default commit mode
			-- (from ECOM_STGC)

	stgc_onlyifcurrent: INTEGER
			-- EOLE_STGC_ONLYIFCURRENT prevents multiple users of an IStorage
			-- from overwriting the other's changes. EOLE_STGC_ONLYIFCURRENT
			-- commits changes only if no one else has made changes since the
			-- last time this user opened the IStorage or committed. If other
			-- changes have been made, EOLE_STG_E_NOTCURRENT is returned.
			-- If the caller chooses to overwrite the changes, IStorage.Commit
			-- can be called with commit mode set to EOLE_STGC_DEFAULT.
			-- (from ECOM_STGC)

	stgc_overwrite: INTEGER
			-- EOLE_STGC_OVERWRITE allows new data to overwrite the old data,
			-- reducing space requirements. EOLE_STGC_OVERWRITE is not recommended
			-- for usual operation, but it could be useful in the following
			-- situations:
			--    1. A commit was tried and EOLE_STG_E_MEDIUMFULL was returned.
			--    2. The user has somehow specified a willingness to risk
			--       overwriting the old data.
			--    3. A low-memory save sequence is being used to end up with a
			--       smaller file.
			-- The commit operation obtains all the disk space it needs before
			-- attempting to store the new data, whether or not EOLE_STGC_OVERWRITE
			-- is specified. If space requirements prohibit the save, the old
			-- data will be intact, including all uncommitted changes. However,
			-- if the commit fails due to reasons other than lack of disk space
			-- and EOLE_STGC_OVERWRITE was specified, it is possible that neither
			-- the old nor the new version of the data will be intact.
			-- (from ECOM_STGC)

	stgm_convert: INTEGER
			-- This flag is applicable only to the creation of IStorage objects.
			-- Stgm_convert allows the creation to proceed while preserving
			-- existing data. The old data is saved to a stream named CONTENTS
			-- containing the same data that was in the old IStorage or IStream
			-- instance. In the IStorage case, the data is flattened to a
			-- stream regardless of whether the existing file currently contains
			-- a layered storage object.
			-- (from ECOM_STGM)

	stgm_create: INTEGER
			-- Stgm_create indicates an existing IStorage or IStream object
			-- should be removed before the new one replaces it. A new object
			-- is created when this flag is specified only if the existing
			-- IStorage or IStream has been successfully removed.
			-- (from ECOM_STGM)

	stgm_deleteonrelease: INTEGER
			-- The Stgm_deleteonrelease flag indicates that the underlying
			-- file is to be automatically destroyed when the root IStorage
			-- object is released. This capability is most useful for
			-- creating temporary files.
			-- (from ECOM_STGM)

	stgm_direct: INTEGER
			-- Stgm_DIrect is always specified for IStream objects.
			-- Stgm_transacted is not supported in the compound file
			-- implementation of IStream. Other implementations can choose
			-- to support it.
			-- (from ECOM_STGM)

	stgm_failifthere: INTEGER
			-- Stgm_failifthere causes the create operation to fail if an
			-- existing object with the specified name exists. In this case,
			-- Stg_e_filealreadyexists is returned. Stgm_failifthere
			-- applies to both IStorage and IStream objects.
			-- (from ECOM_STGM)

	stgm_priority: INTEGER
			-- The Stgm_priority flag allows an IStorage object to be opened
			-- so that a subsequent copy operation can be done at reduced cost.
			-- Stgm_priority allows an application to read certain streams
			-- from storage before opening the storage object in a mode that would
			-- require a snapshot copy to be made. Priority mode has exclusive
			-- access to the committed version of the IStorage object.
			-- While a compound file is open in priority mode, no other opening
			-- of the compound file can commit changes even one that was opened
			-- before the priority mode opening. Therefore, applications should
			-- keep IStorage objects open in priority mode for as short a time
			-- as possible.
			-- (from ECOM_STGM)

	stgm_read: INTEGER
			-- When applied to an IStream object, Stgm_READ enables
			-- applications to successfully call IStream.Read. If Stgm_read
			-- is omitted, IStream.Read will return an error. When applied to an
			-- IStorage, Stgm_READ allows the enumeration of the storage
			-- object's elements and enables applications to open these elements
			-- in read mode. Parents of storage objects to be opened in read mode
			-- must also have been opened in read mode otherwise, an error is
			-- returned.
			-- (from ECOM_STGM)

	stgm_readwrite: INTEGER
			-- Stgm_readwrite is the logical combination of the
			-- Stgm_read and Stgm_write. However, the defined value
			-- of Stgm_readwrite is not equal to
			-- (Stgm_read or Stgm_write).
			-- (from ECOM_STGM)

	stgm_share_deny_none: INTEGER
			-- 0x00000040L
			-- Stgm_SHARE_DENY_NONE indicates that neither read access nor
			-- write access should be denied to subsequent openings. This is the
			-- default sharing mode and if no Stgm_SHARE_* flag is explicitly
			-- given, Stgm_SHARE_DENY_NONE is implied.
			-- (from ECOM_STGM)

	stgm_share_deny_read: INTEGER
			-- 0x00000030L
			-- When successfully applied to a root IStorage, the
			-- Stgm_SHARE_DENY_READ flag prevents others from opening the
			-- object in read mode. The open call fails and returns an error if
			-- the object is presently open in deny-read mode.
			-- Stgm_SHARE_DENY_READ is most useful when opening root storage
			-- objects. Deny modes on inner elements are still useful if some
			-- component is coordinating the opening of these inner elements, as
			-- might happen in a Copy/Paste operation. However, inner elements
			-- always require Stgm_SHARE_EXCLUSIVE. Opening a parent storage
			-- object with Stgm_SHARE_DENY_READ applies only to that opening,
			-- not the network-wide set of openings of the parent.
			-- (from ECOM_STGM)

	stgm_share_deny_write: INTEGER
			-- When successfully applied the Stgm_share_deny_write flag
			-- prevents subsequent openings of either a storage or a stream from
			-- specifying write mode. The open call fails and returns an error
			-- if the storage or stream is presently open in write mode.
			-- For information about the interaction of this flag with nested
			-- openings, see the earlier discussion about Stgm_share_deny_read.
			-- (from ECOM_STGM)

	stgm_share_exclusive: INTEGER
			-- The compound files implementation requires that all inner elements
			-- be opened Stgm_share_exclusive. It is the logical combination
			-- of the Stgm_share_deny_read and Stgm_share_deny_write.
			-- All root storage objects, as well as child storage and stream
			-- objects must be opened with Stgm_share_exclusive.
			-- (from ECOM_STGM)

	stgm_transacted: INTEGER
			-- The transaction for each open object is nested in the transaction
			-- for its parent storage object. Therefore, committing changes at the
			-- child level is dependent on committing changes in the parent and
			-- a commit of the root storage object (top-level parent) is necessary
			-- before changes to an object are actually written to disk.
			-- The changes percolate upward: inner objects publish changes to the
			-- transaction of the next object outwards. Outermost objects publish
			-- changes permanently into the file system. Transacted mode is not
			-- required on the parent storage object in order to use transacted
			-- mode on a contained object.The scope of changes that are buffered
			-- in transacted mode is very broad. A storage or stream object can
			-- be opened, have arbitrary changes made to it, and then have the
			-- changes reverted, preserving the object as it was when it was
			-- first opened. The creation and destruction of elements within a
			-- storage object are scoped by its transaction.
			-- (from ECOM_STGM)

	stgm_write: INTEGER
			-- Stgm_write lets an object commit changes to the storage.
			-- Specifically, unless this flag has been given, IStorage.Commit
			-- and IStream.Commit will fail. An open object whose changes cannot
			-- be committed can save its changes by copying the storage or stream
			-- with IStorage.CopyTo or IStream.CopyTo. In direct mode,
			-- changes are committed after every change operation. Thus, write
			-- permissions are needed to call any function that causes a change.
			-- On streams, this includes IStream.Write and IStream.SetSize.
			-- If a parent storage is opened in direct mode without write
			-- permission, any attempt to open a child stream within it in direct
			-- mode with write permission will fail, because it causes an implicit
			-- commit to be made on the storage. Similarly, trying to create or
			-- destroy a contained element in this storage object also causes an
			-- implicit commit, resulting in an error.
			-- (from ECOM_STGM)

	stgmove_copy: INTEGER
			-- Carry out the first part of the move operation but do
			-- not remove the original element.
			-- (from ECOM_STGMOVE)

	stgmove_move: INTEGER
			-- Carry out the move operation, as expected.
			-- (from ECOM_STGMOVE)
	
feature -- Access
--	com_api: ECOM_COM is
--		once
--			create Result
--		end

	guid_routines: ECOM_GUID_ROUTINES
			-- (from ECOM_ROUTINES)
	
feature -- Basic Operations

	commit (a_flags: INTEGER)
			-- Commit any changes.
			-- Notify parent storage.
		require
			valid_flags: is_valid_stgc (a_flags)

	copy_all_to (dest_storage: ECOM_STORAGE)
			-- Copy entire contents to dest_storage.
		require
			non_void_destination: dest_storage /= void
			valid_destination: dest_storage.exists

	destroy_element (a_name: STRING)
			-- Remove element with name a_name from storage.
		require
			non_void_name: a_name /= void
			valid_name: is_valid_name (a_name)
		ensure
			element_removed: not is_valid_name (a_name)

	is_compound_file (a_name: STRING): BOOLEAN
			-- Does file a_name contain a storage object?
			-- (from ECOM_STORAGE_ROUTINES)

	rename_element (old_name: STRING; new_name: STRING)
			-- Rename element old_name into new_name
		require
			non_void_old_name: old_name /= void
			valid_old_name: is_valid_name (old_name)
			non_void_new_name: new_name /= void
			valid_new_name: is_valid_name (new_name)
		ensure
			not_valid_old_name: not is_valid_name (old_name)
			valid_new_name: is_valid_name (new_name)

	revert
			-- Discard all changes made to storage object
			-- since the last commit
	
feature -- Element Change

	move_element_to (a_element_name: STRING; dest_storage: ECOM_STORAGE; new_name: STRING; a_mode: INTEGER)
			-- Copy or move (depending on mode) element a_element_name
			-- of root storage to dest_storage.
			-- Create new element in dest_storage with new_name.
			-- See class ECOM_STGM for a_mode values.
			-- Before calling this method, the element to be moved must
			-- be closed, and the destination storage must be open.
		require
			non_void_element_name: a_element_name /= void
			valid_element_name: is_valid_name (a_element_name)
			non_void_dest_storage: dest_storage /= void
			valid_dest_storage: dest_storage.exists
			non_void_new_name: new_name /= void
			valid_new_name: not new_name.is_empty
			valid_mode: is_valid_stgmove (a_mode)
		ensure
			element_moved: dest_storage.is_valid_name (new_name)

	set_access_time (an_access_time: WEL_FILE_TIME)
			-- Set access time with an_access_time.
		require
			non_void_access_time: an_access_time /= void
		ensure
			access_time_set: access_time.is_equal (an_access_time)

	set_class (a_class_id: POINTER)
			-- Associate storage with COM component with class id a_class-id
		require
			valid_clsid: a_class_id /= default_pointer

	set_creation_time (a_creation_time: WEL_FILE_TIME)
			-- Set creation time with creation_time.
		require
			non_void_creation_time: a_creation_time /= void
		ensure
			creation_time_set: creation_time.is_equal (a_creation_time)

	set_element_access_time (a_element_name: STRING; an_access_time: WEL_FILE_TIME)
			-- Set access time of element a_element_name with an_access_time.
		require
			non_void_element_name: a_element_name /= void
			valid_element_name: is_valid_name (a_element_name)
			valid_access_time: an_access_time /= void
		ensure
			element_access_time_set: element_access_time (a_element_name).is_equal (an_access_time)

	set_element_creation_time (a_element_name: STRING; a_creation_time: WEL_FILE_TIME)
			-- Set creation time of element a_element_name with a_creation_time.
		require
			non_void_element_name: a_element_name /= void
			valid_element_name: is_valid_name (a_element_name)
			valid_creation_time: a_creation_time /= void
		ensure
			element_creation_time_set: element_creation_time (a_element_name).is_equal (a_creation_time)

	set_element_modification_time (a_element_name: STRING; a_modification_time: WEL_FILE_TIME)
			-- Set modification time of element a_element_name with a_modification_time.
		require
			non_void_element_name: a_element_name /= void
			valid_element_name: is_valid_name (a_element_name)
			valid_modification_time: a_modification_time /= void
		ensure
			element_access_time_set: element_modification_time (a_element_name).is_equal (a_modification_time)

	set_modification_time (a_modification_time: WEL_FILE_TIME)
			-- Set modification time with a_modification_time.
		require
			non_void_modification_time: a_modification_time /= void
		ensure
			modification_time_set: modification_time.is_equal (a_modification_time)
	
invariant

		-- from ANY
	reflexive_equality: standard_is_equal (Current)
	reflexive_conformance: conforms_to (Current)
		-- from ECOM_QUERIABLE
	queriable_invariant: initializer /= default_pointer and then exists

end -- class ECOM_STORAGE