merge the formfield patch from ooo-build
[ooovba.git] / configmgr / source / backend / layermerge.cxx
blob05c11577ea12d79972671d68d929838eb3492ffb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: layermerge.cxx,v $
10 * $Revision: 1.28 $
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 "layermerge.hxx"
35 #include "treenodefactory.hxx"
36 #include "matchlocale.hxx"
37 #include "valuetypeconverter.hxx"
38 #include "typeconverter.hxx"
39 #include <com/sun/star/configuration/backend/SchemaAttribute.hpp>
40 #include <com/sun/star/configuration/backend/NodeAttribute.hpp>
42 #include <rtl/ustrbuf.hxx>
44 namespace configmgr
46 // -----------------------------------------------------------------------------
47 namespace backend
49 // -----------------------------------------------------------------------------
51 namespace SchemaAttribute = backenduno::SchemaAttribute;
52 namespace NodeAttribute = backenduno::NodeAttribute;
53 // -----------------------------------------------------------------------------
54 // -----------------------------------------------------------------------------
55 // -----------------------------------------------------------------------------
56 //#if OSL_DEBUG_LEVEL > 0
57 // currently not used in debug builds
58 #if 0
59 static void check_if_complete(uno::Reference< uno::XComponentContext > const & _xContext)
61 MergedComponentData aData;
63 uno::Reference< backenduno::XLayerHandler >
64 test(new LayerMergeHandler(_xContext, aData));
66 #endif
68 // -----------------------------------------------------------------------------
70 struct LayerMergeHandler::Converter
72 explicit
73 Converter(uno::Reference< uno::XComponentContext > const & xContext);
75 uno::Any convertValue(uno::Type const & _aTargetType, uno::Any const & _aValue);
77 static uno::Reference< com::sun::star::script::XTypeConverter > createTCV(uno::Reference< uno::XComponentContext > const & xContext);
79 ValueConverter m_aConverter;
80 bool m_bConvertData;
82 // -----------------------------------------------------------------------------
83 LayerMergeHandler::LayerMergeHandler(uno::Reference< uno::XComponentContext > const & xContext, MergedComponentData & _rData, ITemplateDataProvider* aTemplateProvider )
84 : m_rData(_rData)
85 //, m_aContext(xContext,static_cast<backenduno::XLayerHandler*>(this),aTemplateProvider )
86 , m_aContext(xContext)
87 , m_aFactory()
88 , m_aLocale()
89 , m_pProperty(NULL)
90 , m_pConverter( new Converter(xContext) )
91 , m_nSkipping(0)
92 , m_bSublayer(false)
94 m_aContext = DataBuilderContext(xContext,static_cast<backenduno::XLayerHandler*>(this),aTemplateProvider );
95 OSL_ENSURE( m_rData.hasSchema(), "Creating layer merger without default data" );
97 // -----------------------------------------------------------------------------
99 LayerMergeHandler::~LayerMergeHandler( )
101 delete m_pConverter;
103 // -----------------------------------------------------------------------------
105 void LayerMergeHandler::prepareLayer()
107 OSL_ENSURE(isDone(), "LayerMergeHandler: Warning: Previous layer or schema not terminated properly");
108 if (!isDone())
109 m_aContext.getLogger().error("Previous layer or schema not terminated properly", "prepareLayer()", "configmgr::LayerMergeHandler");
111 m_aLocale = localehelper:: getDefaultLanguage();
112 m_bSublayer = false;
114 promoteToDefault(m_rData);
116 // -----------------------------------------------------------------------------
118 bool LayerMergeHandler::prepareSublayer(rtl::OUString const & aLocale)
120 OSL_ENSURE(isDone(), "LayerMergeHandler: Warning: Previous layer not terminated properly");
121 if (!isDone())
122 m_aContext.getLogger().error("Previous layer not terminated properly", "prepareSublayer()", "configmgr::LayerMergeHandler");
124 m_aLocale = aLocale;
125 m_bSublayer = (aLocale.getLength() != 0);
127 return m_bSublayer;
129 // -----------------------------------------------------------------------------
131 namespace
133 struct CheckRestrictedAccessVisitor : NodeAction
135 node::Access m_access;
137 CheckRestrictedAccessVisitor(node::Access _access) : m_access(_access) {}
139 void handle(ValueNode const & _aNode) { check(_aNode); }
141 void handle(ISubtree const & _aNode)
143 node::Access aNext = check(_aNode);
144 CheckRestrictedAccessVisitor(aNext).applyToChildren(_aNode);
147 node::Access check(INode const & _aNode)
149 node::Attributes const aFoundAttr = _aNode.getAttributes();
150 node::Access const aFoundAccess = aFoundAttr.getAccess();
151 OSL_ENSURE(m_access <= aFoundAccess, "Subnode has more access than its parent");
153 return aFoundAccess;
156 // --------------------
157 struct RestrictAccessVisitor : NodeModification
159 node::Access m_access;
161 RestrictAccessVisitor(bool _bFinalize)
162 : m_access(_bFinalize ? node::accessFinal : node::accessReadonly)
165 void handle(ValueNode & _aNode) { restrict(_aNode); }
167 void handle(ISubtree & _aNode)
169 if (restrict(_aNode))
170 this->applyToChildren(_aNode);
171 else
172 OSL_DEBUG_ONLY(CheckRestrictedAccessVisitor(m_access).applyToNode(_aNode));
175 bool restrict(INode & _aNode)
177 node::Attributes const aFoundAttr = _aNode.getAttributes();
179 if (aFoundAttr.getAccess() >= m_access) return false; // already restricted enough
181 _aNode.modifyAccess(m_access);
182 return true;
186 // -----------------------------------------------------------------------------
187 void LayerMergeHandler::propagateAttributes(ISubtree & _rParent)
189 node::Attributes aAttributes = _rParent.getAttributes();
191 if (aAttributes.isReadonly() || aAttributes.isFinalized())
192 RestrictAccessVisitor(aAttributes.isWritable()).applyToChildren(_rParent);
194 // -----------------------------------------------------------------------------
196 node::Attributes LayerMergeHandler::makePropertyAttributes(sal_Int16 aSchemaAttributes)
197 SAL_THROW((com::sun::star::configuration::backend::MalformedDataException , com::sun::star::uno::RuntimeException))
199 const sal_uInt16 k_allPropertySchemaAttributes =
200 SchemaAttribute::REQUIRED;
202 if ((aSchemaAttributes & k_allPropertySchemaAttributes) !=
203 (aSchemaAttributes & SchemaAttribute::MASK))
205 sal_Char const * pMsg = (aSchemaAttributes & SchemaAttribute::LOCALIZED) ?
206 "Layer merging: Cannot add localized property to extensible node" :
207 "Layer merging: Unreckognized Schema Attribute for new Property" ;
209 m_aContext.raiseIllegalArgumentException(pMsg,2);
211 OSL_ASSERT( !(aSchemaAttributes & SchemaAttribute::LOCALIZED) ); // check the check
213 node::Attributes aAttributes = m_aContext.getCurrentAttributes();
215 if (aSchemaAttributes & SchemaAttribute::REQUIRED)
216 aAttributes.setNullable (false);
218 //Set state, removable and mandatory attribute flags
219 aAttributes.setState(node::isAdded);
220 aAttributes.setRemovability(true,true);
223 return aAttributes;
226 // -----------------------------------------------------------------------------
228 void LayerMergeHandler::checkPropertyType(uno::Type const & _aType)
229 SAL_THROW((com::sun::star::configuration::backend::MalformedDataException , com::sun::star::uno::RuntimeException))
231 OSL_ASSERT(m_pProperty);
233 if (ValueNode * pValue = m_pProperty->asValueNode())
235 if (pValue->getValueType() != _aType)
237 if (pValue->getValueType().getTypeClass() == uno::TypeClass_ANY)
239 OSL_ENSURE( pValue->isNull(), "Layer merging: Non-null 'any' value" );
241 if (_aType != uno::Type())
242 OSL_VERIFY( pValue->setValueType(_aType) );
244 else
246 OSL_TRACE("Layer merging: Illegal property type: VOID overriding ANY");
247 m_aContext.getLogger().warning("Illegal property type: VOID overriding ANY - ignoring",
248 "checkPropertyType()", "configmgr::LayerMergeHandler");
249 // m_aContext.raiseIllegalTypeException("Layer merging: Illegal property type: VOID overriding ANY");
252 else if (_aType == uno::Type() && m_pConverter)
253 m_pConverter->m_bConvertData = true;
255 else
256 m_aContext.raiseIllegalTypeException("Layer merging: Cannot merge property value: types does not match");
259 else if (ISubtree *localisedSet = m_pProperty->asISubtree()) {
260 // We're dealing with localised data.
261 uno::Type valueType = parseTemplateName(
262 localisedSet->getElementTemplateName()) ;
264 if (valueType != _aType) {
265 if (valueType.getTypeClass() == uno::TypeClass_ANY) {
266 if (_aType == uno::Type()) {
267 // VOID value
268 m_aContext.raiseIllegalTypeException(
269 "Layer merging: VOID value for localised ANY type") ;
271 // TODO Could we have to set the localised data type?
273 else if (_aType == uno::Type() && m_pConverter) {
274 m_pConverter->m_bConvertData = sal_True ;
276 else {
277 m_aContext.raiseIllegalTypeException("Layer merging: property value does not match localised type") ;
283 // -----------------------------------------------------------------------------
285 void LayerMergeHandler::setValueAndCheck(ValueNode& _rValueNode, uno::Any const & _aValue)
286 SAL_THROW((com::sun::star::configuration::backend::MalformedDataException , com::sun::star::uno::RuntimeException))
288 if (_aValue.hasValue() && m_pConverter && m_pConverter->m_bConvertData)
290 uno::Any aConvertedValue = m_pConverter->convertValue(_rValueNode.getValueType(),_aValue);
291 if (!aConvertedValue.hasValue())
292 m_aContext.raiseIllegalTypeException("Layer merging: Cannot merge property value: cannot convert data to type of property");
294 if (! _rValueNode.setValue(aConvertedValue) )
295 m_aContext.raiseIllegalTypeException("Layer merging: Cannot merge property value: converted type does not match");
297 else if (! _rValueNode.setValue(_aValue) )
299 m_aContext.raiseIllegalTypeException("Layer merging: Cannot merge property value: type does not match");
303 // -----------------------------------------------------------------------------
305 void LayerMergeHandler::setLocalizedValue(ISubtree * pProperty, uno::Any const & _aValue, rtl::OUString const & _aLocale)
306 SAL_THROW((com::sun::star::configuration::backend::MalformedDataException , com::sun::star::uno::RuntimeException))
308 if (ISubtree * pLocalizedCont = pProperty->asISubtree())
310 OSL_ENSURE(isLocalizedValueSet(*pLocalizedCont),"Layer merging: property node is not a value");
312 if (INode * pLocale = pLocalizedCont->getChild(_aLocale))
314 if (ValueNode * pLocValue = pLocale->asValueNode())
316 setValueAndCheck(*pLocValue,_aValue);
318 else
320 OSL_ENSURE(false,"Layer merging: Localized subnode is not a value");
321 m_aContext.getLogger().error("Localized subnode is not a value - ignoring data",
322 "setLocalizedValue()", "configmgr::LayerMergeHandler");
325 else {
326 node::Attributes attributes = pLocalizedCont->getAttributes() ;
327 uno::Type valueType = parseTemplateName(
328 pLocalizedCont->getElementTemplateName()) ;
330 attributes.setLocalized(false) ;
331 OSL_ENSURE(valueType != uno::Type(),
332 "Cannot determine type for localised value") ;
333 std::auto_ptr<ValueNode> localisedValue =
334 m_aFactory.getNodeFactory().createNullValueNode(_aLocale,
335 valueType,
336 attributes) ;
338 if (_aValue.hasValue()) {
339 setValueAndCheck(*localisedValue, _aValue) ;
341 pLocalizedCont->addChild(base_ptr(localisedValue)) ;
345 else if (ValueNode * pValue = pProperty->asValueNode())
347 OSL_ENSURE(false, "Layer merging: Got locale-dependent value for non-localized node");
348 m_aContext.getLogger().error("Got locale-dependent value for non-localized node",
349 "setLocalizedValue()", "configmgr::LayerMergeHandler");
350 setValueAndCheck(*pValue,_aValue);
353 else
355 OSL_ENSURE(false, "Layer merging: Unknown node type for localized node");
356 m_aContext.getLogger().error("Unknown node type for localized node",
357 "setLocalizedValue()", "configmgr::LayerMergeHandler");
360 // -----------------------------------------------------------------------------
362 void LayerMergeHandler::applyPropertyValue(uno::Any const & _aValue)
363 SAL_THROW((com::sun::star::configuration::backend::MalformedDataException , com::sun::star::uno::RuntimeException))
365 OSL_ASSERT(m_pProperty);
367 if (ValueNode * pValue = m_pProperty->asValueNode())
369 setValueAndCheck(*pValue,_aValue);
372 else if (ISubtree * pLocalizedCont = m_pProperty->asISubtree())
374 setLocalizedValue(pLocalizedCont,_aValue,m_aLocale);
377 else
379 OSL_ENSURE(false, "Layer merging: Unknown node type for property");
380 m_aContext.getLogger().error("Unknown node type for property",
381 "applyPropertyValue()", "configmgr::LayerMergeHandler");
384 // -----------------------------------------------------------------------------
386 void LayerMergeHandler::applyPropertyValue(uno::Any const & _aValue, rtl::OUString const & _aLocale)
387 SAL_THROW((com::sun::star::configuration::backend::MalformedDataException , com::sun::star::uno::RuntimeException))
389 OSL_ASSERT(m_pProperty);
391 if (_aLocale.getLength() == 0)
392 m_aContext.raiseIllegalArgumentException("Locale string is empty");
394 if (ISubtree * pLocalizedCont = m_pProperty->asISubtree())
396 setLocalizedValue(pLocalizedCont,_aValue, _aLocale);
399 else if (ValueNode * pValue = m_pProperty->asValueNode())
401 //OSL_ENSURE(false, "Layer merging: Got locale-dependent value for non localized node");
402 setValueAndCheck(*pValue,_aValue);
405 else
407 OSL_ENSURE(false, "Layer merging: Unknown node type for localized property");
408 m_aContext.getLogger().error("Unknown node type for localized property",
409 "applyPropertyValue()", "configmgr::LayerMergeHandler");
412 // -----------------------------------------------------------------------------
414 void LayerMergeHandler::applyAttributes(INode * pNode, sal_Int16 aNodeAttributes)
415 SAL_THROW((com::sun::star::configuration::backend::MalformedDataException , com::sun::star::uno::RuntimeException))
417 sal_Int16 const k_allNodeAttributes =
418 NodeAttribute::MANDATORY |
419 NodeAttribute::FINALIZED |
420 NodeAttribute::READONLY;
422 if ((aNodeAttributes & k_allNodeAttributes) !=
423 (aNodeAttributes & NodeAttribute::MASK))
425 sal_Char const * pMsg =
426 "Layer merging: Unreckognized Node Attribute" ;
428 m_aContext.raiseIllegalArgumentException(pMsg,2);
431 if (aNodeAttributes & NodeAttribute::READONLY)
433 OSL_ENSURE(!(aNodeAttributes & NodeAttribute::FINALIZED),
434 "Layer merging: Warning: Node is both read-only and finalized");
435 if (aNodeAttributes & NodeAttribute::FINALIZED)
436 m_aContext.getLogger().warning("Node is both read-only and finalized - treating as readonly",
437 "applyAttributes()", "configmgr::LayerMergeHandler");
439 pNode->modifyAccess(node::accessReadonly);
441 else if (aNodeAttributes & NodeAttribute::FINALIZED)
443 pNode->modifyAccess(node::accessFinal);
446 if ( m_aContext.isNode(pNode) )
448 if (aNodeAttributes & NodeAttribute::MANDATORY)
450 pNode->markMandatory();
453 else if (aNodeAttributes) // do this only if there actually was something to do
455 if (ISubtree * pLocCont = pNode->asISubtree())
457 OSL_ENSURE(isLocalizedValueSet(*pLocCont),"Layer merging: Property subtree must be a localized value set");
458 propagateAttributes(*pLocCont);
464 // -----------------------------------------------------------------------------
466 static
467 void doLogRejection(sal_Int16 loglevel, DataBuilderContext const & aContext,
468 INode * pNode, bool bMandatory)
470 rtl::OUStringBuffer aMessage;
471 aMessage.appendAscii("Rejecting override: Node/Property ")
472 .append(aContext.getNodePath(pNode->getName()))
473 .appendAscii(" is ").appendAscii(bMandatory ? "mandatory" : "finalized")
474 .appendAscii(" in a prior layer.");
476 aContext.getLogger().log(loglevel,aMessage.makeStringAndClear(),
477 bMandatory ? "addOrReplace/dropNode()" : "startOverride()",
478 "configmgr::LayerMergeHandler");
481 static inline
482 void logRejection(DataBuilderContext const & aContext, INode * pNode, bool bMandatory=false)
484 const sal_Int16 loglevel = LogLevel::INFO;
485 if (aContext.getLogger().isLogging(loglevel))
487 doLogRejection(loglevel, aContext, pNode, bMandatory);
490 // -----------------------------------------------------------------------------
492 bool LayerMergeHandler::startOverride(INode * pNode, sal_Bool bClear) /* ensure writable, mark merged */
493 SAL_THROW(())
495 OSL_PRECOND(pNode,"startOverride: non-NULL base node required");
496 if (!m_aContext.isWritable(pNode))
498 // #i41700# write-protection is enforced, unless merging localizations
499 if (!m_bSublayer)
501 logRejection(m_aContext,pNode);
502 return false;
504 else
505 OSL_ASSERT(m_aLocale.getLength() != 0);
508 OSL_ENSURE(!bClear,"'clear' operation is not yet supported");
509 if (bClear)
510 m_aContext.getLogger().warning("'clear' operation is not yet supported",
511 "startOverride()", "configmgr::LayerMergeHandler");
513 return true;
515 // -----------------------------------------------------------------------------
517 void LayerMergeHandler::ensureUnchanged(INode const * pNode) const
518 SAL_THROW((com::sun::star::configuration::backend::MalformedDataException , com::sun::star::uno::RuntimeException))
520 // to do: change state handling to detect this within sets
521 OSL_PRECOND(pNode,"INTERNAL ERROR: Unexpected NULL node pointer");
523 if (!this->isInSublayer())
524 if (pNode->getAttributes().state() == node::isMerged)
525 m_aContext.raiseMalformedDataException("Layer merging: Duplicate node or property in this layer");
527 // -----------------------------------------------------------------------------
529 // -----------------------------------------------------------------------------
530 // -----------------------------------------------------------------------------
531 // XLayerHandler
533 void SAL_CALL LayerMergeHandler::startLayer( )
534 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
536 ISubtree * pSchema = m_rData.getSchemaTree();
537 OSL_ENSURE(pSchema,"No base data to merge layer into");
539 if (!pSchema)
541 m_aContext.getLogger().error("No schema data for merging layer", "startLayer", "configmgr::LayerMergeHandler");
542 throw uno::RuntimeException(rtl::OUString::createFromAscii("Layer merging: No data to merge with"),*this);
545 m_aContext.startActiveComponent(pSchema->getName());
547 m_pProperty = NULL;
548 m_nSkipping = 0;
550 OSL_POSTCOND( m_aContext.hasActiveComponent(), "Layer merging: could not set active component");
551 OSL_POSTCOND( m_aContext.isDone(), "Layer merging: newly started component is not empty");
552 OSL_POSTCOND( !this->isSkipping(), "Layer merging: newly started component is in skipping state");
554 // -----------------------------------------------------------------------------
556 void SAL_CALL LayerMergeHandler::endLayer( )
557 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
559 if (this->isSkipping())
560 m_aContext.raiseMalformedDataException("Layer merging: Unmatched data being skipped was not terminated properly.");
562 m_aContext.endActiveComponent();
564 m_bSublayer = false;
566 OSL_POSTCOND( !m_aContext.hasActiveComponent(), "Layer merging: could not clear active component");
567 OSL_POSTCOND( m_aContext.isDone(), "Layer merging: could not finish processing");
569 // -----------------------------------------------------------------------------
571 void LayerMergeHandler::overrideLayerRoot( const rtl::OUString& aName, sal_Int16 aAttributes, sal_Bool bClear )
572 SAL_THROW((com::sun::star::configuration::backend::MalformedDataException , com::sun::star::uno::RuntimeException))
574 OSL_PRECOND( m_aContext.hasActiveComponent(), "Layer merging: active component is not set");
575 OSL_PRECOND( m_aContext.isDone(), "Layer merging: node is not root");
577 if (m_aContext.getActiveComponent() != aName)
578 m_aContext.raiseIllegalArgumentException("Layer merging: Name of layer being merged does not match component name",1);
580 // check the argument
581 if (ISubtree * pSchema = m_rData.getSchemaTree())
583 OSL_ENSURE(pSchema->getName() == aName,"Schema name does not match active component");
585 ensureUnchanged(pSchema);
587 if (startOverride(pSchema,bClear))
589 applyAttributes(pSchema,aAttributes);
591 m_aContext.pushNode(pSchema);
593 OSL_POSTCOND( m_aContext.hasActiveComponent(), "Layer merging: could not set active component");
594 OSL_POSTCOND( !m_aContext.isDone(), "Layer merging: could not start component");
596 else
597 this->skipNode();
599 else
601 OSL_ENSURE(false,"No base data to merge layer into");
602 m_aContext.getLogger().warning("No component data in schema for merging layer",
603 "overrideNode() [for layer root]", "configmgr::LayerMergeHandler");
604 this->skipNode();
607 // -----------------------------------------------------------------------------
609 static inline
610 sal_Int16 getOverrideViolationLogLevel(bool bIsSublayer)
611 { return bIsSublayer ? LogLevel::FINER : LogLevel::INFO; }
612 // -----------------------------------------------------------------------------
614 void LayerMergeHandler::implOverrideNode(
615 ISubtree * node, sal_Int16 attributes, bool clear)
617 ensureUnchanged(node);
618 if (startOverride(node, clear)) {
619 applyAttributes(node, attributes);
620 m_aContext.pushNode(node);
621 } else {
622 skipNode();
626 void SAL_CALL LayerMergeHandler::overrideNode( const rtl::OUString& aName, sal_Int16 aAttributes, sal_Bool bClear )
627 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
629 if (this->isSkipping())
631 this->skipNode();
633 else if (m_aContext.isDone())
635 this->overrideLayerRoot(aName,aAttributes,bClear);
637 else if (ISubtree * pNode = m_aContext.findNode(aName))
639 implOverrideNode(pNode, aAttributes, bClear);
641 else // ignore non-matched data
643 const sal_Int16 loglevel = getOverrideViolationLogLevel(m_bSublayer);
644 if (m_aContext.getLogger().isLogging(loglevel))
646 rtl::OUStringBuffer aMessage;
647 aMessage.appendAscii("Node ").append(m_aContext.getNodePath(aName))
648 .appendAscii(" to be overridden does not exist - skipping");
650 m_aContext.getLogger().log(loglevel,aMessage.makeStringAndClear(), "overrideNode()", "configmgr::LayerMergeHandler");
652 // m_aContext.raiseNoSuchElementException("Layer merging: The node to be overridden does not exist.",aName);
653 this->skipNode();
656 // -----------------------------------------------------------------------------
658 void LayerMergeHandler::implAddOrReplaceNode( const rtl::OUString& aName, const backenduno::TemplateIdentifier& aTemplate, sal_Int16 aAttributes )
659 SAL_THROW((com::sun::star::configuration::backend::MalformedDataException , com::sun::star::uno::RuntimeException))
661 ISubtree * pReplacedNode = m_aContext.findNode(aName);
662 if (pReplacedNode)
664 if ((aAttributes & NodeAttribute::FUSE) == 0) {
665 this->ensureUnchanged(pReplacedNode);
667 if (!m_aContext.isRemovable(pReplacedNode))
669 logRejection(m_aContext,pReplacedNode,true);
670 this->skipNode();
671 return;
673 } else {
674 implOverrideNode(
675 pReplacedNode, aAttributes & ~NodeAttribute::FUSE, false);
676 return;
680 std::auto_ptr<INode> apNewInstance;
681 if (aTemplate.Component == m_aContext.getActiveComponent())
683 apNewInstance = m_rData.instantiateTemplate(aName, aTemplate.Name);
685 else
687 TemplateRequest aTemplateRequest(aTemplate.Name, aTemplate.Component);
688 apNewInstance = m_aContext.getTemplateData( aTemplateRequest ).extractDataAndClear();
689 if (apNewInstance.get())
690 apNewInstance->setName( aName );
693 if (NULL == apNewInstance.get())
694 m_aContext.raiseNoSuchElementException("Layer merging: Cannot instantiate template.", aTemplate.Name);
696 applyAttributes(apNewInstance.get(), aAttributes & ~NodeAttribute::FUSE);
697 //Set removable flag
698 apNewInstance->markRemovable();
700 m_aContext.markCurrentMerged();
702 if (pReplacedNode) m_aContext.getCurrentParent().removeChild( aName );
704 INode * pAddedInstance = m_aContext.getCurrentParent().addChild( apNewInstance );
706 m_aContext.pushNode(pAddedInstance->asISubtree());
708 // -----------------------------------------------------------------------------
710 void SAL_CALL LayerMergeHandler::addOrReplaceNode( const rtl::OUString& aName, sal_Int16 aAttributes )
711 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
713 if (this->isSkipping())
715 this->skipNode();
716 return;
719 implAddOrReplaceNode( aName, m_aContext.getCurrentItemType(), aAttributes);
721 // -----------------------------------------------------------------------------
723 void SAL_CALL LayerMergeHandler::addOrReplaceNodeFromTemplate( const rtl::OUString& aName, const backenduno::TemplateIdentifier& aTemplate, sal_Int16 aAttributes )
724 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
726 if (this->isSkipping())
728 this->skipNode();
729 return;
732 // TODO: correct argument position (from 2 to 3) for an illegal argument exception wrt attributes
733 implAddOrReplaceNode( aName, m_aContext.getValidItemType(aTemplate), aAttributes);
735 // -----------------------------------------------------------------------------
737 void SAL_CALL LayerMergeHandler::endNode( )
738 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
740 if (this->leaveSkippedNode())
741 return;
743 this->propagateAttributes(m_aContext.getCurrentParent());
745 m_aContext.popNode();
747 // -----------------------------------------------------------------------------
749 void SAL_CALL LayerMergeHandler::dropNode( const rtl::OUString& aName )
750 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
752 if (this->isSkipping())
753 return;
755 if (!m_aContext.getCurrentParent().isSetNode())
756 m_aContext.raiseMalformedDataException("Layer merging: Removing child nodes is only possible in set nodes.");
758 if (ISubtree * pDropped = m_aContext.findNode(aName))
760 this->ensureUnchanged(pDropped);
761 if (!m_aContext.isRemovable(pDropped))
763 logRejection(m_aContext,pDropped,true);
764 return;
767 else
769 const sal_Int16 loglevel = getOverrideViolationLogLevel(m_bSublayer);
770 if (m_aContext.getLogger().isLogging(loglevel))
772 rtl::OUStringBuffer aMessage;
773 aMessage.appendAscii("Node ").append(m_aContext.getNodePath(aName))
774 .appendAscii(" to be removed does not exist - ignoring");
776 m_aContext.getLogger().log(loglevel,aMessage.makeStringAndClear(), "dropNode()", "configmgr::LayerMergeHandler");
778 // m_aContext.raiseNoSuchElementException("Layer merging: The node to be removed does not exist.",aName);
780 m_aContext.markCurrentMerged();
781 m_aContext.getCurrentParent().removeChild(aName);
783 // -----------------------------------------------------------------------------
785 void SAL_CALL LayerMergeHandler::overrideProperty( const rtl::OUString& aName, sal_Int16 aAttributes, const uno::Type& aType, sal_Bool bClear )
786 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
788 if (this->isSkipping())
790 this->skipNode();
792 else if (INode * pProp = m_aContext.findProperty(aName))
794 ensureUnchanged(pProp);
796 if (startOverride(pProp,bClear))
798 applyAttributes(pProp,aAttributes);
800 m_pProperty = pProp;
802 checkPropertyType(aType);
804 else
805 this->skipNode();
807 else // ignore non-matched data
809 const sal_Int16 loglevel = getOverrideViolationLogLevel(m_bSublayer);
810 if (m_aContext.getLogger().isLogging(loglevel))
812 rtl::OUStringBuffer aMessage;
813 aMessage.appendAscii("Property ").append(m_aContext.getNodePath(aName))
814 .appendAscii(" to be overridden does not exist - skipping");
816 m_aContext.getLogger().log(loglevel,aMessage.makeStringAndClear(), "overrideNode()", "configmgr::LayerMergeHandler");
818 // m_aContext.raiseUnknownPropertyException("Layer merging: The property to be overridden does not exist.",aName);
819 this->skipNode();
822 // -----------------------------------------------------------------------------
824 void SAL_CALL LayerMergeHandler::endProperty( )
825 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
827 if (this->leaveSkippedNode())
828 return;
830 if (!m_pProperty)
831 m_aContext.raiseMalformedDataException("Layer merging: Invalid data: Ending a property that wasn't started.");
833 if (ISubtree * pLocalizedSet = m_pProperty->asISubtree())
834 this->propagateAttributes(*pLocalizedSet);
836 m_pProperty = NULL;
837 if (m_pConverter) m_pConverter->m_bConvertData = false;
839 // -----------------------------------------------------------------------------
841 void SAL_CALL LayerMergeHandler::addProperty( const rtl::OUString& aName, sal_Int16 aAttributes, const uno::Type& aType )
842 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
844 if (this->isSkipping())
845 return;
847 // TODO: add type validation
848 node::Attributes aValueAttributes = makePropertyAttributes(aAttributes & SchemaAttribute::MASK);
850 std::auto_ptr<ValueNode> aPropertyValue =
851 m_aFactory.getNodeFactory().createNullValueNode(aName,aType,aValueAttributes);
853 applyAttributes(aPropertyValue.get(),aAttributes & NodeAttribute::MASK);
855 // can be a replace for dynamic properties (current update limitation)
856 m_aContext.markCurrentMerged();
857 m_aContext.addPropertyToCurrent(aPropertyValue, true);
859 // -----------------------------------------------------------------------------
861 void SAL_CALL LayerMergeHandler::addPropertyWithValue( const rtl::OUString& aName, sal_Int16 aAttributes, const uno::Any& aValue )
862 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
864 if (this->isSkipping())
865 return;
867 node::Attributes aValueAttributes = makePropertyAttributes(aAttributes & SchemaAttribute::MASK);
869 std::auto_ptr<ValueNode> aPropertyValue =
870 m_aFactory.getNodeFactory().createValueNode(aName,aValue,aValueAttributes);
872 applyAttributes(aPropertyValue.get(),aAttributes & NodeAttribute::MASK);
874 // can be a replace for dynamic properties (current update limitation)
875 m_aContext.markCurrentMerged();
876 m_aContext.addPropertyToCurrent(aPropertyValue, true);
878 // -----------------------------------------------------------------------------
880 void SAL_CALL LayerMergeHandler::setPropertyValue( const uno::Any& aValue )
881 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
883 if (this->isSkipping())
884 return;
886 if (!m_pProperty)
887 m_aContext.raiseMalformedDataException("Layer merging: Invalid data: Overriding a value without a property.");
889 OSL_ASSERT( !m_pProperty->getAttributes().isReplacedForUser() );
890 m_pProperty->modifyState( node::isMerged );
891 m_aContext.markCurrentMerged();
893 applyPropertyValue(aValue);
895 // -----------------------------------------------------------------------------
897 void SAL_CALL LayerMergeHandler::setPropertyValueForLocale( const uno::Any& aValue, rtl::OUString const & aLocale )
898 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
900 if (this->isSkipping())
901 return;
903 if (!m_pProperty)
904 m_aContext.raiseMalformedDataException("Layer merging: Invalid data: Overriding a (localized) value without a property.");
906 OSL_ASSERT( !m_pProperty->getAttributes().isReplacedForUser() );
907 m_pProperty->modifyState( node::isMerged );
908 m_aContext.markCurrentMerged();
910 applyPropertyValue(aValue,aLocale);
912 // -----------------------------------------------------------------------------
913 // -----------------------------------------------------------------------------
915 uno::Reference< com::sun::star::script::XTypeConverter >
916 LayerMergeHandler::Converter::createTCV(uno::Reference< uno::XComponentContext > const & xContext)
918 OSL_ENSURE(xContext.is(),"Cannot create TypeConverter for LayerMergeHandler without a Context");
920 uno::Reference< lang::XMultiComponentFactory > xFactory = xContext->getServiceManager();
921 OSL_ENSURE(xFactory.is(),"Cannot create TypeConverter for LayerMergeHandler without a ServiceManager");
923 uno::Reference< com::sun::star::script::XTypeConverter > xTCV;
924 if (xFactory.is())
926 static const rtl::OUString k_sTCVService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter"));
928 xTCV = uno::Reference< com::sun::star::script::XTypeConverter >::query(xFactory->createInstanceWithContext(k_sTCVService,xContext));
930 return xTCV;
932 // -----------------------------------------------------------------------------
934 LayerMergeHandler::Converter::Converter(uno::Reference< uno::XComponentContext > const & xContext)
935 : m_aConverter( createTCV(xContext) )
936 , m_bConvertData(false)
939 // -----------------------------------------------------------------------------
940 static
941 inline
942 uno::Type getBinaryDataType()
944 uno::Sequence< sal_Int8 > const * const forBinary = 0;
945 return ::getCppuType(forBinary);
947 // -----------------------------------------------------------------------------
949 uno::Any LayerMergeHandler::Converter::convertValue(uno::Type const & _aTargetType, uno::Any const & _aValue)
951 OSL_ENSURE( m_bConvertData, "Unexpected: Calling convert data, when data conversion is not active");
952 OSL_ENSURE( _aValue.hasValue(), "Unexpected: Calling convert data, when data to convert is VOID");
954 if (_aTargetType == _aValue.getValueType()) return _aValue;
956 m_aConverter.reset(_aTargetType);
958 if (m_aConverter.isList())
960 uno::Sequence< rtl::OUString > aStringList;
961 if (_aValue >>= aStringList)
962 return m_aConverter.convertListToAny(aStringList);
965 rtl::OUString aContent;
966 if (_aValue >>= aContent)
967 return m_aConverter.convertToAny(aContent);
970 OSL_ENSURE(false, "Cannot convert typed value (not a string)");
972 return uno::Any();
974 // -----------------------------------------------------------------------------
975 // -----------------------------------------------------------------------------
976 namespace
978 // -----------------------------------------------------------------------------
979 static inline bool isFinal(node::Attributes const& _aAttributes)
981 return _aAttributes.isFinalized() || _aAttributes.isReadonly();
983 // --------------------------------- AttributeSetter ---------------------------------
985 class DefaultPromoter : NodeModification
987 public:
988 explicit
989 DefaultPromoter()
992 void adjustAccess(INode& _rNode);
994 using NodeModification::applyToNode;
995 private:
996 void handle(ValueNode& _rValueNode);
997 void handle(ISubtree& _rSubtree);
999 // -----------------------------------------------------------------------------
1001 void DefaultPromoter::adjustAccess(INode& _rNode)
1003 _rNode.promoteAccessToDefault();
1005 // -----------------------------------------------------------------------------
1007 void DefaultPromoter::handle(ValueNode& _rValueNode)
1009 _rValueNode.promoteToDefault();
1010 adjustAccess(_rValueNode);
1012 // -----------------------------------------------------------------------------
1014 void DefaultPromoter::handle(ISubtree& _rSubtree)
1016 _rSubtree.markAsDefault();
1017 this->applyToChildren(_rSubtree);
1018 adjustAccess(_rSubtree);
1020 //--------------------------------------------------------------------------
1023 // -----------------------------------------------------------------------------
1024 void promoteToDefault(MergedComponentData & _rTree)
1026 if (ISubtree * pTreeData = _rTree.getSchemaTree())
1027 DefaultPromoter().applyToNode(*pTreeData);
1029 else
1030 OSL_ENSURE(false,"No Data to promote to default");
1034 // -----------------------------------------------------------------------------
1035 // -----------------------------------------------------------------------------
1036 } // namespace backend
1038 // -------------------------------------------------------------------------
1039 } // namespace configmgr