Difference between revisions of "Documentation/DevGuide/Config/Updating Configuration Data"
(2 intermediate revisions by one other user not shown) | |||
Line 15: | Line 15: | ||
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 <idl>com.sun.star.util.XChangesBatch</idl> that is implemented by the root element of an updatable configuration view. | 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 <idl>com.sun.star.util.XChangesBatch</idl> that is implemented by the root element of an updatable configuration view. | ||
− | {{ | + | {{Warn|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 <idl>com.sun.star.configuration.ConfigurationProvider</idl> a high degree of transactional behavior is achieved. |
The configuration management component does not guarantee true transactional behavior. Committing the changes to the <idl>com.sun.star.configuration.ConfigurationProvider</idl> 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 <idl>com.sun.star.configuration.ConfigurationProvider</idl> may cache and combine requests, so that updates are propagated to the data store at a later time. | The configuration management component does not guarantee true transactional behavior. Committing the changes to the <idl>com.sun.star.configuration.ConfigurationProvider</idl> 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 <idl>com.sun.star.configuration.ConfigurationProvider</idl> may cache and combine requests, so that updates are propagated to the data store at a later time. | ||
Line 26: | Line 26: | ||
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: | ||
− | + | <syntaxhighlight 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 74: | Line 74: | ||
((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose(); | ((XComponent)UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose(); | ||
} | } | ||
− | + | </syntaxhighlight> | |
− | 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, <idlm>com.sun.star.util.XChangesListener:changesOccurred</idlm>() is sent to the listener supplied by the dialog which can then update its display accordingly. |
− | 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 <idlm>com.sun.star.beans.XPropertySetInfo:getPropertyByName</idlm>() or <idlm>com.sun.star.beans.XPropertySetInfo:getProperties</idlm>() 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 {{ | + | The following is an example code using this feature to reset the {{AOo}} Calc grid settings used in the preceding examples to their default state: |
− | + | <syntaxhighlight 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 133: | Line 133: | ||
} | } | ||
− | + | </syntaxhighlight> | |
− | {{Note|Currently, group nodes do not support the attribute < | + | {{Note|Currently, group nodes do not support the attribute <idlm>com.sun.star.beans.PropertyAttribute:MAYBEDEFAULT</idlm> set in the <idl>com.sun.star.beans.Property</idl> structure available from <idl>com.sun.star.beans.XPropertySetInfo</idl>. Attempts to use <idlm>com.sun.star.beans.XPropertyState:setPropertyToDefault</idlm> to reset an entire group node fail. |
− | Also, because the group nodes can not be reset, the < | + | Also, because the group nodes can not be reset, the <idlm>com.sun.star.beans.XPropertyState:setPropertyToDefault</idlm> or <idlm>com.sun.star.beans.XMultiPropertyStates:setAllPropertiesToDefault</idlm> 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 < | + | 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 <idlm>com.sun.star.beans.XPropertyState:setPropertyToDefault</idlm> only to actual properties, such as value items, or set nodes. In particular, you should avoid <idlm>com.sun.star.beans.XMultiPropertyStates:setAllPropertiesToDefault</idlm>() on group nodes.}} |
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. | ||
− | This example uses the {{ | + | This example uses the {{AOo}} configuration module <code>org.openoffice.Office.DataAccess</code>. This component has a set item <code>DataSources</code> that contains group items described by the template <code>DataSourceDescription</code>. A data source description holds information about the settings required to connect to a data source. |
The template <code>org.openoffice.Office.DataAccess/DataSourceDescription</code> has the following properties that describe the data source connection: | The template <code>org.openoffice.Office.DataAccess/DataSourceDescription</code> has the following properties that describe the data source connection: | ||
Line 191: | Line 191: | ||
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 <idlm>com.sun.star.util.XChangesBatch:commitChanges</idlm> 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. |
− | {{ | + | {{Warn|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.}} |
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 <code>DataSourceSettings</code> 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 <code>DataSourceSettings</code> set. | ||
Line 199: | Line 199: | ||
The resulting routine is: | The resulting routine is: | ||
<!--[SOURCE:Config/ConfigExamples.java]--> | <!--[SOURCE:Config/ConfigExamples.java]--> | ||
− | + | <syntaxhighlight 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 247: | Line 247: | ||
((XComponent) UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose(); | ((XComponent) UnoRuntime.queryInterface(XComponent.class, xViewRoot)).dispose(); | ||
} | } | ||
− | </ | + | </syntaxhighlight> |
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. | ||
<!--[SOURCE:Config/ConfigExamples.java]--> | <!--[SOURCE:Config/ConfigExamples.java]--> | ||
− | + | <syntaxhighlight 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 336: | Line 336: | ||
return xDataSourceDescriptor ; | return xDataSourceDescriptor ; | ||
} | } | ||
− | </ | + | </syntaxhighlight> |
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:Config/ConfigExamples.java]--> | ||
− | + | <syntaxhighlight 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 362: | Line 362: | ||
return xResult; | return xResult; | ||
} | } | ||
− | </ | + | </syntaxhighlight> |
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]--> | ||
− | + | <syntaxhighlight 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 397: | Line 397: | ||
} | } | ||
} | } | ||
− | </ | + | </syntaxhighlight> |
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. | ||
− | {{ | + | {{Tip|The methods <idlm>com.sun.star.container.XNamed:setName</idlm>() and <idlm>com.sun.star.container.XChild:setParent</idlm>() 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 {{ | + | In the current release of {{AOo}}, these methods are not supported correctly. You can achieve the same effect by using a sequence of remove item - insert item. |
In some cases you need to commit the changes in the current view between these two steps. | In some cases you need to commit the changes in the current view between these two steps. | ||
Line 408: | Line 408: | ||
To rename an item: | To rename an item: | ||
<!--[SOURCE:Config/ConfigExamples.java]--> | <!--[SOURCE:Config/ConfigExamples.java]--> | ||
− | + | <syntaxhighlight lang="java"> | |
− | + | /// Does the same as xNamedItem.setName(sNewName) should do | |
void renameSetItem(XNamed xNamedItem, String sNewName) throws com.sun.star.uno.Exception { | void renameSetItem(XNamed xNamedItem, String sNewName) throws com.sun.star.uno.Exception { | ||
XChild xChildItem = (XChild) | XChild xChildItem = (XChild) | ||
Line 424: | Line 424: | ||
getViewRoot(xParentSet).commitChanges(); | getViewRoot(xParentSet).commitChanges(); | ||
xParentSet.insertByName(sNewName,xNamedItem); | xParentSet.insertByName(sNewName,xNamedItem); | ||
− | }</ | + | }</syntaxhighlight> |
To move an item to a different parent: | To move an item to a different parent: | ||
<!--[SOURCE:Config/ConfigExamples.java]--> | <!--[SOURCE:Config/ConfigExamples.java]--> | ||
− | + | <syntaxhighlight lang="java"> | |
− | + | /// Does the same as xChildItem.setParent( xNewParent ) should do | |
void moveSetItem(XChild xChildItem, XNameContainer xNewParent) throws com.sun.star.uno.Exception { | void moveSetItem(XChild xChildItem, XNameContainer xNewParent) throws com.sun.star.uno.Exception { | ||
XNamed xNamedItem = (XNamed) | XNamed xNamedItem = (XNamed) | ||
Line 444: | Line 444: | ||
getViewRoot(xOldParent).commitChanges(); | getViewRoot(xOldParent).commitChanges(); | ||
xNewParent.insertByName(sItemName,xChildItem); | xNewParent.insertByName(sItemName,xChildItem); | ||
− | } </ | + | }</syntaxhighlight> |
}} | }} | ||
Latest revision as of 17:11, 21 December 2020
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. 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. 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 view Object xViewRoot = createUpdatableView(cGridOptionsPath); // 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, changesOccurred() is sent to the listener supplied by the dialog which can then update its display accordingly.
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 getPropertyByName() or getProperties() 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 Apache OpenOffice 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(); }
Currently, group nodes do not support the attribute MAYBEDEFAULT set in the com.sun.star.beans.Property structure available from com.sun.star.beans.XPropertySetInfo. Attempts to use setPropertyToDefault to reset an entire group node fail.
Also, because the group nodes can not be reset, the setPropertyToDefault or setAllPropertiesToDefault 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 setPropertyToDefault only to actual properties, such as value items, or set nodes. In particular, you should avoid setAllPropertiesToDefault() on group nodes. |
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 Apache OpenOffice 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 commitChanges 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.
/** This method gets the DataSourceDescription for a data source. It either gets the existing entry or creates a new instance. */ 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 ; Object[] aArguments = new Object[1]; aArguments[0] = aPathArgument; // create the view 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 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 Object[] aDeepArguments = new Object[1]; aDeepArguments[0] = aPathArgument; // create the view 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.err.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.
The methods setName() and setParent() are supported by a com.sun.star.configuration.ConfigurationUpdateAccess only if it is a com.sun.star.configuration.SetElement. They offer another way to move an item within a set or from one set to another set.
In the current release of Apache OpenOffice, these methods are not supported correctly. You can achieve the same effect by using a sequence of remove item - insert item. In some cases you need to commit the changes in the current view between these two steps. To rename an item: /// Does the same as xNamedItem.setName(sNewName) should do void renameSetItem(XNamed xNamedItem, String sNewName) throws com.sun.star.uno.Exception { XChild xChildItem = (XChild) UnoRuntime.queryInterface(XChild.class, xNamedItem); XNameContainer xParentSet = (XNameContainer) UnoRuntime.queryInterface(XNameContainer.class, xChildItem.getParent()); String sOldName = xNamedItem.getName(); // now rename the item xParentSet.removeByName(sOldName); // commit needed to work around known bug getViewRoot(xParentSet).commitChanges(); xParentSet.insertByName(sNewName,xNamedItem); } To move an item to a different parent: /// Does the same as xChildItem.setParent( xNewParent ) should do void moveSetItem(XChild xChildItem, XNameContainer xNewParent) throws com.sun.star.uno.Exception { XNamed xNamedItem = (XNamed) UnoRuntime.queryInterface(XNamed.class, xChildItem); XNameContainer xOldParent = (XNameContainer) UnoRuntime.queryInterface(XNameContainer.class, xChildItem.getParent()); String sItemName = xNamedItem.getName(); // now rename the item xOldParent.removeByName(sItemName); // commit needed to work around known bug getViewRoot(xOldParent).commitChanges(); xNewParent.insertByName(sItemName,xChildItem); } |
Content on this page is licensed under the Public Documentation License (PDL). |