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: layermerge.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 "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>
46 // -----------------------------------------------------------------------------
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
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
));
68 // -----------------------------------------------------------------------------
70 struct LayerMergeHandler::Converter
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
;
82 // -----------------------------------------------------------------------------
83 LayerMergeHandler::LayerMergeHandler(uno::Reference
< uno::XComponentContext
> const & xContext
, MergedComponentData
& _rData
, ITemplateDataProvider
* aTemplateProvider
)
85 //, m_aContext(xContext,static_cast<backenduno::XLayerHandler*>(this),aTemplateProvider )
86 , m_aContext(xContext
)
90 , m_pConverter( new Converter(xContext
) )
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( )
103 // -----------------------------------------------------------------------------
105 void LayerMergeHandler::prepareLayer()
107 OSL_ENSURE(isDone(), "LayerMergeHandler: Warning: Previous layer or schema not terminated properly");
109 m_aContext
.getLogger().error("Previous layer or schema not terminated properly", "prepareLayer()", "configmgr::LayerMergeHandler");
111 m_aLocale
= localehelper:: getDefaultLanguage();
114 promoteToDefault(m_rData
);
116 // -----------------------------------------------------------------------------
118 bool LayerMergeHandler::prepareSublayer(rtl::OUString
const & aLocale
)
120 OSL_ENSURE(isDone(), "LayerMergeHandler: Warning: Previous layer not terminated properly");
122 m_aContext
.getLogger().error("Previous layer not terminated properly", "prepareSublayer()", "configmgr::LayerMergeHandler");
125 m_bSublayer
= (aLocale
.getLength() != 0);
129 // -----------------------------------------------------------------------------
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");
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
);
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
);
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);
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
) );
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;
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()) {
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
;
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
);
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");
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
,
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
);
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
);
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
);
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 // -----------------------------------------------------------------------------
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");
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 */
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
501 logRejection(m_aContext
,pNode
);
505 OSL_ASSERT(m_aLocale
.getLength() != 0);
508 OSL_ENSURE(!bClear
,"'clear' operation is not yet supported");
510 m_aContext
.getLogger().warning("'clear' operation is not yet supported",
511 "startOverride()", "configmgr::LayerMergeHandler");
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 // -----------------------------------------------------------------------------
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");
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());
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();
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");
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");
607 // -----------------------------------------------------------------------------
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
);
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())
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);
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
);
664 if ((aAttributes
& NodeAttribute::FUSE
) == 0) {
665 this->ensureUnchanged(pReplacedNode
);
667 if (!m_aContext
.isRemovable(pReplacedNode
))
669 logRejection(m_aContext
,pReplacedNode
,true);
675 pReplacedNode
, aAttributes
& ~NodeAttribute::FUSE
, false);
680 std::auto_ptr
<INode
> apNewInstance
;
681 if (aTemplate
.Component
== m_aContext
.getActiveComponent())
683 apNewInstance
= m_rData
.instantiateTemplate(aName
, aTemplate
.Name
);
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
);
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())
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())
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())
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())
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);
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())
792 else if (INode
* pProp
= m_aContext
.findProperty(aName
))
794 ensureUnchanged(pProp
);
796 if (startOverride(pProp
,bClear
))
798 applyAttributes(pProp
,aAttributes
);
802 checkPropertyType(aType
);
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);
822 // -----------------------------------------------------------------------------
824 void SAL_CALL
LayerMergeHandler::endProperty( )
825 throw (backenduno::MalformedDataException
, lang::WrappedTargetException
, uno::RuntimeException
)
827 if (this->leaveSkippedNode())
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
);
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())
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())
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())
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())
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
;
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
));
932 // -----------------------------------------------------------------------------
934 LayerMergeHandler::Converter::Converter(uno::Reference
< uno::XComponentContext
> const & xContext
)
935 : m_aConverter( createTCV(xContext
) )
936 , m_bConvertData(false)
939 // -----------------------------------------------------------------------------
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)");
974 // -----------------------------------------------------------------------------
975 // -----------------------------------------------------------------------------
978 // -----------------------------------------------------------------------------
979 static inline bool isFinal(node::Attributes
const& _aAttributes
)
981 return _aAttributes
.isFinalized() || _aAttributes
.isReadonly();
983 // --------------------------------- AttributeSetter ---------------------------------
985 class DefaultPromoter
: NodeModification
992 void adjustAccess(INode
& _rNode
);
994 using NodeModification::applyToNode
;
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
);
1030 OSL_ENSURE(false,"No Data to promote to default");
1034 // -----------------------------------------------------------------------------
1035 // -----------------------------------------------------------------------------
1036 } // namespace backend
1038 // -------------------------------------------------------------------------
1039 } // namespace configmgr