/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "access.hxx" #include "childaccess.hxx" #include "components.hxx" #include "data.hxx" #include "localizedpropertynode.hxx" #include "localizedvaluenode.hxx" #include "lock.hxx" #include "modifications.hxx" #include "node.hxx" #include "propertynode.hxx" #include "rootaccess.hxx" #include "type.hxx" namespace configmgr { ChildAccess::ChildAccess( Components & components, rtl::Reference< RootAccess > const & root, rtl::Reference< Access > const & parent, OUString name, rtl::Reference< Node > const & node): Access(components), root_(root), parent_(parent), name_(std::move(name)), node_(node), inTransaction_(false), lock_( lock() ) { assert(root.is() && parent.is() && node.is()); } ChildAccess::ChildAccess( Components & components, rtl::Reference< RootAccess > const & root, rtl::Reference< Node > const & node): Access(components), root_(root), node_(node), inTransaction_(false), lock_( lock() ) { assert(root.is() && node.is()); } std::vector ChildAccess::getAbsolutePath() { rtl::Reference< Access > parent(getParentAccess()); assert(parent.is()); std::vector path(parent->getAbsolutePath()); path.push_back(name_); return path; } std::vector ChildAccess::getRelativePath() { std::vector path; rtl::Reference< Access > parent(getParentAccess()); if (parent.is()) { path = parent->getRelativePath(); } path.push_back(name_); return path; } OUString ChildAccess::getRelativePathRepresentation() { OUStringBuffer path(128); rtl::Reference< Access > parent(getParentAccess()); if (parent.is()) { path.append(parent->getRelativePathRepresentation()); if (!path.isEmpty()) { path.append('/'); } } path.append(Data::createSegment(node_->getTemplateName(), name_)); return path.makeStringAndClear(); } const rtl::Reference< Node > & ChildAccess::getNode() { return node_; } bool ChildAccess::isFinalized() { return node_->getFinalized() != Data::NO_LAYER || (parent_.is() && parent_->isFinalized()); } const OUString & ChildAccess::getNameInternal() { return name_; } rtl::Reference< RootAccess > ChildAccess::getRootAccess() { return root_; } rtl::Reference< Access > ChildAccess::getParentAccess() { return parent_; } void ChildAccess::acquire() noexcept { Access::acquire(); } void ChildAccess::release() noexcept { Access::release(); } css::uno::Reference< css::uno::XInterface > ChildAccess::getParent() { assert(thisIs(IS_ANY)); osl::MutexGuard g(*lock_); checkLocalizedPropertyAccess(); return cppu::getXWeak(parent_.get()); } void ChildAccess::setParent(css::uno::Reference< css::uno::XInterface > const &) { assert(thisIs(IS_ANY)); osl::MutexGuard g(*lock_); checkLocalizedPropertyAccess(); throw css::lang::NoSupportException( "setParent", getXWeak()); } void ChildAccess::bind( rtl::Reference< RootAccess > const & root, rtl::Reference< Access > const & parent, OUString const & name) noexcept { assert(!parent_.is() && root.is() && parent.is() && !name.isEmpty()); root_ = root; parent_ = parent; name_ = name; } void ChildAccess::unbind() noexcept { assert(parent_.is()); parent_->releaseChild(name_); parent_.clear(); inTransaction_ = true; } void ChildAccess::committed() { inTransaction_ = false; } void ChildAccess::setNode(rtl::Reference< Node > const & node) { node_ = node; } void ChildAccess::setProperty( css::uno::Any const & value, Modifications * localModifications) { assert(localModifications != nullptr); Type type = TYPE_ERROR; bool isNillable = false; switch (node_->kind()) { case Node::KIND_PROPERTY: { PropertyNode * prop = static_cast< PropertyNode * >(node_.get()); type = prop->getStaticType(); isNillable = prop->isNillable(); } break; case Node::KIND_LOCALIZED_PROPERTY: { OUString locale(getRootAccess()->getLocale()); if (!Components::allLocales(locale)) { rtl::Reference< ChildAccess > child(getChild(locale)); if (child.is()) { child->setProperty(value, localModifications); } else { insertLocalizedValueChild( locale, value, localModifications); } return; } } break; case Node::KIND_LOCALIZED_VALUE: { LocalizedPropertyNode * locprop = static_cast< LocalizedPropertyNode * >(getParentNode().get()); type = locprop->getStaticType(); isNillable = locprop->isNillable(); } break; default: break; } checkValue(value, type, isNillable); getParentAccess()->markChildAsModified(this); changedValue_.emplace(value); localModifications->add(getRelativePath()); } css::uno::Any ChildAccess::asValue() { if (changedValue_) { return *changedValue_; } css::uno::Any value; if (!asSimpleValue(node_, value, getComponents())) { if (node_->kind() == Node::KIND_LOCALIZED_PROPERTY) { OUString locale(getRootAccess()->getLocale()); if (!Components::allLocales(locale)) { rtl::Reference< ChildAccess > child(getChild("*" + locale)); // As a last resort, return a nil value even though it may be // illegal for the given property: return child.is() ? child->asValue() : css::uno::Any(); } } value <<= css::uno::Reference(getXWeak()); } return value; } /// Can we quickly extract a simple value into value ? if so returns true bool ChildAccess::asSimpleValue(const rtl::Reference< Node > &rNode, css::uno::Any &value, Components &components) { switch (rNode->kind()) { case Node::KIND_PROPERTY: value = static_cast< PropertyNode * >(rNode.get())->getValue(components); return true; case Node::KIND_LOCALIZED_VALUE: value = static_cast< LocalizedValueNode * >(rNode.get())->getValue(); return true; default: return false; } } void ChildAccess::commitChanges(bool valid, Modifications * globalModifications) { assert(globalModifications != nullptr); commitChildChanges(valid, globalModifications); if (valid && changedValue_) { std::vector path(getAbsolutePath()); getComponents().addModification(path); globalModifications->add(path); switch (node_->kind()) { case Node::KIND_PROPERTY: static_cast< PropertyNode * >(node_.get())->setValue( Data::NO_LAYER, *changedValue_, true); break; case Node::KIND_LOCALIZED_VALUE: static_cast< LocalizedValueNode * >(node_.get())->setValue( Data::NO_LAYER, *changedValue_, true); break; default: assert(false); // this cannot happen break; } } changedValue_.reset(); } ChildAccess::~ChildAccess() { osl::MutexGuard g(*lock_); if (parent_.is()) { parent_->releaseChild(name_); } } void ChildAccess::addTypes(std::vector< css::uno::Type > * types) const { assert(types != nullptr); types->push_back(cppu::UnoType< css::container::XChild >::get()); types->push_back(cppu::UnoType< css::lang::XUnoTunnel >::get()); } void ChildAccess::addSupportedServiceNames( std::vector * services) { assert(services != nullptr); services->push_back( getParentNode()->kind() == Node::KIND_GROUP ? OUString("com.sun.star.configuration.GroupElement") : OUString("com.sun.star.configuration.SetElement")); } css::uno::Any ChildAccess::queryInterface(css::uno::Type const & aType) { assert(thisIs(IS_ANY)); osl::MutexGuard g(*lock_); checkLocalizedPropertyAccess(); css::uno::Any res(Access::queryInterface(aType)); return res.hasValue() ? res : cppu::queryInterface( aType, static_cast< css::container::XChild * >(this)); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */