Difference between revisions of "Documentation/DevGuide/Config/Updating Configuration Data"
m (1 revision(s)) |
m |
||
Line 25: | Line 25: | ||
The following example demonstrates how the configuration interfaces are used to feed a user-interface for preference changes. This shows the framework needed to update configuration values, and demonstrates how listeners are used with configuration views. This example concentrates on properties in group nodes with a fixed structure. It uses the same {{PRODUCTNAME}} Calc grid settings as the previous example. It assumes that there is a class <code>GridOptionsEditor</code> that drives a dialog to display and edit the configuration data: | The following example demonstrates how the configuration interfaces are used to feed a user-interface for preference changes. This shows the framework needed to update configuration values, and demonstrates how listeners are used with configuration views. This example concentrates on properties in group nodes with a fixed structure. It uses the same {{PRODUCTNAME}} Calc grid settings as the previous example. It assumes that there is a class <code>GridOptionsEditor</code> that drives a dialog to display and edit the configuration data: | ||
− | + | <source lang="java"> | |
// This method simulates editing configuration data using a GridEditor dialog class | // This method simulates editing configuration data using a GridEditor dialog class | ||
public void editGridOptions() throws com.sun.star.uno.Exception { | public void editGridOptions() throws com.sun.star.uno.Exception { | ||
Line 73: | Line 73: | ||
((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose(); | ((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose(); | ||
} | } | ||
− | + | </source> | |
− | In this example, the dialog controller uses the <idl>com.sun.star.beans.XMultiHierarchicalPropertySet</idl> interface to read and change configuration values. If the grid options are changed and committed in another view, | + | In this example, the dialog controller uses the <idl>com.sun.star.beans.XMultiHierarchicalPropertySet</idl> interface to read and change configuration values. If the grid options are changed and committed in another view, <idlml>com.sun.star.util.XChangesListener:changesOccurred</idlml>() is sent to the listener supplied by the dialog which can then update its display accordingly. |
Note that a synchronous <idl>com.sun.star.configuration.ConfigurationUpdateAccess</idl> was created for this example (argument <code>lazywrite==false</code>). As the action here is driven by user interaction, synchronous committing is used to detect errors immediately. | Note that a synchronous <idl>com.sun.star.configuration.ConfigurationUpdateAccess</idl> was created for this example (argument <code>lazywrite==false</code>). As the action here is driven by user interaction, synchronous committing is used to detect errors immediately. | ||
− | Besides the values for the current user, there are also default values that are determined by merging the schema with any default layers. It is possible to retrieve the default values for individual properties, and to reset a property or a set node to their default states, thus backing out any changes done for the current user. For this purpose, group nodes support the interfaces <idl>com.sun.star.beans.XPropertyState</idl> and <idl>com.sun.star.beans.XMultiPropertyStates</idl>, offering operations to query if a property assumes its default state or the default value, and to reset an updatable property to its default state. The <idl>com.sun.star.beans.Property</idl> structs available through | + | Besides the values for the current user, there are also default values that are determined by merging the schema with any default layers. It is possible to retrieve the default values for individual properties, and to reset a property or a set node to their default states, thus backing out any changes done for the current user. For this purpose, group nodes support the interfaces <idl>com.sun.star.beans.XPropertyState</idl> and <idl>com.sun.star.beans.XMultiPropertyStates</idl>, offering operations to query if a property assumes its default state or the default value, and to reset an updatable property to its default state. The <idl>com.sun.star.beans.Property</idl> structs available through <idlml>com.sun.star.beans.XPropertySetInfo:getPropertyByName</idlml>() or <idlml>com.sun.star.beans.XPropertySetInfo:getProperties</idlml>() are used to determine if a particular item or node supports this operation. |
Individual set elements can not be reset because set nodes do not support <idl>com.sun.star.beans.XPropertyState</idl>. Instead a <idl>com.sun.star.configuration.SetAccess</idl> supports <idl>com.sun.star.beans.XPropertyWithState</idl>that resets the set as a whole. | Individual set elements can not be reset because set nodes do not support <idl>com.sun.star.beans.XPropertyState</idl>. Instead a <idl>com.sun.star.configuration.SetAccess</idl> supports <idl>com.sun.star.beans.XPropertyWithState</idl>that resets the set as a whole. | ||
The following is an example code using this feature to reset the {{PRODUCTNAME}} Calc grid settings used in the preceding examples to their default state: | The following is an example code using this feature to reset the {{PRODUCTNAME}} Calc grid settings used in the preceding examples to their default state: | ||
− | + | <source lang="java"> | |
/// This method resets the grid settings to their default values | /// This method resets the grid settings to their default values | ||
protected void resetGridConfiguration() throws com.sun.star.uno.Exception { | protected void resetGridConfiguration() throws com.sun.star.uno.Exception { | ||
Line 134: | Line 134: | ||
} | } | ||
+ | </source> | ||
+ | {{Documentation/Note|Currently, group nodes do not support the attribute <idlml>com.sun.star.beans.PropertyAttribute:MAYBEDEFAULT</idlml> set in the <idl>com.sun.star.beans.Property</idl> structure available from <idl>com.sun.star.beans.XPropertySetInfo</idl>. Attempts to use <idlml>com.sun.star.beans.XPropertyState:setPropertyToDefault</idlml> to reset an entire group node fail. | ||
− | + | Also, because the group nodes can not be reset, the <idlml>com.sun.star.beans.XPropertyState:setPropertyToDefault</idlml> or <idlml>com.sun.star.beans.XMultiPropertyStates:setAllPropertiesToDefault</idlml> cannot be used to reset all descendants of a node. | |
− | + | It is intended to lift this restriction in a future release. To avoid unexpected changes in behavior when this change is introduced, you should apply <idlml>com.sun.star.beans.XPropertyState:setPropertyToDefault</idlml> only to actual properties, such as value items, or set nodes. In particular, you should avoid <idlml>com.sun.star.beans.XMultiPropertyStates:setAllPropertiesToDefault</idlml>() on group nodes.}} | |
− | + | ||
− | It is intended to lift this restriction in a future release. To avoid unexpected changes in behavior when this change is introduced, you should apply | + | |
A more comprehensive example is provided that shows how set elements are created and added, and how it employs advanced techniques for reducing the amount of data that needs to be loaded. | A more comprehensive example is provided that shows how set elements are created and added, and how it employs advanced techniques for reducing the amount of data that needs to be loaded. | ||
Line 192: | Line 192: | ||
It also contains the binary properties <code>NumberFormatSettings</code> and <code>LayoutInformation</code> that store information for layout and display of the data source contents. It also contains the set items <code>Tables</code> and <code>Queries</code> containing the layout information for the data access views. | It also contains the binary properties <code>NumberFormatSettings</code> and <code>LayoutInformation</code> that store information for layout and display of the data source contents. It also contains the set items <code>Tables</code> and <code>Queries</code> containing the layout information for the data access views. | ||
− | The example shows a procedure that creates and saves basic settings for connecting to a new data source. It uses an asynchronous <idl>com.sun.star.configuration.ConfigurationUpdateAccess</idl>. Thus, when | + | The example shows a procedure that creates and saves basic settings for connecting to a new data source. It uses an asynchronous <idl>com.sun.star.configuration.ConfigurationUpdateAccess</idl>. Thus, when <idlml>com.sun.star.util.XChangesBatch:commitChanges</idlml> is called, the data becomes visible at the <idl>com.sun.star.configuration.ConfigurationProvider</idl>, but is only stored in the provider's cache. It is written to the data store at later when the cache is automatically flushed by the <idl>com.sun.star.configuration.ConfigurationProvider</idl>. As this is done in the background there is no exception when the write-back fails. |
{{Documentation/Caution|The recommended method to configure a new data source is to use the <idl>com.sun.star.sdb.DatabaseContext</idl> service as described in [[Documentation/DevGuide/Database/Data Sources in OpenOffice.org API#DatabaseContext|DatabaseContext]]. This is a high-level service that ensures that all the settings required to establish a connection are properly set.}} | {{Documentation/Caution|The recommended method to configure a new data source is to use the <idl>com.sun.star.sdb.DatabaseContext</idl> service as described in [[Documentation/DevGuide/Database/Data Sources in OpenOffice.org API#DatabaseContext|DatabaseContext]]. This is a high-level service that ensures that all the settings required to establish a connection are properly set.}} | ||
Line 200: | Line 200: | ||
The resulting routine is: | The resulting routine is: | ||
<!--[SOURCE:Config/ConfigExamples.java]--> | <!--[SOURCE:Config/ConfigExamples.java]--> | ||
− | + | <source lang="java"> | |
// This method stores a data source for given connection data | // This method stores a data source for given connection data | ||
void storeDataSource( | void storeDataSource( | ||
Line 248: | Line 248: | ||
((XComponent) UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose(); | ((XComponent) UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose(); | ||
} | } | ||
− | + | </source> | |
Notice the function <code>createDataSourceDescription</code> in our example. It is called to get a <code>DataSourceDescription</code> instance to access a pre-existing item, or create and insert a new item using the passed name. | Notice the function <code>createDataSourceDescription</code> in our example. It is called to get a <code>DataSourceDescription</code> instance to access a pre-existing item, or create and insert a new item using the passed name. | ||
Line 257: | Line 257: | ||
This results in a view where descendants of the root are only included in the view up to the given nesting depth. In this case, where depth = 1, only the immediate children are loaded. If the requested item is found, the function gets a deeper view for only that item, otherwise it creates a new instance. In the latter case, the item returned is not the root of the view. | This results in a view where descendants of the root are only included in the view up to the given nesting depth. In this case, where depth = 1, only the immediate children are loaded. If the requested item is found, the function gets a deeper view for only that item, otherwise it creates a new instance. In the latter case, the item returned is not the root of the view. | ||
<!--[SOURCE:Config/ConfigExamples.java]--> | <!--[SOURCE:Config/ConfigExamples.java]--> | ||
− | + | <source lang="java"> | |
/** This method gets the DataSourceDescription for a data source. | /** This method gets the DataSourceDescription for a data source. | ||
It either gets the existing entry or creates a new instance. | It either gets the existing entry or creates a new instance. | ||
Line 355: | Line 355: | ||
return xDataSourceDescriptor ; | return xDataSourceDescriptor ; | ||
} | } | ||
− | + | </source> | |
A method is required to recover the view root from an element object, because it is unknown if the item is the root of the view or a descendant : | A method is required to recover the view root from an element object, because it is unknown if the item is the root of the view or a descendant : | ||
− | < | + | <!--[SOURCE:Config/ConfigExamples.java]--> |
− | + | <source lang="java"> | |
// This method get the view root node given an interface to any node in the view | // This method get the view root node given an interface to any node in the view | ||
public static Object getViewRoot(Object xElement) { | public static Object getViewRoot(Object xElement) { | ||
Line 381: | Line 381: | ||
return xResult; | return xResult; | ||
} | } | ||
− | + | </source> | |
Another function used is <code>storeDataSource</code> is <code>storeSettings</code> to store an array of <idl>com.sun.star.beans.NamedValue</idl>s in a set of <code>DataSourceSetting</code> items. A <code>DataSourceSetting</code> contains a single property named <code>Value</code> that is set to any of the basic types supported for configuration values. This example demonstrates the two steps required to add a new item to a set node: | Another function used is <code>storeDataSource</code> is <code>storeSettings</code> to store an array of <idl>com.sun.star.beans.NamedValue</idl>s in a set of <code>DataSourceSetting</code> items. A <code>DataSourceSetting</code> contains a single property named <code>Value</code> that is set to any of the basic types supported for configuration values. This example demonstrates the two steps required to add a new item to a set node: | ||
<!--[SOURCE:Config/ConfigExamples.java]--> | <!--[SOURCE:Config/ConfigExamples.java]--> | ||
− | + | <source lang="java"> | |
/// this method stores a number of settings in a set node containing DataSourceSetting objects | /// this method stores a number of settings in a set node containing DataSourceSetting objects | ||
void storeSettings(Object xSettingsSet, com.sun.star.beans.NamedValue [] aSettings) | void storeSettings(Object xSettingsSet, com.sun.star.beans.NamedValue [] aSettings) | ||
Line 416: | Line 416: | ||
} | } | ||
} | } | ||
− | + | </source> | |
Besides adding a freshly created instance of a template, a set item can be removed from a set and added to any other set supporting the same template for its elements, provided both sets are part of the same view. You cannot move a set item between views, as this contradicts the transactional isolation of views. The set item you removed in one view will still be in its old place in the other. If a set item is moved between sets in one view and the changes are committed, the change appears in another overlapping view as removal of the original item and insertion of a new element in the target location, not as relocation of an identical element. | Besides adding a freshly created instance of a template, a set item can be removed from a set and added to any other set supporting the same template for its elements, provided both sets are part of the same view. You cannot move a set item between views, as this contradicts the transactional isolation of views. The set item you removed in one view will still be in its old place in the other. If a set item is moved between sets in one view and the changes are committed, the change appears in another overlapping view as removal of the original item and insertion of a new element in the target location, not as relocation of an identical element. | ||
− | {{Documentation/Tip|The methods | + | {{Documentation/Tip|The methods <idlml>com.sun.star.container.XNamed:setName</idlml>() and <idlml>com.sun.star.container.XChild:setParent</idlml>() are supported by a <idl>com.sun.star.configuration.ConfigurationUpdateAccess</idl> only if it is a <idl>com.sun.star.configuration.SetElement</idl>. They offer another way to move an item within a set or from one set to another set. |
In the current release of {{PRODUCTNAME}}, these methods are not supported correctly. You can achieve the same effect by using a sequence of remove item - insert item. | In the current release of {{PRODUCTNAME}}, these methods are not supported correctly. You can achieve the same effect by using a sequence of remove item - insert item. |
Revision as of 20:15, 4 April 2008
A com.sun.star.configuration.ConfigurationUpdateAccess provides operations for updating configuration data, by extending the interfaces supported by a com.sun.star.configuration.ConfigurationAccess.
For com.sun.star.beans.XPropertySet and related interfaces, the semantics are extended to set property values. Support for container interfaces is extended to set properties in group nodes, and insert or remove elements in set nodes. Thus, a com.sun.star.configuration.GroupUpdate supports interface com.sun.star.container.XNameReplace and a com.sun.star.configuration.SetUpdate supports com.sun.star.container.XNameContainer. Only complete trees having the appropriate structure are inserted for sets whose elements are complete structures as described by a template,. To support this, the set object is used as a factory that can create structures of the appropriate type. For this purpose, the set supports com.sun.star.lang.XSingleServiceFactory.
Updates done through a configuration view are only visible within that view, providing transactional isolation. When a set of updates is ready, it must be committed explicitly to become visible beyond this view. All pending updates are then sent to the configuration provider in one batch. This batch update behavior is controlled through interface com.sun.star.util.XChangesBatch that is implemented by the root element of an updatable configuration view.
When a set of changes is committed to the provider it becomes visible to other views obtained from the same provider as an atomic and consistent set of changes. Thus, in the local scope of a single com.sun.star.configuration.ConfigurationProvider a high degree of transactional behavior is achieved.
The configuration management component does not guarantee true transactional behavior. Committing the changes to the com.sun.star.configuration.ConfigurationProvider does not ensure persistence or durability of the changes. When the provider writes back the changes to the persistent data store, they become durable. Generally, the com.sun.star.configuration.ConfigurationProvider may cache and combine requests, so that updates are propagated to the data store at a later time. If several sets of changes are combined before being saved, isolation and consistency may be weakened in case of failure. As long as the backend does not fully support transactions, only parts of an update request might be stored successfully, thus violating atomicity and consistency. If failures occur while writing configuration data into the backend data store, the com.sun.star.configuration.ConfigurationProvider resynchronizes with the data stored in the backend. The listeners are notified of any differences as if they had been stored through another view. If an application has more stringent error handling needs, the caching behavior can be adjusted by providing arguments when creating the view. In summary, there are few overall guarantees regarding transactional integrity for the configuration database, but locally, the configuration behaves as if the support is in place. Depending on the backend capabilities, the com.sun.star.configuration.ConfigurationProvider tries to provide the best approximation to transactional integrity that can be achieved considering the capabilities of the backend without compromising performance. |
The following example demonstrates how the configuration interfaces are used to feed a user-interface for preference changes. This shows the framework needed to update configuration values, and demonstrates how listeners are used with configuration views. This example concentrates on properties in group nodes with a fixed structure. It uses the same OpenOffice.org Calc grid settings as the previous example. It assumes that there is a class GridOptionsEditor
that drives a dialog to display and edit the configuration data:
// This method simulates editing configuration data using a GridEditor dialog class public void editGridOptions() throws com.sun.star.uno.Exception { // The path to the root element final String cGridOptionsPath = "/org.openoffice.Office.Calc/Grid"; // create a synchronous view for better error handling (lazywrite = false) Object xViewRoot = createUpdatableView(cGridOptionsPath, false); // the 'editor' GridOptionsEditor dialog = new GridOptionsEditor(); // set up the initial values and register listeners // get a data access interface, to supply the view with a model XMultiHierarchicalPropertySet xProperties = (XMultiHierarchicalPropertySet) UnoRuntime.queryInterface(XMultiHierarchicalPropertySet.class, xViewRoot); dialog.setModel(xProperties); // get a listener object (probably an adapter) that notifies // the dialog of external changes to its model XChangesListener xListener = dialog.createChangesListener( ); XChangesNotifier xNotifier = (XChangesNotifier)UnoRuntime.queryInterface(XChangesNotifier.class, xViewRoot); xNotifier.addChangesListener(xListener); if (dialog.execute() == GridOptionsEditor.SAVE_SETTINGS) { // changes have been applied to the view here XChangesBatch xUpdateControl = (XChangesBatch) UnoRuntime.queryInterface(XChangesBatch.class,xViewRoot); try { xUpdateControl.commitChanges(); } catch (Exception e) { dialog.informUserOfError( e ); } } // all changes have been handled - clean up and return // listener is done now xNotifier.removeChangesListener(xListener); // we are done with the view - dispose it ((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose(); }
In this example, the dialog controller uses the com.sun.star.beans.XMultiHierarchicalPropertySet interface to read and change configuration values. If the grid options are changed and committed in another view, <idlml>com.sun.star.util.XChangesListener:changesOccurred</idlml>() is sent to the listener supplied by the dialog which can then update its display accordingly.
Note that a synchronous com.sun.star.configuration.ConfigurationUpdateAccess was created for this example (argument lazywrite==false
). As the action here is driven by user interaction, synchronous committing is used to detect errors immediately.
Besides the values for the current user, there are also default values that are determined by merging the schema with any default layers. It is possible to retrieve the default values for individual properties, and to reset a property or a set node to their default states, thus backing out any changes done for the current user. For this purpose, group nodes support the interfaces com.sun.star.beans.XPropertyState and com.sun.star.beans.XMultiPropertyStates, offering operations to query if a property assumes its default state or the default value, and to reset an updatable property to its default state. The com.sun.star.beans.Property structs available through <idlml>com.sun.star.beans.XPropertySetInfo:getPropertyByName</idlml>() or <idlml>com.sun.star.beans.XPropertySetInfo:getProperties</idlml>() are used to determine if a particular item or node supports this operation.
Individual set elements can not be reset because set nodes do not support com.sun.star.beans.XPropertyState. Instead a com.sun.star.configuration.SetAccess supports com.sun.star.beans.XPropertyWithStatethat resets the set as a whole.
The following is an example code using this feature to reset the OpenOffice.org Calc grid settings used in the preceding examples to their default state:
/// This method resets the grid settings to their default values protected void resetGridConfiguration() throws com.sun.star.uno.Exception { // The path to the root element final String cGridOptionsPath = "/org.openoffice.Office.Calc/Grid"; // create the view Object xViewRoot = createUpdatableView(cGridOptionsPath); // ### resetting a single nested value ### XHierarchicalNameAccess xHierarchicalAccess = (XHierarchicalNameAccess)UnoRuntime.queryInterface(XHierarchicalNameAccess.class, xViewRoot); // get using absolute name Object xOptions = xHierarchicalAccess.getByHierarchicalName(cGridOptionsPath + "/Option"); XPropertyState xOptionState = (XPropertyState)UnoRuntime.queryInterface(XPropertyState.class, xOptions); xOptionState.setPropertyToDefault("VisibleGrid"); // ### resetting more deeply nested values ### Object xResolutionX = xHierarchicalAccess.getByHierarchicalName("Resolution/XAxis"); Object xResolutionY = xHierarchicalAccess.getByHierarchicalName("Resolution/YAxis"); XPropertyState xResolutionStateX = (XPropertyState)UnoRuntime.queryInterface(XPropertyState.class, xResolutionX); XPropertyState xResolutionStateY = (XPropertyState)UnoRuntime.queryInterface(XPropertyState.class, xResolutionY); xResolutionStateX.setPropertyToDefault("Metric"); xResolutionStateY.setPropertyToDefault("Metric"); // ### resetting multiple sibling values ### Object xSubdivision = xHierarchicalAccess.getByHierarchicalName("Subdivision"); XMultiPropertyStates xSubdivisionStates = (XMultiPropertyStates)UnoRuntime.queryInterface(XMultiPropertyStates.class, xSubdivision); xSubdivisionStates.setAllPropertiesToDefault(); // commit the changes XChangesBatch xUpdateControl = (XChangesBatch) UnoRuntime.queryInterface(XChangesBatch.class, xViewRoot); xUpdateControl.commitChanges(); // we are done with the view - dispose it ((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose(); }
A more comprehensive example is provided that shows how set elements are created and added, and how it employs advanced techniques for reducing the amount of data that needs to be loaded.
This example uses the OpenOffice.org configuration module org.openoffice.Office.DataAccess
. This component has a set item DataSources
that contains group items described by the template DataSourceDescription
. A data source description holds information about the settings required to connect to a data source.
The template org.openoffice.Office.DataAccess/DataSourceDescription
has the following properties that describe the data source connection:
Name | Type | Comment |
---|---|---|
URL
|
String
|
Data source URL. |
IsPasswordRequired
|
Boolean
|
Is a password needed to connect. |
TableFilter
|
String []
|
Filters tables for display. |
TableTypeFilter
|
String []
|
Filters tables for display. |
User
|
String
|
User name to be used for connecting. |
LoginTimeout
|
int
|
Default time-out for connection attempt. |
SuppressVersionColumns
|
Boolean
|
Controls display of certain data. |
DataSourceSettings
|
set node
|
Contains DataSourceSetting entries that contain driver-specific settings.
|
Bookmarks
|
set node
|
Contains Bookmark entries that link to related documents, for example, Forms.
|
It also contains the binary properties NumberFormatSettings
and LayoutInformation
that store information for layout and display of the data source contents. It also contains the set items Tables
and Queries
containing the layout information for the data access views.
The example shows a procedure that creates and saves basic settings for connecting to a new data source. It uses an asynchronous com.sun.star.configuration.ConfigurationUpdateAccess. Thus, when <idlml>com.sun.star.util.XChangesBatch:commitChanges</idlml> is called, the data becomes visible at the com.sun.star.configuration.ConfigurationProvider, but is only stored in the provider's cache. It is written to the data store at later when the cache is automatically flushed by the com.sun.star.configuration.ConfigurationProvider. As this is done in the background there is no exception when the write-back fails.
The recommended method to configure a new data source is to use the com.sun.star.sdb.DatabaseContext service as described in DatabaseContext. This is a high-level service that ensures that all the settings required to establish a connection are properly set. |
Among the parameters of the routine is the name of the data source that must be chosen to uniquely identify the data source from other parameters directly related to the above properties. There also is a parameter to pass a list of entries for the DataSourceSettings
set.
The resulting routine is:
// This method stores a data source for given connection data void storeDataSource( String sDataSourceName, String sDataSourceURL, String sUser, boolean bNeedsPassword, int nTimeout, com.sun.star.beans.NamedValue [] aDriverSettings, String [] aTableFilter ) throws com.sun.star.uno.Exception { // create the view and get the data source element in a // helper method createDataSourceDescription() (see below) Object xDataSource = createDataSourceDescription(getProvider(), sDataSourceName); // set the values XPropertySet xDataSourceProperties = (XPropertySet)UnoRuntime.queryInterface( XPropertySet.class, xDataSource); xDataSourceProperties.setPropertyValue("URL", sDataSourceURL); xDataSourceProperties.setPropertyValue("User", sUser); xDataSourceProperties.setPropertyValue("IsPasswordRequired", new Boolean(bNeedsPassword)); xDataSourceProperties.setPropertyValue("LoginTimeout", new Integer(nTimeout)); if (aTableFilter != null) xDataSourceProperties.setPropertyValue("TableFilter", aTableFilter); // ### store the driver-specific settings ### if (aDriverSettings != null) { Object xSettingsSet = xDataSourceProperties.getPropertyValue("DataSourceSettings"); // helper for storing (see below) storeSettings( xSettingsSet, aDriverSettings); } // ### save the data and dispose the view ### // recover the view root (helper method) Object xViewRoot = getViewRoot(xDataSource); // commit the changes XChangesBatch xUpdateControl = (XChangesBatch) UnoRuntime.queryInterface( XChangesBatch.class, xViewRoot); xUpdateControl.commitChanges(); // now clean up ((XComponent) UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose(); }
Notice the function createDataSourceDescription
in our example. It is called to get a DataSourceDescription
instance to access a pre-existing item, or create and insert a new item using the passed name.
The function is optimized to reduce the view to as little data as necessary. To this end it employs the depth parameter when creating the view.
This results in a view where descendants of the root are only included in the view up to the given nesting depth. In this case, where depth = 1, only the immediate children are loaded. If the requested item is found, the function gets a deeper view for only that item, otherwise it creates a new instance. In the latter case, the item returned is not the root of the view.
/** This method gets the DataSourceDescription for a data source. It either gets the existing entry or creates a new instance. The method attempts to keep the view used as small as possible. In particular there is no view created, that contains data for all data source that are registered. */ Object createDataSourceDescription(XMultiServiceFactory xProvider, String sDataSourceName) throws com.sun.star.uno.Exception { // The service name: Need an update access: final String cUpdatableView = "com.sun.star.configuration.ConfigurationUpdateAccess"; // The path to the DataSources set node final String cDataSourcesPath = "/org.openoffice.Office.DataAccess/DataSources"; // creation arguments: nodepath com.sun.star.beans.PropertyValue aPathArgument = new com.sun.star.beans.PropertyValue(); aPathArgument.Name = "nodepath"; aPathArgument.Value = cDataSourcesPath ; // creation arguments: commit mode com.sun.star.beans.PropertyValue aModeArgument = new com.sun.star.beans.PropertyValue(); aModeArgument.Name = "lazywrite"; aModeArgument.Value = new Boolean(true); // creation arguments: depth com.sun.star.beans.PropertyValue aDepthArgument = new com.sun.star.beans.PropertyValue(); aDepthArgument.Name = "depth"; aDepthArgument.Value = new Integer(1); Object[] aArguments = new Object[3]; aArguments[0] = aPathArgument; aArguments[1] = aModeArgument; aArguments[2] = aDepthArgument; // create the view: asynchronously updatable, with depth 1 Object xViewRoot = xProvider.createInstanceWithArguments(cUpdatableView, aArguments); XNameAccess xSetOfDataSources = (XNameAccess) UnoRuntime.queryInterface( XNameAccess.class,xViewRoot); Object xDataSourceDescriptor = null; // the result if (xSetOfDataSources .hasByName(sDataSourceName)) { // the element is there, but it is loaded only with depth zero ! try { // the view should point to the element directly, so we need to extend the path XHierarchicalName xComposePath = (XHierarchicalName) UnoRuntime.queryInterface( XHierarchicalName.class, xSetOfDataSources ); String sElementPath = xComposePath.composeHierarchicalName( sDataSourceName ); // use the name of the element now aPathArgument.Value = sElementPath; // create another view now (without depth limit) Object[] aDeepArguments = new Object[2]; aDeepArguments[0] = aPathArgument; aDeepArguments[1] = aModeArgument; // create the view: asynchronously updatable, with unlimited depth xDataSourceDescriptor = xProvider.createInstanceWithArguments(cUpdatableView, aDeepArguments); if ( xDataSourceDescriptor != null) // all went fine { // dispose the other view ((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose(); xViewRoot = null; } } catch (Exception e) { // something went wrong, we retry with a new element System.out.println("WARNING: An exception occurred while creating a view" + " for an existing data source: " + e); xDataSourceDescriptor = null; } } // do we have a result element yet ? if (xDataSourceDescriptor == null) { // get the container XNameContainer xSetUpdate = (XNameContainer)UnoRuntime.queryInterface( XNameContainer.class, xViewRoot); // create a new detached set element (instance of DataSourceDescription) XSingleServiceFactory xElementFactory = (XSingleServiceFactory)UnoRuntime.queryInterface( XSingleServiceFactory.class, xSetUpdate); // the new element is the result ! xDataSourceDescriptor = xElementFactory.createInstance(); // insert it - this also names the element xSetUpdate.insertByName( sDataSourceName , xDataSourceDescriptor ); } return xDataSourceDescriptor ; }
A method is required to recover the view root from an element object, because it is unknown if the item is the root of the view or a descendant :
// This method get the view root node given an interface to any node in the view public static Object getViewRoot(Object xElement) { Object xResult = xElement; // set the result to its parent until that would be null Object xParent; do { XChild xParentAccess = (XChild) UnoRuntime.queryInterface(XChild.class,xResult); if (xParentAccess != null) xParent = xParentAccess.getParent(); else xParent = null; if (xParent != null) xResult = xParent; } while (xParent != null); return xResult; }
Another function used is storeDataSource
is storeSettings
to store an array of com.sun.star.beans.NamedValues in a set of DataSourceSetting
items. A DataSourceSetting
contains a single property named Value
that is set to any of the basic types supported for configuration values. This example demonstrates the two steps required to add a new item to a set node:
/// this method stores a number of settings in a set node containing DataSourceSetting objects void storeSettings(Object xSettingsSet, com.sun.star.beans.NamedValue [] aSettings) throws com.sun.star.uno.Exception { if (aSettings == null) return; // get the settings set as a container XNameContainer xSettingsContainer = (XNameContainer) UnoRuntime.queryInterface( XNameContainer.class, xSettingsSet); // and get a factory interface for creating the entries XSingleServiceFactory xSettingsFactory = (XSingleServiceFactory) UnoRuntime.queryInterface(XSingleServiceFactory.class, xSettingsSet); // now insert the individual settings for (int i = 0; i < aSettings.length; ++i) { // create a DataSourceSetting object XPropertySet xSetting = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, xSettingsFactory.createInstance()); // can set the value before inserting xSetting.setPropertyValue("Value", aSettings[i].Value); // and now insert or replace as appropriate if (xSettingsContainer.hasByName(aSettings[i].Name)) xSettingsContainer.replaceByName(aSettings[i].Name, xSetting); else xSettingsContainer.insertByName(aSettings[i].Name, xSetting); } }
Besides adding a freshly created instance of a template, a set item can be removed from a set and added to any other set supporting the same template for its elements, provided both sets are part of the same view. You cannot move a set item between views, as this contradicts the transactional isolation of views. The set item you removed in one view will still be in its old place in the other. If a set item is moved between sets in one view and the changes are committed, the change appears in another overlapping view as removal of the original item and insertion of a new element in the target location, not as relocation of an identical element.
Content on this page is licensed under the Public Documentation License (PDL). |