merge the formfield patch from ooo-build
[ooovba.git] / configmgr / source / backend / schemabuilder.cxx
blob0956119e858f0fe648f375bbf27e761e0cf573f1
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: schemabuilder.cxx,v $
10 * $Revision: 1.18 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
34 #include "schemabuilder.hxx"
35 #include "treenodefactory.hxx"
36 #include "matchlocale.hxx"
37 #include <com/sun/star/configuration/backend/SchemaAttribute.hpp>
38 #include <rtl/ustrbuf.hxx>
40 #ifndef INCLUDED_ALGORITHM
41 #include <algorithm>
42 #define INCLUDED_ALGORITHM
43 #endif
44 #ifndef INCLUDED_VECTOR
45 #include <vector>
46 #define INCLUDED_VECTOR
47 #endif
49 namespace configmgr
51 // -----------------------------------------------------------------------------
52 namespace backend
54 // -----------------------------------------------------------------------------
56 namespace SchemaAttribute = backenduno::SchemaAttribute;
57 // -----------------------------------------------------------------------------
58 //#if OSL_DEBUG_LEVEL > 0
59 // currently not used in debug builds
60 #if 0
61 static void check_if_complete(MergedComponentData & md, uno::Reference< uno::XComponentContext > const & xContext)
63 uno::Reference< backenduno::XSchemaHandler >
64 test(new SchemaBuilder(xContext, rtl::OUString(),md,NULL));
66 #endif
67 // -----------------------------------------------------------------------------
69 SchemaBuilder::SchemaBuilder(uno::Reference< uno::XComponentContext > const & xContext, const rtl::OUString& aExpectedComponentName, MergedComponentData & rData, ITemplateDataProvider* aTemplateProvider )
70 : m_aData(rData)
71 , m_aContext(xContext)
72 //, m_aContext(xContext,static_cast<backenduno::XSchemaHandler*>(this), aExpectedComponentName, aTemplateProvider )
73 , m_aFactory()
75 m_aContext = DataBuilderContext(xContext,static_cast<backenduno::XSchemaHandler*>(this), aExpectedComponentName, aTemplateProvider );
77 // -----------------------------------------------------------------------------
79 SchemaBuilder::~SchemaBuilder( )
83 // -----------------------------------------------------------------------------
85 // -----------------------------------------------------------------------------
86 // XSchemaHandler
88 void SAL_CALL SchemaBuilder::startSchema( )
89 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
91 if (!this->isDone())
92 m_aContext.raiseMalformedDataException("Schema builder: Unexpected Restart of Schema");
94 m_aData.clear();
96 OSL_ASSERT(!m_aContext.hasActiveComponent());
97 OSL_ASSERT( m_aContext.isDone());
99 // -----------------------------------------------------------------------------
101 void SAL_CALL SchemaBuilder::endSchema( )
102 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
104 if (!this->isDone())
105 m_aContext.raiseMalformedDataException("Schema builder: Unexpected End of Schema");
107 substituteInstances();
109 // -----------------------------------------------------------------------------
111 void SAL_CALL SchemaBuilder::importComponent( const rtl::OUString& /*aName*/ )
112 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
114 //OSL_TRACE("WARNING: Configuration schema parser: Cross-component references are not yet supported\n");
116 // -----------------------------------------------------------------------------
119 void SAL_CALL SchemaBuilder::startComponent( const rtl::OUString& aName )
120 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
122 if (m_aData.hasSchema())
123 m_aContext.raiseElementExistException("Schema builder: The component schema is already loaded", rtl::OUString());
125 m_aContext.startActiveComponent(aName);
127 std::auto_ptr<ISubtree> apSchema =
128 m_aFactory.createGroup(aName,0,getComponentRootAttributes());
130 ISubtree * pSchema = m_aData.setSchemaRoot(apSchema);
132 m_aContext.pushNode(pSchema);
134 // -----------------------------------------------------------------------------
136 void SAL_CALL SchemaBuilder::endComponent( )
137 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
139 m_aContext.popNode();
141 m_aContext.endActiveComponent();
143 // -----------------------------------------------------------------------------
145 bool SchemaBuilder::isExtensible(sal_Int16 aSchemaAttributes)
147 sal_Int16 const aValidAttributes = aSchemaAttributes & SchemaAttribute::EXTENSIBLE;
149 if (aValidAttributes != aSchemaAttributes)
150 m_aContext.raiseIllegalArgumentException("Schema builder: Illegal attribute specified for node.",2);
152 return (aValidAttributes != 0);
154 // -----------------------------------------------------------------------------
156 void SAL_CALL SchemaBuilder::startGroupTemplate( const backenduno::TemplateIdentifier& aTemplate, sal_Int16 aAttributes )
157 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
159 if (aTemplate.Component.getLength() == 0)
160 m_aContext.raiseIllegalArgumentException("Schema builder: Starting template without owning component",1);
162 m_aContext.startActiveComponent(aTemplate.Component);
164 if (m_aData.hasTemplate(aTemplate.Name))
165 m_aContext.raiseElementExistException("Schema builder: Template already exists",aTemplate.Name);
167 rtl::OUString aName = m_aData.getTemplateAccessor(aTemplate);
168 bool bExtensible = isExtensible(aAttributes);
170 std::auto_ptr<ISubtree> aTemplateTree =
171 m_aFactory.createGroup(aName,bExtensible,getTemplateBaseAttributes());
173 ISubtree * pTree = m_aData.addTemplate(aTemplateTree,aTemplate);
175 m_aContext.pushNode(pTree);
177 // -----------------------------------------------------------------------------
179 void SAL_CALL SchemaBuilder::startSetTemplate( const backenduno::TemplateIdentifier& aTemplate, sal_Int16 aAttributes, const backenduno::TemplateIdentifier& aItemType )
180 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
182 if (aTemplate.Component.getLength() == 0)
183 m_aContext.raiseIllegalArgumentException("Schema builder: Starting template without owning component",1);
185 m_aContext.startActiveComponent(aTemplate.Component);
187 if (m_aData.hasTemplate(aTemplate.Name))
188 m_aContext.raiseElementExistException("Schema builder: Template already exists",aTemplate.Name);
190 rtl::OUString aName = m_aData.getTemplateAccessor(aTemplate);
191 backenduno::TemplateIdentifier aFullType = m_aContext.completeComponent(aItemType);
192 bool bExtensible = isExtensible(aAttributes);
194 std::auto_ptr<ISubtree> aTemplateTree =
195 m_aFactory.createSet( aName,aFullType,bExtensible,getTemplateBaseAttributes());
197 ISubtree * pTree = m_aData.addTemplate(aTemplateTree,aTemplate);
199 m_aContext.pushNode(pTree);
201 // -----------------------------------------------------------------------------
203 void SAL_CALL SchemaBuilder::endTemplate( )
204 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
206 m_aContext.popNode();
208 m_aContext.endActiveComponent();
210 // -----------------------------------------------------------------------------
212 void SAL_CALL SchemaBuilder::startGroup( const rtl::OUString& aName, sal_Int16 aAttributes )
213 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
215 bool bExtensible = isExtensible(aAttributes);
217 std::auto_ptr<ISubtree> aTree = m_aFactory.createGroup(aName,bExtensible,getNodeAttributes());
219 ISubtree * pTree = m_aContext.addNodeToCurrent(aTree);
221 m_aContext.pushNode(pTree);
223 // -----------------------------------------------------------------------------
225 void SAL_CALL SchemaBuilder::startSet( const rtl::OUString& aName, sal_Int16 aAttributes, const backenduno::TemplateIdentifier& aItemType )
226 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
228 backenduno::TemplateIdentifier aFullType = m_aContext.completeComponent(aItemType);
229 bool bExtensible = isExtensible(aAttributes);
231 std::auto_ptr<ISubtree> aTree = m_aFactory.createSet(aName,aFullType,bExtensible,getNodeAttributes());
233 ISubtree * pTree = m_aContext.addNodeToCurrent(aTree);
235 m_aContext.pushNode(pTree);
237 // -----------------------------------------------------------------------------
239 void SAL_CALL SchemaBuilder::endNode( )
240 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
242 m_aContext.popNode();
244 if (m_aContext.isDone())
245 m_aContext.raiseMalformedDataException("Schema builder: Incorrect Termination");
247 // -----------------------------------------------------------------------------
249 node::Attributes SchemaBuilder::makePropertyAttributes(sal_Int16 aSchemaAttributes) const
251 const sal_uInt16 c_AllPropertyAttributes =
252 SchemaAttribute::REQUIRED | SchemaAttribute::LOCALIZED;
254 if ((aSchemaAttributes & c_AllPropertyAttributes) != aSchemaAttributes)
255 m_aContext.raiseIllegalArgumentException("SchemaBuilder: Unreckognized Attribute for Property",2);
257 node::Attributes aAttributes = getNodeAttributes();
259 if (aSchemaAttributes & SchemaAttribute::REQUIRED)
260 aAttributes.setNullable (false);
262 return aAttributes;
264 // -----------------------------------------------------------------------------
266 void SAL_CALL SchemaBuilder::addProperty( const rtl::OUString& aName, sal_Int16 aAttributes, const uno::Type& aType )
267 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
269 // TODO: add type validation
270 node::Attributes aValueAttributes = makePropertyAttributes(aAttributes);
272 if (aAttributes & SchemaAttribute::LOCALIZED)
274 std::auto_ptr<ISubtree> aLocalizedProp =
275 m_aFactory.createLocalizedContainer(aName,aType,aValueAttributes);
277 m_aContext.addLocalizedToCurrent(aLocalizedProp);
279 else
281 std::auto_ptr<ValueNode> aPropertyValue =
282 m_aFactory.getNodeFactory().createNullValueNode(aName,aType,aValueAttributes);
284 m_aContext.addPropertyToCurrent(aPropertyValue);
287 // -----------------------------------------------------------------------------
289 void SAL_CALL SchemaBuilder::addPropertyWithDefault( const rtl::OUString& aName, sal_Int16 aAttributes, const uno::Any& aDefaultValue )
290 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
292 // TODO: add parameter validation
293 node::Attributes aValueAttributes = makePropertyAttributes(aAttributes);
295 if (aAttributes & SchemaAttribute::LOCALIZED)
297 std::auto_ptr<ISubtree> aLocalizedProp =
298 m_aFactory.createLocalizedContainer(aName,aDefaultValue.getValueType(),aValueAttributes);
300 std::auto_ptr<ValueNode> aPropertyValue =
301 m_aFactory.getNodeFactory().createValueNode(localehelper::getDefaultLanguage(),aDefaultValue,aValueAttributes);
303 aLocalizedProp->addChild( base_ptr(aPropertyValue) );
305 m_aContext.addLocalizedToCurrent(aLocalizedProp);
307 else
309 std::auto_ptr<ValueNode> aPropertyValue =
310 m_aFactory.getNodeFactory().createValueNode(aName,aDefaultValue,aValueAttributes);
313 m_aContext.addPropertyToCurrent( aPropertyValue);
316 // -----------------------------------------------------------------------------
318 void SAL_CALL SchemaBuilder::addInstance( const rtl::OUString& aName, const backenduno::TemplateIdentifier& aTemplate )
319 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
321 backenduno::TemplateIdentifier aFullType = m_aContext.completeComponent(aTemplate);
323 std::auto_ptr<ISubtree> aPlaceHolder =
324 m_aFactory.createPlaceHolder(aName,aFullType);
326 m_aContext.addNodeToCurrent(aPlaceHolder);
328 // -----------------------------------------------------------------------------
330 void SAL_CALL SchemaBuilder::addItemType( const backenduno::TemplateIdentifier& aItemType )
331 throw (backenduno::MalformedDataException, lang::WrappedTargetException, uno::RuntimeException)
333 if ( m_aContext.getCurrentParent().getElementTemplateName() != aItemType.Name ||
334 m_aContext.getCurrentParent().getElementTemplateModule() != m_aContext.getTemplateComponent(aItemType) )
336 OSL_ENSURE(false, "SchemaBuilder: Multiple ItemTypes for Sets are currently not supported");
337 m_aContext.raiseMalformedDataException("SchemaBuilder: Unsupported Feature: Multiple ItemTypes for Sets");
340 // -----------------------------------------------------------------------------
341 // -----------------------------------------------------------------------------
343 node::Attributes SchemaBuilder::getNodeAttributes() const
345 node::Attributes aResult = m_aContext.getCurrentAttributes();
346 aResult.setState( node::isDefault );
347 return aResult;
349 // -----------------------------------------------------------------------------
351 node::Attributes SchemaBuilder::getComponentRootAttributes()
353 node::Attributes aResult;
354 aResult.setState( node::isDefault );
355 return aResult;
357 // -----------------------------------------------------------------------------
359 node::Attributes SchemaBuilder::getTemplateBaseAttributes()
361 node::Attributes aResult;
362 aResult.setState( node::isReplaced );
363 return aResult;
365 // -----------------------------------------------------------------------------
366 // -----------------------------------------------------------------------------
368 namespace
370 class SubstitutionHelper : NodeModification
372 MergedComponentData & m_rData;
373 DataBuilderContext m_aContext;
374 ComponentDataFactory m_aFactory;
376 std::vector< rtl::OUString > m_aReplacementList;
377 std::vector< ISubtree const * > m_aTemplateStack;
378 public:
379 SubstitutionHelper(DataBuilderContext const & aBaseContext, MergedComponentData & _rData, uno::XInterface * _pContext)
380 : m_rData(_rData)
381 , m_aContext(aBaseContext,_pContext)
382 , m_aReplacementList()
383 , m_aTemplateStack()
386 void substituteInData();
387 private:
388 void substituteInComponent(ISubtree * _pComponent);
389 void substituteInNode(ISubtree & _rNode);
390 void substituteInList();
392 void substitute(rtl::OUString const & _aName);
394 virtual void handle(ValueNode&);
395 virtual void handle(ISubtree&);
398 // -----------------------------------------------------------------------------
400 void SchemaBuilder::substituteInstances()
402 SubstitutionHelper helper(m_aContext, m_aData, static_cast<backenduno::XSchemaHandler*>(this));
404 helper.substituteInData();
406 // -----------------------------------------------------------------------------
407 // -----------------------------------------------------------------------------
408 namespace
410 // -----------------------------------------------------------------------------
411 void SubstitutionHelper::substituteInData()
413 if (m_rData.hasTemplates())
414 substituteInComponent(m_rData.getTemplatesTree());
416 if (m_rData.hasSchema())
417 substituteInComponent(m_rData.getSchemaTree());
419 // -----------------------------------------------------------------------------
421 void SubstitutionHelper::substituteInComponent(ISubtree * _pComponent)
423 OSL_ENSURE(_pComponent,"ERROR: Trying to substitute in NULL component");
425 if (_pComponent)
427 m_aContext.startActiveComponent(_pComponent->getName());
428 this->substituteInNode(*_pComponent);
429 m_aContext.endActiveComponent();
432 // -----------------------------------------------------------------------------
434 void SubstitutionHelper::substituteInNode(ISubtree & _rNode)
436 std::vector< rtl::OUString > aSaveInstances;
437 aSaveInstances.swap(m_aReplacementList);
439 // todo: own stack to check against infinite recursion
440 m_aContext.pushNode(&_rNode);
442 this->applyToChildren(_rNode); // fill the list
444 this->substituteInList();
446 m_aContext.popNode();
448 aSaveInstances.swap(m_aReplacementList);
450 // -----------------------------------------------------------------------------
452 void SubstitutionHelper::substituteInList()
454 for(std::vector< rtl::OUString >::iterator it = m_aReplacementList.begin();
455 it != m_aReplacementList.end(); ++it)
457 this->substitute(*it);
460 // -----------------------------------------------------------------------------
462 void SubstitutionHelper::substitute(rtl::OUString const & _aName)
465 ISubtree & rParent = m_aContext.getCurrentParent();
467 std::auto_ptr<INode> pReplacedNode = rParent.removeChild(_aName);
468 OSL_ASSERT( pReplacedNode.get() != NULL );
470 ISubtree * pReplacedInstance = pReplacedNode->asISubtree();
471 OSL_ASSERT( pReplacedInstance != NULL );
473 backenduno::TemplateIdentifier aTemplateName = m_aFactory.getInstanceType(*pReplacedInstance);
474 if (aTemplateName.Component == m_aContext.getActiveComponent())
476 if (ISubtree const * pTemplate = m_rData.findTemplate(aTemplateName.Name))
478 std::vector< ISubtree const * >::iterator beg = m_aTemplateStack.begin(), end = m_aTemplateStack.end();
479 if (std::find(beg,end,pTemplate) != end)
480 m_aContext.raiseMalformedDataException("SchemaBuilder: Could not expand instances: Template is recursive");
482 m_aTemplateStack.push_back(pTemplate);
484 std::auto_ptr< INode > pTemplateInstance = pTemplate->clone();
486 pTemplateInstance->setName(_aName);
487 // TODO: adjust state/attributes here (?)
489 ISubtree * pAddedTree = rParent.addChild(pTemplateInstance)->asISubtree();
491 OSL_ENSURE(pAddedTree, "Could not obtain added template instance");
493 this->substituteInNode(*pAddedTree);
495 m_aTemplateStack.pop_back();
497 else
499 m_aContext.raiseMalformedDataException("SchemaBuilder: Could not expand instances: Template not found");
502 //Import Template from different component
503 else
505 TemplateRequest aTemplateRequest(aTemplateName.Name,
506 aTemplateName.Component );
507 ResultHolder< TemplateInstance > aResult = m_aContext.getTemplateData( aTemplateRequest );
509 std::auto_ptr<INode> pTemplateInstance = aResult.extractDataAndClear();
510 pTemplateInstance->setName(_aName);
512 // Add template instance - must be a tree as any template
513 OSL_VERIFY(
514 rParent.addChild(pTemplateInstance)->asISubtree() );
517 // -----------------------------------------------------------------------------
519 void SubstitutionHelper::handle(ValueNode&)
522 // -----------------------------------------------------------------------------
524 void SubstitutionHelper::handle(ISubtree& _rTree)
526 if (m_aFactory.isInstancePlaceHolder(_rTree))
527 m_aReplacementList.push_back(_rTree.getName());
529 else
530 substituteInNode(_rTree);
532 // -----------------------------------------------------------------------------
534 // -----------------------------------------------------------------------------
535 // -----------------------------------------------------------------------------
536 } // namespace backend
538 // -------------------------------------------------------------------------
539 } // namespace configmgr