xref: /aoo41x/main/configmgr/source/xcsparser.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 <cstddef>
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 "groupnode.hxx"
46cdf0e10cSrcweir #include "node.hxx"
47cdf0e10cSrcweir #include "nodemap.hxx"
48cdf0e10cSrcweir #include "parsemanager.hxx"
49cdf0e10cSrcweir #include "propertynode.hxx"
50cdf0e10cSrcweir #include "setnode.hxx"
51cdf0e10cSrcweir #include "xcsparser.hxx"
52cdf0e10cSrcweir #include "xmldata.hxx"
53cdf0e10cSrcweir 
54cdf0e10cSrcweir namespace configmgr {
55cdf0e10cSrcweir 
56cdf0e10cSrcweir namespace {
57cdf0e10cSrcweir 
58cdf0e10cSrcweir namespace css = com::sun::star;
59cdf0e10cSrcweir 
60cdf0e10cSrcweir // Conservatively merge a template or component (and its recursive parts) into
61cdf0e10cSrcweir // an existing instance:
merge(rtl::Reference<Node> const & original,rtl::Reference<Node> const & update)62cdf0e10cSrcweir void merge(
63cdf0e10cSrcweir     rtl::Reference< Node > const & original,
64cdf0e10cSrcweir     rtl::Reference< Node > const & update)
65cdf0e10cSrcweir {
66cdf0e10cSrcweir     OSL_ASSERT(
67cdf0e10cSrcweir         original.is() && update.is() && original->kind() == update->kind() &&
68cdf0e10cSrcweir         update->getFinalized() == Data::NO_LAYER);
69cdf0e10cSrcweir     if (update->getLayer() >= original->getLayer() &&
70cdf0e10cSrcweir         update->getLayer() <= original->getFinalized())
71cdf0e10cSrcweir     {
72cdf0e10cSrcweir         switch (original->kind()) {
73cdf0e10cSrcweir         case Node::KIND_PROPERTY:
74cdf0e10cSrcweir         case Node::KIND_LOCALIZED_PROPERTY:
75cdf0e10cSrcweir         case Node::KIND_LOCALIZED_VALUE:
76cdf0e10cSrcweir             break; //TODO: merge certain parts?
77cdf0e10cSrcweir         case Node::KIND_GROUP:
78cdf0e10cSrcweir             for (NodeMap::iterator i2(update->getMembers().begin());
79cdf0e10cSrcweir                  i2 != update->getMembers().end(); ++i2)
80cdf0e10cSrcweir             {
81cdf0e10cSrcweir                 NodeMap::iterator i1(original->getMembers().find(i2->first));
82cdf0e10cSrcweir                 if (i1 == original->getMembers().end()) {
83cdf0e10cSrcweir                     if (i2->second->kind() == Node::KIND_PROPERTY &&
84cdf0e10cSrcweir                         dynamic_cast< GroupNode * >(
85cdf0e10cSrcweir                             original.get())->isExtensible())
86cdf0e10cSrcweir                     {
87cdf0e10cSrcweir                         original->getMembers().insert(*i2);
88cdf0e10cSrcweir                     }
89cdf0e10cSrcweir                 } else if (i2->second->kind() == i1->second->kind()) {
90cdf0e10cSrcweir                     merge(i1->second, i2->second);
91cdf0e10cSrcweir                 }
92cdf0e10cSrcweir             }
93cdf0e10cSrcweir             break;
94cdf0e10cSrcweir         case Node::KIND_SET:
95cdf0e10cSrcweir             for (NodeMap::iterator i2(update->getMembers().begin());
96cdf0e10cSrcweir                  i2 != update->getMembers().end(); ++i2)
97cdf0e10cSrcweir             {
98cdf0e10cSrcweir                 NodeMap::iterator i1(original->getMembers().find(i2->first));
99cdf0e10cSrcweir                 if (i1 == original->getMembers().end()) {
100cdf0e10cSrcweir                     if (dynamic_cast< SetNode * >(original.get())->
101cdf0e10cSrcweir                         isValidTemplate(i2->second->getTemplateName()))
102cdf0e10cSrcweir                     {
103cdf0e10cSrcweir                         original->getMembers().insert(*i2);
104cdf0e10cSrcweir                     }
105cdf0e10cSrcweir                 } else if (i2->second->kind() == i1->second->kind() &&
106cdf0e10cSrcweir                            (i2->second->getTemplateName() ==
107cdf0e10cSrcweir                             i1->second->getTemplateName()))
108cdf0e10cSrcweir                 {
109cdf0e10cSrcweir                     merge(i1->second, i2->second);
110cdf0e10cSrcweir                 }
111cdf0e10cSrcweir             }
112cdf0e10cSrcweir             break;
113cdf0e10cSrcweir         }
114cdf0e10cSrcweir     }
115cdf0e10cSrcweir }
116cdf0e10cSrcweir 
117cdf0e10cSrcweir }
118cdf0e10cSrcweir 
XcsParser(int layer,Data & data)119cdf0e10cSrcweir XcsParser::XcsParser(int layer, Data & data):
120cdf0e10cSrcweir     valueParser_(layer), data_(data), state_(STATE_START)
121cdf0e10cSrcweir {}
122cdf0e10cSrcweir 
~XcsParser()123cdf0e10cSrcweir XcsParser::~XcsParser() {}
124cdf0e10cSrcweir 
getTextMode()125cdf0e10cSrcweir xmlreader::XmlReader::Text XcsParser::getTextMode() {
126cdf0e10cSrcweir     return valueParser_.getTextMode();
127cdf0e10cSrcweir }
128cdf0e10cSrcweir 
startElement(xmlreader::XmlReader & reader,int nsId,xmlreader::Span const & name)129cdf0e10cSrcweir bool XcsParser::startElement(
130cdf0e10cSrcweir     xmlreader::XmlReader & reader, int nsId, xmlreader::Span const & name)
131cdf0e10cSrcweir {
132cdf0e10cSrcweir     if (valueParser_.startElement(reader, nsId, name)) {
133cdf0e10cSrcweir         return true;
134cdf0e10cSrcweir     }
135cdf0e10cSrcweir     if (state_ == STATE_START) {
136cdf0e10cSrcweir         if (nsId == ParseManager::NAMESPACE_OOR &&
137cdf0e10cSrcweir             name.equals(RTL_CONSTASCII_STRINGPARAM("component-schema"))) {
138cdf0e10cSrcweir             handleComponentSchema(reader);
139cdf0e10cSrcweir             state_ = STATE_COMPONENT_SCHEMA;
140cdf0e10cSrcweir             ignoring_ = 0;
141cdf0e10cSrcweir             return true;
142cdf0e10cSrcweir         }
143cdf0e10cSrcweir     } else {
144cdf0e10cSrcweir         //TODO: ignoring component-schema import, component-schema uses, and
145cdf0e10cSrcweir         // prop constraints; accepting all four at illegal places (and with
146cdf0e10cSrcweir         // illegal content):
147cdf0e10cSrcweir         if (ignoring_ > 0 ||
148cdf0e10cSrcweir             (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
149cdf0e10cSrcweir              (name.equals(RTL_CONSTASCII_STRINGPARAM("info")) ||
150cdf0e10cSrcweir               name.equals(RTL_CONSTASCII_STRINGPARAM("import")) ||
151cdf0e10cSrcweir               name.equals(RTL_CONSTASCII_STRINGPARAM("uses")) ||
152cdf0e10cSrcweir               name.equals(RTL_CONSTASCII_STRINGPARAM("constraints")))))
153cdf0e10cSrcweir         {
154cdf0e10cSrcweir             OSL_ASSERT(ignoring_ < LONG_MAX);
155cdf0e10cSrcweir             ++ignoring_;
156cdf0e10cSrcweir             return true;
157cdf0e10cSrcweir         }
158cdf0e10cSrcweir         switch (state_) {
159cdf0e10cSrcweir         case STATE_COMPONENT_SCHEMA:
160cdf0e10cSrcweir             if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
161cdf0e10cSrcweir                 name.equals(RTL_CONSTASCII_STRINGPARAM("templates")))
162cdf0e10cSrcweir             {
163cdf0e10cSrcweir                 state_ = STATE_TEMPLATES;
164cdf0e10cSrcweir                 return true;
165cdf0e10cSrcweir             }
166cdf0e10cSrcweir             // fall through
167cdf0e10cSrcweir         case STATE_TEMPLATES_DONE:
168cdf0e10cSrcweir             if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
169cdf0e10cSrcweir                 name.equals(RTL_CONSTASCII_STRINGPARAM("component")))
170cdf0e10cSrcweir             {
171cdf0e10cSrcweir                 state_ = STATE_COMPONENT;
172cdf0e10cSrcweir                 OSL_ASSERT(elements_.empty());
173cdf0e10cSrcweir                 elements_.push(
174cdf0e10cSrcweir                     Element(
175cdf0e10cSrcweir                         new GroupNode(
176cdf0e10cSrcweir                             valueParser_.getLayer(), false, rtl::OUString()),
177cdf0e10cSrcweir                         componentName_));
178cdf0e10cSrcweir                 return true;
179cdf0e10cSrcweir             }
180cdf0e10cSrcweir             break;
181cdf0e10cSrcweir         case STATE_TEMPLATES:
182cdf0e10cSrcweir             if (elements_.empty()) {
183cdf0e10cSrcweir                 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
184cdf0e10cSrcweir                     name.equals(RTL_CONSTASCII_STRINGPARAM("group")))
185cdf0e10cSrcweir                 {
186cdf0e10cSrcweir                     handleGroup(reader, true);
187cdf0e10cSrcweir                     return true;
188cdf0e10cSrcweir                 }
189cdf0e10cSrcweir                 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
190cdf0e10cSrcweir                     name.equals(RTL_CONSTASCII_STRINGPARAM("set")))
191cdf0e10cSrcweir                 {
192cdf0e10cSrcweir                     handleSet(reader, true);
193cdf0e10cSrcweir                     return true;
194cdf0e10cSrcweir                 }
195cdf0e10cSrcweir                 break;
196cdf0e10cSrcweir             }
197cdf0e10cSrcweir             // fall through
198cdf0e10cSrcweir         case STATE_COMPONENT:
199cdf0e10cSrcweir             OSL_ASSERT(!elements_.empty());
200cdf0e10cSrcweir             switch (elements_.top().node->kind()) {
201cdf0e10cSrcweir             case Node::KIND_PROPERTY:
202cdf0e10cSrcweir             case Node::KIND_LOCALIZED_PROPERTY:
203cdf0e10cSrcweir                 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
204cdf0e10cSrcweir                     name.equals(RTL_CONSTASCII_STRINGPARAM("value")))
205cdf0e10cSrcweir                 {
206cdf0e10cSrcweir                     handlePropValue(reader, elements_.top().node);
207cdf0e10cSrcweir                     return true;
208cdf0e10cSrcweir                 }
209cdf0e10cSrcweir                 break;
210cdf0e10cSrcweir             case Node::KIND_GROUP:
211cdf0e10cSrcweir                 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
212cdf0e10cSrcweir                     name.equals(RTL_CONSTASCII_STRINGPARAM("prop")))
213cdf0e10cSrcweir                 {
214cdf0e10cSrcweir                     handleProp(reader);
215cdf0e10cSrcweir                     return true;
216cdf0e10cSrcweir                 }
217cdf0e10cSrcweir                 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
218cdf0e10cSrcweir                     name.equals(RTL_CONSTASCII_STRINGPARAM("node-ref")))
219cdf0e10cSrcweir                 {
220cdf0e10cSrcweir                     handleNodeRef(reader);
221cdf0e10cSrcweir                     return true;
222cdf0e10cSrcweir                 }
223cdf0e10cSrcweir                 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
224cdf0e10cSrcweir                     name.equals(RTL_CONSTASCII_STRINGPARAM("group")))
225cdf0e10cSrcweir                 {
226cdf0e10cSrcweir                     handleGroup(reader, false);
227cdf0e10cSrcweir                     return true;
228cdf0e10cSrcweir                 }
229cdf0e10cSrcweir                 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
230cdf0e10cSrcweir                     name.equals(RTL_CONSTASCII_STRINGPARAM("set")))
231cdf0e10cSrcweir                 {
232cdf0e10cSrcweir                     handleSet(reader, false);
233cdf0e10cSrcweir                     return true;
234cdf0e10cSrcweir                 }
235cdf0e10cSrcweir                 break;
236cdf0e10cSrcweir             case Node::KIND_SET:
237cdf0e10cSrcweir                 if (nsId == xmlreader::XmlReader::NAMESPACE_NONE &&
238cdf0e10cSrcweir                     name.equals(RTL_CONSTASCII_STRINGPARAM("item")))
239cdf0e10cSrcweir                 {
240cdf0e10cSrcweir                     handleSetItem(
241cdf0e10cSrcweir                         reader,
242cdf0e10cSrcweir                         dynamic_cast< SetNode * >(elements_.top().node.get()));
243cdf0e10cSrcweir                     return true;
244cdf0e10cSrcweir                 }
245cdf0e10cSrcweir                 break;
246cdf0e10cSrcweir             default: // Node::KIND_LOCALIZED_VALUE
247cdf0e10cSrcweir                 OSL_ASSERT(false); // this cannot happen
248cdf0e10cSrcweir                 break;
249cdf0e10cSrcweir             }
250cdf0e10cSrcweir             break;
251cdf0e10cSrcweir         case STATE_COMPONENT_DONE:
252cdf0e10cSrcweir             break;
253cdf0e10cSrcweir         default: // STATE_START
254cdf0e10cSrcweir             OSL_ASSERT(false); // this cannot happen
255cdf0e10cSrcweir             break;
256cdf0e10cSrcweir         }
257cdf0e10cSrcweir     }
258cdf0e10cSrcweir     throw css::uno::RuntimeException(
259cdf0e10cSrcweir         (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("bad member <")) +
260cdf0e10cSrcweir          name.convertFromUtf8() +
261cdf0e10cSrcweir          rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("> in ")) + reader.getUrl()),
262cdf0e10cSrcweir         css::uno::Reference< css::uno::XInterface >());
263cdf0e10cSrcweir }
264cdf0e10cSrcweir 
endElement(xmlreader::XmlReader const & reader)265cdf0e10cSrcweir void XcsParser::endElement(xmlreader::XmlReader const & reader) {
266cdf0e10cSrcweir     if (valueParser_.endElement()) {
267cdf0e10cSrcweir         return;
268cdf0e10cSrcweir     }
269cdf0e10cSrcweir     if (ignoring_ > 0) {
270cdf0e10cSrcweir         --ignoring_;
271cdf0e10cSrcweir     } else if (!elements_.empty()) {
272cdf0e10cSrcweir         Element top(elements_.top());
273cdf0e10cSrcweir         elements_.pop();
274cdf0e10cSrcweir         if (top.node.is()) {
275cdf0e10cSrcweir             if (elements_.empty()) {
276cdf0e10cSrcweir                 switch (state_) {
277cdf0e10cSrcweir                 case STATE_TEMPLATES:
278cdf0e10cSrcweir                     {
279cdf0e10cSrcweir                         NodeMap::iterator i(data_.templates.find(top.name));
280cdf0e10cSrcweir                         if (i == data_.templates.end()) {
281cdf0e10cSrcweir                             data_.templates.insert(
282cdf0e10cSrcweir                                 NodeMap::value_type(top.name, top.node));
283cdf0e10cSrcweir                         } else {
284cdf0e10cSrcweir                             merge(i->second, top.node);
285cdf0e10cSrcweir                         }
286cdf0e10cSrcweir                     }
287cdf0e10cSrcweir                     break;
288cdf0e10cSrcweir                 case STATE_COMPONENT:
289cdf0e10cSrcweir                     {
290cdf0e10cSrcweir                         NodeMap::iterator i(data_.components.find(top.name));
291cdf0e10cSrcweir                         if (i == data_.components.end()) {
292cdf0e10cSrcweir                             data_.components.insert(
293cdf0e10cSrcweir                                 NodeMap::value_type(top.name, top.node));
294cdf0e10cSrcweir                         } else {
295cdf0e10cSrcweir                             merge(i->second, top.node);
296cdf0e10cSrcweir                         }
297cdf0e10cSrcweir                         state_ = STATE_COMPONENT_DONE;
298cdf0e10cSrcweir                     }
299cdf0e10cSrcweir                     break;
300cdf0e10cSrcweir                 default:
301cdf0e10cSrcweir                     OSL_ASSERT(false);
302cdf0e10cSrcweir                     throw css::uno::RuntimeException(
303cdf0e10cSrcweir                         rtl::OUString(
304cdf0e10cSrcweir                             RTL_CONSTASCII_USTRINGPARAM("this cannot happen")),
305cdf0e10cSrcweir                         css::uno::Reference< css::uno::XInterface >());
306cdf0e10cSrcweir                 }
307cdf0e10cSrcweir             } else if (!elements_.top().node->getMembers().insert(
308cdf0e10cSrcweir                            NodeMap::value_type(top.name, top.node)).second)
309cdf0e10cSrcweir             {
310cdf0e10cSrcweir                 throw css::uno::RuntimeException(
311cdf0e10cSrcweir                     (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("duplicate ")) +
312cdf0e10cSrcweir                      top.name +
313cdf0e10cSrcweir                      rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
314cdf0e10cSrcweir                      reader.getUrl()),
315cdf0e10cSrcweir                     css::uno::Reference< css::uno::XInterface >());
316cdf0e10cSrcweir             }
317cdf0e10cSrcweir         }
318cdf0e10cSrcweir     } else {
319cdf0e10cSrcweir         switch (state_) {
320cdf0e10cSrcweir         case STATE_COMPONENT_SCHEMA:
321cdf0e10cSrcweir             // To support old, broken extensions with .xcs files that contain
322cdf0e10cSrcweir             // empty <component-schema> elements:
323cdf0e10cSrcweir             state_ = STATE_COMPONENT_DONE;
324cdf0e10cSrcweir             break;
325cdf0e10cSrcweir         case STATE_TEMPLATES:
326cdf0e10cSrcweir             state_ = STATE_TEMPLATES_DONE;
327cdf0e10cSrcweir             break;
328cdf0e10cSrcweir         case STATE_TEMPLATES_DONE:
329cdf0e10cSrcweir             throw css::uno::RuntimeException(
330cdf0e10cSrcweir                 (rtl::OUString(
331cdf0e10cSrcweir                     RTL_CONSTASCII_USTRINGPARAM("no component element in ")) +
332cdf0e10cSrcweir                  reader.getUrl()),
333cdf0e10cSrcweir                 css::uno::Reference< css::uno::XInterface >());
334cdf0e10cSrcweir         case STATE_COMPONENT_DONE:
335cdf0e10cSrcweir             break;
336cdf0e10cSrcweir         default:
337cdf0e10cSrcweir             OSL_ASSERT(false); // this cannot happen
338cdf0e10cSrcweir         }
339cdf0e10cSrcweir     }
340cdf0e10cSrcweir }
341cdf0e10cSrcweir 
characters(xmlreader::Span const & text)342cdf0e10cSrcweir void XcsParser::characters(xmlreader::Span const & text) {
343cdf0e10cSrcweir     valueParser_.characters(text);
344cdf0e10cSrcweir }
345cdf0e10cSrcweir 
handleComponentSchema(xmlreader::XmlReader & reader)346cdf0e10cSrcweir void XcsParser::handleComponentSchema(xmlreader::XmlReader & reader) {
347cdf0e10cSrcweir     //TODO: oor:version, xml:lang attributes
348cdf0e10cSrcweir     rtl::OStringBuffer buf;
349cdf0e10cSrcweir     buf.append('.');
350cdf0e10cSrcweir     bool hasPackage = false;
351cdf0e10cSrcweir     bool hasName = false;
352cdf0e10cSrcweir     for (;;) {
353cdf0e10cSrcweir         int attrNsId;
354cdf0e10cSrcweir         xmlreader::Span attrLn;
355cdf0e10cSrcweir         if (!reader.nextAttribute(&attrNsId, &attrLn)) {
356cdf0e10cSrcweir             break;
357cdf0e10cSrcweir         }
358cdf0e10cSrcweir         if (attrNsId == ParseManager::NAMESPACE_OOR &&
359cdf0e10cSrcweir             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("package")))
360cdf0e10cSrcweir         {
361cdf0e10cSrcweir             if (hasPackage) {
362cdf0e10cSrcweir                 throw css::uno::RuntimeException(
363cdf0e10cSrcweir                     (rtl::OUString(
364cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM(
365cdf0e10cSrcweir                             "multiple component-schema package attributes"
366cdf0e10cSrcweir                             " in ")) +
367cdf0e10cSrcweir                      reader.getUrl()),
368cdf0e10cSrcweir                     css::uno::Reference< css::uno::XInterface >());
369cdf0e10cSrcweir             }
370cdf0e10cSrcweir             hasPackage = true;
371cdf0e10cSrcweir             xmlreader::Span s(reader.getAttributeValue(false));
372cdf0e10cSrcweir             buf.insert(0, s.begin, s.length);
373cdf0e10cSrcweir         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
374cdf0e10cSrcweir                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
375cdf0e10cSrcweir         {
376cdf0e10cSrcweir             if (hasName) {
377cdf0e10cSrcweir                 throw css::uno::RuntimeException(
378cdf0e10cSrcweir                     (rtl::OUString(
379cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM(
380cdf0e10cSrcweir                             "multiple component-schema name attributes in ")) +
381cdf0e10cSrcweir                      reader.getUrl()),
382cdf0e10cSrcweir                     css::uno::Reference< css::uno::XInterface >());
383cdf0e10cSrcweir             }
384cdf0e10cSrcweir             hasName = true;
385cdf0e10cSrcweir             xmlreader::Span s(reader.getAttributeValue(false));
386cdf0e10cSrcweir             buf.append(s.begin, s.length);
387cdf0e10cSrcweir         }
388cdf0e10cSrcweir     }
389cdf0e10cSrcweir     if (!hasPackage) {
390cdf0e10cSrcweir         throw css::uno::RuntimeException(
391cdf0e10cSrcweir             (rtl::OUString(
392cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
393cdf0e10cSrcweir                     "no component-schema package attribute in ")) +
394cdf0e10cSrcweir              reader.getUrl()),
395cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
396cdf0e10cSrcweir     }
397cdf0e10cSrcweir     if (!hasName) {
398cdf0e10cSrcweir         throw css::uno::RuntimeException(
399cdf0e10cSrcweir             (rtl::OUString(
400cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM(
401cdf0e10cSrcweir                     "no component-schema name attribute in ")) +
402cdf0e10cSrcweir              reader.getUrl()),
403cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
404cdf0e10cSrcweir     }
405cdf0e10cSrcweir     componentName_ = xmlreader::Span(buf.getStr(), buf.getLength()).
406cdf0e10cSrcweir         convertFromUtf8();
407cdf0e10cSrcweir }
408cdf0e10cSrcweir 
handleNodeRef(xmlreader::XmlReader & reader)409cdf0e10cSrcweir void XcsParser::handleNodeRef(xmlreader::XmlReader & reader) {
410cdf0e10cSrcweir     bool hasName = false;
411cdf0e10cSrcweir     rtl::OUString name;
412cdf0e10cSrcweir     rtl::OUString component(componentName_);
413cdf0e10cSrcweir     bool hasNodeType = false;
414cdf0e10cSrcweir     rtl::OUString nodeType;
415cdf0e10cSrcweir     for (;;) {
416cdf0e10cSrcweir         int attrNsId;
417cdf0e10cSrcweir         xmlreader::Span attrLn;
418cdf0e10cSrcweir         if (!reader.nextAttribute(&attrNsId, &attrLn)) {
419cdf0e10cSrcweir             break;
420cdf0e10cSrcweir         }
421cdf0e10cSrcweir         if (attrNsId == ParseManager::NAMESPACE_OOR &&
422cdf0e10cSrcweir             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
423cdf0e10cSrcweir         {
424cdf0e10cSrcweir             hasName = true;
425cdf0e10cSrcweir             name = reader.getAttributeValue(false).convertFromUtf8();
426cdf0e10cSrcweir         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
427cdf0e10cSrcweir                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("component")))
428cdf0e10cSrcweir         {
429cdf0e10cSrcweir             component = reader.getAttributeValue(false).convertFromUtf8();
430cdf0e10cSrcweir         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
431cdf0e10cSrcweir                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("node-type")))
432cdf0e10cSrcweir         {
433cdf0e10cSrcweir             hasNodeType = true;
434cdf0e10cSrcweir             nodeType = reader.getAttributeValue(false).convertFromUtf8();
435cdf0e10cSrcweir         }
436cdf0e10cSrcweir     }
437cdf0e10cSrcweir     if (!hasName) {
438cdf0e10cSrcweir         throw css::uno::RuntimeException(
439cdf0e10cSrcweir             (rtl::OUString(
440cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("no node-ref name attribute in ")) +
441cdf0e10cSrcweir              reader.getUrl()),
442cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
443cdf0e10cSrcweir     }
444cdf0e10cSrcweir     rtl::Reference< Node > tmpl(
445cdf0e10cSrcweir         data_.getTemplate(
446cdf0e10cSrcweir             valueParser_.getLayer(),
447cdf0e10cSrcweir             xmldata::parseTemplateReference(
448cdf0e10cSrcweir                 component, hasNodeType, nodeType, 0)));
449cdf0e10cSrcweir     if (!tmpl.is()) {
450cdf0e10cSrcweir         //TODO: this can erroneously happen as long as import/uses attributes
451cdf0e10cSrcweir         // are not correctly processed
452cdf0e10cSrcweir         throw css::uno::RuntimeException(
453cdf0e10cSrcweir             (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unknown node-ref ")) +
454cdf0e10cSrcweir              name + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" in ")) +
455cdf0e10cSrcweir              reader.getUrl()),
456cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
457cdf0e10cSrcweir     }
458cdf0e10cSrcweir     rtl::Reference< Node > node(tmpl->clone(false));
459cdf0e10cSrcweir     node->setLayer(valueParser_.getLayer());
460cdf0e10cSrcweir     elements_.push(Element(node, name));
461cdf0e10cSrcweir }
462cdf0e10cSrcweir 
handleProp(xmlreader::XmlReader & reader)463cdf0e10cSrcweir void XcsParser::handleProp(xmlreader::XmlReader & reader) {
464cdf0e10cSrcweir     bool hasName = false;
465cdf0e10cSrcweir     rtl::OUString name;
466cdf0e10cSrcweir     valueParser_.type_ = TYPE_ERROR;
467cdf0e10cSrcweir     bool localized = false;
468cdf0e10cSrcweir     bool nillable = true;
469cdf0e10cSrcweir     for (;;) {
470cdf0e10cSrcweir         int attrNsId;
471cdf0e10cSrcweir         xmlreader::Span attrLn;
472cdf0e10cSrcweir         if (!reader.nextAttribute(&attrNsId, &attrLn)) {
473cdf0e10cSrcweir             break;
474cdf0e10cSrcweir         }
475cdf0e10cSrcweir         if (attrNsId == ParseManager::NAMESPACE_OOR &&
476cdf0e10cSrcweir             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
477cdf0e10cSrcweir         {
478cdf0e10cSrcweir             hasName = true;
479cdf0e10cSrcweir             name = reader.getAttributeValue(false).convertFromUtf8();
480cdf0e10cSrcweir         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
481cdf0e10cSrcweir                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("type")))
482cdf0e10cSrcweir         {
483cdf0e10cSrcweir             valueParser_.type_ = xmldata::parseType(
484cdf0e10cSrcweir                 reader, reader.getAttributeValue(true));
485cdf0e10cSrcweir         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
486cdf0e10cSrcweir                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("localized")))
487cdf0e10cSrcweir         {
488cdf0e10cSrcweir             localized = xmldata::parseBoolean(reader.getAttributeValue(true));
489cdf0e10cSrcweir         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
490cdf0e10cSrcweir                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("nillable")))
491cdf0e10cSrcweir         {
492cdf0e10cSrcweir             nillable = xmldata::parseBoolean(reader.getAttributeValue(true));
493cdf0e10cSrcweir         }
494cdf0e10cSrcweir     }
495cdf0e10cSrcweir     if (!hasName) {
496cdf0e10cSrcweir         throw css::uno::RuntimeException(
497cdf0e10cSrcweir             (rtl::OUString(
498cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("no prop name attribute in ")) +
499cdf0e10cSrcweir              reader.getUrl()),
500cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
501cdf0e10cSrcweir     }
502cdf0e10cSrcweir     if (valueParser_.type_ == TYPE_ERROR) {
503cdf0e10cSrcweir         throw css::uno::RuntimeException(
504cdf0e10cSrcweir             (rtl::OUString(
505cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("no prop type attribute in ")) +
506cdf0e10cSrcweir              reader.getUrl()),
507cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
508cdf0e10cSrcweir     }
509cdf0e10cSrcweir     elements_.push(
510cdf0e10cSrcweir         Element(
511cdf0e10cSrcweir             (localized
512cdf0e10cSrcweir              ? rtl::Reference< Node >(
513cdf0e10cSrcweir                  new LocalizedPropertyNode(
514cdf0e10cSrcweir                      valueParser_.getLayer(), valueParser_.type_, nillable))
515cdf0e10cSrcweir              : rtl::Reference< Node >(
516cdf0e10cSrcweir                  new PropertyNode(
517cdf0e10cSrcweir                      valueParser_.getLayer(), valueParser_.type_, nillable,
518cdf0e10cSrcweir                      css::uno::Any(), false))),
519cdf0e10cSrcweir             name));
520cdf0e10cSrcweir }
521cdf0e10cSrcweir 
handlePropValue(xmlreader::XmlReader & reader,rtl::Reference<Node> const & property)522cdf0e10cSrcweir void XcsParser::handlePropValue(
523cdf0e10cSrcweir     xmlreader::XmlReader & reader, rtl::Reference< Node > const & property)
524cdf0e10cSrcweir {
525cdf0e10cSrcweir     xmlreader::Span attrSeparator;
526cdf0e10cSrcweir     for (;;) {
527cdf0e10cSrcweir         int attrNsId;
528cdf0e10cSrcweir         xmlreader::Span attrLn;
529cdf0e10cSrcweir         if (!reader.nextAttribute(&attrNsId, &attrLn)) {
530cdf0e10cSrcweir             break;
531cdf0e10cSrcweir         }
532cdf0e10cSrcweir         if (attrNsId == ParseManager::NAMESPACE_OOR &&
533cdf0e10cSrcweir             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("separator")))
534cdf0e10cSrcweir         {
535cdf0e10cSrcweir             attrSeparator = reader.getAttributeValue(false);
536cdf0e10cSrcweir             if (attrSeparator.length == 0) {
537cdf0e10cSrcweir                 throw css::uno::RuntimeException(
538cdf0e10cSrcweir                     (rtl::OUString(
539cdf0e10cSrcweir                         RTL_CONSTASCII_USTRINGPARAM(
540cdf0e10cSrcweir                             "bad oor:separator attribute in ")) +
541cdf0e10cSrcweir                      reader.getUrl()),
542cdf0e10cSrcweir                     css::uno::Reference< css::uno::XInterface >());
543cdf0e10cSrcweir             }
544cdf0e10cSrcweir         }
545cdf0e10cSrcweir     }
546cdf0e10cSrcweir     valueParser_.separator_ = rtl::OString(
547cdf0e10cSrcweir         attrSeparator.begin, attrSeparator.length);
548cdf0e10cSrcweir     valueParser_.start(property);
549cdf0e10cSrcweir }
550cdf0e10cSrcweir 
handleGroup(xmlreader::XmlReader & reader,bool isTemplate)551cdf0e10cSrcweir void XcsParser::handleGroup(xmlreader::XmlReader & reader, bool isTemplate) {
552cdf0e10cSrcweir     bool hasName = false;
553cdf0e10cSrcweir     rtl::OUString name;
554cdf0e10cSrcweir     bool extensible = false;
555cdf0e10cSrcweir     for (;;) {
556cdf0e10cSrcweir         int attrNsId;
557cdf0e10cSrcweir         xmlreader::Span attrLn;
558cdf0e10cSrcweir         if (!reader.nextAttribute(&attrNsId, &attrLn)) {
559cdf0e10cSrcweir             break;
560cdf0e10cSrcweir         }
561cdf0e10cSrcweir         if (attrNsId == ParseManager::NAMESPACE_OOR &&
562cdf0e10cSrcweir             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
563cdf0e10cSrcweir         {
564cdf0e10cSrcweir             hasName = true;
565cdf0e10cSrcweir             name = reader.getAttributeValue(false).convertFromUtf8();
566cdf0e10cSrcweir         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
567cdf0e10cSrcweir                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("extensible")))
568cdf0e10cSrcweir         {
569cdf0e10cSrcweir             extensible = xmldata::parseBoolean(reader.getAttributeValue(true));
570cdf0e10cSrcweir         }
571cdf0e10cSrcweir     }
572cdf0e10cSrcweir     if (!hasName) {
573cdf0e10cSrcweir         throw css::uno::RuntimeException(
574cdf0e10cSrcweir             (rtl::OUString(
575cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("no group name attribute in ")) +
576cdf0e10cSrcweir              reader.getUrl()),
577cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
578cdf0e10cSrcweir     }
579cdf0e10cSrcweir     if (isTemplate) {
580cdf0e10cSrcweir         name = Data::fullTemplateName(componentName_, name);
581cdf0e10cSrcweir     }
582cdf0e10cSrcweir     elements_.push(
583cdf0e10cSrcweir         Element(
584cdf0e10cSrcweir             new GroupNode(
585cdf0e10cSrcweir                 valueParser_.getLayer(), extensible,
586cdf0e10cSrcweir                 isTemplate ? name : rtl::OUString()),
587cdf0e10cSrcweir             name));
588cdf0e10cSrcweir }
589cdf0e10cSrcweir 
handleSet(xmlreader::XmlReader & reader,bool isTemplate)590cdf0e10cSrcweir void XcsParser::handleSet(xmlreader::XmlReader & reader, bool isTemplate) {
591cdf0e10cSrcweir     bool hasName = false;
592cdf0e10cSrcweir     rtl::OUString name;
593cdf0e10cSrcweir     rtl::OUString component(componentName_);
594cdf0e10cSrcweir     bool hasNodeType = false;
595cdf0e10cSrcweir     rtl::OUString nodeType;
596cdf0e10cSrcweir     for (;;) {
597cdf0e10cSrcweir         int attrNsId;
598cdf0e10cSrcweir         xmlreader::Span attrLn;
599cdf0e10cSrcweir         if (!reader.nextAttribute(&attrNsId, &attrLn)) {
600cdf0e10cSrcweir             break;
601cdf0e10cSrcweir         }
602cdf0e10cSrcweir         if (attrNsId == ParseManager::NAMESPACE_OOR &&
603cdf0e10cSrcweir             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("name")))
604cdf0e10cSrcweir         {
605cdf0e10cSrcweir             hasName = true;
606cdf0e10cSrcweir             name = reader.getAttributeValue(false).convertFromUtf8();
607cdf0e10cSrcweir         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
608cdf0e10cSrcweir                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("component")))
609cdf0e10cSrcweir         {
610cdf0e10cSrcweir             component = reader.getAttributeValue(false).convertFromUtf8();
611cdf0e10cSrcweir         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
612cdf0e10cSrcweir                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("node-type")))
613cdf0e10cSrcweir         {
614cdf0e10cSrcweir             hasNodeType = true;
615cdf0e10cSrcweir             nodeType = reader.getAttributeValue(false).convertFromUtf8();
616cdf0e10cSrcweir         }
617cdf0e10cSrcweir     }
618cdf0e10cSrcweir     if (!hasName) {
619cdf0e10cSrcweir         throw css::uno::RuntimeException(
620cdf0e10cSrcweir             (rtl::OUString(
621cdf0e10cSrcweir                 RTL_CONSTASCII_USTRINGPARAM("no set name attribute in ")) +
622cdf0e10cSrcweir              reader.getUrl()),
623cdf0e10cSrcweir             css::uno::Reference< css::uno::XInterface >());
624cdf0e10cSrcweir     }
625cdf0e10cSrcweir     if (isTemplate) {
626cdf0e10cSrcweir         name = Data::fullTemplateName(componentName_, name);
627cdf0e10cSrcweir     }
628cdf0e10cSrcweir     elements_.push(
629cdf0e10cSrcweir         Element(
630cdf0e10cSrcweir             new SetNode(
631cdf0e10cSrcweir                 valueParser_.getLayer(),
632cdf0e10cSrcweir                 xmldata::parseTemplateReference(
633cdf0e10cSrcweir                     component, hasNodeType, nodeType, 0),
634cdf0e10cSrcweir                 isTemplate ? name : rtl::OUString()),
635cdf0e10cSrcweir             name));
636cdf0e10cSrcweir }
637cdf0e10cSrcweir 
handleSetItem(xmlreader::XmlReader & reader,SetNode * set)638cdf0e10cSrcweir void XcsParser::handleSetItem(xmlreader::XmlReader & reader, SetNode * set) {
639cdf0e10cSrcweir     rtl::OUString component(componentName_);
640cdf0e10cSrcweir     bool hasNodeType = false;
641cdf0e10cSrcweir     rtl::OUString nodeType;
642cdf0e10cSrcweir     for (;;) {
643cdf0e10cSrcweir         int attrNsId;
644cdf0e10cSrcweir         xmlreader::Span attrLn;
645cdf0e10cSrcweir         if (!reader.nextAttribute(&attrNsId, &attrLn)) {
646cdf0e10cSrcweir             break;
647cdf0e10cSrcweir         }
648cdf0e10cSrcweir         if (attrNsId == ParseManager::NAMESPACE_OOR &&
649cdf0e10cSrcweir             attrLn.equals(RTL_CONSTASCII_STRINGPARAM("component")))
650cdf0e10cSrcweir         {
651cdf0e10cSrcweir             component = reader.getAttributeValue(false).convertFromUtf8();
652cdf0e10cSrcweir         } else if (attrNsId == ParseManager::NAMESPACE_OOR &&
653cdf0e10cSrcweir                    attrLn.equals(RTL_CONSTASCII_STRINGPARAM("node-type")))
654cdf0e10cSrcweir         {
655cdf0e10cSrcweir             hasNodeType = true;
656cdf0e10cSrcweir             nodeType = reader.getAttributeValue(false).convertFromUtf8();
657cdf0e10cSrcweir         }
658cdf0e10cSrcweir     }
659cdf0e10cSrcweir     set->getAdditionalTemplateNames().push_back(
660cdf0e10cSrcweir         xmldata::parseTemplateReference(component, hasNodeType, nodeType, 0));
661cdf0e10cSrcweir     elements_.push(Element(rtl::Reference< Node >(), rtl::OUString()));
662cdf0e10cSrcweir }
663cdf0e10cSrcweir 
664cdf0e10cSrcweir }
665