LCOV - code coverage report
Current view: top level - libreoffice/configmgr/source - xcuparser.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 378 567 66.7 %
Date: 2012-12-17 Functions: 19 19 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <algorithm>
      23             : #include <cassert>
      24             : #include <set>
      25             : 
      26             : #include "com/sun/star/uno/Any.hxx"
      27             : #include "com/sun/star/uno/Reference.hxx"
      28             : #include "com/sun/star/uno/RuntimeException.hpp"
      29             : #include "com/sun/star/uno/XInterface.hpp"
      30             : #include "rtl/ref.hxx"
      31             : #include "rtl/strbuf.hxx"
      32             : #include "rtl/string.h"
      33             : #include "rtl/string.hxx"
      34             : #include "rtl/ustring.h"
      35             : #include "rtl/ustring.hxx"
      36             : #include "sal/log.hxx"
      37             : #include "xmlreader/span.hxx"
      38             : #include "xmlreader/xmlreader.hxx"
      39             : 
      40             : #include "data.hxx"
      41             : #include "localizedpropertynode.hxx"
      42             : #include "localizedvaluenode.hxx"
      43             : #include "groupnode.hxx"
      44             : #include "modifications.hxx"
      45             : #include "node.hxx"
      46             : #include "nodemap.hxx"
      47             : #include "parsemanager.hxx"
      48             : #include "partial.hxx"
      49             : #include "path.hxx"
      50             : #include "propertynode.hxx"
      51             : #include "setnode.hxx"
      52             : #include "xcuparser.hxx"
      53             : #include "xmldata.hxx"
      54             : 
      55             : namespace configmgr {
      56             : 
      57       14200 : XcuParser::XcuParser(
      58             :     int layer, Data & data, Partial const * partial,
      59             :     Modifications * broadcastModifications, Additions * additions):
      60             :     valueParser_(layer), data_(data),
      61             :     partial_(partial), broadcastModifications_(broadcastModifications),
      62             :     additions_(additions), recordModifications_(layer == Data::NO_LAYER),
      63             :     trackPath_(
      64             :         partial_ != 0 || broadcastModifications_ != 0 || additions_ != 0 ||
      65       14200 :         recordModifications_)
      66       14200 : {}
      67             : 
      68       28400 : XcuParser::~XcuParser() {}
      69             : 
      70    10999561 : xmlreader::XmlReader::Text XcuParser::getTextMode() {
      71    10999561 :     return valueParser_.getTextMode();
      72             : }
      73             : 
      74     4609972 : bool XcuParser::startElement(
      75             :     xmlreader::XmlReader & reader, int nsId, xmlreader::Span const & name,
      76             :     std::set< OUString > const * existingDependencies)
      77             : {
      78     4609972 :     if (valueParser_.startElement(reader, nsId, name, existingDependencies)) {
      79       10682 :         return true;
      80             :     }
      81     4599290 :     if (state_.empty()) {
      82       28400 :         if (nsId == ParseManager::NAMESPACE_OOR &&
      83       14200 :             name.equals(RTL_CONSTASCII_STRINGPARAM("component-data")))
      84             :         {
      85       14192 :             handleComponentData(reader);
      86          16 :         } else if (nsId == ParseManager::NAMESPACE_OOR &&
      87           8 :                    name.equals(RTL_CONSTASCII_STRINGPARAM("items")))
      88             :         {
      89           8 :             state_.push(State(rtl::Reference< Node >(), false));
      90             :         } else {
      91             :             throw css::uno::RuntimeException(
      92             :                 (OUString("bad root element <") +
      93           0 :                  name.convertFromUtf8() +
      94           0 :                  OUString("> in ") +
      95           0 :                  reader.getUrl()),
      96           0 :                 css::uno::Reference< css::uno::XInterface >());
      97             :         }
      98     4585090 :     } else if (state_.top().ignore) {
      99           0 :         state_.push(State(false));
     100     4585090 :     } else if (!state_.top().node.is()) {
     101        1964 :         if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
     102         982 :             name.equals(RTL_CONSTASCII_STRINGPARAM("item")))
     103             :         {
     104         982 :             handleItem(reader);
     105             :         } else {
     106             :             throw css::uno::RuntimeException(
     107             :                 (OUString("bad items node member <") +
     108           0 :                  name.convertFromUtf8() +
     109           0 :                  OUString("> in ") +
     110           0 :                  reader.getUrl()),
     111           0 :                 css::uno::Reference< css::uno::XInterface >());
     112             :         }
     113             :     } else {
     114     4584108 :         switch (state_.top().node->kind()) {
     115             :         case Node::KIND_PROPERTY:
     116     2609384 :             if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
     117     1304692 :                 name.equals(RTL_CONSTASCII_STRINGPARAM("value")))
     118             :             {
     119             :                 handlePropValue(
     120             :                     reader,
     121     1304692 :                     dynamic_cast< PropertyNode * >(state_.top().node.get()));
     122             :             } else {
     123             :                 throw css::uno::RuntimeException(
     124             :                     (OUString("bad property node member <") +
     125           0 :                      name.convertFromUtf8() +
     126           0 :                      OUString("> in ") +
     127           0 :                      reader.getUrl()),
     128           0 :                     css::uno::Reference< css::uno::XInterface >());
     129             :             }
     130     1304692 :             break;
     131             :         case Node::KIND_LOCALIZED_PROPERTY:
     132     1082052 :             if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
     133      541026 :                 name.equals(RTL_CONSTASCII_STRINGPARAM("value")))
     134             :             {
     135             :                 handleLocpropValue(
     136             :                     reader,
     137             :                     dynamic_cast< LocalizedPropertyNode * >(
     138      541026 :                         state_.top().node.get()));
     139             :             } else {
     140             :                 throw css::uno::RuntimeException(
     141             :                     (OUString("bad localized property node member <") +
     142           0 :                      name.convertFromUtf8() +
     143           0 :                      OUString("> in ") +
     144           0 :                      reader.getUrl()),
     145           0 :                     css::uno::Reference< css::uno::XInterface >());
     146             :             }
     147      541026 :             break;
     148             :         case Node::KIND_LOCALIZED_VALUE:
     149             :             throw css::uno::RuntimeException(
     150             :                 (OUString("bad member <") +
     151           0 :                  name.convertFromUtf8() +
     152           0 :                  OUString("> in ") +
     153           0 :                  reader.getUrl()),
     154           0 :                 css::uno::Reference< css::uno::XInterface >());
     155             :         case Node::KIND_GROUP:
     156     3956022 :             if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
     157     1978011 :                 name.equals(RTL_CONSTASCII_STRINGPARAM("prop")))
     158             :             {
     159             :                 handleGroupProp(
     160             :                     reader,
     161     1915658 :                     dynamic_cast< GroupNode * >(state_.top().node.get()));
     162      124706 :             } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
     163       62353 :                        name.equals(RTL_CONSTASCII_STRINGPARAM("node")))
     164             :             {
     165       62353 :                 handleGroupNode(reader, state_.top().node);
     166             :             } else {
     167             :                 throw css::uno::RuntimeException(
     168             :                     (OUString("bad group node member <") +
     169           0 :                      name.convertFromUtf8() +
     170           0 :                      OUString("> in ") +
     171           0 :                      reader.getUrl()),
     172           0 :                     css::uno::Reference< css::uno::XInterface >());
     173             :             }
     174     1978011 :             break;
     175             :         case Node::KIND_SET:
     176     1520758 :             if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
     177      760379 :                 name.equals(RTL_CONSTASCII_STRINGPARAM("node")))
     178             :             {
     179             :                 handleSetNode(
     180      760379 :                     reader, dynamic_cast< SetNode * >(state_.top().node.get()));
     181           0 :             } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
     182           0 :                        name.equals(RTL_CONSTASCII_STRINGPARAM("prop")))
     183             :             {
     184             :                 SAL_WARN(
     185             :                     "configmgr",
     186             :                     "bad set node <prop> member in \"" << reader.getUrl()
     187             :                         << '"');
     188           0 :                 state_.push(State(true)); // ignored
     189             :             } else {
     190             :                 throw css::uno::RuntimeException(
     191             :                     (OUString("bad set node member <") +
     192           0 :                      name.convertFromUtf8() +
     193           0 :                      OUString("> in ") +
     194           0 :                      reader.getUrl()),
     195           0 :                     css::uno::Reference< css::uno::XInterface >());
     196             :             }
     197      760379 :             break;
     198             :         case Node::KIND_ROOT:
     199             :             assert(false); // this cannot happen
     200           0 :             break;
     201             :         }
     202             :     }
     203     4599290 :     return true;
     204             : }
     205             : 
     206     4609972 : void XcuParser::endElement(xmlreader::XmlReader const &) {
     207     4609972 :     if (valueParser_.endElement()) {
     208     4609972 :         return;
     209             :     }
     210             :     assert(!state_.empty());
     211     2757119 :     bool pop = state_.top().pop;
     212     2757119 :     rtl::Reference< Node > insert;
     213     2757119 :     OUString name;
     214     2757119 :     if (state_.top().insert) {
     215      781472 :         insert = state_.top().node;
     216             :         assert(insert.is());
     217      781472 :         name = state_.top().name;
     218             :     }
     219     2757119 :     state_.pop();
     220     2757119 :     if (insert.is()) {
     221             :         assert(!state_.empty() && state_.top().node.is());
     222      781472 :         state_.top().node->getMembers()[name] = insert;
     223             :     }
     224     2757119 :     if (pop && !path_.empty()) {
     225        2128 :         path_.pop_back();
     226             :             // </item> will pop less than <item> pushed, but that is harmless,
     227             :             // as the next <item> will reset path_
     228     2757119 :     }
     229             : }
     230             : 
     231     1768209 : void XcuParser::characters(xmlreader::Span const & text) {
     232     1768209 :     valueParser_.characters(text);
     233     1768209 : }
     234             : 
     235      781937 : XcuParser::Operation XcuParser::parseOperation(xmlreader::Span const & text) {
     236             :     assert(text.is());
     237      781937 :     if (text.equals(RTL_CONSTASCII_STRINGPARAM("modify"))) {
     238           0 :         return OPERATION_MODIFY;
     239             :     }
     240      781937 :     if (text.equals(RTL_CONSTASCII_STRINGPARAM("replace"))) {
     241      775991 :         return OPERATION_REPLACE;
     242             :     }
     243        5946 :     if (text.equals(RTL_CONSTASCII_STRINGPARAM("fuse"))) {
     244        5946 :         return OPERATION_FUSE;
     245             :     }
     246           0 :     if (text.equals(RTL_CONSTASCII_STRINGPARAM("remove"))) {
     247           0 :         return OPERATION_REMOVE;
     248             :     }
     249             :     throw css::uno::RuntimeException(
     250             :         (OUString("invalid op ") +
     251           0 :          text.convertFromUtf8()),
     252           0 :         css::uno::Reference< css::uno::XInterface >());
     253             : }
     254             : 
     255       14192 : void XcuParser::handleComponentData(xmlreader::XmlReader & reader) {
     256       14192 :     rtl::OStringBuffer buf;
     257       14192 :     buf.append('.');
     258       14192 :     bool hasPackage = false;
     259       14192 :     bool hasName = false;
     260       14192 :     Operation op = OPERATION_MODIFY;
     261       14192 :     bool finalized = false;
     262       28384 :     for (;;) {
     263             :         int attrNsId;
     264       42576 :         xmlreader::Span attrLn;
     265       42576 :         if (!reader.nextAttribute(&attrNsId, &attrLn)) {
     266             :             break;
     267             :         }
     268       56768 :         if (attrNsId == ParseManager::NAMESPACE_OOR &&
     269       28384 :             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("package")))
     270             :         {
     271       14192 :             if (hasPackage) {
     272             :                 throw css::uno::RuntimeException(
     273             :                     (OUString("multiple component-update package attributes"
     274             :                             " in ") +
     275           0 :                      reader.getUrl()),
     276           0 :                     css::uno::Reference< css::uno::XInterface >());
     277             :             }
     278       14192 :             hasPackage = true;
     279       14192 :             xmlreader::Span s(reader.getAttributeValue(false));
     280       14192 :             buf.insert(0, s.begin, s.length);
     281       28384 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     282       14192 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
     283             :         {
     284       14192 :             if (hasName) {
     285             :                 throw css::uno::RuntimeException(
     286             :                     (OUString("multiple component-update name attributes in ") +
     287           0 :                      reader.getUrl()),
     288           0 :                     css::uno::Reference< css::uno::XInterface >());
     289             :             }
     290       14192 :             hasName = true;
     291       14192 :             xmlreader::Span s(reader.getAttributeValue(false));
     292       14192 :             buf.append(s.begin, s.length);
     293           0 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     294           0 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
     295             :         {
     296           0 :             op = parseOperation(reader.getAttributeValue(true));
     297           0 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     298           0 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("finalized")))
     299             :         {
     300           0 :             finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
     301             :         }
     302             :     }
     303       14192 :     if (!hasPackage) {
     304             :         throw css::uno::RuntimeException(
     305             :             (OUString("no component-data package attribute in ") +
     306           0 :              reader.getUrl()),
     307           0 :             css::uno::Reference< css::uno::XInterface >());
     308             :     }
     309       14192 :     if (!hasName) {
     310             :         throw css::uno::RuntimeException(
     311             :             (OUString("no component-data name attribute in ") +
     312           0 :              reader.getUrl()),
     313           0 :             css::uno::Reference< css::uno::XInterface >());
     314             :     }
     315             :     componentName_ = xmlreader::Span(buf.getStr(), buf.getLength()).
     316       14192 :         convertFromUtf8();
     317       14192 :     if (trackPath_) {
     318             :         assert(path_.empty());
     319           0 :         path_.push_back(componentName_);
     320           0 :         if (partial_ != 0 && partial_->contains(path_) == Partial::CONTAINS_NOT)
     321             :         {
     322           0 :             state_.push(State(true)); // ignored
     323             :             return;
     324             :         }
     325             :     }
     326             :     rtl::Reference< Node > node(
     327             :         Data::findNode(
     328       14192 :             valueParser_.getLayer(), data_.getComponents(), componentName_));
     329       14192 :     if (!node.is()) {
     330             :         SAL_WARN(
     331             :             "configmgr",
     332             :             "unknown component \"" << componentName_ << "\" in \""
     333             :                 << reader.getUrl() << '"');
     334           0 :         state_.push(State(true)); // ignored
     335             :         return;
     336             :     }
     337       14192 :     switch (op) {
     338             :     case OPERATION_MODIFY:
     339             :     case OPERATION_FUSE:
     340       14192 :         break;
     341             :     default:
     342             :         throw css::uno::RuntimeException(
     343             :             (OUString("invalid operation on root node in ") +
     344           0 :              reader.getUrl()),
     345           0 :             css::uno::Reference< css::uno::XInterface >());
     346             :     }
     347             :     int finalizedLayer = std::min(
     348           0 :         finalized ? valueParser_.getLayer() : Data::NO_LAYER,
     349       14192 :         node->getFinalized());
     350       14192 :     node->setFinalized(finalizedLayer);
     351       14192 :     state_.push(State(node, finalizedLayer < valueParser_.getLayer()));
     352             : }
     353             : 
     354         982 : void XcuParser::handleItem(xmlreader::XmlReader & reader) {
     355         982 :     xmlreader::Span attrPath;
     356         982 :     for (;;) {
     357             :         int attrNsId;
     358        1964 :         xmlreader::Span attrLn;
     359        1964 :         if (!reader.nextAttribute(&attrNsId, &attrLn)) {
     360             :             break;
     361             :         }
     362        1964 :         if (attrNsId == ParseManager::NAMESPACE_OOR &&
     363         982 :             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("path")))
     364             :         {
     365         982 :             attrPath = reader.getAttributeValue(false);
     366             :         }
     367             :     }
     368         982 :     if (!attrPath.is()) {
     369             :         throw css::uno::RuntimeException(
     370             :             (OUString("missing path attribute in ") +
     371           0 :              reader.getUrl()),
     372           0 :             css::uno::Reference< css::uno::XInterface >());
     373             :     }
     374         982 :     OUString path(attrPath.convertFromUtf8());
     375             :     int finalizedLayer;
     376             :     rtl::Reference< Node > node(
     377             :         data_.resolvePathRepresentation(
     378         982 :             path, 0, &path_, &finalizedLayer));
     379         982 :     if (!node.is()) {
     380             :         SAL_WARN(
     381             :             "configmgr",
     382             :             "unknown item \"" << path << "\" in \"" << reader.getUrl() << '"');
     383           0 :         state_.push(State(true)); // ignored
     384             :         return;
     385             :     }
     386             :     assert(!path_.empty());
     387         982 :     componentName_ = path_.front();
     388         982 :     if (trackPath_) {
     389         982 :         if (partial_ != 0 && partial_->contains(path_) == Partial::CONTAINS_NOT)
     390             :         {
     391           0 :             state_.push(State(true)); // ignored
     392             :             return;
     393             :         }
     394             :     } else {
     395           0 :         path_.clear();
     396             :     }
     397         982 :     switch (node->kind()) {
     398             :     case Node::KIND_PROPERTY:
     399             :     case Node::KIND_LOCALIZED_VALUE:
     400             :         SAL_WARN(
     401             :             "configmgr",
     402             :             "item of bad type \"" << path << "\" in \"" << reader.getUrl()
     403             :                 << '"');
     404           0 :         state_.push(State(true)); // ignored
     405             :         return;
     406             :     case Node::KIND_LOCALIZED_PROPERTY:
     407             :         valueParser_.type_ = dynamic_cast< LocalizedPropertyNode * >(
     408          10 :             node.get())->getStaticType();
     409          10 :         break;
     410             :     default:
     411         972 :         break;
     412             :     }
     413         982 :     state_.push(State(node, finalizedLayer < valueParser_.getLayer()));
     414             : }
     415             : 
     416     1304692 : void XcuParser::handlePropValue(
     417             :     xmlreader::XmlReader & reader, PropertyNode * prop)
     418             :  {
     419     1304692 :     bool nil = false;
     420     1304692 :     rtl::OString separator;
     421     1304692 :     OUString external;
     422       13389 :     for (;;) {
     423             :         int attrNsId;
     424     1318081 :         xmlreader::Span attrLn;
     425     1318081 :         if (!reader.nextAttribute(&attrNsId, &attrLn)) {
     426             :             break;
     427             :         }
     428       13444 :         if (attrNsId == ParseManager::NAMESPACE_XSI &&
     429          55 :             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("nil")))
     430             :         {
     431          55 :             nil = xmldata::parseBoolean(reader.getAttributeValue(true));
     432       23924 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     433       10590 :             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("type")))
     434             :         {
     435             :             Type type = xmldata::parseType(
     436           0 :                 reader, reader.getAttributeValue(true));
     437           0 :             if (valueParser_.type_ != TYPE_ANY && type != valueParser_.type_) {
     438             :                 throw css::uno::RuntimeException(
     439             :                     (OUString("invalid value type in ") +
     440           0 :                      reader.getUrl()),
     441           0 :                     css::uno::Reference< css::uno::XInterface >());
     442             :             }
     443           0 :             valueParser_.type_ = type;
     444       23924 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     445       10590 :             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("separator")))
     446             :         {
     447        7098 :             xmlreader::Span s(reader.getAttributeValue(false));
     448        7098 :             if (s.length == 0) {
     449             :                 throw css::uno::RuntimeException(
     450             :                     (OUString("bad oor:separator attribute in ") +
     451           0 :                      reader.getUrl()),
     452           0 :                     css::uno::Reference< css::uno::XInterface >());
     453             :             }
     454        7098 :             separator = rtl::OString(s.begin, s.length);
     455        9728 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     456        3492 :             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("external")))
     457             :         {
     458        3492 :             external = reader.getAttributeValue(true).convertFromUtf8();
     459        3492 :             if (external.isEmpty()) {
     460             :                 throw css::uno::RuntimeException(
     461             :                     (OUString("bad oor:external attribute value in ") +
     462           0 :                      reader.getUrl()),
     463           0 :                     css::uno::Reference< css::uno::XInterface >());
     464             :             }
     465             :         }
     466             :     }
     467     1304692 :     if (nil) {
     468          55 :         if (!prop->isNillable()) {
     469             :             throw css::uno::RuntimeException(
     470             :                 (OUString("xsi:nil attribute for non-nillable prop in ") +
     471           0 :                  reader.getUrl()),
     472           0 :                 css::uno::Reference< css::uno::XInterface >());
     473             :         }
     474          55 :         if (!external.isEmpty()) {
     475             :             throw css::uno::RuntimeException(
     476             :                 (OUString("xsi:nil and oor:external attributes for prop in ") +
     477           0 :                  reader.getUrl()),
     478           0 :                 css::uno::Reference< css::uno::XInterface >());
     479             :         }
     480          55 :         prop->setValue(valueParser_.getLayer(), css::uno::Any());
     481          55 :         state_.push(State(false));
     482     1304637 :     } else if (external.isEmpty()) {
     483     1301145 :         valueParser_.separator_ = separator;
     484     1301145 :         valueParser_.start(prop);
     485             :     } else {
     486        3492 :         prop->setExternal(valueParser_.getLayer(), external);
     487        3492 :         state_.push(State(false));
     488     1304692 :     }
     489     1304692 : }
     490             : 
     491      541026 : void XcuParser::handleLocpropValue(
     492             :     xmlreader::XmlReader & reader, LocalizedPropertyNode * locprop)
     493             : {
     494      541026 :     OUString name;
     495      541026 :     bool nil = false;
     496      541026 :     rtl::OString separator;
     497      541026 :     Operation op = OPERATION_FUSE;
     498      520982 :     for (;;) {
     499             :         int attrNsId;
     500     1062008 :         xmlreader::Span attrLn;
     501     1062008 :         if (!reader.nextAttribute(&attrNsId, &attrLn)) {
     502             :             break;
     503             :         }
     504     1041412 :         if (attrNsId == xmlreader::XmlReader::NAMESPACE_XML &&
     505      520430 :             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("lang")))
     506             :         {
     507      520430 :             name = reader.getAttributeValue(false).convertFromUtf8();
     508         552 :         } else if (attrNsId == ParseManager::NAMESPACE_XSI &&
     509           0 :             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("nil")))
     510             :         {
     511           0 :             nil = xmldata::parseBoolean(reader.getAttributeValue(true));
     512         908 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     513         356 :             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("type")))
     514             :         {
     515             :             Type type = xmldata::parseType(
     516           0 :                 reader, reader.getAttributeValue(true));
     517           0 :             if (valueParser_.type_ != TYPE_ANY && type != valueParser_.type_) {
     518             :                 throw css::uno::RuntimeException(
     519             :                     (OUString("invalid value type in ") +
     520           0 :                      reader.getUrl()),
     521           0 :                     css::uno::Reference< css::uno::XInterface >());
     522             :             }
     523           0 :             valueParser_.type_ = type;
     524         908 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     525         356 :             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("separator")))
     526             :         {
     527         356 :             xmlreader::Span s(reader.getAttributeValue(false));
     528         356 :             if (s.length == 0) {
     529             :                 throw css::uno::RuntimeException(
     530             :                     (OUString("bad oor:separator attribute in ") +
     531           0 :                      reader.getUrl()),
     532           0 :                     css::uno::Reference< css::uno::XInterface >());
     533             :             }
     534         356 :             separator = rtl::OString(s.begin, s.length);
     535         196 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     536           0 :             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
     537             :         {
     538           0 :             op = parseOperation(reader.getAttributeValue(true));
     539             :         }
     540             :     }
     541      541026 :     if (trackPath_) {
     542          10 :         path_.push_back(name);
     543          10 :         if (partial_ != 0 &&
     544           0 :             partial_->contains(path_) != Partial::CONTAINS_NODE)
     545             :         {
     546           0 :             state_.push(State(true)); // ignored
     547             :             return;
     548             :         }
     549             :     }
     550      541026 :     NodeMap & members = locprop->getMembers();
     551      541026 :     NodeMap::iterator i(members.find(name));
     552      541026 :     if (i != members.end() && i->second->getLayer() > valueParser_.getLayer()) {
     553           0 :         state_.push(State(true)); // ignored
     554             :         return;
     555             :     }
     556      541026 :     if (nil && !locprop->isNillable()) {
     557             :         throw css::uno::RuntimeException(
     558             :             (OUString("xsi:nil attribute for non-nillable prop in ") +
     559           0 :              reader.getUrl()),
     560           0 :             css::uno::Reference< css::uno::XInterface >());
     561             :     }
     562      541026 :     switch (op) {
     563             :     case OPERATION_FUSE:
     564             :         {
     565      541026 :             bool pop = false;
     566      541026 :             if (nil) {
     567           0 :                 if (i == members.end()) {
     568           0 :                     members[name] = new LocalizedValueNode(
     569           0 :                         valueParser_.getLayer(), css::uno::Any());
     570             :                 } else {
     571             :                     dynamic_cast< LocalizedValueNode * >(
     572           0 :                         i->second.get())->setValue(
     573           0 :                             valueParser_.getLayer(), css::uno::Any());
     574             :                 }
     575           0 :                 state_.push(State(true));
     576             :             } else {
     577      541026 :                 valueParser_.separator_ = separator;
     578      541026 :                 valueParser_.start(locprop, name);
     579      541026 :                 pop = true;
     580             :             }
     581      541026 :             if (trackPath_) {
     582          10 :                 recordModification(false);
     583          10 :                 if (pop) {
     584          10 :                     path_.pop_back();
     585             :                 }
     586             :             }
     587             :         }
     588      541026 :         break;
     589             :     case OPERATION_REMOVE:
     590             :         //TODO: only allow if parent.op == OPERATION_FUSE
     591             :         //TODO: disallow removing when e.g. lang=""?
     592           0 :         if (i != members.end()) {
     593           0 :             members.erase(i);
     594             :         }
     595           0 :         state_.push(State(true));
     596           0 :         recordModification(false);
     597           0 :         break;
     598             :     default:
     599             :         throw css::uno::RuntimeException(
     600             :             (OUString("bad op attribute for value element in ") +
     601           0 :              reader.getUrl()),
     602           0 :             css::uno::Reference< css::uno::XInterface >());
     603      541026 :     }
     604             : }
     605             : 
     606     1915658 : void XcuParser::handleGroupProp(
     607             :     xmlreader::XmlReader & reader, GroupNode * group)
     608             : {
     609     1915658 :     bool hasName = false;
     610     1915658 :     OUString name;
     611     1915658 :     Type type = TYPE_ERROR;
     612     1915658 :     Operation op = OPERATION_MODIFY;
     613     1915658 :     bool finalized = false;
     614     2522017 :     for (;;) {
     615             :         int attrNsId;
     616     4437675 :         xmlreader::Span attrLn;
     617     4437675 :         if (!reader.nextAttribute(&attrNsId, &attrLn)) {
     618             :             break;
     619             :         }
     620     5044034 :         if (attrNsId == ParseManager::NAMESPACE_OOR &&
     621     2522017 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
     622             :         {
     623     1915658 :             hasName = true;
     624     1915658 :             name = reader.getAttributeValue(false).convertFromUtf8();
     625     1212718 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     626      606359 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("type")))
     627             :         {
     628      572595 :             type = xmldata::parseType(reader, reader.getAttributeValue(true));
     629       67528 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     630       33764 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
     631             :         {
     632       26370 :             op = parseOperation(reader.getAttributeValue(true));
     633       14788 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     634        7394 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("finalized")))
     635             :         {
     636        7394 :             finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
     637             :         }
     638             :     }
     639     1915658 :     if (!hasName) {
     640             :         throw css::uno::RuntimeException(
     641             :             (OUString("no prop name attribute in ") +
     642           0 :              reader.getUrl()),
     643           0 :             css::uno::Reference< css::uno::XInterface >());
     644             :     }
     645     1915658 :     if (trackPath_) {
     646        1062 :         path_.push_back(name);
     647             :         //TODO: This ignores locprop values for which specific include paths
     648             :         // exist (i.e., for which contains(locprop path) = CONTAINS_SUBNODES):
     649        1062 :         if (partial_ != 0 &&
     650           0 :             partial_->contains(path_) != Partial::CONTAINS_NODE)
     651             :         {
     652           0 :             state_.push(State(true)); // ignored
     653     1915658 :             return;
     654             :         }
     655             :     }
     656     1915658 :     NodeMap & members = group->getMembers();
     657     1915658 :     NodeMap::iterator i(members.find(name));
     658     1915658 :     if (i == members.end()) {
     659       25913 :         handleUnknownGroupProp(reader, group, name, type, op, finalized);
     660             :     } else {
     661     1889745 :         switch (i->second->kind()) {
     662             :         case Node::KIND_PROPERTY:
     663     1339679 :             handlePlainGroupProp(reader, group, i, name, type, op, finalized);
     664     1339679 :             break;
     665             :         case Node::KIND_LOCALIZED_PROPERTY:
     666             :             handleLocalizedGroupProp(
     667             :                 reader,
     668      550066 :                 dynamic_cast< LocalizedPropertyNode * >(i->second.get()), name,
     669     1100132 :                 type, op, finalized);
     670      550066 :             break;
     671             :         default:
     672             :             throw css::uno::RuntimeException(
     673             :                 (OUString("inappropriate prop ") +
     674           0 :                  name + OUString(" in ") +
     675           0 :                  reader.getUrl()),
     676           0 :                 css::uno::Reference< css::uno::XInterface >());
     677             :         }
     678     1915658 :     }
     679             : }
     680             : 
     681       25913 : void XcuParser::handleUnknownGroupProp(
     682             :     xmlreader::XmlReader const & reader, GroupNode * group,
     683             :     OUString const & name, Type type, Operation operation, bool finalized)
     684             : {
     685       25913 :     switch (operation) {
     686             :     case OPERATION_REPLACE:
     687             :     case OPERATION_FUSE:
     688       25913 :         if (group->isExtensible()) {
     689       25913 :             if (type == TYPE_ERROR) {
     690             :                 throw css::uno::RuntimeException(
     691             :                     (OUString("missing type attribute for prop ") +
     692           0 :                  name + OUString(" in ") +
     693           0 :                  reader.getUrl()),
     694           0 :                 css::uno::Reference< css::uno::XInterface >());
     695             :             }
     696       25913 :             valueParser_.type_ = type;
     697             :             rtl::Reference< Node > prop(
     698             :                 new PropertyNode(
     699       25913 :                     valueParser_.getLayer(), TYPE_ANY, true, css::uno::Any(),
     700       25913 :                     true));
     701       25913 :             if (finalized) {
     702           0 :                 prop->setFinalized(valueParser_.getLayer());
     703             :             }
     704       25913 :             state_.push(State(prop, name, state_.top().locked));
     705       25913 :             recordModification(false);
     706       25913 :             break;
     707             :         }
     708             :         // fall through
     709             :     default:
     710             :         SAL_WARN(
     711             :             "configmgr",
     712             :             "unknown property \"" << name << "\" in \"" << reader.getUrl()
     713             :                 << '"');
     714           0 :         state_.push(State(true)); // ignored
     715           0 :         break;
     716             :     }
     717       25913 : }
     718             : 
     719     1339679 : void XcuParser::handlePlainGroupProp(
     720             :     xmlreader::XmlReader const & reader, GroupNode * group,
     721             :     NodeMap::iterator const & propertyIndex, OUString const & name,
     722             :     Type type, Operation operation, bool finalized)
     723             : {
     724             :     PropertyNode * property = dynamic_cast< PropertyNode * >(
     725     1339679 :         propertyIndex->second.get());
     726     1339679 :     if (property->getLayer() > valueParser_.getLayer()) {
     727           0 :         state_.push(State(true)); // ignored
     728     1339679 :         return;
     729             :     }
     730             :     int finalizedLayer = std::min(
     731        7394 :         finalized ? valueParser_.getLayer() : Data::NO_LAYER,
     732     1347073 :         property->getFinalized());
     733     1339679 :     property->setFinalized(finalizedLayer);
     734     1603085 :     if (type != TYPE_ERROR && property->getStaticType() != TYPE_ANY &&
     735      263406 :         type != property->getStaticType())
     736             :     {
     737             :         throw css::uno::RuntimeException(
     738             :             (OUString("invalid type for prop ") +
     739           0 :              name + OUString(" in ") +
     740           0 :              reader.getUrl()),
     741           0 :             css::uno::Reference< css::uno::XInterface >());
     742             :     }
     743     1339679 :     valueParser_.type_ = type == TYPE_ERROR ? property->getStaticType() : type;
     744     1339679 :     switch (operation) {
     745             :     case OPERATION_MODIFY:
     746             :     case OPERATION_REPLACE:
     747             :     case OPERATION_FUSE:
     748             :         state_.push(
     749             :             State(
     750             :                 property,
     751     1339679 :                 (state_.top().locked ||
     752     1339679 :                  finalizedLayer < valueParser_.getLayer())));
     753     1339679 :         recordModification(false);
     754     1339679 :         break;
     755             :     case OPERATION_REMOVE:
     756           0 :         if (!property->isExtension()) {
     757             :             throw css::uno::RuntimeException(
     758             :                 (OUString("invalid remove of non-extension prop ") +
     759           0 :                  name + OUString(" in ") +
     760           0 :                  reader.getUrl()),
     761           0 :                 css::uno::Reference< css::uno::XInterface >());
     762             :         }
     763           0 :         group->getMembers().erase(propertyIndex);
     764           0 :         state_.push(State(true)); // ignore children
     765           0 :         recordModification(false);
     766           0 :         break;
     767             :     }
     768             : }
     769             : 
     770      550066 : void XcuParser::handleLocalizedGroupProp(
     771             :     xmlreader::XmlReader const & reader, LocalizedPropertyNode * property,
     772             :     OUString const & name, Type type, Operation operation, bool finalized)
     773             : {
     774      550066 :     if (property->getLayer() > valueParser_.getLayer()) {
     775           0 :         state_.push(State(true)); // ignored
     776      550066 :         return;
     777             :     }
     778             :     int finalizedLayer = std::min(
     779           0 :         finalized ? valueParser_.getLayer() : Data::NO_LAYER,
     780      550066 :         property->getFinalized());
     781      550066 :     property->setFinalized(finalizedLayer);
     782      828694 :     if (type != TYPE_ERROR && property->getStaticType() != TYPE_ANY &&
     783      278628 :         type != property->getStaticType())
     784             :     {
     785             :         throw css::uno::RuntimeException(
     786             :             (OUString("invalid type for prop ") +
     787           0 :              name + OUString(" in ") +
     788           0 :              reader.getUrl()),
     789           0 :             css::uno::Reference< css::uno::XInterface >());
     790             :     }
     791      550066 :     valueParser_.type_ = type == TYPE_ERROR ? property->getStaticType() : type;
     792      550066 :     switch (operation) {
     793             :     case OPERATION_MODIFY:
     794             :     case OPERATION_FUSE:
     795             :         state_.push(
     796             :             State(
     797             :                 property,
     798      550066 :                 (state_.top().locked ||
     799      550066 :                  finalizedLayer < valueParser_.getLayer())));
     800      550066 :         break;
     801             :     case OPERATION_REPLACE:
     802             :         {
     803             :             rtl::Reference< Node > replacement(
     804             :                 new LocalizedPropertyNode(
     805           0 :                     valueParser_.getLayer(), property->getStaticType(),
     806           0 :                     property->isNillable()));
     807           0 :             replacement->setFinalized(property->getFinalized());
     808             :             state_.push(
     809             :                 State(
     810             :                     replacement, name,
     811           0 :                     (state_.top().locked ||
     812           0 :                      finalizedLayer < valueParser_.getLayer())));
     813           0 :             recordModification(false);
     814             :         }
     815           0 :         break;
     816             :     case OPERATION_REMOVE:
     817             :         throw css::uno::RuntimeException(
     818             :             (OUString("invalid remove of non-extension prop ") +
     819           0 :              name + OUString(" in ") +
     820           0 :              reader.getUrl()),
     821           0 :             css::uno::Reference< css::uno::XInterface >());
     822             :     }
     823             : }
     824             : 
     825       62353 : void XcuParser::handleGroupNode(
     826             :     xmlreader::XmlReader & reader, rtl::Reference< Node > const & group)
     827             : {
     828       62353 :     bool hasName = false;
     829       62353 :     OUString name;
     830       62353 :     Operation op = OPERATION_MODIFY;
     831       62353 :     bool finalized = false;
     832       62851 :     for (;;) {
     833             :         int attrNsId;
     834      125204 :         xmlreader::Span attrLn;
     835      125204 :         if (!reader.nextAttribute(&attrNsId, &attrLn)) {
     836             :             break;
     837             :         }
     838      125702 :         if (attrNsId == ParseManager::NAMESPACE_OOR &&
     839       62851 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
     840             :         {
     841       62353 :             hasName = true;
     842       62353 :             name = reader.getAttributeValue(false).convertFromUtf8();
     843         996 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     844         498 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
     845             :         {
     846           0 :             op = parseOperation(reader.getAttributeValue(true));
     847         996 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     848         498 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("finalized")))
     849             :         {
     850         490 :             finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
     851             :         }
     852             :     }
     853       62353 :     if (!hasName) {
     854             :         throw css::uno::RuntimeException(
     855             :             (OUString("no node name attribute in ") +
     856           0 :              reader.getUrl()),
     857           0 :             css::uno::Reference< css::uno::XInterface >());
     858             :     }
     859       62353 :     if (trackPath_) {
     860          31 :         path_.push_back(name);
     861          31 :         if (partial_ != 0 && partial_->contains(path_) == Partial::CONTAINS_NOT)
     862             :         {
     863           0 :             state_.push(State(true)); // ignored
     864             :             return;
     865             :         }
     866             :     }
     867             :     rtl::Reference< Node > child(
     868       62353 :         Data::findNode(valueParser_.getLayer(), group->getMembers(), name));
     869       62353 :     if (!child.is()) {
     870             :         SAL_WARN(
     871             :             "configmgr",
     872             :             "unknown node \"" << name << "\" in \"" << reader.getUrl() << '"');
     873           0 :         state_.push(State(true)); // ignored
     874             :         return;
     875             :     }
     876       62353 :     Node::Kind kind = child->kind();
     877       62353 :     if (kind != Node::KIND_GROUP && kind != Node::KIND_SET) {
     878             :         throw css::uno::RuntimeException(
     879             :             (OUString("bad <node> \"") +
     880           0 :              name +
     881           0 :              OUString("\" of non group/set kind in ") +
     882           0 :              reader.getUrl()),
     883           0 :             css::uno::Reference< css::uno::XInterface >());
     884             :     }
     885       62353 :     if (op != OPERATION_MODIFY && op != OPERATION_FUSE) {
     886             :         throw css::uno::RuntimeException(
     887             :             (OUString("invalid operation on group node in ") +
     888           0 :              reader.getUrl()),
     889           0 :             css::uno::Reference< css::uno::XInterface >());
     890             :     }
     891             :     int finalizedLayer = std::min(
     892         490 :         finalized ? valueParser_.getLayer() : Data::NO_LAYER,
     893       62843 :         child->getFinalized());
     894       62353 :     child->setFinalized(finalizedLayer);
     895             :     state_.push(
     896             :         State(
     897             :             child,
     898       62353 :             state_.top().locked || finalizedLayer < valueParser_.getLayer()));
     899             : }
     900             : 
     901      760379 : void XcuParser::handleSetNode(xmlreader::XmlReader & reader, SetNode * set) {
     902      760379 :     bool hasName = false;
     903      760379 :     OUString name;
     904      760379 :     OUString component(componentName_);
     905      760379 :     bool hasNodeType = false;
     906      760379 :     OUString nodeType;
     907      760379 :     Operation op = OPERATION_MODIFY;
     908      760379 :     bool finalized = false;
     909      760379 :     bool mandatory = false;
     910     1688524 :     for (;;) {
     911             :         int attrNsId;
     912     2448903 :         xmlreader::Span attrLn;
     913     2448903 :         if (!reader.nextAttribute(&attrNsId, &attrLn)) {
     914             :             break;
     915             :         }
     916     3377048 :         if (attrNsId == ParseManager::NAMESPACE_OOR &&
     917     1688524 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
     918             :         {
     919      760379 :             hasName = true;
     920      760379 :             name = reader.getAttributeValue(false).convertFromUtf8();
     921     1856290 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     922      928145 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("component")))
     923             :         {
     924           0 :             component = reader.getAttributeValue(false).convertFromUtf8();
     925     1856290 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     926      928145 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("node-type")))
     927             :         {
     928           0 :             hasNodeType = true;
     929           0 :             nodeType = reader.getAttributeValue(false).convertFromUtf8();
     930     1856290 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     931      928145 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("op")))
     932             :         {
     933      755567 :             op = parseOperation(reader.getAttributeValue(true));
     934      345156 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     935      172578 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("finalized")))
     936             :         {
     937      169412 :             finalized = xmldata::parseBoolean(reader.getAttributeValue(true));
     938        6332 :         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
     939        3166 :                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("mandatory")))
     940             :         {
     941        3142 :             mandatory = xmldata::parseBoolean(reader.getAttributeValue(true));
     942             :         }
     943             :     }
     944      760379 :     if (!hasName) {
     945             :         throw css::uno::RuntimeException(
     946             :             (OUString("no node name attribute in ") +
     947           0 :              reader.getUrl()),
     948           0 :             css::uno::Reference< css::uno::XInterface >());
     949             :     }
     950      760379 :     if (trackPath_) {
     951          45 :         path_.push_back(name);
     952          45 :         if (partial_ != 0 && partial_->contains(path_) == Partial::CONTAINS_NOT)
     953             :         {
     954           0 :             state_.push(State(true)); // ignored
     955             :             return;
     956             :         }
     957             :     }
     958             :     OUString templateName(
     959             :         xmldata::parseTemplateReference(
     960      760379 :             component, hasNodeType, nodeType, &set->getDefaultTemplateName()));
     961      760379 :     if (!set->isValidTemplate(templateName)) {
     962             :         throw css::uno::RuntimeException(
     963             :             (OUString("set member node ") +
     964           0 :              name +
     965           0 :              OUString(" references invalid template ") +
     966           0 :              templateName + OUString(" in ") +
     967           0 :              reader.getUrl()),
     968           0 :             css::uno::Reference< css::uno::XInterface >());
     969             :     }
     970             :     rtl::Reference< Node > tmpl(
     971      760379 :         data_.getTemplate(valueParser_.getLayer(), templateName));
     972      760379 :     if (!tmpl.is()) {
     973             :         throw css::uno::RuntimeException(
     974             :             (OUString("set member node ") +
     975           0 :              name +
     976           0 :              OUString(" references undefined template ") +
     977           0 :              templateName + OUString(" in ") +
     978           0 :              reader.getUrl()),
     979           0 :             css::uno::Reference< css::uno::XInterface >());
     980             :     }
     981      760379 :     int finalizedLayer = finalized ? valueParser_.getLayer() : Data::NO_LAYER;
     982      760379 :     int mandatoryLayer = mandatory ? valueParser_.getLayer() : Data::NO_LAYER;
     983      760379 :     NodeMap & members = set->getMembers();
     984      760379 :     NodeMap::iterator i(members.find(name));
     985      760379 :     if (i != members.end()) {
     986        9036 :         finalizedLayer = std::min(finalizedLayer, i->second->getFinalized());
     987        9036 :         i->second->setFinalized(finalizedLayer);
     988        9036 :         mandatoryLayer = std::min(mandatoryLayer, i->second->getMandatory());
     989        9036 :         i->second->setMandatory(mandatoryLayer);
     990        9036 :         if (i->second->getLayer() > valueParser_.getLayer()) {
     991           0 :             state_.push(State(true)); // ignored
     992             :             return;
     993             :         }
     994             :     }
     995      760379 :     switch (op) {
     996             :     case OPERATION_MODIFY:
     997        4812 :         if (i == members.end()) {
     998             :             SAL_WARN(
     999             :                 "configmgr",
    1000             :                 "ignoring modify of unknown set member node \"" << name
    1001             :                     << "\" in \"" << reader.getUrl() << '"');
    1002           0 :             state_.push(State(true)); // ignored
    1003             :         } else {
    1004             :             state_.push(
    1005             :                 State(
    1006        4812 :                     i->second,
    1007        4812 :                     (state_.top().locked ||
    1008        9624 :                      finalizedLayer < valueParser_.getLayer())));
    1009             :         }
    1010        4812 :         break;
    1011             :     case OPERATION_REPLACE:
    1012      750683 :         if (state_.top().locked || finalizedLayer < valueParser_.getLayer()) {
    1013           0 :             state_.push(State(true)); // ignored
    1014             :         } else {
    1015      750683 :             rtl::Reference< Node > member(tmpl->clone(true));
    1016      750683 :             member->setLayer(valueParser_.getLayer());
    1017      750683 :             member->setFinalized(finalizedLayer);
    1018      750683 :             member->setMandatory(mandatoryLayer);
    1019      750683 :             state_.push(State(member, name, false));
    1020      750683 :             recordModification(i == members.end());
    1021             :         }
    1022      750683 :         break;
    1023             :     case OPERATION_FUSE:
    1024        4884 :         if (i == members.end()) {
    1025        4876 :             if (state_.top().locked || finalizedLayer < valueParser_.getLayer())
    1026             :             {
    1027           0 :                 state_.push(State(true)); // ignored
    1028             :             } else {
    1029        4876 :                 rtl::Reference< Node > member(tmpl->clone(true));
    1030        4876 :                 member->setLayer(valueParser_.getLayer());
    1031        4876 :                 member->setFinalized(finalizedLayer);
    1032        4876 :                 member->setMandatory(mandatoryLayer);
    1033        4876 :                 state_.push(State(member, name, false));
    1034        4876 :                 recordModification(true);
    1035             :             }
    1036             :         } else {
    1037             :             state_.push(
    1038             :                 State(
    1039           8 :                     i->second,
    1040           8 :                     (state_.top().locked ||
    1041          16 :                      finalizedLayer < valueParser_.getLayer())));
    1042             :         }
    1043        4884 :         break;
    1044             :     case OPERATION_REMOVE:
    1045             :         {
    1046             :             // Ignore removal of unknown members, members finalized in a lower
    1047             :             // layer, and members made mandatory in this or a lower layer;
    1048             :             // forget about user-layer removals that no longer remove anything
    1049             :             // (so that paired additions/removals in the user layer do not grow
    1050             :             // registrymodifications.xcu unbounded):
    1051           0 :             bool known = i != members.end();
    1052           0 :             if (known && !state_.top().locked &&
    1053           0 :                 finalizedLayer >= valueParser_.getLayer() &&
    1054             :                 (mandatoryLayer == Data::NO_LAYER ||
    1055           0 :                  mandatoryLayer > valueParser_.getLayer()))
    1056             :             {
    1057           0 :                 members.erase(i);
    1058             :             }
    1059           0 :             state_.push(State(true));
    1060           0 :             if (known) {
    1061           0 :                 recordModification(false);
    1062             :             }
    1063           0 :             break;
    1064             :         }
    1065      760379 :     }
    1066             : }
    1067             : 
    1068     2121161 : void XcuParser::recordModification(bool addition) {
    1069     2121161 :     if (broadcastModifications_ != 0) {
    1070           0 :         broadcastModifications_->add(path_);
    1071             :     }
    1072     2121161 :     if (addition && additions_ != 0) {
    1073           0 :         additions_->push_back(path_);
    1074             :     }
    1075     2121161 :     if (recordModifications_) {
    1076        1117 :         data_.modifications.add(path_);
    1077             :     }
    1078     2121161 : }
    1079             : 
    1080             : }
    1081             : 
    1082             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10