<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
<script:module xmlns:script="http://openoffice.org/2000/script" script:name="SF_Register" script:language="StarBasic" script:moduleType="normal">REM =======================================================================================================================
REM ===			The ScriptForge library and its associated libraries are part of the LibreOffice project.				===
REM	===						The SFDatabases library is one of the associated libraries.									===
REM ===					Full documentation is available on https://help.libreoffice.org/								===
REM =======================================================================================================================

Option Compatible
Option Explicit

&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;
&apos;&apos;&apos;	SF_Register
&apos;&apos;&apos;	===========
&apos;&apos;&apos;		The ScriptForge framework includes
&apos;&apos;&apos;			the master ScriptForge library
&apos;&apos;&apos;			a number of &quot;associated&quot; libraries SF*
&apos;&apos;&apos;			any user/contributor extension wanting to fit into the framework 
&apos;&apos;&apos;
&apos;&apos;&apos;		The main methods in this module allow the current library to cling to ScriptForge
&apos;&apos;&apos;			- RegisterScriptServices
&apos;&apos;&apos;				Register the list of services implemented by the current library
&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;&apos;

REM ================================================================== EXCEPTIONS

Private Const BASEDOCUMENTOPENERROR	=	&quot;BASEDOCUMENTOPENERROR&quot;
Private Const DBCONNECTERROR		=	&quot;DBCONNECTERROR&quot;

REM ============================================================== PUBLIC METHODS

REM -----------------------------------------------------------------------------
Public Sub RegisterScriptServices() As Variant
&apos;&apos;&apos;	Register into ScriptForge the list of the services implemented by the current library
&apos;&apos;&apos;	Each library pertaining to the framework must implement its own version of this method
&apos;&apos;&apos;
&apos;&apos;&apos;	It consists in successive calls to the RegisterService() and RegisterEventManager() methods
&apos;&apos;&apos;	with 2 arguments:
&apos;&apos;&apos;		ServiceName: the name of the service as a case-insensitive string
&apos;&apos;&apos;		ServiceReference: the reference as an object
&apos;&apos;&apos;			If the reference refers to a module, then return the module as an object:
&apos;&apos;&apos;				GlobalScope.Library.Module
&apos;&apos;&apos;			If the reference is a class instance, then return a string referring to the method
&apos;&apos;&apos;			containing the New statement creating the instance
&apos;&apos;&apos;				&quot;libraryname.modulename.function&quot;

	With GlobalScope.ScriptForge.SF_Services
		.RegisterService(&quot;Database&quot;,				&quot;SFDatabases.SF_Register._NewDatabase&quot;)		&apos;	Reference to the function initializing the service
		.RegisterService(&quot;DatabaseFromDocument&quot;,	&quot;SFDatabases.SF_Register._NewDatabaseFromSource&quot;)
		.RegisterService(&quot;Datasheet&quot;,				&quot;SFDatabases.SF_Register._NewDatasheet&quot;)
	End With

End Sub			&apos;	SFDatabases.SF_Register.RegisterScriptServices

REM =========================================================== PRIVATE FUNCTIONS

REM -----------------------------------------------------------------------------
Public Function _NewDatabase(Optional ByVal pvArgs As Variant) As Object
&apos;&apos;&apos;	Create a new instance of the SF_Database class
&apos;&apos;&apos;	Args:
&apos;&apos;&apos;		FileName : the name of the file (compliant with the SF_FileSystem.FileNaming notation)
&apos;&apos;&apos;		RegistrationName: mutually exclusive with FileName. Used when database is registered
&apos;&apos;&apos;		ReadOnly : (boolean). Default = True
&apos;&apos;&apos;		User : connection parameters
&apos;&apos;&apos;		Password
&apos;&apos;&apos;	Returns:
&apos;&apos;&apos;		The instance or Nothing
&apos;&apos;&apos;	Exceptions:
&apos;&apos;&apos;		BASEDOCUMENTOPENERROR		The database file could not be opened
&apos;&apos;&apos;		DBCONNECTERROR				The database could not be connected, credentials are probably wrong

Dim oDatabase As Object					&apos;	Return value
Dim vFileName As Variant				&apos;	alias of pvArgs(0)
Dim vRegistration As Variant			&apos;	Alias of pvArgs(1)
Dim vReadOnly As Variant				&apos;	Alias of pvArgs(2)
Dim vUser As Variant					&apos;	Alias of pvArgs(3)
Dim vPassword As Variant				&apos;	Alias of pvArgs(4)
Dim oDBContext As Object				&apos;	com.sun.star.sdb.DatabaseContext
Const cstService = &quot;SFDatabases.Database&quot;
Const cstGlobal = &quot;GlobalScope&quot;

	If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch

Check:
	If IsMissing(pvArgs) Or IsEmpty(pvArgs) Then pvArgs = Array()
	If UBound(pvArgs) &gt;= 0 Then vFileName = pvArgs(0) Else vFileName = &quot;&quot;
	If IsEmpty(vFileName) Then vFileName = &quot;&quot;
	If UBound(pvArgs) &gt;= 1 Then vRegistration = pvArgs(1) Else vRegistration = &quot;&quot;
	If IsEmpty(vRegistration) Then vRegistration = &quot;&quot;
	If UBound(pvArgs) &gt;= 2 Then vReadOnly = pvArgs(2) Else vReadOnly = True
	If IsEmpty(vReadOnly) Then vReadOnly = True
	If UBound(pvArgs) &gt;= 3 Then vUser = pvArgs(3) Else vUser = &quot;&quot;
	If IsEmpty(vUser) Then vUser = &quot;&quot;
	If UBound(pvArgs) &gt;= 4 Then vPassword = pvArgs(4) Else vPassword = &quot;&quot;
	If IsEmpty(vPassword) Then vPassword = &quot;&quot;
	If Not ScriptForge.SF_Utils._Validate(vFileName, &quot;FileName&quot;, V_STRING) Then GoTo Finally
	If Not ScriptForge.SF_Utils._Validate(vRegistration, &quot;RegistrationName&quot;, V_STRING) Then GoTo Finally
	If Not ScriptForge.SF_Utils._Validate(vReadOnly, &quot;ReadOnly&quot;, ScriptForge.V_BOOLEAN) Then GoTo Finally
	If Not ScriptForge.SF_Utils._Validate(vUser, &quot;User&quot;, V_STRING) Then GoTo Finally
	If Not ScriptForge.SF_Utils._Validate(vPassword, &quot;Password&quot;, V_STRING) Then GoTo Finally
	Set oDatabase = Nothing

	&apos;	Check the existence of FileName
	With ScriptForge
		Set oDBContext = .SF_Utils._GetUNOService(&quot;DatabaseContext&quot;)
		If Len(vFileName) = 0 Then	&apos;	FileName has precedence over RegistrationName
			If Len(vRegistration) = 0 Then GoTo CatchError
			If Not oDBContext.hasRegisteredDatabase(vRegistration) Then GoTo CatchError
			vFileName = .SF_FileSystem._ConvertFromUrl(oDBContext.getDatabaseLocation(vRegistration))
		End If	
		If Not .SF_FileSystem.FileExists(vFileName) Then GoTo CatchError
	End With

Try:
	&apos;	Create the database Basic object and initialize attributes
	Set oDatabase = New SF_Database
	With oDatabase
		Set .[Me] = oDatabase
		._Location = ConvertToUrl(vFileName)
		Set ._DataSource = oDBContext.getByName(._Location)
		If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo CatchConnect
		Set ._Connection = ._DataSource.getConnection(vUser, vPassword)
		If IsNull(._Connection) Then GoTo CatchConnect
		._User = vUser
		._Password = vPassword
		._ReadOnly = vReadOnly
		Set ._MetaData = ._Connection.MetaData
		._URL = ._MetaData.URL
	End With

Finally:
	Set _NewDatabase = oDatabase
	Exit Function
Catch:
	GoTo Finally
CatchError:
	ScriptForge.SF_Exception.RaiseFatal(BASEDOCUMENTOPENERROR, &quot;FileName&quot;, vFileName, &quot;RegistrationName&quot;, vRegistration)
	GoTo Finally
CatchConnect:
	ScriptForge.SF_Exception.RaiseFatal(DBCONNECTERROR, &quot;User&quot;, vUser, &quot;Password&quot;, vPassword, vFileName)
	GoTo Finally
End Function	&apos;	SFDatabases.SF_Register._NewDatabase

REM -----------------------------------------------------------------------------
Public Function _NewDatabaseFromSource(Optional ByVal pvArgs As Variant) As Object
&apos;										ByRef oDataSource As Object _
&apos;											, ByVal sUser As String _
&apos;											, ByVal sPassword As String _
&apos;											) As Object
&apos;&apos;&apos;	Create a new instance of the SF_Database class from the given datasource
&apos;&apos;&apos;	established in the SFDocuments.Base service
&apos;&apos;&apos;	THIS SERVICE MUST NOT BE CALLED FROM A USER SCRIPT
&apos;&apos;&apos;	Args:
&apos;&apos;&apos;		oDataSource: 	com.sun.star.sdbc.XDataSource
&apos;&apos;&apos;		sUser, sPassword : connection parameters
&apos;&apos;&apos;	Returns:
&apos;&apos;&apos;		The instance or Nothing
&apos;&apos;&apos;	Exceptions:
&apos;&apos;&apos;		managed in the calling routines when Nothing is returned

Dim oDatabase As Object					&apos;	Return value
Dim oConnection As Object				&apos;	com.sun.star.sdbc.XConnection
Dim oDataSource As Object				&apos;	Alias of pvArgs(0)
Dim sUser As String						&apos;	Alias of pvArgs(1)
Dim sPassword As String					&apos;	Alias of pvArgs(2)

	If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
	Set oDatabase = Nothing

Try:
	&apos;	Get arguments
	Set oDataSource = pvArgs(0)
	sUser = pvArgs(1)
	sPassword = pvArgs(2)

	&apos;	Setup the connection
	If oDataSource.IsPasswordRequired Then
		Set oConnection = oDataSource.getConnection(sUser, sPassword)
	Else
		Set oConnection = oDataSource.getConnection(&quot;&quot;, &quot;&quot;)
	End If

	&apos;	Create the database Basic object and initialize attributes
	If Not IsNull(oConnection) Then
		Set oDatabase = New SF_Database
		With oDatabase
			Set .[Me] = oDatabase
			._Location = &quot;&quot;
			Set ._DataSource = oDataSource
			Set ._Connection = oConnection
			._ReadOnly = oConnection.isReadOnly()
			Set ._MetaData = oConnection.MetaData
			._URL = ._MetaData.URL
		End With
	End If

Finally:
	Set _NewDatabaseFromSource = oDatabase
	Exit Function
Catch:
	ScriptForge.SF_Exception.Clear()
	GoTo Finally
End Function	&apos;	SFDatabases.SF_Register._NewDatabaseFromSource

REM -----------------------------------------------------------------------------
Public Function _NewDatasheet(Optional ByVal pvArgs As Variant) As Object
&apos;							  Optional ByRef poComponent As Object _
&apos;							  	, Optional ByRef poParent As Object _
&apos;								) As Object
&apos;&apos;&apos;	Create a new instance of the SF_Datasheet class
&apos;&apos;&apos;	Called from
&apos;&apos;&apos;		base.Datasheets()
&apos;&apos;&apos;		base.OpenTable()
&apos;&apos;&apos;		base.OpenQuery()
&apos;&apos;&apos;		database.OpenTable()
&apos;&apos;&apos;		database.OpenQuery()
&apos;&apos;&apos;		database.OpenSql()
&apos;&apos;&apos;	Args:
&apos;&apos;&apos;		Component:	the component of the new datasheet
&apos;&apos;&apos;						com.sun.star.lang.XComponent - org.openoffice.comp.dbu.ODatasourceBrowser
&apos;&apos;&apos;		Parent: the parent SF_Database or SF_Base instance having produced the new datasheet
&apos;&apos;&apos;				When absent, the SF_Database instance will be derived from the component
&apos;&apos;&apos;	Returns:
&apos;&apos;&apos;		The instance or Nothing

Dim oDatasheet As Object		&apos;	Return value
Dim oParent As Object			&apos;	The parent SF_Database or SF_Base instance having produced the new datasheet
Dim oComponent As Object		&apos;	The component of the new datasheet
Dim oWindow As Object			&apos;	ui.Window user-defined type
Dim oUi As Object				:	Set oUi = ScriptForge.SF_Services.CreateScriptService(&quot;ScriptForge.UI&quot;)

Const TABLEDATA					= &quot;TableData&quot;
Const QUERYDATA					= &quot;QueryData&quot;
Const SQLDATA					= &quot;SqlData&quot;

	If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
	Set oDatasheet = Nothing

Check:
	&apos;	Get, check and assign arguments
	If Not IsArray(pvArgs) Then GoTo Catch
	If UBound(pvArgs) &gt;= 0 Then
		Set oComponent = pvArgs(0)
	End If
	If UBound(pvArgs) = 0 Then
		Set oParent = Nothing
	ElseIf  UBound(pvArgs) = 1 Then
		Set oParent = pvArgs(1)
	Else
		GoTo Catch
	End If

	&apos;	Check the validity of the proposed window: is it really a datasheet ? Otherwise, do nothing
	If IsNull(oComponent) Then GoTo Catch
	Set oWindow = oUi._IdentifyWindow(oComponent)
	With oWindow
		If .DocumentType &lt;&gt; TABLEDATA And .DocumentType &lt;&gt; QUERYDATA And .DocumentType &lt;&gt; SQLDATA Then GoTo Catch
	End With
	If IsEmpty(oComponent.Selection) Then GoTo Catch

Try:
	Set oDatasheet = New SF_Datasheet
	With oDatasheet
		Set .[Me] = oDatasheet
		Set .[_Parent] = oParent
		Set ._Component = oComponent
		&apos;	Achieve the initialization
		._Initialize()
	End With

Finally:
	Set _NewDatasheet = oDatasheet
	Exit Function
Catch:
	Set oDatasheet = Nothing
	GoTo Finally
End Function	&apos;	SFDatabases.SF_Register._NewDatasheet

REM ============================================== END OF SFDATABASES.SF_REGISTER
</script:module>