/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/

package complex.ofopxmlstorages;

import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XInterface;
import com.sun.star.uno.AnyConverter;

import com.sun.star.lang.*;
import com.sun.star.embed.*;
import com.sun.star.packages.*;
import com.sun.star.io.*;
import com.sun.star.beans.*;

import share.LogWriter;

public class TestHelper  {

	LogWriter m_aLogWriter;
	String m_sTestPrefix;

	public TestHelper( LogWriter aLogWriter, String sTestPrefix )
	{
		m_aLogWriter = aLogWriter;
		m_sTestPrefix = sTestPrefix;
	}

	public boolean WriteBytesToStream( XStream xStream,
										String sStreamName,
										String sMediaType,
										boolean bCompressed,
										byte[] pBytes,
										StringPair[][] aRelations )
	{
		// get output stream of substream
		XOutputStream xOutput = xStream.getOutputStream();
		if ( xOutput == null )
		{
			Error( "Can't get XOutputStream implementation from substream '" + sStreamName + "'!" );
			return false;
		}
	
		// get XTrucate implementation from output stream
		XTruncate xTruncate = (XTruncate) UnoRuntime.queryInterface( XTruncate.class, xOutput );
		if ( xTruncate == null )
		{
			Error( "Can't get XTruncate implementation from substream '" + sStreamName + "'!" );
			return false;
		}
		
		// write requested byte sequence
		try
		{
			xTruncate.truncate();
			xOutput.writeBytes( pBytes );
		}
		catch( Exception e )
		{
			Error( "Can't write to stream '" + sStreamName + "', exception: " + e );
			return false;
		}

		// get access to the XPropertySet interface
		XPropertySet xPropSet = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, xStream );
		if ( xPropSet == null )
		{
			Error( "Can't get XPropertySet implementation from substream '" + sStreamName + "'!" );
			return false;
		}

		// set properties to the stream
		try
		{
			xPropSet.setPropertyValue( "MediaType", sMediaType );
			xPropSet.setPropertyValue( "Compressed", new Boolean( bCompressed ) );
		}
		catch( Exception e )
		{
			Error( "Can't set properties to substream '" + sStreamName + "', exception: " + e );
			return false;
		}

		// check size property of the stream
		try
		{
			int nSize = AnyConverter.toInt( xPropSet.getPropertyValue( "Size" ) );
			if ( nSize != pBytes.length )
			{
				Error( "The 'Size' property of substream '" + sStreamName + "' contains wrong value!" );
				return false;
			}
		}
		catch( Exception e )
		{
			Error( "Can't get 'Size' property from substream '" + sStreamName + "', exception: " + e );
			return false;
		}

		// get access to the relationship information
		XRelationshipAccess xRelAccess = (XRelationshipAccess) UnoRuntime.queryInterface( XRelationshipAccess.class, xStream );
		if ( xRelAccess == null )
		{
			Error( "Can't get XRelationshipAccess implementation from substream '" + sStreamName + "'!" );
			return false;
		}

		// set the relationship information
		try
		{
			xRelAccess.insertRelationships( aRelations, false );
		}
		catch( Exception e )
		{
			Error( "Can't set relationships to substream '" + sStreamName + "', exception: " + e );
			return false;
		}

		// free the stream resources, garbage collector may remove the object too late
		if ( !disposeStream( xStream, sStreamName ) )
			return false;

		return true;
	}

	public boolean WriteBytesToSubstream( XStorage xStorage,
										  String sStreamName,
										  String sMediaType,
										  boolean bCompressed,
										  byte[] pBytes,
										  StringPair[][] aRelations )
	{
		// open substream element
		XStream xSubStream = null;
		try
		{
			Object oSubStream = xStorage.openStreamElement( sStreamName, ElementModes.WRITE );
			xSubStream = (XStream) UnoRuntime.queryInterface( XStream.class, oSubStream );
			if ( xSubStream == null )
			{
				Error( "Can't create substream '" + sStreamName + "'!" );
				return false;
			}
		}
		catch( Exception e )
		{
			Error( "Can't create substream '" + sStreamName + "', exception : " + e + "!" );
			return false;
		}
		
		return WriteBytesToStream( xSubStream, sStreamName, sMediaType, bCompressed, pBytes, aRelations );
	}

	public boolean setStorageTypeAndCheckProps( XStorage xStorage,
												boolean bIsRoot,
												int nMode,
												StringPair[][] aRelations )
	{
		boolean bOk = false;

		// get access to the XPropertySet interface
		XPropertySet xPropSet = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, xStorage );
		if ( xPropSet != null )
		{
			try
			{
				// get "IsRoot" and "OpenMode" properties and control there values
				boolean bPropIsRoot = AnyConverter.toBoolean( xPropSet.getPropertyValue( "IsRoot" ) );
				int nPropMode = AnyConverter.toInt( xPropSet.getPropertyValue( "OpenMode" ) );

				bOk = true;
				if ( bPropIsRoot != bIsRoot )
				{
					Error( "'IsRoot' property contains wrong value!" );
					bOk = false;
				}
					
				if ( ( bIsRoot
				  && ( nPropMode | ElementModes.READ ) != ( nMode | ElementModes.READ ) )
				  || ( !bIsRoot && ( nPropMode & nMode ) != nMode ) )
				{
					Error( "'OpenMode' property contains wrong value, expected " + nMode + ", in reality " + nPropMode + "!" );
					bOk = false;
				}
			}
			catch( Exception e )
			{
				Error( "Can't control properties of substorage, exception: " + e );
			}
		}
		else
		{
			Error( "Can't get XPropertySet implementation from storage!" );
		}

		// get access to the relationship information
		XRelationshipAccess xRelAccess = (XRelationshipAccess) UnoRuntime.queryInterface( XRelationshipAccess.class, xStorage );

		if ( xRelAccess == null )
		{
			Error( "Can't get XRelationshipAccess implementation from the storage!" );
			return false;
		}

		// set the relationship information
		try
		{
			xRelAccess.insertRelationships( aRelations, false );
		}
		catch( Exception e )
		{
			Error( "Can't set relationships to the storage, exception: " + e );
			return false;
		}


		return bOk;
	}

	public boolean checkRelations( StringPair[][] aStorRels, StringPair[][] aTestRels )
	{
		// Message( "StorageRels:" );
		// PrintRelations( aStorRels );
		// Message( "TestRels:" );
		// PrintRelations( aTestRels );

		if ( aStorRels.length != aTestRels.length )
		{
			Error( "The provided relations sequence has different size than the storage's one!" );
			return false;
		}

		for ( int nStorInd = 0; nStorInd < aStorRels.length; nStorInd++ )
		{
			int nStorIDInd = -1;
			for ( int nStorTagInd = 0; nStorTagInd < aStorRels[nStorInd].length; nStorTagInd++ )
			{
				if ( aStorRels[nStorInd][nStorTagInd].First.equals( "Id" ) )
				{
					nStorIDInd = nStorTagInd;
					break;
				}
			}

			if ( nStorIDInd == -1 )
			{
				Error( "One of the storage relations entries has no ID!" );
				return false;
			}

			for ( int nInd = 0; nInd < aTestRels.length; nInd++ )
			{
				int nIDInd = -1;
				for ( int nTagInd = 0; nTagInd < aTestRels[nInd].length; nTagInd++ )
				{
					if ( aTestRels[nInd][nTagInd].First.equals( "Id" ) )
					{
						nIDInd = nTagInd;
						break;
					}
				}

				if ( nIDInd == -1 )
				{
					Error( "One of the test hardcoded entries has no ID, num = " + nInd + ", length = " + aTestRels[nInd].length + ", global length = " + aTestRels.length + "!" );
					return false;
				}

				if ( aStorRels[nStorInd][nStorIDInd].Second.equals( aTestRels[nInd][nIDInd].Second ) )
				{
					boolean[] pRelCheckMark = new boolean[ aTestRels[nInd].length ];
					for ( int nCheckInd = 0; nCheckInd < pRelCheckMark.length; nCheckInd++ )
					{
						pRelCheckMark[nCheckInd] = false;
					}

					for ( int nStorTagInd = 0; nStorTagInd < aStorRels[nStorInd].length; nStorTagInd++ )
					{
						boolean bFound = false;
						for ( int nTagInd = 0; nTagInd < aTestRels[nInd].length; nTagInd++ )
						{
							if ( aTestRels[nInd][nTagInd].First.equals( aStorRels[nStorInd][nStorTagInd].First ) )
							{
								if ( !aTestRels[nInd][nTagInd].Second.equals( aStorRels[nStorInd][nStorTagInd].Second ) )
								{
									Error( "Test rel. num. " + nInd + " has different tag \"" + aTestRels[nInd][nTagInd].First + "\" value!" );
									return false;
								}

								bFound = true;
								pRelCheckMark[nTagInd] = true;
								break;
							}
						}

						if ( !bFound )
						{
							Error( "Stor rel. num. " + nStorInd + " has unexpected tag \"" + aStorRels[nStorInd][nStorTagInd].First + "\", ID = \"" + aStorRels[nStorInd][nStorIDInd].Second + "\"!" );
							return false;
						}
					}

					for ( int nCheckInd = 0; nCheckInd < pRelCheckMark.length; nCheckInd++ )
					{
						if ( !pRelCheckMark[nCheckInd] && !aTestRels[nInd][nCheckInd].Second.equals( "" ) )
						{
							Error( "Test rel. num. " + nInd + " has unexpected tag \"" + aTestRels[nInd][nCheckInd].First + "\" with nonempty value!" );
							return false;
						}
					}
				
					break;
				}
			}
		}

		return true;
	}
	
	public boolean checkStorageProperties( XStorage xStorage,
											boolean bIsRoot,
											int nMode,
											StringPair[][] aRelations )
	{
		boolean bOk = false;

		// get access to the XPropertySet interface
		XPropertySet xPropSet = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, xStorage );
		if ( xPropSet != null )
		{
			try
			{
				// get "IsRoot" and "OpenMode" properties and control there values
				boolean bPropIsRoot = AnyConverter.toBoolean( xPropSet.getPropertyValue( "IsRoot" ) );
				int nPropMode = AnyConverter.toInt( xPropSet.getPropertyValue( "OpenMode" ) );

				bOk = true;
				if ( bPropIsRoot != bIsRoot )
				{
					Error( "'IsRoot' property contains wrong value!" );
					bOk = false;
				}
					
				if ( ( bIsRoot
				  && ( nPropMode | ElementModes.READ ) != ( nMode | ElementModes.READ ) )
				  || ( !bIsRoot && ( nPropMode & nMode ) != nMode ) )
				{
					Error( "'OpenMode' property contains wrong value, expected " + nMode + ", in reality " + nPropMode + "!" );
					bOk = false;
				}
			}
			catch( Exception e )
			{
				Error( "Can't get properties of substorage, exception: " + e );
			}
		}
		else
		{
			Error( "Can't get XPropertySet implementation from storage!" );
		}

		// get access to the relationship information
		XRelationshipAccess xRelAccess = (XRelationshipAccess) UnoRuntime.queryInterface( XRelationshipAccess.class, xStorage );

		if ( xRelAccess == null )
		{
			Error( "Can't get XRelationshipAccess implementation from the checked storage!" );
			return false;
		}

		// get the relationship information
		StringPair[][] aStorRels;
		try
		{
			aStorRels = xRelAccess.getAllRelationships();
		}
		catch( Exception e )
		{
			Error( "Can't get relationships of the checked storage, exception: " + e );
			return false;
		}

		if ( !checkRelations( aStorRels, aRelations ) )
		{
			Error( "StorageRelationsChecking has failed!" );
			return false;
		}

		return bOk;
	}

	public boolean InternalCheckStream( XStream xStream,
										String sName,
										String sMediaType,
										byte[] pBytes,
										StringPair[][] aRelations )
	{
		// get input stream of substream
		XInputStream xInput = xStream.getInputStream();
		if ( xInput == null )
		{
			Error( "Can't get XInputStream implementation from substream '" + sName + "'!" );
			return false;
		}
	
		byte pContents[][] = new byte[1][]; // ???

		// read contents
		try
		{
			xInput.readBytes( pContents, pBytes.length + 1 );
		}
		catch( Exception e )
		{
			Error( "Can't read from stream '" + sName + "', exception: " + e );
			return false;
		}

		// check size of stream data
		if ( pContents.length == 0 )
		{
			Error( "SubStream '" + sName + "' reading produced disaster!"  );
			return false;
		}

		if ( pBytes.length != pContents[0].length )
		{
			Error( "SubStream '" + sName + "' contains wrong amount of data! (" + pContents[0].length + "/" + pBytes.length + ")" );
			return false;
		}

		// check stream data
		for ( int ind = 0; ind < pBytes.length; ind++ )
		{
			if ( pBytes[ind] != pContents[0][ind] )
			{
				Error( "SubStream '" + sName + "' contains wrong data! ( byte num. "
						+ ind + " should be" + pBytes[ind] + " but it is " + pContents[0][ind] + ")" );
				return false;
			}
		}

		// check properties
		boolean bOk = false;

		// get access to the XPropertySet interface
		XPropertySet xPropSet = (XPropertySet) UnoRuntime.queryInterface( XPropertySet.class, xStream );
		if ( xPropSet != null )
		{
			try
			{
				// get "MediaType" and "Size" properties and control there values
				String sPropMediaType = AnyConverter.toString( xPropSet.getPropertyValue( "MediaType" ) );
				int nPropSize = AnyConverter.toInt( xPropSet.getPropertyValue( "Size" ) );

				bOk = true;
				if ( !sPropMediaType.equals( sMediaType ) )
				{
					Error( "'MediaType' property contains wrong value for stream '" + sName + "',\nexpected: '" 
							+ sMediaType + "', set: '" + sPropMediaType + "'!" );
					bOk = false;
				}
	
				if ( nPropSize != pBytes.length )
				{
					Error( "'Size' property contains wrong value for stream'" + sName + "'!" );
					bOk = false;
				}
			}
			catch( Exception e )
			{
				Error( "Can't get properties of substream '" + sName + "', exception: " + e );
			}
		}
		else
		{
			Error( "Can't get XPropertySet implementation from stream '" + sName + "'!" );
		}


		// get access to the relationship information
		XRelationshipAccess xRelAccess = (XRelationshipAccess) UnoRuntime.queryInterface( XRelationshipAccess.class, xStream );

		if ( xRelAccess == null )
		{
			Error( "Can't get XRelationshipAccess implementation from the stream\"" + sName + "\"!" );
			return false;
		}

		// get the relationship information
		StringPair[][] aStorRels;
		try
		{
			aStorRels = xRelAccess.getAllRelationships();
		}
		catch( Exception e )
		{
			Error( "Can't get relationships of the substream '" + sName + "', exception: " + e );
			return false;
		}

		if ( !checkRelations( aStorRels, aRelations ) )
		{
			Error( "Stream '" + sName + "' RelationsChecking has failed!" );
			return false;
		}

		return bOk;
	}

	public boolean checkStream( XStorage xParentStorage,
								String sName,
								String sMediaType,
								byte[] pBytes,
								StringPair[][] aRelations )
	{
		// open substream element first
		XStream xSubStream = null;
		try
		{
			Object oSubStream = xParentStorage.openStreamElement( sName, ElementModes.READ );
			xSubStream = (XStream) UnoRuntime.queryInterface( XStream.class, oSubStream );
			if ( xSubStream == null )
			{
				Error( "Can't open substream '" + sName + "'!" );
				return false;
			}
		}
		catch( Exception e )
		{
			Error( "Can't open substream '" + sName + "', exception : " + e + "!" );
			return false;
		}
		
		boolean bResult = InternalCheckStream( xSubStream, sName, sMediaType, pBytes, aRelations );

		// free the stream resources, garbage collector may remove the object too late
		if ( !disposeStream( xSubStream, sName ) )
			return false;

		return bResult;
	}

	public boolean copyStorage( XStorage xSourceStorage, XStorage xDestStorage )
	{
		// copy xSourceStorage to xDestStorage
		try
		{
			xSourceStorage.copyToStorage( xDestStorage );
		}
		catch( Exception e )
		{
			Error( "Storage copying failed, exception: " + e );
			return false;
		}

		return true;
	}

	public boolean commitStorage( XStorage xStorage )
	{
		// XTransactedObject must be supported by storages
		XTransactedObject xTransact = (XTransactedObject) UnoRuntime.queryInterface( XTransactedObject.class, xStorage );
		if ( xTransact == null )
		{
			Error( "Storage doesn't implement transacted access!" );
			return false;
		}

		try
		{
			xTransact.commit();
		}
		catch( Exception e )
		{
			Error( "Storage commit failed, exception:" + e );
			return false;
		}

		return true;
	}
	
	public boolean disposeStream( XStream xStream, String sStreamName )
	{
		XComponent xComponent = (XComponent) UnoRuntime.queryInterface( XComponent.class, xStream );
		if ( xComponent == null )
		{
			Error( "Can't get XComponent implementation from substream '" + sStreamName + "'!" );
			return false;
		}
		
		try
		{
			xComponent.dispose();
		}
		catch( Exception e )
		{
			Error( "Substream '" + sStreamName + "' disposing throws exception: " + e );
			return false;
		}

		return true;
	}

	public boolean disposeStorage( XStorage xStorage )
	{
		// dispose the storage
		XComponent xComponent = (XComponent) UnoRuntime.queryInterface( XComponent.class, xStorage );
		if ( xComponent == null )
		{
			Error( "Can't retrieve XComponent implementation from storage!" );
			return false;
		}

		try
		{
			xComponent.dispose();
		}
		catch( Exception e )
		{
			Error( "Storage disposing failed!" );
			return false;
		}

		return true;
	}

	public XInputStream getInputStream( XStream xStream )
	{
		XInputStream xInTemp = null;
		try
		{
			xInTemp = xStream.getInputStream();
			if ( xInTemp == null )
				Error( "Can't get the input part of a stream!" );
		}
		catch ( Exception e )
		{
			Error( "Can't get the input part of a stream, exception :" + e );
		}

		return xInTemp;
	}

	public boolean closeOutput( XStream xStream )
	{
		XOutputStream xOutTemp = null;
		try
		{
			xOutTemp = xStream.getOutputStream();
			if ( xOutTemp == null )
			{
				Error( "Can't get the output part of a stream!" );
				return false;
			}
		}
		catch ( Exception e )
		{
			Error( "Can't get the output part of a stream, exception :" + e );
			return false;
		}

		try
		{
			xOutTemp.closeOutput();
		}
		catch ( Exception e )
		{
			Error( "Can't close output part of a stream, exception :" + e );
			return false;
		}
		
		return true;
	}

	public XStorage openSubStorage( XStorage xStorage, String sName, int nMode )
	{
		// open existing substorage
		try
		{
			Object oSubStorage = xStorage.openStorageElement( sName, nMode );
			XStorage xSubStorage = (XStorage) UnoRuntime.queryInterface( XStorage.class, oSubStorage );
			return xSubStorage;
		}
		catch( Exception e )
		{
			Error( "Can't open substorage '" + sName + "', exception: " + e );
		}

		return null;
	}

	public XStream CreateTempFileStream( XMultiServiceFactory xMSF )
	{
		// try to get temporary file representation
		XStream xTempFileStream = null;
		try
		{
			Object oTempFile = xMSF.createInstance( "com.sun.star.io.TempFile" );
			xTempFileStream = (XStream)UnoRuntime.queryInterface( XStream.class, oTempFile );
		}
		catch( Exception e )
		{}

		if ( xTempFileStream == null )
			Error( "Can't create temporary file!" );

		return xTempFileStream;
	}

	public String CreateTempFile( XMultiServiceFactory xMSF )
	{
		String sResult = null;
	
		// try to get temporary file representation
		XPropertySet xTempFileProps = null;
		try
		{
			Object oTempFile = xMSF.createInstance( "com.sun.star.io.TempFile" );
			xTempFileProps = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, oTempFile );
		}
		catch( Exception e )
		{}

		if ( xTempFileProps != null )
		{
			try
			{
				xTempFileProps.setPropertyValue( "RemoveFile", new Boolean( false ) );
				sResult = AnyConverter.toString( xTempFileProps.getPropertyValue( "Uri" ) );
			}
			catch( Exception e )
			{
				Error( "Can't control TempFile properties, exception: " + e );
			}
		}
		else
		{
			Error( "Can't create temporary file representation!" );
		}

		// close temporary file explicitly
		try
		{
			XStream xStream = (XStream)UnoRuntime.queryInterface( XStream.class, xTempFileProps );
			if ( xStream != null )
			{
				XOutputStream xOut = xStream.getOutputStream();
				if ( xOut != null )
					xOut.closeOutput();

				XInputStream xIn = xStream.getInputStream();
				if ( xIn != null )
					xIn.closeInput();
			}
			else
				Error( "Can't close TempFile!" );
		}
		catch( Exception e )
		{
			Error( "Can't close TempFile, exception: " + e );
		}

		return sResult;
	}

	public boolean copyElementTo( XStorage xSource, String sName, XStorage xDest )
	{
		// copy element with name sName from xSource to xDest
		try
		{
			xSource.copyElementTo( sName, xDest, sName );
		}
		catch( Exception e )
		{
			Error( "Element copying failed, exception: " + e );
			return false;
		}

		return true;
	}

	public boolean copyElementTo( XStorage xSource, String sName, XStorage xDest, String sTargetName )
	{
		// copy element with name sName from xSource to xDest
		try
		{
			xSource.copyElementTo( sName, xDest, sTargetName );
		}
		catch( Exception e )
		{
			Error( "Element copying failed, exception: " + e );
			return false;
		}

		return true;
	}

	public boolean moveElementTo( XStorage xSource, String sName, XStorage xDest )
	{
		// move element with name sName from xSource to xDest
		try
		{
			xSource.moveElementTo( sName, xDest, sName );
		}
		catch( Exception e )
		{
			Error( "Element moving failed, exception: " + e );
			return false;
		}

		return true;
	}

	public boolean renameElement( XStorage xStorage, String sOldName, String sNewName )
	{
		// rename element with name sOldName to sNewName
		try
		{
			xStorage.renameElement( sOldName, sNewName );
		}
		catch( Exception e )
		{
			Error( "Element renaming failed, exception: " + e );
			return false;
		}

		return true;
	}

	public boolean removeElement( XStorage xStorage, String sName )
	{
		// remove element with name sName
		try
		{
			xStorage.removeElement( sName );
		}
		catch( Exception e )
		{
			Error( "Element removing failed, exception: " + e );
			return false;
		}

		return true;
	}

	public XStream OpenStream( XStorage xStorage,
								String sStreamName,
								int nMode )
	{
		// open substream element
		XStream xSubStream = null;
		try
		{
			Object oSubStream = xStorage.openStreamElement( sStreamName, nMode );
			xSubStream = (XStream) UnoRuntime.queryInterface( XStream.class, oSubStream );
			if ( xSubStream == null )
				Error( "Can't create substream '" + sStreamName + "'!" );
		}
		catch( Exception e )
		{
			Error( "Can't create substream '" + sStreamName + "', exception : " + e + "!" );
		}

		return xSubStream;
	}

	public boolean cantOpenStorage( XStorage xStorage, String sName )
	{
		// try to open an opened substorage, open call must fail
		try
		{
			Object oDummyStorage = xStorage.openStorageElement( sName, ElementModes.READ );
			Error( "The trying to reopen opened substorage '" + sName + "' must fail!" );
		}
		catch( Exception e )
		{
			return true;
		}

		return false;
	}

	public boolean cantOpenStream( XStorage xStorage, String sName, int nMode )
	{
		// try to open the substream with specified mode must fail
		try
		{
			Object oDummyStream = xStorage.openStreamElement( sName, nMode );
			Error( "The trying to open substoream '" + sName + "' must fail!" );
		}
		catch( Exception e )
		{
			return true;
		}

		return false;
	}

	public XStorage createStorageFromURL(
								XSingleServiceFactory xFactory,
								String aURL,
								int nMode )
	{
		XStorage xResult = null;
		
		try
		{
			PropertyValue[] aAddArgs = new PropertyValue[1];
			aAddArgs[0] = new PropertyValue();
			aAddArgs[0].Name = "StorageFormat";
			aAddArgs[0].Value = "OFOPXMLFormat";

			Object pArgs[] = new Object[3];
			pArgs[0] = (Object) aURL;
			pArgs[1] = new Integer( nMode );
			pArgs[2] = (Object) aAddArgs;

			Object oTempStorage = xFactory.createInstanceWithArguments( pArgs );
			xResult = (XStorage) UnoRuntime.queryInterface( XStorage.class, oTempStorage );
		}
		catch( Exception e )
		{
			Error( "Can't create storage from URL, exception: " + e );
			return null;
		}

		if ( xResult == null )
			Error( "Can't create storage from URL!" );
			
		return xResult;
	}

	public XStorage createStorageFromStream(
								XSingleServiceFactory xFactory,
								XStream xStream,
								int nMode )
	{
		XStorage xResult = null;
		
		try
		{
			PropertyValue[] aAddArgs = new PropertyValue[1];
			aAddArgs[0] = new PropertyValue();
			aAddArgs[0].Name = "StorageFormat";
			aAddArgs[0].Value = "OFOPXMLFormat";

			Object pArgs[] = new Object[3];
			pArgs[0] = (Object) xStream;
			pArgs[1] = new Integer( nMode );
			pArgs[2] = (Object) aAddArgs;

			Object oTempStorage = xFactory.createInstanceWithArguments( pArgs );
			xResult = (XStorage) UnoRuntime.queryInterface( XStorage.class, oTempStorage );
		}
		catch( Exception e )
		{
			Error( "Can't create storage from stream, exception: " + e );
			return null;
		}

		if ( xResult == null )
			Error( "Can't create storage from stream!" );
			
		return xResult;
	}

	public XStorage createStorageFromInputStream(
								XSingleServiceFactory xFactory,
								XInputStream xInStream )
	{
		XStorage xResult = null;
		
		try
		{
			PropertyValue[] aAddArgs = new PropertyValue[1];
			aAddArgs[0] = new PropertyValue();
			aAddArgs[0].Name = "StorageFormat";
			aAddArgs[0].Value = "OFOPXMLFormat";

			Object pArgs[] = new Object[3];
			pArgs[0] = (Object) xInStream;
			pArgs[1] = new Integer( ElementModes.READ );
			pArgs[2] = (Object) aAddArgs;

			Object oTempStorage = xFactory.createInstanceWithArguments( pArgs );
			xResult = (XStorage) UnoRuntime.queryInterface( XStorage.class, oTempStorage );
		}
		catch( Exception e )
		{
			Error( "Can't create storage from input stream, exception: " + e );
			return null;
		}

		if ( xResult == null )
			Error( "Can't create storage from input stream!" );
			
		return xResult;
	}

	public XStorage createTempStorage( XMultiServiceFactory xMSF, XSingleServiceFactory xFactory )
	{
		// create a temporary storage
		XStorage xResult = null;
		XStream xStream = CreateTempFileStream( xMSF );
		if ( xStream == null )
		{
			Error( "Can't create temp file stream!" );
			return null;
		}
		
		try
		{
			xResult = createStorageFromStream( xFactory, xStream, ElementModes.WRITE );
		}
		catch( Exception e )
		{
			Error( "Can't create temp storage, exception: " + e );
		}

		return xResult;
	}

	public XStorage cloneStorage( XMultiServiceFactory xMSF, XSingleServiceFactory xFactory, XStorage xStorage )
	{
		// create a copy of a last committed version of specified storage
		XStorage xResult = null;
		try
		{
			xResult = createTempStorage( xMSF, xFactory );
			if ( xResult != null )
				xStorage.copyLastCommitTo( xResult );
		}
		catch( Exception e )
		{
			Error( "Can't clone storage, exception: " + e );
			return null;
		}

		return xResult;
	}

	public XStorage cloneSubStorage( XMultiServiceFactory xMSF, XSingleServiceFactory xFactory, XStorage xStorage, String sName )
	{
		// create a copy of a last committed version of specified substorage
		XStorage xResult = null;
		try
		{
			xResult = createTempStorage( xMSF, xFactory );
			if ( xResult != null )
				xStorage.copyStorageElementLastCommitTo( sName, xResult );
		}
		catch( Exception e )
		{
			Error( "Can't clone substorage '" + sName + "', exception: " + e );
			return null;
		}

		return xResult;
	}

	public XStream cloneSubStream( XStorage xStorage, String sName )
	{
		// clone existing substream
		try
		{
			XStream xStream = xStorage.cloneStreamElement( sName );
			return xStream;
		}
		catch( Exception e )
		{
			Error( "Can't clone substream '" + sName + "', exception: " + e );
		}

		return null;
	}

	public void Error( String sError )
	{
		m_aLogWriter.println( m_sTestPrefix + "Error: " + sError );
	}

	public void Message( String sMessage )
	{
		m_aLogWriter.println( m_sTestPrefix + sMessage );
	}

	public void PrintRelations( StringPair[][] aRels )
	{
		m_aLogWriter.println( "========" );
		for ( int nInd1 = 0; nInd1 < aRels.length; nInd1++ )
		{
			for ( int nInd2 = 0; nInd2 < aRels[nInd1].length; nInd2++ )
			{
				m_aLogWriter.println( "\"" + aRels[nInd1][nInd2].First + "\" = \"" + aRels[nInd1][nInd2].Second + "\", " );
			}
			m_aLogWriter.println( "========" );
		}
	}
}

