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