1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: updatedispatch.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
34 #include "treefragment.hxx"
35 #include "updatedispatch.hxx"
36 #include "configpath.hxx"
38 #include "matchlocale.hxx"
40 #include <com/sun/star/configuration/backend/XUpdateHandler.hpp>
41 #include <com/sun/star/configuration/backend/NodeAttribute.hpp>
45 // -----------------------------------------------------------------------------
48 // -----------------------------------------------------------------------------
50 UpdateDispatcher::UpdateDispatcher(uno::Reference
< backenduno::XUpdateHandler
> const & _xUpdateHandler
, rtl::OUString
const & _aLocale
)
51 : m_pContextPath(NULL
)
52 , m_xUpdateHandler(_xUpdateHandler
)
55 , m_bInValueSet(false)
56 , m_bInLocalizedValues(false)
59 // -----------------------------------------------------------------------------
61 UpdateDispatcher::~UpdateDispatcher()
64 // -----------------------------------------------------------------------------
66 void UpdateDispatcher::dispatchUpdate(configuration::AbsolutePath
const & _aRootPath
, SubtreeChange
const& _anUpdate
)
68 if (!m_xUpdateHandler
.is())
70 rtl::OUString
sMsg( RTL_CONSTASCII_USTRINGPARAM("ERROR: Cannot dispatch update - no handler found") );
71 throw uno::RuntimeException(sMsg
,NULL
);
74 OSL_PRECOND( !_aRootPath
.isRoot(), "Cannot apply update, where root is outside a component" );
76 OSL_PRECOND( m_pContextPath
== NULL
, "Update Dispatcher already has a context path" );
77 if (!_aRootPath
.getParentPath().isRoot())
79 OSL_ENSURE(false,"Obsolete functionality used: starting update with non-empty context");
80 m_pContextPath
= &_aRootPath
;
84 this->applyToChange(_anUpdate
);
87 m_pContextPath
= NULL
;
89 // -----------------------------------------------------------------------------
91 void UpdateDispatcher::startUpdate()
93 m_xUpdateHandler
->startUpdate();
94 m_bInValueSet
= false;
95 m_bInLocalizedValues
= false;
96 m_aElementName
= rtl::OUString();
100 std::vector
<configuration::Path::Component
>::const_reverse_iterator it
= m_pContextPath
->begin();
101 std::vector
<configuration::Path::Component
>::const_reverse_iterator stop
= m_pContextPath
->end();
103 OSL_ASSERT(it
!= stop
);
106 for ( ; it
!= stop
; ++it
)
108 m_xUpdateHandler
->modifyNode(it
->getName(),0,0,false);
112 // -----------------------------------------------------------------------------
114 void UpdateDispatcher::endUpdate()
118 std::vector
<configuration::Path::Component
>::const_reverse_iterator it
= m_pContextPath
->begin();
119 std::vector
<configuration::Path::Component
>::const_reverse_iterator stop
= m_pContextPath
->end();
121 OSL_ASSERT(it
!= stop
);
124 for ( ; it
!= stop
; ++it
)
126 m_xUpdateHandler
->endNode();
129 m_xUpdateHandler
->endUpdate();
131 // -----------------------------------------------------------------------------
133 void UpdateDispatcher::handle(ValueChange
const& aValueNode
)
135 // special case: doing members of a localized property (as set)
136 if (m_bInLocalizedValues
)
138 rtl::OUString aLocale
= aValueNode
.getNodeName();
140 if (aLocale
.getLength())
142 if ( aValueNode
.isToDefault() )
143 m_xUpdateHandler
->resetPropertyValueForLocale( aLocale
);
145 m_xUpdateHandler
->setPropertyValueForLocale( aValueNode
.getNewValue(), aLocale
);
149 if ( aValueNode
.isToDefault() )
150 m_xUpdateHandler
->resetPropertyValue( );
152 m_xUpdateHandler
->setPropertyValue( aValueNode
.getNewValue() );
157 // normal case: updating a single property
158 switch (aValueNode
.getMode())
160 case ValueChange::wasDefault
:
161 if (aValueNode
.isReplacedValue())
164 OSL_ENSURE(m_bInValueSet
, "UpdateDispatcher: Cannot add/replace a value in a nonextensible node");
165 OSL_ENSURE(!aValueNode
.isLocalizedValue(), "UpdateDispatcher: Cannot add a localized value in a layer");
167 sal_Int16 nAttr
= getUpdateAttributes(aValueNode
.getAttributes(),true);
169 if (aValueNode
.getNewValue().hasValue())
171 m_xUpdateHandler
->addOrReplacePropertyWithValue( aValueNode
.getNodeName(),
173 aValueNode
.getNewValue());
177 m_xUpdateHandler
->addOrReplaceProperty( aValueNode
.getNodeName(),
179 aValueNode
.getValueType());
184 // else fall thru to changeValue case
186 case ValueChange::changeValue
:
188 sal_Int16 nAttr
= getUpdateAttributes(aValueNode
.getAttributes(),false);
189 sal_Int16 nAttrMask
= getUpdateAttributeMask(aValueNode
.getAttributes());
191 m_xUpdateHandler
->modifyProperty( aValueNode
.getNodeName(),
193 aValueNode
.getValueType() );
195 if (aValueNode
.isLocalizedValue() && m_aLocale
.getLength())
197 m_xUpdateHandler
->setPropertyValueForLocale( aValueNode
.getNewValue(), m_aLocale
);
201 m_xUpdateHandler
->setPropertyValue( aValueNode
.getNewValue() );
204 m_xUpdateHandler
->endProperty();
208 case ValueChange::setToDefault
:
209 m_xUpdateHandler
->resetProperty( aValueNode
.getNodeName() );
212 case ValueChange::changeDefault
:
213 OSL_ENSURE(false, "Illegal mode in ValueChange");
217 OSL_ENSURE(false, "Illegal mode in ValueChange");
221 // -----------------------------------------------------------------------------
223 void UpdateDispatcher::handle(AddNode
const& aAddNode
)
225 rtl::Reference
< data::TreeSegment
> aAddedTree
= aAddNode
.getNewTree();
227 OSL_ENSURE(aAddedTree
.is(), "AddNode has no new data -> cannot add anything");
229 OSL_ENSURE( ((m_bInValueSet
||m_bInLocalizedValues
) == aAddedTree
->fragment
->nodes
[0].isValue()),
230 "Found added subtree in value set (extensible group)\n" );
232 this->visitTree(aAddedTree
->fragment
);
234 // -----------------------------------------------------------------------------
236 void UpdateDispatcher::handle(RemoveNode
const& aRemoveNode
)
238 OSL_ENSURE( !m_bInLocalizedValues
, "UpdateDispatcher: Removing values for a specific locale is currently not supported");
240 rtl::Reference
< data::TreeSegment
> aRemovedTree
= aRemoveNode
.getRemovedTree();
242 OSL_ENSURE( !aRemovedTree
.is() ||
243 ((m_bInValueSet
||m_bInLocalizedValues
) == aRemovedTree
->fragment
->nodes
[0].isValue()),
244 "Found removed subtree in value set (extensible group)\n" );
246 if (m_bInLocalizedValues
)
247 OSL_TRACE("configmgr: UpdateDispatcher - Removing value for locale ignored");
249 else if (m_bInValueSet
)
250 m_xUpdateHandler
->removeProperty( aRemoveNode
.getNodeName() );
253 m_xUpdateHandler
->removeNode( aRemoveNode
.getNodeName() );
255 // -----------------------------------------------------------------------------
257 void UpdateDispatcher::handle(SubtreeChange
const& aSubtree
)
259 OSL_ENSURE( !m_bInLocalizedValues
, "UpdateDispatcher: A localized value cannot be a complete subtree");
260 OSL_ENSURE( !m_bInValueSet
, "UpdateDispatcher: A dynamic property cannot be a complete subtree");
262 sal_Int16 nAttr
= getUpdateAttributes(aSubtree
.getAttributes(),false);
263 sal_Int16 nAttrMask
= getUpdateAttributeMask(aSubtree
.getAttributes());
265 if (isLocalizedValueSet(aSubtree
))
267 m_xUpdateHandler
->modifyProperty( aSubtree
.getNodeName(),
271 m_bInLocalizedValues
= true;
272 this->applyToChildren(aSubtree
);
273 m_bInLocalizedValues
= false;
275 m_xUpdateHandler
->endProperty();
280 m_xUpdateHandler
->modifyNode( aSubtree
.getNodeName(),
282 aSubtree
.isToDefault() );
284 m_bInValueSet
= isValueSet(aSubtree
);
285 this->applyToChildren(aSubtree
);
286 m_bInValueSet
= false;
288 m_xUpdateHandler
->endNode();
291 // -----------------------------------------------------------------------------
293 bool UpdateDispatcher::handle(sharable::ValueNode
* node
)
297 // special case: doing members of a localized property (as set)
298 if (m_bInLocalizedValues
)
300 // the node name is the locale
301 rtl::OUString aLocale
;
302 OSL_VERIFY(testReplacedAndGetName(sharable::node(node
), aLocale
)); // "Adding a localized subvalue but not as root of element tree"
304 if (aLocale
.getLength() && ! localehelper::isDefaultLanguage(aLocale
))
306 m_xUpdateHandler
->setPropertyValueForLocale(node
->getValue(), aLocale
);
310 m_xUpdateHandler
->setPropertyValue(node
->getValue());
313 else if (testReplacedAndGetName(sharable::node(node
), aName
) && sharable::node(node
)->getAttributes().isRemovable()) // we must be inside a set of values
316 OSL_ENSURE(!node
->info
.isLocalized(), "UpdateDispatcher: Cannot add a localized value in a layer .");
318 sal_Int16 nAttr
= getUpdateAttributes(sharable::node(node
)->getAttributes(),true);
322 m_xUpdateHandler
->addOrReplacePropertyWithValue( aName
,
328 m_xUpdateHandler
->addOrReplaceProperty( aName
,
330 node
->getValueType());
333 else // normal case: updating a single property //Inserting set
335 sal_Int16 nAttr
= getUpdateAttributes(sharable::node(node
)->getAttributes(),false);
336 sal_Int16 nAttrMask
= getUpdateAttributeMask(sharable::node(node
)->getAttributes());
338 m_xUpdateHandler
->modifyProperty( aName
, nAttr
, nAttrMask
, node
->getValueType() );
340 if (node
->info
.isLocalized() && m_aLocale
.getLength())
342 m_xUpdateHandler
->setPropertyValueForLocale(node
->getValue(), m_aLocale
);
346 m_xUpdateHandler
->setPropertyValue(node
->getValue());
349 m_xUpdateHandler
->endProperty();
353 // -----------------------------------------------------------------------------
355 bool UpdateDispatcher::handle(sharable::GroupNode
* node
)
357 OSL_ENSURE( !m_bInLocalizedValues
, "UpdateDispatcher: A localized value cannot be a complete group");
361 if ( testReplacedAndGetName(sharable::node(node
), aName
) )
363 sal_Int16 nAttr
= getUpdateAttributes(sharable::node(node
)->getAttributes(),true);
365 m_xUpdateHandler
->addOrReplaceNode( aName
, nAttr
);
367 this->visitChildren(node
);
369 m_xUpdateHandler
->endNode();
373 sal_Int16 nAttr
= getUpdateAttributes(sharable::node(node
)->getAttributes(),false);
374 sal_Int16 nAttrMask
= getUpdateAttributeMask(sharable::node(node
)->getAttributes());
376 m_xUpdateHandler
->modifyNode( aName
, nAttr
, nAttrMask
, false );
378 this->visitChildren(node
);
380 m_xUpdateHandler
->endNode();
384 // -----------------------------------------------------------------------------
386 bool UpdateDispatcher::handle(sharable::SetNode
* node
)
388 OSL_ENSURE( !m_bInLocalizedValues
, "UpdateDispatcher: A localized value cannot be a complete set");
392 if ( testReplacedAndGetName(sharable::node(node
), aName
) )
394 OSL_ENSURE( !node
->info
.isLocalized(), "UpdateDispatcher: Cannot add a localized value in a layer." );
396 sal_Int16 nAttr
= getUpdateAttributes(sharable::node(node
)->getAttributes(),true);
398 m_xUpdateHandler
->addOrReplaceNode( aName
, nAttr
);
400 this->visitElements(node
);
402 m_xUpdateHandler
->endNode();
406 sal_Int16 nAttr
= getUpdateAttributes(sharable::node(node
)->getAttributes(),false);
407 sal_Int16 nAttrMask
= getUpdateAttributeMask(sharable::node(node
)->getAttributes());
409 if (node
->info
.isLocalized())
411 m_xUpdateHandler
->modifyProperty( aName
, nAttr
, nAttrMask
, uno::Type() );
413 m_bInLocalizedValues
= true;
414 this->visitElements(node
);
415 m_bInLocalizedValues
= false;
417 m_xUpdateHandler
->endProperty();
422 m_xUpdateHandler
->modifyNode( aName
, nAttr
, nAttrMask
, false );
424 this->visitElements(node
);
426 m_xUpdateHandler
->endNode();
431 // -----------------------------------------------------------------------------
433 bool UpdateDispatcher::testReplacedAndGetName(sharable::Node
* node
, rtl::OUString
& _aName
)
435 if (m_aElementName
.getLength())
437 OSL_ENSURE( node
->isFragmentRoot(), "ERROR - UpdateDispatcher: Found orphaned 'element' name for inner node");
438 _aName
= m_aElementName
;
439 m_aElementName
= rtl::OUString();
444 OSL_ENSURE(!node
->isFragmentRoot(), "ERROR - UpdateDispatcher: Found no 'element' name for fragment root node");
445 _aName
= node
->getName();
449 // -----------------------------------------------------------------------------
451 bool UpdateDispatcher::handle(sharable::TreeFragment
* tree
)
453 m_aElementName
= tree
->getName();
454 bool done
= SetVisitor::handle(tree
); // dispatch to root node
455 m_aElementName
= rtl::OUString(); // clear - just to be safe
458 // -----------------------------------------------------------------------------
460 sal_Int16
UpdateDispatcher::getUpdateAttributes(node::Attributes
const & _aAttributes
, bool bAdded
)
462 namespace NodeAttribute
= backenduno::NodeAttribute
;
464 // no support for post-creation attribute changes yet
467 OSL_ENSURE( getUpdateAttributeMask(_aAttributes
) == 0,
468 "Incomplete support for attribute changes" );
472 sal_Int16 nResult
= 0;
474 if (_aAttributes
.isReadonly())
475 nResult
= NodeAttribute::READONLY
;
477 if (_aAttributes
.isFinalized())
478 nResult
|= NodeAttribute::FINALIZED
;
480 if (!_aAttributes
.isNullable())
481 nResult
|= NodeAttribute::MANDATORY
;
485 // -----------------------------------------------------------------------------
487 sal_Int16
UpdateDispatcher::getUpdateAttributeMask(node::Attributes
const & /*_aAttributes*/)
489 // no support for post-creation attribute changes yet
492 // -----------------------------------------------------------------------------
494 // -----------------------------------------------------------------------------
495 // -----------------------------------------------------------------------------
496 } // namespace backend
498 // -------------------------------------------------------------------------
499 } // namespace configmgr