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