LibreOffice Module configmgr (master) 1
access.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <cassert>
23#include <cstdlib>
24#include <utility>
25#include <vector>
26
27#include <com/sun/star/beans/Property.hpp>
28#include <com/sun/star/beans/PropertyAttribute.hpp>
29#include <com/sun/star/beans/PropertyChangeEvent.hpp>
30#include <com/sun/star/beans/UnknownPropertyException.hpp>
31#include <com/sun/star/beans/XExactName.hpp>
32#include <com/sun/star/beans/XHierarchicalPropertySet.hpp>
33#include <com/sun/star/beans/XHierarchicalPropertySetInfo.hpp>
34#include <com/sun/star/beans/XMultiHierarchicalPropertySet.hpp>
35#include <com/sun/star/beans/XMultiPropertySet.hpp>
36#include <com/sun/star/beans/XPropertiesChangeListener.hpp>
37#include <com/sun/star/beans/XProperty.hpp>
38#include <com/sun/star/beans/XPropertyChangeListener.hpp>
39#include <com/sun/star/beans/XPropertySet.hpp>
40#include <com/sun/star/beans/XPropertySetInfo.hpp>
41#include <com/sun/star/beans/XVetoableChangeListener.hpp>
42#include <com/sun/star/container/ContainerEvent.hpp>
43#include <com/sun/star/container/NoSuchElementException.hpp>
44#include <com/sun/star/container/XContainer.hpp>
45#include <com/sun/star/container/XContainerListener.hpp>
46#include <com/sun/star/container/XElementAccess.hpp>
47#include <com/sun/star/container/XHierarchicalName.hpp>
48#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
49#include <com/sun/star/container/XHierarchicalNameReplace.hpp>
50#include <com/sun/star/container/XNameAccess.hpp>
51#include <com/sun/star/container/XNameContainer.hpp>
52#include <com/sun/star/container/XNamed.hpp>
53#include <com/sun/star/lang/DisposedException.hpp>
54#include <com/sun/star/lang/EventObject.hpp>
55#include <com/sun/star/lang/IllegalArgumentException.hpp>
56#include <com/sun/star/lang/XComponent.hpp>
57#include <com/sun/star/lang/XEventListener.hpp>
58#include <com/sun/star/lang/XServiceInfo.hpp>
59#include <com/sun/star/lang/XSingleServiceFactory.hpp>
60#include <com/sun/star/lang/XTypeProvider.hpp>
61#include <com/sun/star/uno/Any.hxx>
62#include <com/sun/star/uno/Reference.hxx>
63#include <com/sun/star/uno/RuntimeException.hpp>
64#include <com/sun/star/uno/Sequence.hxx>
65#include <com/sun/star/uno/Type.hxx>
66#include <com/sun/star/uno/XInterface.hpp>
67#include <com/sun/star/uno/XWeak.hpp>
68#include <com/sun/star/util/ElementChange.hpp>
71#include <comphelper/string.hxx>
72#include <comphelper/lok.hxx>
74#include <cppu/unotype.hxx>
77#include <cppuhelper/weak.hxx>
78#include <osl/interlck.h>
79#include <osl/mutex.hxx>
80#include <rtl/character.hxx>
81#include <rtl/ref.hxx>
82#include <rtl/ustrbuf.hxx>
83#include <rtl/ustring.hxx>
84#include <sal/log.hxx>
85#include <sal/types.h>
86
87#include "access.hxx"
88#include "broadcaster.hxx"
89#include "childaccess.hxx"
90#include "components.hxx"
91#include "data.hxx"
92#include "groupnode.hxx"
95#include "lock.hxx"
96#include "modifications.hxx"
97#include "node.hxx"
98#include "nodemap.hxx"
99#include "propertynode.hxx"
100#include "rootaccess.hxx"
101#include "setnode.hxx"
102#include "type.hxx"
103
104namespace configmgr {
105
106namespace {
107
108// Conservatively forbid what is either not an XML Char (including lone
109// surrogates, even though they should not appear in well-formed UNO OUString
110// instances anyway), or is a slash (as it causes problems in path syntax):
111bool isValidName(OUString const & name, bool setMember) {
112 for (sal_Int32 i = 0; i != name.getLength();) {
113 sal_uInt32 c = name.iterateCodePoints(&i);
114 if ((c < 0x20 && !(c == 0x09 || c == 0x0A || c == 0x0D))
115 || rtl::isSurrogate(c) || c == 0xFFFE || c == 0xFFFF
116 || (!setMember && c == '/'))
117 {
118 return false;
119 }
120 }
121 return !name.isEmpty();
122}
123
124}
125
126oslInterlockedCount Access::acquireCounting() {
127 return osl_atomic_increment(&m_refCount);
128}
129
131 osl_atomic_decrement(&m_refCount);
132}
133
136 switch (p->kind()) {
139 return true;
142 default:
143 return false;
144 }
145}
146
148 assert(child.is() && child->getParentAccess() == this);
149 modifiedChildren_[child->getNameInternal()] = ModifiedChild(child, true);
150 for (rtl::Reference< Access > p(this);;) {
151 rtl::Reference< Access > parent(p->getParentAccess());
152 if (!parent.is()) {
153 break;
154 }
155 assert(dynamic_cast< ChildAccess * >(p.get()) != nullptr);
156 parent->modifiedChildren_.emplace(
157 p->getNameInternal(),
158 ModifiedChild(static_cast< ChildAccess * >(p.get()), false));
159 p = parent;
160 }
161}
162
163void Access::releaseChild(OUString const & name) {
164 cachedChildren_.erase(name);
165}
166
168 Modifications::Node const & modifications, Broadcaster * broadcaster)
169{
170 initBroadcasterAndChanges(modifications, broadcaster, nullptr);
171}
172
173css::uno::Sequence< css::uno::Type > Access::getTypes()
174{
175 assert(thisIs(IS_ANY));
176 osl::MutexGuard g(*lock_);
178 std::vector< css::uno::Type > types { cppu::UnoType< css::uno::XInterface >::get(),
190 };
191 if (getNode()->kind() == Node::KIND_GROUP) {
195 types.push_back(
197 types.push_back(
199 types.push_back(
201 }
202 if (getRootAccess()->isUpdate()) {
204 types.push_back(
206 if (getNode()->kind() != Node::KIND_GROUP ||
207 static_cast< GroupNode * >(getNode().get())->isExtensible())
208 {
209 types.push_back(
211 }
212 if (getNode()->kind() == Node::KIND_SET) {
213 types.push_back(
215 }
216 } else {
217 types.push_back(
219 }
220 addTypes(&types);
222}
223
224css::uno::Sequence< sal_Int8 > Access::getImplementationId()
225{
226 assert(thisIs(IS_ANY));
227 osl::MutexGuard g(*lock_);
229 return css::uno::Sequence< sal_Int8 >();
230}
231
233{
234 assert(thisIs(IS_ANY));
235 osl::MutexGuard g(*lock_);
237 return "org.openoffice-configmgr::Access";
238}
239
240sal_Bool Access::supportsService(OUString const & ServiceName)
241{
243}
244
245css::uno::Sequence< OUString > Access::getSupportedServiceNames()
246{
247 assert(thisIs(IS_ANY));
248 osl::MutexGuard g(*lock_);
250 std::vector<OUString> services;
251 services.emplace_back("com.sun.star.configuration.ConfigurationAccess");
252 if (getRootAccess()->isUpdate()) {
253 services.emplace_back("com.sun.star.configuration.ConfigurationUpdateAccess");
254 }
255 services.emplace_back("com.sun.star.configuration.HierarchyAccess");
256 services.emplace_back("com.sun.star.configuration.HierarchyElement");
257 if (getNode()->kind() == Node::KIND_GROUP) {
258 services.emplace_back("com.sun.star.configuration.GroupAccess");
259 services.emplace_back("com.sun.star.configuration.PropertyHierarchy");
260 if (getRootAccess()->isUpdate()) {
261 services.emplace_back("com.sun.star.configuration.GroupUpdate");
262 }
263 } else {
264 services.emplace_back("com.sun.star.configuration.SetAccess");
265 services.emplace_back("com.sun.star.configuration.SimpleSetAccess");
266 if (getRootAccess()->isUpdate()) {
267 services.emplace_back("com.sun.star.configuration.SetUpdate");
268 services.emplace_back("com.sun.star.configuration.SimpleSetUpdate");
269 }
270 }
271 addSupportedServiceNames(&services);
272 return comphelper::containerToSequence(services);
273}
274
276 assert(thisIs(IS_ANY));
277 Broadcaster bc;
278 {
279 osl::MutexGuard g(*lock_);
281 if (getParentAccess().is()) {
282 throw css::uno::RuntimeException(
283 "configmgr dispose inappropriate Access",
284 getXWeak());
285 }
286 if (disposed_) {
287 return;
288 }
291 disposed_ = true;
292 }
293 bc.send();
294}
295
297 css::uno::Reference< css::lang::XEventListener > const & xListener)
298{
299 assert(thisIs(IS_ANY));
300 {
301 osl::MutexGuard g(*lock_);
303 if (!xListener.is()) {
304 throw css::uno::RuntimeException(
305 "null listener", getXWeak());
306 }
307 if (!disposed_) {
308 disposeListeners_.insert(xListener);
309 return;
310 }
311 }
312 try {
313 xListener->disposing(
314 css::lang::EventObject(getXWeak()));
315 } catch (css::lang::DisposedException &) {}
316}
317
319 css::uno::Reference< css::lang::XEventListener > const & aListener)
320{
321 assert(thisIs(IS_ANY));
322 osl::MutexGuard g(*lock_);
324 DisposeListeners::iterator i(disposeListeners_.find(aListener));
325 if (i != disposeListeners_.end()) {
326 disposeListeners_.erase(i);
327 }
328}
329
331 assert(thisIs(IS_ANY));
332 osl::MutexGuard g(*lock_);
335 switch (p->kind()) {
337 return mapType(
338 static_cast< LocalizedPropertyNode * >(p.get())->getStaticType());
339 case Node::KIND_GROUP:
340 //TODO: Should a specific type be returned for a non-extensible group
341 // with homogeneous members or for an extensible group that currently
342 // has only homogeneous members?
344 case Node::KIND_SET:
345 return cppu::UnoType<void>::get(); //TODO: correct?
346 default:
347 assert(false);
348 throw css::uno::RuntimeException(
349 "this cannot happen", getXWeak());
350 }
351}
352
354 assert(thisIs(IS_ANY));
355 osl::MutexGuard g(*lock_);
357 return !getAllChildren().empty(); //TODO: optimize
358}
359
360bool Access::getByNameFast(const OUString & name, css::uno::Any & value)
361{
362 bool bGotValue = false;
364
365 if (getNode()->kind() != Node::KIND_LOCALIZED_PROPERTY)
366 { // try to get it directly
367 ModifiedChildren::iterator i(modifiedChildren_.find(name));
368 if (i != modifiedChildren_.end())
369 {
370 child = getModifiedChild(i);
371 if (child.is())
372 {
373 value = child->asValue();
374 bGotValue = true;
375 }
376 }
377 else
378 {
379 rtl::Reference< Node > node(getNode()->getMember(name));
380 if (!node.is())
381 return false;
382 bGotValue = ChildAccess::asSimpleValue(node, value, components_);
383 }
384 }
385
386 if (!bGotValue)
387 {
388 child = getChild(name);
389 if (!child.is())
390 return false;
391 value = child->asValue();
392 }
393 return true;
394}
395
396css::uno::Any Access::getByName(OUString const & aName)
397{
398 assert(thisIs(IS_ANY));
399 osl::MutexGuard g(*lock_);
401 css::uno::Any value;
403 throw css::container::NoSuchElementException(
404 aName, getXWeak());
405 return value;
406}
407
408css::uno::Sequence< OUString > Access::getElementNames()
409{
410 assert(thisIs(IS_ANY));
411 osl::MutexGuard g(*lock_);
413 std::vector< rtl::Reference< ChildAccess > > children(getAllChildren());
414 css::uno::Sequence<OUString> names(children.size());
415 OUString* pArray = names.getArray();
416 for (auto const& child : children)
417 {
418 *pArray++ = child->getNameInternal();
419 }
420 return names;
421}
422
423sal_Bool Access::hasByName(OUString const & aName)
424{
425 assert(thisIs(IS_ANY));
426 osl::MutexGuard g(*lock_);
428 return getChild(aName).is();
429}
430
431css::uno::Any Access::getByHierarchicalName(OUString const & aName)
432{
433 assert(thisIs(IS_ANY));
434 osl::MutexGuard g(*lock_);
437 if (!child.is()) {
438 throw css::container::NoSuchElementException(
439 aName, getXWeak());
440 }
441 return child->asValue();
442}
443
445{
446 assert(thisIs(IS_ANY));
447 osl::MutexGuard g(*lock_);
449 return getSubChild(aName).is();
450}
451
453 OUString const & aName, css::uno::Any const & aElement)
454{
455 //TODO: Actually support sets and combine with replaceByName:
456 assert(thisIs(IS_UPDATE));
457 Broadcaster bc;
458 {
459 osl::MutexGuard g(*lock_);
462 if (!child.is()) {
463 throw css::container::NoSuchElementException(
464 aName, getXWeak());
465 }
466 child->checkFinalized();
467 rtl::Reference< Node > parent(child->getParentNode());
468 assert(parent.is());
469 Modifications localMods;
470 switch (parent->kind()) {
472 case Node::KIND_GROUP:
473 child->setProperty(aElement, &localMods);
474 break;
475 case Node::KIND_SET:
476 throw css::lang::IllegalArgumentException(
477 ("configmgr::Access::replaceByHierarchicalName does not"
478 " currently support set members"),
479 getXWeak(), 0);
480 case Node::KIND_ROOT:
481 throw css::lang::IllegalArgumentException(
482 ("configmgr::Access::replaceByHierarchicalName does not allow"
483 " changing component " + aName),
484 getXWeak(), 0);
485 default:
486 assert(false); // this cannot happen
487 break;
488 }
489 getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
490 }
491 bc.send();
492}
493
495 css::uno::Reference< css::container::XContainerListener > const & xListener)
496{
497 assert(thisIs(IS_ANY));
498 {
499 osl::MutexGuard g(*lock_);
501 if (!xListener.is()) {
502 throw css::uno::RuntimeException(
503 "null listener", getXWeak());
504 }
505 if (!disposed_) {
506 containerListeners_.insert(xListener);
507 return;
508 }
509 }
510 try {
511 xListener->disposing(
512 css::lang::EventObject(getXWeak()));
513 } catch (css::lang::DisposedException &) {}
514}
515
517 css::uno::Reference< css::container::XContainerListener > const & xListener)
518{
519 assert(thisIs(IS_ANY));
520 osl::MutexGuard g(*lock_);
522 ContainerListeners::iterator i(containerListeners_.find(xListener));
523 if (i != containerListeners_.end()) {
524 containerListeners_.erase(i);
525 }
526}
527
528OUString Access::getExactName(OUString const & aApproximateName)
529{
530 assert(thisIs(IS_ANY));
531 osl::MutexGuard g(*lock_);
533 return aApproximateName;
534}
535
536css::uno::Sequence< css::beans::Property > Access::getProperties()
537{
538 assert(thisIs(IS_GROUP));
539 osl::MutexGuard g(*lock_);
540 std::vector< rtl::Reference< ChildAccess > > children(getAllChildren());
541 std::vector< css::beans::Property > properties;
542 properties.reserve(children.size());
543 for (auto const& child : children)
544 {
545 properties.push_back(child->asProperty());
546 }
548}
549
550css::beans::Property Access::getPropertyByName(OUString const & aName)
551{
552 assert(thisIs(IS_GROUP));
553 osl::MutexGuard g(*lock_);
555 if (!child.is()) {
556 throw css::beans::UnknownPropertyException(
557 aName, getXWeak());
558 }
559 return child->asProperty();
560}
561
563{
564 assert(thisIs(IS_GROUP));
565 osl::MutexGuard g(*lock_);
566 return getChild(Name).is();
567}
568
570 assert(thisIs(IS_ANY));
571 osl::MutexGuard g(*lock_);
573 // For backwards compatibility, return an absolute path representation where
574 // available:
575 OUString rootPath;
577 if (root.is()) {
578 rootPath = root->getAbsolutePathRepresentation();
579 }
580 OUString rel(getRelativePathRepresentation());
581 OUStringBuffer path(rootPath);
582 if (!rootPath.isEmpty() && rootPath != "/" && !rel.isEmpty()) {
583 path.append('/');
584 }
585 path.append(rel);
586 return path.makeStringAndClear();
587}
588
590 OUString const & aRelativeName)
591{
592 assert(thisIs(IS_ANY));
593 osl::MutexGuard g(*lock_);
595 if (aRelativeName.isEmpty() || aRelativeName[0] == '/') {
596 throw css::lang::IllegalArgumentException(
597 "configmgr composeHierarchicalName inappropriate relative name",
598 getXWeak(), -1);
599 }
600 OUStringBuffer path(getRelativePathRepresentation());
601 if (!path.isEmpty()) {
602 path.append('/');
603 }
604 path.append(aRelativeName);
605 return path.makeStringAndClear();
606}
607
608OUString Access::getName() {
609 assert(thisIs(IS_ANY));
610 osl::MutexGuard g(*lock_);
612 return getNameInternal();
613}
614
615void Access::setName(OUString const & aName)
616{
617 assert(thisIs(IS_ANY));
618 Broadcaster bc;
619 {
620 osl::MutexGuard g(*lock_);
623 Modifications localMods;
624 switch (getNode()->kind()) {
625 case Node::KIND_GROUP:
626 case Node::KIND_SET:
627 {
629 if (parent.is()) {
631 if (! node->getTemplateName().isEmpty()) {
633 parent->getChild(aName));
634 if (other.get() == this) {
635 break;
636 }
637 if (node->getMandatory() == Data::NO_LAYER &&
638 !(other.is() && other->isFinalized()))
639 {
640 if (!isValidName(aName, true)) {
641 throw css::uno::RuntimeException(
642 "invalid element name " + aName);
643 }
646 static_cast< ChildAccess * >(this));
647 localMods.add(getRelativePath());
648 // unbind() modifies the parent chain that
649 // markChildAsModified() walks, so order is
650 // important:
651 parent->markChildAsModified(childAccess);
652 //TODO: must not throw
653 childAccess->unbind(); // must not throw
654 if (other.is()) {
655 other->unbind(); // must not throw
656 }
657 childAccess->bind(root, parent, aName);
658 // must not throw
659 parent->markChildAsModified(childAccess);
660 //TODO: must not throw
661 localMods.add(getRelativePath());
662 break;
663 }
664 }
665 }
666 }
667 [[fallthrough]];
669 // renaming a property could only work for an extension property,
670 // but a localized property is never an extension property
671 throw css::uno::RuntimeException(
672 "configmgr setName inappropriate node",
673 getXWeak());
674 default:
675 assert(false); // this cannot happen
676 break;
677 }
678 getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
679 }
680 bc.send();
681}
682
683css::beans::Property Access::getAsProperty()
684{
685 assert(thisIs(IS_ANY));
686 osl::MutexGuard g(*lock_);
688 return asProperty();
689}
690
691css::uno::Reference< css::beans::XPropertySetInfo > Access::getPropertySetInfo()
692{
693 assert(thisIs(IS_GROUP));
694 return this;
695}
696
698 OUString const & aPropertyName, css::uno::Any const & aValue)
699{
700 assert(thisIs(IS_GROUP));
701 Broadcaster bc;
702 {
703 osl::MutexGuard g(*lock_);
704 if (!getRootAccess()->isUpdate()) {
705 throw css::uno::RuntimeException(
706 "configmgr setPropertyValue on non-update access",
707 getXWeak());
708 }
709 Modifications localMods;
710 if (!setChildProperty(aPropertyName, aValue, &localMods)) {
711 throw css::beans::UnknownPropertyException(
712 aPropertyName, getXWeak());
713 }
714 getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
715 }
716 bc.send();
717}
718
719css::uno::Any Access::getPropertyValue(OUString const & PropertyName)
720{
721 assert(thisIs(IS_GROUP));
722 osl::MutexGuard g(*lock_);
723
724 css::uno::Any value;
725 if (!getByNameFast(PropertyName, value))
726 throw css::beans::UnknownPropertyException(
727 PropertyName, getXWeak());
728 return value;
729}
730
732 OUString const & aPropertyName,
733 css::uno::Reference< css::beans::XPropertyChangeListener > const &
734 xListener)
735{
736 assert(thisIs(IS_GROUP));
737 {
738 osl::MutexGuard g(*lock_);
739 if (!xListener.is()) {
740 throw css::uno::RuntimeException(
741 "null listener", getXWeak());
742 }
743 checkKnownProperty(aPropertyName);
744 if (!disposed_) {
745 propertyChangeListeners_[aPropertyName].insert(xListener);
746 return;
747 }
748 }
749 try {
750 xListener->disposing(
751 css::lang::EventObject(getXWeak()));
752 } catch (css::lang::DisposedException &) {}
753}
754
756 OUString const & aPropertyName,
757 css::uno::Reference< css::beans::XPropertyChangeListener > const &
758 aListener)
759{
760 assert(thisIs(IS_GROUP));
761 osl::MutexGuard g(*lock_);
762 checkKnownProperty(aPropertyName);
763 PropertyChangeListeners::iterator i(
764 propertyChangeListeners_.find(aPropertyName));
765 if (i != propertyChangeListeners_.end()) {
766 PropertyChangeListenersElement::iterator j(i->second.find(aListener));
767 if (j != i->second.end()) {
768 i->second.erase(j);
769 if (i->second.empty()) {
771 }
772 }
773 }
774}
775
777 OUString const & PropertyName,
778 css::uno::Reference< css::beans::XVetoableChangeListener > const &
779 aListener)
780{
781 assert(thisIs(IS_GROUP));
782 {
783 osl::MutexGuard g(*lock_);
784 if (!aListener.is()) {
785 throw css::uno::RuntimeException(
786 "null listener", getXWeak());
787 }
788 checkKnownProperty(PropertyName);
789 if (!disposed_) {
790 vetoableChangeListeners_[PropertyName].insert(aListener);
791 //TODO: actually call vetoableChangeListeners_
792 return;
793 }
794 }
795 try {
796 aListener->disposing(
797 css::lang::EventObject(getXWeak()));
798 } catch (css::lang::DisposedException &) {}
799}
800
802 OUString const & PropertyName,
803 css::uno::Reference< css::beans::XVetoableChangeListener > const &
804 aListener)
805{
806 assert(thisIs(IS_GROUP));
807 osl::MutexGuard g(*lock_);
808 checkKnownProperty(PropertyName);
809 VetoableChangeListeners::iterator i(
810 vetoableChangeListeners_.find(PropertyName));
811 if (i != vetoableChangeListeners_.end()) {
812 VetoableChangeListenersElement::iterator j(i->second.find(aListener));
813 if (j != i->second.end()) {
814 i->second.erase(j);
815 if (i->second.empty()) {
817 }
818 }
819 }
820}
821
823 css::uno::Sequence< OUString > const & aPropertyNames,
824 css::uno::Sequence< css::uno::Any > const & aValues)
825{
826 assert(thisIs(IS_GROUP));
827 Broadcaster bc;
828 {
829 osl::MutexGuard g(*lock_);
830 if (!getRootAccess()->isUpdate()) {
831 throw css::uno::RuntimeException(
832 "configmgr setPropertyValues on non-update access",
833 getXWeak());
834 }
835 if (aPropertyNames.getLength() != aValues.getLength()) {
836 throw css::lang::IllegalArgumentException(
837 ("configmgr setPropertyValues: aPropertyNames/aValues of"
838 " different length"),
839 getXWeak(), -1);
840 }
841 Modifications localMods;
842 for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i) {
843 if (!setChildProperty(aPropertyNames[i], aValues[i], &localMods)) {
844 throw css::lang::IllegalArgumentException(
845 "configmgr setPropertyValues inappropriate property name",
846 getXWeak(), -1);
847 }
848 }
849 getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
850 }
851 bc.send();
852}
853
854css::uno::Sequence< css::uno::Any > Access::getPropertyValues(
855 css::uno::Sequence< OUString > const & aPropertyNames)
856{
857 assert(thisIs(IS_GROUP));
858 osl::MutexGuard g(*lock_);
859 css::uno::Sequence< css::uno::Any > vals(aPropertyNames.getLength());
860 auto aValsRange = asNonConstRange(vals);
861 for (sal_Int32 i = 0; i < aPropertyNames.getLength(); ++i)
862 {
863 if (!getByNameFast(aPropertyNames[i], aValsRange[i]))
864 throw css::uno::RuntimeException(
865 "configmgr getPropertyValues inappropriate property name",
866 getXWeak());
867 }
868
869 return vals;
870}
871
873 css::uno::Sequence< OUString > const &,
874 css::uno::Reference< css::beans::XPropertiesChangeListener > const &
875 xListener)
876{
877 assert(thisIs(IS_GROUP));
878 {
879 osl::MutexGuard g(*lock_);
880 if (!xListener.is()) {
881 throw css::uno::RuntimeException(
882 "null listener", getXWeak());
883 }
884 if (!disposed_) {
885 propertiesChangeListeners_.insert(xListener);
886 return;
887 }
888 }
889 try {
890 xListener->disposing(
891 css::lang::EventObject(getXWeak()));
892 } catch (css::lang::DisposedException &) {}
893}
894
896 css::uno::Reference< css::beans::XPropertiesChangeListener > const &
897 xListener)
898{
899 assert(thisIs(IS_GROUP));
900 osl::MutexGuard g(*lock_);
901 PropertiesChangeListeners::iterator i(
902 propertiesChangeListeners_.find(xListener));
903 if (i != propertiesChangeListeners_.end()) {
905 }
906}
907
909 css::uno::Sequence< OUString > const & aPropertyNames,
910 css::uno::Reference< css::beans::XPropertiesChangeListener > const &
911 xListener)
912{
913 assert(thisIs(IS_GROUP));
914 css::uno::Sequence< css::beans::PropertyChangeEvent > events(
915 aPropertyNames.getLength());
916 auto aEventsRange = asNonConstRange(events);
917 for (sal_Int32 i = 0; i < events.getLength(); ++i) {
918 aEventsRange[i].Source = getXWeak();
919 aEventsRange[i].PropertyName = aPropertyNames[i];
920 aEventsRange[i].Further = false;
921 aEventsRange[i].PropertyHandle = -1;
922 }
923 xListener->propertiesChange(events);
924}
925
926css::uno::Reference< css::beans::XHierarchicalPropertySetInfo >
928 assert(thisIs(IS_GROUP));
929 return this;
930}
931
933 OUString const & aHierarchicalPropertyName,
934 css::uno::Any const & aValue)
935{
936 assert(thisIs(IS_GROUP));
937 Broadcaster bc;
938 {
939 osl::MutexGuard g(*lock_);
940 if (!getRootAccess()->isUpdate()) {
941 throw css::uno::RuntimeException(
942 "configmgr setHierarchicalPropertyName on non-update access",
943 getXWeak());
944 }
946 getSubChild(aHierarchicalPropertyName));
947 if (!child.is()) {
948 throw css::beans::UnknownPropertyException(
949 aHierarchicalPropertyName,
950 getXWeak());
951 }
952 child->checkFinalized();
953 Modifications localMods;
954 child->setProperty(aValue, &localMods);
955 getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
956 }
957 bc.send();
958}
959
961 OUString const & aHierarchicalPropertyName)
962{
963 assert(thisIs(IS_GROUP));
964 osl::MutexGuard g(*lock_);
965 rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalPropertyName));
966 if (!child.is()) {
967 throw css::beans::UnknownPropertyException(
968 aHierarchicalPropertyName,
969 getXWeak());
970 }
971 return child->asValue();
972}
973
975 css::uno::Sequence< OUString > const & aHierarchicalPropertyNames,
976 css::uno::Sequence< css::uno::Any > const & Values)
977{
978 assert(thisIs(IS_GROUP));
979 Broadcaster bc;
980 {
981 osl::MutexGuard g(*lock_);
982 if (!getRootAccess()->isUpdate()) {
983 throw css::uno::RuntimeException(
984 "configmgr setPropertyValues on non-update access",
985 getXWeak());
986 }
987 if (aHierarchicalPropertyNames.getLength() != Values.getLength()) {
988 throw css::lang::IllegalArgumentException(
989 ("configmgr setHierarchicalPropertyValues:"
990 " aHierarchicalPropertyNames/Values of different length"),
991 getXWeak(), -1);
992 }
993 Modifications localMods;
994 for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) {
996 getSubChild(aHierarchicalPropertyNames[i]));
997 if (!child.is()) {
998 throw css::lang::IllegalArgumentException(
999 ("configmgr setHierarchicalPropertyValues inappropriate"
1000 " property name"),
1001 getXWeak(), -1);
1002 }
1003 child->checkFinalized();
1004 child->setProperty(Values[i], &localMods);
1005 }
1006 getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
1007 }
1008 bc.send();
1009}
1010
1011css::uno::Sequence< css::uno::Any > Access::getHierarchicalPropertyValues(
1012 css::uno::Sequence< OUString > const & aHierarchicalPropertyNames)
1013{
1014 assert(thisIs(IS_GROUP));
1015 osl::MutexGuard g(*lock_);
1016 css::uno::Sequence< css::uno::Any > vals(
1017 aHierarchicalPropertyNames.getLength());
1018 auto aValsRange = asNonConstRange(vals);
1019 for (sal_Int32 i = 0; i < aHierarchicalPropertyNames.getLength(); ++i) {
1021 getSubChild(aHierarchicalPropertyNames[i]));
1022 if (!child.is()) {
1023 throw css::lang::IllegalArgumentException(
1024 ("configmgr getHierarchicalPropertyValues inappropriate"
1025 " hierarchical property name"),
1026 getXWeak(), -1);
1027 }
1028 aValsRange[i] = child->asValue();
1029 }
1030 return vals;
1031}
1032
1034 OUString const & aHierarchicalName)
1035{
1036 assert(thisIs(IS_GROUP));
1037 osl::MutexGuard g(*lock_);
1038 rtl::Reference< ChildAccess > child(getSubChild(aHierarchicalName));
1039 if (!child.is()) {
1040 throw css::beans::UnknownPropertyException(
1041 aHierarchicalName, getXWeak());
1042 }
1043 return child->asProperty();
1044}
1045
1047 OUString const & aHierarchicalName)
1048{
1049 assert(thisIs(IS_GROUP));
1050 osl::MutexGuard g(*lock_);
1051 return getSubChild(aHierarchicalName).is();
1052}
1053
1055 OUString const & aName, css::uno::Any const & aElement)
1056{
1057 assert(thisIs(IS_UPDATE));
1058 Broadcaster bc;
1059 {
1060 osl::MutexGuard g(*lock_);
1063 if (!child.is()) {
1064 throw css::container::NoSuchElementException(
1065 aName, getXWeak());
1066 }
1067 child->checkFinalized();
1068 Modifications localMods;
1069 switch (getNode()->kind()) {
1071 case Node::KIND_GROUP:
1072 child->setProperty(aElement, &localMods);
1073 break;
1074 case Node::KIND_SET:
1075 {
1077 getFreeSetMember(aElement));
1079 localMods.add(child->getRelativePath());
1080 child->unbind(); // must not throw
1081 freeAcc->bind(root, this, aName); // must not throw
1082 markChildAsModified(freeAcc); //TODO: must not throw
1083 }
1084 break;
1085 default:
1086 assert(false); // this cannot happen
1087 break;
1088 }
1089 getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
1090 }
1091 bc.send();
1092}
1093
1095 OUString const & aName, css::uno::Any const & aElement)
1096{
1098 Broadcaster bc;
1099 {
1100 osl::MutexGuard g(*lock_);
1103 if (getChild(aName).is()) {
1104 throw css::container::ElementExistException(
1105 aName, getXWeak());
1106 }
1107 Modifications localMods;
1108 switch (getNode()->kind()) {
1110 if (!isValidName(aName, false)) {
1111 throw css::lang::IllegalArgumentException(
1112 aName, getXWeak(), 0);
1113 }
1114 insertLocalizedValueChild(aName, aElement, &localMods);
1115 break;
1116 case Node::KIND_GROUP:
1117 {
1118 if (!isValidName(aName, false)) {
1119 throw css::lang::IllegalArgumentException(
1120 aName, getXWeak(), 0);
1121 }
1122 checkValue(aElement, TYPE_ANY, true);
1123 rtl::Reference child(
1124 new ChildAccess(
1126 new PropertyNode(
1127 Data::NO_LAYER, TYPE_ANY, true, aElement, true)));
1128 markChildAsModified(child);
1129 localMods.add(child->getRelativePath());
1130 }
1131 break;
1132 case Node::KIND_SET:
1133 {
1134 if (!isValidName(aName, true)) {
1135 throw css::lang::IllegalArgumentException(
1136 aName, getXWeak(), 0);
1137 }
1139 getFreeSetMember(aElement));
1140 freeAcc->bind(getRootAccess(), this, aName); // must not throw
1141 markChildAsModified(freeAcc); //TODO: must not throw
1142 localMods.add(freeAcc->getRelativePath());
1143 }
1144 break;
1145 default:
1146 assert(false); // this cannot happen
1147 break;
1148 }
1149 getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
1150 }
1151 bc.send();
1152}
1153
1154void Access::removeByName(OUString const & aName)
1155{
1157 Broadcaster bc;
1158 {
1159 osl::MutexGuard g(*lock_);
1162 if (!child.is() || child->isFinalized() ||
1163 child->getNode()->getMandatory() != Data::NO_LAYER)
1164 {
1165 throw css::container::NoSuchElementException(
1166 aName, getXWeak());
1167 }
1168 if (getNode()->kind() == Node::KIND_GROUP) {
1169 rtl::Reference< Node > p(child->getNode());
1170 if (p->kind() != Node::KIND_PROPERTY ||
1171 !static_cast< PropertyNode * >(p.get())->isExtension())
1172 {
1173 throw css::container::NoSuchElementException(
1174 aName, getXWeak());
1175 }
1176 }
1177 Modifications localMods;
1178 localMods.add(child->getRelativePath());
1179 // unbind() modifies the parent chain that markChildAsModified() walks,
1180 // so order is important:
1181 markChildAsModified(child); //TODO: must not throw
1182 child->unbind();
1183 getNotificationRoot()->initBroadcaster(localMods.getRoot(), &bc);
1184 }
1185 bc.send();
1186}
1187
1188css::uno::Reference< css::uno::XInterface > Access::createInstance()
1189{
1190 assert(thisIs(IS_SET|IS_UPDATE));
1191 OUString tmplName(
1192 static_cast< SetNode * >(getNode().get())->getDefaultTemplateName());
1194 components_.getTemplate(tmplName));
1195 if (!tmpl.is()) {
1196 throw css::uno::Exception(
1197 "unknown template " + tmplName,
1198 getXWeak());
1199 }
1200 rtl::Reference< Node > node(tmpl->clone(true));
1201 node->setLayer(Data::NO_LAYER);
1202 return cppu::getXWeak(
1203 new ChildAccess(components_, getRootAccess(), node));
1204}
1205
1206css::uno::Reference< css::uno::XInterface > Access::createInstanceWithArguments(
1207 css::uno::Sequence< css::uno::Any > const & aArguments)
1208{
1209 assert(thisIs(IS_SET|IS_UPDATE));
1210 if (aArguments.hasElements()) {
1211 throw css::uno::Exception(
1212 ("configuration SimpleSetUpdate createInstanceWithArguments"
1213 " must not specify any arguments"),
1214 getXWeak());
1215 }
1216 return createInstance();
1217}
1218
1220 components_(components), disposed_(false), lock_( lock() )
1221{
1222}
1223
1225
1227 assert(broadcaster != nullptr);
1228 for (auto const& disposeListener : disposeListeners_)
1229 {
1230 broadcaster->addDisposeNotification(
1231 disposeListener,
1232 css::lang::EventObject(getXWeak()));
1233 }
1234 for (auto const& containerListener : containerListeners_)
1235 {
1236 broadcaster->addDisposeNotification(
1237 containerListener,
1238 css::lang::EventObject(getXWeak()));
1239 }
1240 for (auto const& propertyChangeListener : propertyChangeListeners_)
1241 {
1242 for (auto const& propertyChangeListenerElement : propertyChangeListener.second)
1243 {
1244 broadcaster->addDisposeNotification(
1245 propertyChangeListenerElement,
1246 css::lang::EventObject(
1247 getXWeak()));
1248 }
1249 }
1250 for (auto const& vetoableChangeListener : vetoableChangeListeners_)
1251 {
1252 for (auto const& vetoableChangeListenerElement : vetoableChangeListener.second)
1253 {
1254 broadcaster->addDisposeNotification(
1255 vetoableChangeListenerElement,
1256 css::lang::EventObject(
1257 getXWeak()));
1258 }
1259 }
1260 for (auto const& propertiesChangeListener : propertiesChangeListeners_)
1261 {
1262 broadcaster->addDisposeNotification(
1263 propertiesChangeListener,
1264 css::lang::EventObject(getXWeak()));
1265 }
1266 //TODO: iterate over children w/ listeners (incl. unmodified ones):
1267 for (ModifiedChildren::iterator i(modifiedChildren_.begin());
1268 i != modifiedChildren_.end(); ++i)
1269 {
1271 if (child.is()) {
1272 child->initDisposeBroadcaster(broadcaster);
1273 }
1274 }
1275}
1276
1277void Access::clearListeners() noexcept {
1278 disposeListeners_.clear();
1279 containerListeners_.clear();
1283 //TODO: iterate over children w/ listeners (incl. unmodified ones):
1284 for (ModifiedChildren::iterator i(modifiedChildren_.begin());
1285 i != modifiedChildren_.end(); ++i)
1286 {
1288 if (child.is()) {
1289 child->clearListeners();
1290 }
1291 }
1292}
1293
1294css::uno::Any Access::queryInterface(css::uno::Type const & aType)
1295{
1296 css::uno::Any res(OWeakObject::queryInterface(aType));
1297 if (res.hasValue()) {
1298 return res;
1299 }
1301 aType, static_cast< css::lang::XTypeProvider * >(this),
1302 static_cast< css::lang::XServiceInfo * >(this),
1303 static_cast< css::lang::XComponent * >(this),
1304 static_cast< css::container::XHierarchicalNameAccess * >(this),
1305 static_cast< css::container::XContainer * >(this),
1306 static_cast< css::beans::XExactName * >(this),
1307 static_cast< css::container::XHierarchicalName * >(this),
1308 static_cast< css::container::XNamed * >(this),
1309 static_cast< css::beans::XProperty * >(this),
1310 static_cast< css::container::XElementAccess * >(this),
1311 static_cast< css::container::XNameAccess * >(this));
1312 if (res.hasValue()) {
1313 return res;
1314 }
1315 if (getNode()->kind() == Node::KIND_GROUP) {
1317 aType, static_cast< css::beans::XPropertySetInfo * >(this),
1318 static_cast< css::beans::XPropertySet * >(this),
1319 static_cast< css::beans::XMultiPropertySet * >(this),
1320 static_cast< css::beans::XHierarchicalPropertySet * >(this),
1321 static_cast< css::beans::XMultiHierarchicalPropertySet * >(this),
1322 static_cast< css::beans::XHierarchicalPropertySetInfo * >(this));
1323 if (res.hasValue()) {
1324 return res;
1325 }
1326 }
1327 if (getRootAccess()->isUpdate()) {
1329 aType, static_cast< css::container::XNameReplace * >(this),
1330 static_cast< css::container::XHierarchicalNameReplace * >(this));
1331 if (res.hasValue()) {
1332 return res;
1333 }
1334 if (getNode()->kind() != Node::KIND_GROUP ||
1335 static_cast< GroupNode * >(getNode().get())->isExtensible())
1336 {
1338 aType, static_cast< css::container::XNameContainer * >(this));
1339 if (res.hasValue()) {
1340 return res;
1341 }
1342 }
1343 if (getNode()->kind() == Node::KIND_SET) {
1345 aType, static_cast< css::lang::XSingleServiceFactory * >(this));
1346 }
1347 }
1348 return res;
1349}
1350
1351
1353 if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY &&
1355 {
1356 throw css::uno::RuntimeException(
1357 "configmgr Access to specialized LocalizedPropertyNode",
1358 getXWeak());
1359 }
1360}
1361
1364 return parent.is() ? parent->getNode() : rtl::Reference< Node >();
1365}
1366
1368 OUString locale;
1369 if (getNode()->kind() == Node::KIND_LOCALIZED_PROPERTY
1370 && name.startsWith("*", &locale))
1371 {
1372 if (locale.startsWith("*")) {
1373 SAL_WARN(
1374 "configmgr",
1375 ("access best-matching localized property value via"
1376 " \"*<locale>\" with <locale> \"")
1377 << locale << "\" recursively starting with \"*\"");
1378 return getChild(locale);
1379 }
1381 locale.isEmpty(), "configmgr",
1382 ("access best-matching localized property value via \"*<locale>\""
1383 " with empty <locale>; falling back to defaults"));
1384
1385 // Since the locale given to us is the one used at initialization,
1386 // here we override it with the actual current-user's language to
1387 // support per-view localization in LOK.
1390
1391 if (!locale.isEmpty()) {
1392 // Try exact match first, avoiding all fallback overhead.
1393 rtl::Reference<ChildAccess> directChild(getChild(locale));
1394 if (directChild.is())
1395 return directChild;
1396
1397 LanguageTag aLanguageTag(locale, true);
1398 if (aLanguageTag.getBcp47() != locale)
1399 {
1400 // Original may be overridden by a known locale, for example
1401 // "zh-Hant-TW" by "zh-TW".
1402 rtl::Reference<ChildAccess> child(getChild(aLanguageTag.getBcp47()));
1403 if (child.is())
1404 return child;
1405 }
1406
1407 // Find the best match using the LanguageTag fallback mechanism,
1408 // excluding the original tag.
1409 std::vector<OUString> aFallbacks = aLanguageTag.getFallbackStrings(false);
1410 for (const OUString& rFallback : aFallbacks)
1411 {
1412 rtl::Reference<ChildAccess> child(getChild(rFallback));
1413 if (child.is())
1414 return child;
1415 }
1416
1417 // As a workaround for broken xcu data that does not use shortest
1418 // xml:lang attributes, look for the first entry with the same first
1419 // segment as the requested language tag before falling back to
1420 // defaults (see fdo#33638):
1421 auto const i = comphelper::string::indexOfAny(locale, u"-_", 1);
1422 if (i != -1) {
1423 locale = locale.copy(0, i);
1424 }
1425 assert(!locale.isEmpty());
1426 std::vector< rtl::Reference< ChildAccess > > children(
1427 getAllChildren());
1428 for (auto const& child : children)
1429 {
1430 const OUString & name2(child->getNameInternal());
1431 if (name2.startsWith(locale) &&
1432 (name2.getLength() == locale.getLength() ||
1433 name2[locale.getLength()] == '-' ||
1434 name2[locale.getLength()] == '_'))
1435 {
1436 return child;
1437 }
1438 }
1439 }
1440 // Defaults are the "en-US" locale, the "en" locale, the empty string locale, the first child (if
1441 // any, and if the property is non-nillable), or a null ChildAccess, in that order:
1443 if (child.is()) {
1444 return child;
1445 }
1446 child = getChild("en");
1447 if (child.is()) {
1448 return child;
1449 }
1450 child = getChild("");
1451 if (child.is()) {
1452 return child;
1453 }
1454 if (!static_cast<LocalizedPropertyNode *>(getNode().get())->isNillable()) {
1455 std::vector< rtl::Reference< ChildAccess > > children(getAllChildren());
1456 if (!children.empty()) {
1457 return children.front();
1458 }
1459 }
1461 }
1462 ModifiedChildren::iterator i(modifiedChildren_.find(name));
1463 return i == modifiedChildren_.end()
1465}
1466
1467std::vector< rtl::Reference< ChildAccess > > Access::getAllChildren() {
1468 std::vector< rtl::Reference< ChildAccess > > vec;
1469 NodeMap const & members = getNode()->getMembers();
1470 for (auto const& member : members)
1471 {
1472 if (modifiedChildren_.find(member.first) == modifiedChildren_.end()) {
1473 vec.push_back(getUnmodifiedChild(member.first));
1474 assert(vec.back().is());
1475 }
1476 }
1477 for (ModifiedChildren::iterator i(modifiedChildren_.begin());
1478 i != modifiedChildren_.end(); ++i)
1479 {
1481 if (child.is()) {
1482 vec.push_back(child);
1483 }
1484 }
1485 return vec;
1486}
1487
1488void Access::checkValue(css::uno::Any const & value, Type type, bool nillable) {
1489 bool ok;
1490 switch (type) {
1491 case TYPE_ERROR:
1492 ok = false;
1493 break;
1494 case TYPE_ANY:
1495 switch (getDynamicType(value)) {
1496 case TYPE_ERROR:
1497 ok = false;
1498 break;
1499 case TYPE_NIL:
1500 ok = nillable;
1501 break;
1502 default:
1503 ok = true;
1504 break;
1505 case TYPE_ANY:
1506 for (;;) std::abort(); // cannot happen
1507 }
1508 break;
1509 default:
1510 ok = value.hasValue() ? value.isExtractableTo(mapType(type)) : nillable;
1511 break;
1512 case TYPE_NIL:
1513 for (;;) std::abort(); // cannot happen
1514 }
1515 if (!ok) {
1516 throw css::lang::IllegalArgumentException(
1517 "configmgr inappropriate property value",
1518 getXWeak(), -1);
1519 }
1520}
1521
1523 OUString const & name, css::uno::Any const & value,
1524 Modifications * localModifications)
1525{
1526 assert(localModifications != nullptr);
1527 LocalizedPropertyNode * locprop = static_cast< LocalizedPropertyNode * >(
1528 getNode().get());
1529 checkValue(value, locprop->getStaticType(), locprop->isNillable());
1530 rtl::Reference child(
1531 new ChildAccess(
1532 components_, getRootAccess(), this, name,
1534 markChildAsModified(child);
1535 localModifications->add(child->getRelativePath());
1536}
1537
1539 std::vector< css::util::ElementChange > * changes)
1540{
1541 assert(changes != nullptr);
1542 for (ModifiedChildren::iterator i(modifiedChildren_.begin());
1543 i != modifiedChildren_.end(); ++i)
1544 {
1546 if (child.is()) {
1547 child->reportChildChanges(changes);
1548 changes->push_back(css::util::ElementChange());
1549 //TODO: changed value and/or inserted node
1550 } else {
1551 changes->push_back(css::util::ElementChange()); //TODO: removed node
1552 }
1553 }
1554}
1555
1557 bool valid, Modifications * globalModifications)
1558{
1559 assert(globalModifications != nullptr);
1560 while (!modifiedChildren_.empty()) {
1561 bool childValid = valid;
1562 ModifiedChildren::iterator i(modifiedChildren_.begin());
1564 if (child.is()) {
1565 childValid = childValid && !child->isFinalized();
1566 child->commitChanges(childValid, globalModifications);
1567 //TODO: currently, this is called here for directly inserted
1568 // children as well as for children whose sub-children were
1569 // modified (and should never be called for directly removed
1570 // children); clarify what exactly should happen here for
1571 // directly inserted children
1572 }
1573 NodeMap & members = getNode()->getMembers();
1574 NodeMap::iterator j(members.find(i->first));
1575 if (child.is()) {
1576 // Inserted:
1577 if (j != members.end()) {
1578 childValid = childValid &&
1579 j->second->getFinalized() == Data::NO_LAYER;
1580 if (childValid) {
1581 child->getNode()->setMandatory(j->second->getMandatory());
1582 }
1583 }
1584 if (childValid) {
1585 members[i->first] = child->getNode();
1586 }
1587 } else {
1588 // Removed:
1589 childValid = childValid && j != members.end() &&
1590 j->second->getFinalized() == Data::NO_LAYER &&
1591 j->second->getMandatory() == Data::NO_LAYER;
1592 if (childValid) {
1593 members.erase(j);
1594 }
1595 }
1596 if (childValid && i->second.directlyModified) {
1597 std::vector<OUString> path(getAbsolutePath());
1598 path.push_back(i->first);
1600 globalModifications->add(path);
1601 }
1602 i->second.child->committed();
1603 modifiedChildren_.erase(i);
1604 }
1605}
1606
1608 Modifications::Node const & modifications, Broadcaster * broadcaster,
1609 std::vector< css::util::ElementChange > * allChanges)
1610{
1611 assert(broadcaster != nullptr);
1612 std::vector< css::beans::PropertyChangeEvent > propChanges;
1613 bool collectPropChanges = !propertiesChangeListeners_.empty();
1614 for (const auto & i : modifications.children)
1615 {
1617 if (child.is()) {
1618 switch (child->getNode()->kind()) {
1620 if (!i.second.children.empty()) {
1622 child->initBroadcasterAndChanges(
1623 i.second, broadcaster, allChanges);
1624 //TODO: if allChanges==0, recurse only into children
1625 // w/ listeners
1626 } else {
1627 //TODO: filter child mods that are irrelevant for
1628 // locale:
1629 for (auto const& containerListener : containerListeners_)
1630 {
1631 broadcaster->
1632 addContainerElementReplacedNotification(
1633 containerListener,
1634 css::container::ContainerEvent(
1635 getXWeak(),
1636 css::uno::Any(i.first),
1637 css::uno::Any(), css::uno::Any()));
1638 //TODO: non-void Element, ReplacedElement
1639 }
1640 PropertyChangeListeners::iterator j(
1641 propertyChangeListeners_.find(i.first));
1642 if (j != propertyChangeListeners_.end()) {
1643 for (auto const& propertyChangeListenerElement : j->second)
1644 {
1645 broadcaster->addPropertyChangeNotification(
1646 propertyChangeListenerElement,
1647 css::beans::PropertyChangeEvent(
1648 getXWeak(),
1649 i.first, false, -1, css::uno::Any(),
1650 css::uno::Any()));
1651 }
1652 }
1653 j = propertyChangeListeners_.find("");
1654 if (j != propertyChangeListeners_.end()) {
1655 for (auto const& propertyChangeListenerElement : j->second)
1656 {
1657 broadcaster->addPropertyChangeNotification(
1658 propertyChangeListenerElement,
1659 css::beans::PropertyChangeEvent(
1660 getXWeak(),
1661 i.first, false, -1, css::uno::Any(),
1662 css::uno::Any()));
1663 }
1664 }
1665 if (allChanges != nullptr) {
1666 allChanges->push_back(
1667 css::util::ElementChange(
1668 css::uno::Any(
1669 child->getRelativePathRepresentation()),
1670 css::uno::Any(), css::uno::Any()));
1671 //TODO: non-void Element, ReplacedElement
1672 }
1673 if (collectPropChanges) {
1674 propChanges.emplace_back(
1675 getXWeak(),
1676 i.first, false, -1, css::uno::Any(),
1677 css::uno::Any());
1678 }
1679 }
1680 }
1681 // else: spurious Modifications::Node not representing a change
1682 break;
1685 for (auto const& containerListener : containerListeners_)
1686 {
1688 containerListener,
1689 css::container::ContainerEvent(
1690 getXWeak(),
1691 css::uno::Any(i.first), child->asValue(),
1692 css::uno::Any()));
1693 //TODO: distinguish add/modify; non-void ReplacedElement
1694 }
1695 if (allChanges != nullptr) {
1696 allChanges->push_back(
1697 css::util::ElementChange(
1698 css::uno::Any(
1699 child->getRelativePathRepresentation()),
1700 child->asValue(), css::uno::Any()));
1701 //TODO: non-void ReplacedElement
1702 }
1703 assert(!collectPropChanges);
1704 break;
1706 {
1707 for (auto const& containerListener : containerListeners_)
1708 {
1710 containerListener,
1711 css::container::ContainerEvent(
1712 getXWeak(),
1713 css::uno::Any(i.first), child->asValue(),
1714 css::uno::Any()));
1715 //TODO: distinguish add/remove/modify; non-void
1716 // ReplacedElement
1717 }
1718 PropertyChangeListeners::iterator j(
1719 propertyChangeListeners_.find(i.first));
1720 if (j != propertyChangeListeners_.end()) {
1721 for (auto const& propertyChangeListenerElement : j->second)
1722 {
1723 broadcaster->addPropertyChangeNotification(
1724 propertyChangeListenerElement,
1725 css::beans::PropertyChangeEvent(
1726 getXWeak(),
1727 i.first, false, -1, css::uno::Any(),
1728 css::uno::Any()));
1729 }
1730 }
1731 j = propertyChangeListeners_.find("");
1732 if (j != propertyChangeListeners_.end()) {
1733 for (auto const& propertyChangeListenerElement : j->second)
1734 {
1735 broadcaster->addPropertyChangeNotification(
1736 propertyChangeListenerElement,
1737 css::beans::PropertyChangeEvent(
1738 getXWeak(),
1739 i.first, false, -1, css::uno::Any(),
1740 css::uno::Any()));
1741 }
1742 }
1743 if (allChanges != nullptr) {
1744 allChanges->push_back(
1745 css::util::ElementChange(
1746 css::uno::Any(
1747 child->getRelativePathRepresentation()),
1748 child->asValue(), css::uno::Any()));
1749 //TODO: non-void ReplacedElement
1750 }
1751 if (collectPropChanges) {
1752 propChanges.emplace_back(
1753 getXWeak(),
1754 i.first, false, -1, css::uno::Any(),
1755 css::uno::Any());
1756 }
1757 }
1758 break;
1759 case Node::KIND_GROUP:
1760 case Node::KIND_SET:
1761 if (i.second.children.empty()) {
1762 if (!child->getNode()->getTemplateName().isEmpty()) {
1763 for (auto const& containerListener : containerListeners_)
1764 {
1765 broadcaster->
1766 addContainerElementInsertedNotification(
1767 containerListener,
1768 css::container::ContainerEvent(
1769 getXWeak(),
1770 css::uno::Any(i.first),
1771 child->asValue(), css::uno::Any()));
1772 }
1773 if (allChanges != nullptr) {
1774 allChanges->push_back(
1775 css::util::ElementChange(
1776 css::uno::Any(
1777 child->getRelativePathRepresentation()),
1778 css::uno::Any(), css::uno::Any()));
1779 //TODO: non-void Element, ReplacedElement
1780 }
1781 }
1782 // else: spurious Modifications::Node not representing a
1783 // change
1784 } else {
1785 child->initBroadcasterAndChanges(
1786 i.second, broadcaster, allChanges);
1787 //TODO: if allChanges==0, recurse only into children w/
1788 // listeners
1789 }
1790 break;
1791 case Node::KIND_ROOT:
1792 assert(false); // this cannot happen
1793 break;
1794 }
1795 } else {
1796 switch (getNode()->kind()) {
1798 // Removed localized property value:
1800 for (auto const& containerListener : containerListeners_)
1801 {
1803 containerListener,
1804 css::container::ContainerEvent(
1805 getXWeak(),
1806 css::uno::Any(i.first), css::uno::Any(),
1807 css::uno::Any()));
1808 //TODO: non-void ReplacedElement
1809 }
1810 if (allChanges != nullptr) {
1811 OUStringBuffer path(getRelativePathRepresentation());
1812 if (!path.isEmpty()) {
1813 path.append('/');
1814 }
1815 path.append(Data::createSegment(u"*", i.first));
1816 allChanges->push_back(
1817 css::util::ElementChange(
1818 css::uno::Any(path.makeStringAndClear()),
1819 css::uno::Any(), css::uno::Any()));
1820 //TODO: non-void ReplacedElement
1821 }
1822 assert(!collectPropChanges);
1823 break;
1824 case Node::KIND_GROUP:
1825 {
1826 // Removed (non-localized) extension property:
1827 for (auto const& containerListener : containerListeners_)
1828 {
1830 containerListener,
1831 css::container::ContainerEvent(
1832 getXWeak(),
1833 css::uno::Any(i.first), css::uno::Any(),
1834 css::uno::Any()));
1835 //TODO: non-void ReplacedElement
1836 }
1837 PropertyChangeListeners::iterator j(
1838 propertyChangeListeners_.find(i.first));
1839 if (j != propertyChangeListeners_.end()) {
1840 for (auto const& propertyChangeListenerElement : j->second)
1841 {
1842 broadcaster->addPropertyChangeNotification(
1843 propertyChangeListenerElement,
1844 css::beans::PropertyChangeEvent(
1845 getXWeak(),
1846 i.first, false, -1, css::uno::Any(),
1847 css::uno::Any()));
1848 }
1849 }
1850 j = propertyChangeListeners_.find("");
1851 if (j != propertyChangeListeners_.end()) {
1852 for (auto const& propertyChangeListenerElement : j->second)
1853 {
1854 broadcaster->addPropertyChangeNotification(
1855 propertyChangeListenerElement,
1856 css::beans::PropertyChangeEvent(
1857 getXWeak(),
1858 i.first, false, -1, css::uno::Any(),
1859 css::uno::Any()));
1860 }
1861 }
1862 if (allChanges != nullptr) {
1863 OUStringBuffer path(
1865 if (!path.isEmpty()) {
1866 path.append('/');
1867 }
1868 path.append(i.first);
1869 allChanges->push_back(
1870 css::util::ElementChange(
1871 css::uno::Any(path.makeStringAndClear()),
1872 css::uno::Any(), css::uno::Any()));
1873 //TODO: non-void ReplacedElement
1874 }
1875 if (collectPropChanges) {
1876 propChanges.emplace_back(
1877 getXWeak(),
1878 i.first, false, -1, css::uno::Any(),
1879 css::uno::Any());
1880 }
1881 }
1882 break;
1883 case Node::KIND_SET:
1884 // Removed set member:
1885 if (i.second.children.empty()) {
1886 for (auto const& containerListener : containerListeners_)
1887 {
1889 containerListener,
1890 css::container::ContainerEvent(
1891 getXWeak(),
1892 css::uno::Any(i.first),
1893 css::uno::Any(), css::uno::Any()));
1894 //TODO: non-void ReplacedElement
1895 }
1896 if (allChanges != nullptr) {
1897 OUStringBuffer path(
1899 if (!path.isEmpty()) {
1900 path.append('/');
1901 }
1902 path.append(Data::createSegment(u"*", i.first));
1903 allChanges->push_back(
1904 css::util::ElementChange(
1905 css::uno::Any(path.makeStringAndClear()),
1906 css::uno::Any(), css::uno::Any()));
1907 //TODO: non-void ReplacedElement
1908 }
1909 }
1910 // else: spurious Modifications::Node not representing a change
1911 break;
1912 default:
1913 assert(false); // this cannot happen
1914 break;
1915 }
1916 }
1917 }
1918 if (!propChanges.empty()) {
1919 css::uno::Sequence< css::beans::PropertyChangeEvent > seq(
1920 comphelper::containerToSequence(propChanges));
1921 for (auto const& propertyChangeListener : propertiesChangeListeners_)
1922 {
1923 broadcaster->addPropertiesChangeNotification(propertyChangeListener, seq);
1924 }
1925 }
1926}
1927
1928
1930 directlyModified(false)
1931{}
1932
1934 rtl::Reference< ChildAccess > theChild, bool theDirectlyModified):
1935 child(std::move(theChild)), directlyModified(theDirectlyModified)
1936{}
1937
1939 ModifiedChildren::iterator const & childIterator)
1940{
1941 return (childIterator->second.child->getParentAccess() == this &&
1942 (childIterator->second.child->getNameInternal() ==
1943 childIterator->first))
1944 ? childIterator->second.child : rtl::Reference< ChildAccess >();
1945}
1946
1948 const OUString &name, const rtl::Reference< Node > &node)
1949{
1950 rtl::Reference child(
1951 new ChildAccess(components_, getRootAccess(), this, name, node));
1952 cachedChildren_[name] = child.get();
1953 return child;
1954}
1955
1957 OUString const & name)
1958{
1959 assert(modifiedChildren_.find(name) == modifiedChildren_.end());
1960 rtl::Reference< Node > node(getNode()->getMember(name));
1961 if (!node.is()) {
1963 }
1964 WeakChildMap::iterator i(cachedChildren_.find(name));
1965 if (i != cachedChildren_.end()) {
1967 if (i->second->acquireCounting() > 1) {
1968 child.set(i->second); // must not throw
1969 }
1970 i->second->releaseNondeleting();
1971 if (child.is()) {
1972 child->setNode(node);
1973 return child;
1974 }
1975 }
1976 return createUnmodifiedChild(name,node);
1977}
1978
1980 sal_Int32 i = 0;
1981 // For backwards compatibility, allow absolute paths where meaningful:
1982 if( path.startsWith("/") ) {
1983 ++i;
1984 if (!getRootAccess().is()) {
1986 }
1987 std::vector<OUString> abs(getAbsolutePath());
1988 for (auto const& elem : abs)
1989 {
1990 OUString name1;
1991 bool setElement1;
1992 OUString templateName1;
1994 path, i, &name1, &setElement1, &templateName1);
1995 if (i == -1 || (i != path.getLength() && path[i] != '/')) {
1997 }
1998 OUString name2;
1999 bool setElement2;
2000 OUString templateName2;
2001 Data::parseSegment(elem, 0, &name2, &setElement2, &templateName2);
2002 if (name1 != name2 || setElement1 != setElement2 ||
2003 (setElement1 &&
2004 !Data::equalTemplateNames(templateName1, templateName2)))
2005 {
2007 }
2008 if (i != path.getLength()) {
2009 ++i;
2010 }
2011 }
2012 }
2013 for (rtl::Reference< Access > parent(this);;) {
2014 OUString name;
2015 bool setElement;
2016 OUString templateName;
2017 i = Data::parseSegment(path, i, &name, &setElement, &templateName);
2018 if (i == -1 || (i != path.getLength() && path[i] != '/')) {
2020 }
2021 rtl::Reference< ChildAccess > child(parent->getChild(name));
2022 if (!child.is()) {
2024 }
2025 if (setElement) {
2026 rtl::Reference< Node > p(parent->getNode());
2027 switch (p->kind()) {
2030 !templateName.isEmpty())
2031 {
2033 }
2034 break;
2035 case Node::KIND_SET:
2036 if (!templateName.isEmpty() &&
2037 !static_cast< SetNode * >(p.get())->isValidTemplate(
2038 templateName))
2039 {
2041 }
2042 break;
2043 default:
2045 }
2046 }
2047 // For backwards compatibility, ignore a final slash after non-value
2048 // nodes:
2049 if (child->isValue()) {
2050 return i == path.getLength()
2052 } else if (i >= path.getLength() - 1) {
2053 return child;
2054 }
2055 ++i;
2056 parent = child.get();
2057 }
2058}
2059
2061 OUString const & name, css::uno::Any const & value,
2062 Modifications * localModifications)
2063{
2064 assert(localModifications != nullptr);
2066 if (!child.is()) {
2067 return false;
2068 }
2069 child->checkFinalized();
2070 child->setProperty(value, localModifications);
2071 return true;
2072}
2073
2074css::beans::Property Access::asProperty() {
2076 bool nillable;
2077 bool removable;
2079 switch (p->kind()) {
2081 {
2082 PropertyNode * prop = static_cast< PropertyNode * >(p.get());
2083 type = mapType(prop->getStaticType());
2084 nillable = prop->isNillable();
2085 removable = prop->isExtension();
2086 }
2087 break;
2089 {
2090 LocalizedPropertyNode * locprop =
2091 static_cast< LocalizedPropertyNode *>(p.get());
2094 //TODO: correct?
2095 removable = false;
2096 } else {
2097 type = mapType(locprop->getStaticType());
2098 removable = false; //TODO ???
2099 }
2100 nillable = locprop->isNillable();
2101 }
2102 break;
2104 {
2105 LocalizedPropertyNode * locprop =
2106 static_cast< LocalizedPropertyNode * >(getParentNode().get());
2107 type = mapType(locprop->getStaticType());
2108 nillable = locprop->isNillable();
2109 removable = false; //TODO ???
2110 }
2111 break;
2112 default:
2114 nillable = false;
2116 removable = parent.is() && parent->kind() == Node::KIND_SET;
2117 break;
2118 }
2119 return css::beans::Property(
2120 getNameInternal(), -1, type,
2121 (css::beans::PropertyAttribute::BOUND | //TODO: correct for group/set?
2122 css::beans::PropertyAttribute::CONSTRAINED |
2123 (nillable ? css::beans::PropertyAttribute::MAYBEVOID : 0) |
2124 (getRootAccess()->isUpdate() && removable
2125 ? css::beans::PropertyAttribute::REMOVABLE : 0) |
2126 (!getRootAccess()->isUpdate() || p->getFinalized() != Data::NO_LAYER
2127 ? css::beans::PropertyAttribute::READONLY : 0))); //TODO: MAYBEDEFAULT
2128}
2129
2131 if (isFinalized()) {
2132 throw css::lang::IllegalArgumentException(
2133 "configmgr modification of finalized item",
2134 getXWeak(), -1);
2135 }
2136}
2137
2138void Access::checkKnownProperty(OUString const & descriptor) {
2139 if (descriptor.isEmpty()) {
2140 return;
2141 }
2142 rtl::Reference< ChildAccess > child(getChild(descriptor));
2143 if (child.is()) {
2144 switch (child->getNode()->kind()) {
2146 return;
2149 return;
2150 }
2151 break;
2154 return;
2155 }
2156 break;
2157 default:
2158 break;
2159 }
2160 }
2161 throw css::beans::UnknownPropertyException(
2162 descriptor, getXWeak());
2163}
2164
2166 css::uno::Any const & value)
2167{
2168 css::uno::Reference<XInterface> xTmp;
2169 value >>= xTmp;
2170 rtl::Reference< ChildAccess > freeAcc = dynamic_cast<ChildAccess*>(xTmp.get());
2171 if (!freeAcc.is() || freeAcc->getParentAccess().is() ||
2172 (freeAcc->isInTransaction() &&
2173 freeAcc->getRootAccess() != getRootAccess()))
2174 {
2175 throw css::lang::IllegalArgumentException(
2176 "configmgr inappropriate set element",
2177 getXWeak(), 1);
2178 }
2179 assert(dynamic_cast< SetNode * >(getNode().get()) != nullptr);
2180 if (!static_cast< SetNode * >(getNode().get())->isValidTemplate(
2181 freeAcc->getNode()->getTemplateName()))
2182 {
2183 throw css::lang::IllegalArgumentException(
2184 "configmgr inappropriate set element",
2185 getXWeak(), 1);
2186 }
2187 return freeAcc;
2188}
2189
2191 for (rtl::Reference< Access > p(this);;) {
2192 rtl::Reference< Access > parent(p->getParentAccess());
2193 if (!parent.is()) {
2194 return p;
2195 }
2196 p = parent;
2197 }
2198}
2199
2200#if !defined NDEBUG
2201bool Access::thisIs(int what) {
2202 osl::MutexGuard g(*lock_);
2204 Node::Kind k(p->kind());
2205 return (k != Node::KIND_PROPERTY && k != Node::KIND_LOCALIZED_VALUE &&
2206 ((what & IS_GROUP) == 0 || k == Node::KIND_GROUP) &&
2207 ((what & IS_SET) == 0 || k == Node::KIND_SET) &&
2208 ((what & IS_EXTENSIBLE) == 0 || k != Node::KIND_GROUP ||
2209 static_cast< GroupNode * >(p.get())->isExtensible()) &&
2210 ((what & IS_GROUP_MEMBER) == 0 ||
2211 getParentNode()->kind() == Node::KIND_GROUP)) ||
2212 ((what & IS_SET_MEMBER) == 0 ||
2213 getParentNode()->kind() == Node::KIND_SET) ||
2214 ((what & IS_UPDATE) == 0 || getRootAccess()->isUpdate());
2215}
2216#endif
2217
2218}
2219
2220/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const OUString & getBcp47(bool bResolveSystem=true) const
::std::vector< OUString > getFallbackStrings(bool bIncludeFullBcp47) const
void commitChildChanges(bool valid, Modifications *globalModifications)
Definition: access.cxx:1556
virtual void SAL_CALL setPropertyValue(OUString const &aPropertyName, css::uno::Any const &aValue) override
Definition: access.cxx:697
PropertyChangeListeners propertyChangeListeners_
Definition: access.hxx:432
virtual css::uno::Any SAL_CALL getByName(OUString const &aName) override
Definition: access.cxx:396
void checkKnownProperty(OUString const &descriptor)
Definition: access.cxx:2138
virtual void SAL_CALL addContainerListener(css::uno::Reference< css::container::XContainerListener > const &xListener) override
Definition: access.cxx:494
virtual css::beans::Property SAL_CALL getAsProperty() override
Definition: access.cxx:683
rtl::Reference< Access > getNotificationRoot()
Definition: access.cxx:2190
virtual css::uno::Sequence< css::uno::Any > SAL_CALL getPropertyValues(css::uno::Sequence< OUString > const &aPropertyNames) override
Definition: access.cxx:854
DisposeListeners disposeListeners_
Definition: access.hxx:430
virtual void SAL_CALL removeEventListener(css::uno::Reference< css::lang::XEventListener > const &aListener) override
Definition: access.cxx:318
PropertiesChangeListeners propertiesChangeListeners_
Definition: access.hxx:434
virtual const OUString & getNameInternal()=0
virtual css::uno::Sequence< css::uno::Any > SAL_CALL getHierarchicalPropertyValues(css::uno::Sequence< OUString > const &aHierarchicalPropertyNames) override
Definition: access.cxx:1011
virtual css::uno::Any SAL_CALL getHierarchicalPropertyValue(OUString const &aHierarchicalPropertyName) override
Definition: access.cxx:960
rtl::Reference< ChildAccess > getModifiedChild(ModifiedChildren::iterator const &childIterator)
Definition: access.cxx:1938
Components & components_
Definition: access.hxx:427
virtual void SAL_CALL removeByName(OUString const &aName) override
Definition: access.cxx:1154
virtual void initBroadcaster(Modifications::Node const &modifications, Broadcaster *broadcaster)
Definition: access.cxx:167
virtual rtl::Reference< RootAccess > getRootAccess()=0
WeakChildMap cachedChildren_
Definition: access.hxx:429
void checkValue(css::uno::Any const &value, Type type, bool nillable)
Definition: access.cxx:1488
rtl::Reference< ChildAccess > getUnmodifiedChild(OUString const &name)
Definition: access.cxx:1956
virtual sal_Bool SAL_CALL hasPropertyByHierarchicalName(OUString const &aHierarchicalName) override
Definition: access.cxx:1046
oslInterlockedCount acquireCounting()
Definition: access.cxx:126
virtual sal_Bool SAL_CALL hasPropertyByName(OUString const &Name) override
Definition: access.cxx:562
virtual css::uno::Sequence< css::beans::Property > SAL_CALL getProperties() override
Definition: access.cxx:536
virtual rtl::Reference< Node > getNode()=0
virtual void clearListeners() noexcept
Definition: access.cxx:1277
rtl::Reference< Node > getParentNode()
Definition: access.cxx:1362
bool setChildProperty(OUString const &name, css::uno::Any const &value, Modifications *localModifications)
Definition: access.cxx:2060
virtual void initDisposeBroadcaster(Broadcaster *broadcaster)
Definition: access.cxx:1226
virtual std::vector< OUString > getAbsolutePath()=0
virtual sal_Bool SAL_CALL hasByName(OUString const &aName) override
Definition: access.cxx:423
void checkFinalized()
Definition: access.cxx:2130
virtual OUString SAL_CALL getHierarchicalName() override
Definition: access.cxx:569
ContainerListeners containerListeners_
Definition: access.hxx:431
virtual sal_Bool SAL_CALL hasElements() override
Definition: access.cxx:353
virtual void SAL_CALL replaceByHierarchicalName(OUString const &aName, css::uno::Any const &aElement) override
Definition: access.cxx:452
virtual void SAL_CALL removePropertyChangeListener(OUString const &aPropertyName, css::uno::Reference< css::beans::XPropertyChangeListener > const &aListener) override
Definition: access.cxx:755
virtual OUString SAL_CALL getExactName(OUString const &aApproximateName) override
Definition: access.cxx:528
void markChildAsModified(rtl::Reference< ChildAccess > const &child)
Definition: access.cxx:147
virtual void SAL_CALL setName(OUString const &aName) override
Definition: access.cxx:615
void initBroadcasterAndChanges(Modifications::Node const &modifications, Broadcaster *broadcaster, std::vector< css::util::ElementChange > *changes)
Definition: access.cxx:1607
virtual css::beans::Property SAL_CALL getPropertyByHierarchicalName(OUString const &aHierarchicalName) override
Definition: access.cxx:1033
virtual OUString SAL_CALL composeHierarchicalName(OUString const &aRelativeName) override
Definition: access.cxx:589
virtual void SAL_CALL addEventListener(css::uno::Reference< css::lang::XEventListener > const &xListener) override
Definition: access.cxx:296
void insertLocalizedValueChild(OUString const &name, css::uno::Any const &value, Modifications *localModifications)
Definition: access.cxx:1522
bool getByNameFast(const OUString &name, css::uno::Any &value)
Definition: access.cxx:360
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &aType) override
Definition: access.cxx:1294
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: access.cxx:245
virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override
Definition: access.cxx:408
virtual void SAL_CALL firePropertiesChangeEvent(css::uno::Sequence< OUString > const &aPropertyNames, css::uno::Reference< css::beans::XPropertiesChangeListener > const &xListener) override
Definition: access.cxx:908
rtl::Reference< ChildAccess > createUnmodifiedChild(const OUString &name, const rtl::Reference< Node > &node)
Definition: access.cxx:1947
virtual void addTypes(std::vector< css::uno::Type > *types) const =0
rtl::Reference< ChildAccess > getSubChild(OUString const &path)
Definition: access.cxx:1979
bool thisIs(int what)
Definition: access.cxx:2201
VetoableChangeListeners vetoableChangeListeners_
Definition: access.hxx:433
virtual css::beans::Property SAL_CALL getPropertyByName(OUString const &aName) override
Definition: access.cxx:550
virtual void SAL_CALL addVetoableChangeListener(OUString const &PropertyName, css::uno::Reference< css::beans::XVetoableChangeListener > const &aListener) override
Definition: access.cxx:776
virtual css::uno::Type SAL_CALL getElementType() override
Definition: access.cxx:330
virtual OUString getRelativePathRepresentation()=0
std::vector< rtl::Reference< ChildAccess > > getAllChildren()
Definition: access.cxx:1467
virtual bool isFinalized()=0
virtual ~Access() override
Definition: access.cxx:1224
virtual void SAL_CALL removeVetoableChangeListener(OUString const &PropertyName, css::uno::Reference< css::beans::XVetoableChangeListener > const &aListener) override
Definition: access.cxx:801
virtual void SAL_CALL addPropertyChangeListener(OUString const &aPropertyName, css::uno::Reference< css::beans::XPropertyChangeListener > const &xListener) override
Definition: access.cxx:731
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
Definition: access.cxx:173
rtl::Reference< ChildAccess > getChild(OUString const &name)
Definition: access.cxx:1367
virtual sal_Bool SAL_CALL supportsService(OUString const &ServiceName) override
Definition: access.cxx:240
virtual sal_Bool SAL_CALL hasByHierarchicalName(OUString const &aName) override
Definition: access.cxx:444
virtual void SAL_CALL insertByName(OUString const &aName, css::uno::Any const &aElement) override
Definition: access.cxx:1094
void checkLocalizedPropertyAccess()
Definition: access.cxx:1352
virtual void SAL_CALL removePropertiesChangeListener(css::uno::Reference< css::beans::XPropertiesChangeListener > const &xListener) override
Definition: access.cxx:895
void releaseChild(OUString const &name)
Definition: access.cxx:163
virtual std::vector< OUString > getRelativePath()=0
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance() override
Definition: access.cxx:1188
virtual css::uno::Any SAL_CALL getByHierarchicalName(OUString const &aName) override
Definition: access.cxx:431
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
Definition: access.cxx:691
virtual void SAL_CALL removeContainerListener(css::uno::Reference< css::container::XContainerListener > const &xListener) override
Definition: access.cxx:516
void reportChildChanges(std::vector< css::util::ElementChange > *changes)
Definition: access.cxx:1538
ModifiedChildren modifiedChildren_
Definition: access.hxx:428
void releaseNondeleting()
Definition: access.cxx:130
virtual void addSupportedServiceNames(std::vector< OUString > *services)=0
virtual rtl::Reference< Access > getParentAccess()=0
virtual css::uno::Reference< css::beans::XHierarchicalPropertySetInfo > SAL_CALL getHierarchicalPropertySetInfo() override
Definition: access.cxx:927
Access(Components &components)
Definition: access.cxx:1219
virtual void SAL_CALL addPropertiesChangeListener(css::uno::Sequence< OUString > const &aPropertyNames, css::uno::Reference< css::beans::XPropertiesChangeListener > const &xListener) override
Definition: access.cxx:872
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
Definition: access.cxx:224
virtual void SAL_CALL replaceByName(OUString const &aName, css::uno::Any const &aElement) override
Definition: access.cxx:1054
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(css::uno::Sequence< css::uno::Any > const &aArguments) override
Definition: access.cxx:1206
virtual void SAL_CALL dispose() override
Definition: access.cxx:275
std::shared_ptr< osl::Mutex > lock_
Definition: access.hxx:437
virtual void SAL_CALL setPropertyValues(css::uno::Sequence< OUString > const &aPropertyNames, css::uno::Sequence< css::uno::Any > const &aValues) override
Definition: access.cxx:822
rtl::Reference< ChildAccess > getFreeSetMember(css::uno::Any const &value)
Definition: access.cxx:2165
virtual void SAL_CALL setHierarchicalPropertyValues(css::uno::Sequence< OUString > const &aHierarchicalPropertyNames, css::uno::Sequence< css::uno::Any > const &Values) override
Definition: access.cxx:974
css::beans::Property asProperty()
Definition: access.cxx:2074
virtual css::uno::Any SAL_CALL getPropertyValue(OUString const &PropertyName) override
Definition: access.cxx:719
virtual OUString SAL_CALL getName() override
Definition: access.cxx:608
virtual void SAL_CALL setHierarchicalPropertyValue(OUString const &aHierarchicalPropertyName, css::uno::Any const &aValue) override
Definition: access.cxx:932
virtual OUString SAL_CALL getImplementationName() override
Definition: access.cxx:232
void addContainerElementRemovedNotification(css::uno::Reference< css::container::XContainerListener > const &listener, css::container::ContainerEvent const &event)
Definition: broadcaster.cxx:76
void addContainerElementReplacedNotification(css::uno::Reference< css::container::XContainerListener > const &listener, css::container::ContainerEvent const &event)
Definition: broadcaster.cxx:62
void addPropertyChangeNotification(css::uno::Reference< css::beans::XPropertyChangeListener > const &listener, css::beans::PropertyChangeEvent const &event)
Definition: broadcaster.cxx:83
void addDisposeNotification(css::uno::Reference< css::lang::XEventListener > const &listener, css::lang::EventObject const &event)
Definition: broadcaster.cxx:55
void addPropertiesChangeNotification(css::uno::Reference< css::beans::XPropertiesChangeListener > const &listener, css::uno::Sequence< css::beans::PropertyChangeEvent > const &event)
Definition: broadcaster.cxx:90
static bool asSimpleValue(const rtl::Reference< Node > &rNode, css::uno::Any &value, Components &components)
Can we quickly extract a simple value into value ? if so returns true.
static bool allLocales(std::u16string_view locale)
Definition: components.cxx:207
void addModification(std::vector< OUString > const &path)
Definition: components.cxx:270
rtl::Reference< Node > getTemplate(OUString const &fullName) const
Definition: components.cxx:220
bool isExtensible() const
Definition: groupnode.hxx:47
void add(std::vector< OUString > const &path)
Node const & getRoot() const
NodeMapImpl::iterator iterator
Definition: nodemap.hxx:37
@ KIND_LOCALIZED_PROPERTY
Definition: node.hxx:35
@ KIND_LOCALIZED_VALUE
Definition: node.hxx:35
Type getStaticType() const
bool isValidTemplate(OUString const &templateName) const
Definition: setnode.cxx:63
oslInterlockedCount m_refCount
css::uno::Type const & get()
Any value
OUString name
Definition: components.cxx:85
std::shared_ptr< osl::Mutex > lock_
float u
Sequence< PropertyValue > aArguments
OUString aName
void * p
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
const LanguageTag & getLocale()
const LanguageTag & getLanguageTag()
sal_Int32 indexOfAny(std::u16string_view rIn, sal_Unicode const *const pChars, sal_Int32 const nPos)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
std::shared_ptr< osl::Mutex > const & lock()
Definition: lock.cxx:28
@ TYPE_NIL
Definition: type.hxx:33
@ TYPE_ANY
Definition: type.hxx:33
@ TYPE_ERROR
Definition: type.hxx:33
css::uno::Type const & mapType(Type type)
Definition: type.cxx:62
Type getDynamicType(css::uno::Any const &value)
Definition: type.cxx:101
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
SwNodeOffset abs(const SwNodeOffset &a)
PyObject_HEAD PyUNO_callable_Internals * members
static sal_Int32 parseSegment(OUString const &path, sal_Int32 index, OUString *name, bool *setElement, OUString *templateName)
Definition: data.cxx:111
static bool equalTemplateNames(OUString const &shortName, OUString const &longName)
Definition: data.cxx:165
static OUString createSegment(std::u16string_view templateName, OUString const &name)
Definition: data.cxx:81
OUString Name
unsigned char sal_Bool
ResultType type