1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: localizedtreeactions.cxx,v $
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"
36 #include "localizedtreeactions.hxx"
37 #include "treeactions.hxx"
38 #include "builddata.hxx"
39 #include "subtree.hxx"
40 #include "matchlocale.hxx"
41 #include "typeconverter.hxx"
43 #include "treechangefactory.hxx"
44 #include "treenodefactory.hxx"
45 #include "strdecl.hxx"
46 #include <osl/diagnose.h>
49 //..........................................................................
53 //--------------------------------------------------------------------------
56 //--------------------------------------------------------------------------
57 //==========================================================================
59 //==========================================================================
60 //= clones a subtree , in the process selecting only the best match locale
61 //= from the set representation of localized values
62 //==========================================================================
63 class OCloneForLocale
: public NodeAction
65 rtl::OUString m_sTargetLocale
;
66 std::auto_ptr
<INode
> m_pClone
;
68 OCloneForLocale(rtl::OUString
const& aLocale
) : m_sTargetLocale(aLocale
) {}
69 std::auto_ptr
<INode
> getResult() { return m_pClone
; }
72 void handle(ValueNode
const& _aValue
);
73 void handle(ISubtree
const& _aSubtree
);
75 //--------------------------------------------------------------------------
76 struct OCloneChildrenForLocale
: NodeAction
79 localehelper::FindBestLocale
& m_rLocaleMatcher
;
81 OCloneChildrenForLocale(ISubtree
& _rParent
, localehelper::FindBestLocale
& _rLocaleMatcher
)
83 , m_rLocaleMatcher(_rLocaleMatcher
)
86 virtual void handle(ValueNode
const& _aValue
);
87 virtual void handle(ISubtree
const& _aSubtree
);
90 //--------------------------------------------------------------------------
91 struct OSelectForLocale
: NodeAction
93 ValueNode
const* m_pFound
;
94 localehelper::FindBestLocale
& m_rLocaleMatcher
;
96 OSelectForLocale(localehelper::FindBestLocale
& _rLocaleMatcher
)
98 , m_rLocaleMatcher(_rLocaleMatcher
)
102 bool hasResult() const
103 { return m_pFound
!= NULL
; }
105 ValueNode
const* getResult() const
109 virtual void handle(ValueNode
const& _aValue
);
110 virtual void handle(ISubtree
const& _aSubtree
);
112 void maybeSelect(ValueNode
const& _aNode
);
115 //--------------------------------------------------------------------------
116 //--------------------------------------------------------------------------
117 void OSelectForLocale::handle(ValueNode
const& _aValue
)
119 maybeSelect(_aValue
);
121 //--------------------------------------------------------------------------
122 void OSelectForLocale::handle(ISubtree
const& /*_aSubtree*/)
124 OSL_ENSURE(false, "INTERNAL ERROR: Inconsistent data: Found a Subtree in a set of localized values");
126 //--------------------------------------------------------------------------
127 void OSelectForLocale::maybeSelect(ValueNode
const& _aNode
)
129 if (m_rLocaleMatcher
.accept( localehelper::makeLocale(_aNode
.getName()) ) )
133 OSL_ENSURE(m_pFound
, "WARNING: Node Locale wasn't accepted, but no node had been found before");
136 //--------------------------------------------------------------------------
137 //--------------------------------------------------------------------------
138 std::auto_ptr
< INode
> implReduceLocalizedSet(ISubtree
const& _aSubtree
, localehelper::FindBestLocale
& _rLocaleMatcher
)
140 // -- find the best-match locale -----------------------------
141 _rLocaleMatcher
.reset();
143 OSelectForLocale
aSelector(_rLocaleMatcher
);
145 aSelector
.applyToChildren(_aSubtree
);
147 std::auto_ptr
< INode
> pResult
;
149 // -- look for a non-NULL value -----------------------------
150 uno::Type aValueType
;
151 if (aSelector
.hasResult())
153 ValueNode
const& rSelected
= *aSelector
.getResult();
155 aValueType
= rSelected
.getValueType();
157 if (!rSelected
.isNull()) // values are present - clone it from the values
159 pResult
.reset ( new ValueNode( _aSubtree
.getName(),
160 rSelected
.getValue(), rSelected
.getDefault(),
161 _aSubtree
.getAttributes()
166 else // no entry - exract the type to be used from the template name
167 aValueType
= parseTemplateName(_aSubtree
.getElementTemplateName());
169 // -- create NULL value, if none was found -----------------------------
170 // create a NULL of the found type
171 if (pResult
.get() == NULL
)
173 pResult
.reset( new ValueNode( _aSubtree
.getName(),
175 _aSubtree
.getAttributes()
179 // -- -----------------------------
180 OSL_ENSURE( aValueType
!= uno::Type(), "VOID result type found");
181 #if OSL_DEBUG_LEVEL > 0
182 uno::Type aTemplateType
= parseTemplateName( _aSubtree
.getElementTemplateName() );
183 OSL_ENSURE( ( aValueType
== aTemplateType
) || ( aTemplateType
.getTypeClass() == uno::TypeClass_ANY
),
184 "ERROR: Found Value Type doesn't match encoded value type in pseudo template name");
186 OSL_POSTCOND( static_cast<ValueNode
&>(*pResult
).getValueType() == aValueType
,
187 "ERROR: Resulting Value Type doesn't match original value type" );
191 //--------------------------------------------------------------------------
192 std::auto_ptr
< INode
> implCloneForLocale(ISubtree
const& _aSubtree
, localehelper::FindBestLocale
& _rLocaleMatcher
)
194 std::auto_ptr
< INode
> pClone
;
196 if (isLocalizedValueSet(_aSubtree
))
198 pClone
= implReduceLocalizedSet(_aSubtree
, _rLocaleMatcher
);
202 // ISubtree should get a clone(NoChildCopy) member ...
203 std::auto_ptr
< Subtree
> pCloneTree( new Subtree(_aSubtree
, treeop::NoChildCopy()) );
205 OCloneChildrenForLocale
aSubCloner(*pCloneTree
,_rLocaleMatcher
);
207 aSubCloner
.applyToChildren(_aSubtree
);
209 pClone
.reset( pCloneTree
.release() );
214 //--------------------------------------------------------------------------
215 //--- OCloneChildrenForLocale:-----------------------------------------------------------------------
217 void OCloneChildrenForLocale::handle(ValueNode
const& _aValue
)
219 // just a single value - nothing to do
220 std::auto_ptr
< INode
> pClone( _aValue
.clone() );
222 m_rParent
.addChild(pClone
);
225 //--------------------------------------------------------------------------
226 void OCloneChildrenForLocale::handle(ISubtree
const& _aSubtree
)
228 std::auto_ptr
< INode
> pClone
= implCloneForLocale(_aSubtree
,m_rLocaleMatcher
);
230 m_rParent
.addChild(pClone
);
233 //--------------------------------------------------------------------------
236 // rtl::OUString m_sTargetLocale;
237 // std::auto_ptr<INode> m_pClone;
239 void OCloneForLocale::handle(ValueNode
const& _aValue
)
241 // just a single value - nothing to do
242 std::auto_ptr
< INode
> pClone( _aValue
.clone() );
246 //--------------------------------------------------------------------------
247 void OCloneForLocale::handle(ISubtree
const& _aSubtree
)
249 localehelper::FindBestLocale
aLocaleMatcher( localehelper::makeLocale(m_sTargetLocale
) );
251 m_pClone
= implCloneForLocale(_aSubtree
,aLocaleMatcher
);
253 //--------------------------------------------------------------------------
255 //--------------------------------------------------------------------------
256 } // anonymous namespace
258 //==========================================================================
259 // Helper function to invoke the previous ones properly
261 // convert to the given locale format, assuming the original representation was expanded
262 static std::auto_ptr
<INode
> impl_cloneExpandedForLocale(INode
const* _pNode
, rtl::OUString
const& _sLocale
)
264 OSL_ASSERT(_pNode
!= NULL
);
266 if ( localehelper::designatesAllLocales(localehelper::makeLocale(_sLocale
)) ) // from expanded to expanded
268 return _pNode
->clone();
271 else // needs reduction
273 OCloneForLocale
aCloner(_sLocale
);
274 aCloner
.applyToNode(*_pNode
);
275 return aCloner
.getResult();
278 //--------------------------------------------------------------------------
280 // convert to the given locale format, assuming the original representation was expanded
281 static rtl::Reference
< data::TreeSegment
> old_cloneExpandedForLocale(rtl::OUString
const& _sName
, INode
const* _pNode
, rtl::OUString
const& _sLocale
)
284 return rtl::Reference
< data::TreeSegment
>();
286 std::auto_ptr
<INode
> aResult
;
287 if (dynamic_cast< ISubtree
const * >(_pNode
) == 0) // simple value - nothing to reduce
288 aResult
= _pNode
->clone();
291 aResult
= impl_cloneExpandedForLocale(_pNode
,_sLocale
);
293 return data::TreeSegment::create(_sName
,aResult
);
295 //--------------------------------------------------------------------------
297 // -----------------------------------------------------------------------------
298 //--------------------------------------------------------------------------
299 rtl::Reference
< data::TreeSegment
> cloneExpandedForLocale(sharable::TreeFragment
* tree
, rtl::OUString
const& _sLocale
)
301 std::auto_ptr
<INode
> aOldTree
= data::convertTree(tree
, true);
303 return old_cloneExpandedForLocale(tree
->getName(), aOldTree
.get(), _sLocale
);
305 //--------------------------------------------------------------------------
306 // convert to the given locale format, assuming the original representation was expanded
307 std::auto_ptr
<INode
> reduceExpandedForLocale(std::auto_ptr
<ISubtree
> _pNode
, rtl::OUString
const& _sLocale
)
309 std::auto_ptr
<INode
> aResult
;
311 if ( _pNode
.get() == NULL
|| // nothing to reduce
312 localehelper::designatesAllLocales(localehelper::makeLocale(_sLocale
)) ) // from expanded to expanded
314 aResult
.reset( _pNode
.release() );
317 else // needs reduction
319 OCloneForLocale
aCloner(_sLocale
);
320 aCloner
.applyToNode(*_pNode
);
321 aResult
= aCloner
.getResult();
323 OSL_ENSURE(aResult
.get(),"Cloning a tree for a locale unexpectedly produced NOTHING");
327 //--------------------------------------------------------------------------
330 //--------------------------------------------------------------------------
331 class ExpandTreeForLocale
: NodeModification
333 ISubtree
& m_rParent
;
334 rtl::OUString
const & m_aSourceLocale
;
336 ExpandTreeForLocale(ISubtree
& _rParent
,rtl::OUString
const & _aSourceLocale
)
337 : m_rParent(_rParent
)
338 , m_aSourceLocale(_aSourceLocale
)
341 void handle(ISubtree
& _rNode
);
342 void handle(ValueNode
& _rNode
);
344 void substitute(std::auto_ptr
<INode
> _aExpanded
);
346 static void expand(ISubtree
& _rTree
, rtl::OUString
const & _aSourceLocale
)
348 ExpandTreeForLocale(_rTree
,_aSourceLocale
).applyToChildren(_rTree
);
351 // returns NULL, if not a localized value
352 static std::auto_ptr
<ISubtree
> expanded(ValueNode
const& _aNode
, rtl::OUString
const & _aSourceLocale
);
355 //--------------------------------------------------------------------------
356 class ExpandChangesForLocale
: ChangeTreeModification
358 SubtreeChange
& m_rParent
;
359 rtl::OUString
const & m_aSourceLocale
;
361 ExpandChangesForLocale(SubtreeChange
& _rParent
,rtl::OUString
const & _aSourceLocale
)
362 : m_rParent(_rParent
)
363 , m_aSourceLocale(_aSourceLocale
)
366 void handle(SubtreeChange
& _rNode
);
367 void handle(ValueChange
& _rNode
);
369 void handle(AddNode
& _rNode
);
370 void handle(RemoveNode
& _rNode
);
372 void substitute(std::auto_ptr
<Change
> _aExpanded
);
374 static void expand(SubtreeChange
& _rTree
, rtl::OUString
const & _aSourceLocale
)
376 ExpandChangesForLocale(_rTree
,_aSourceLocale
).applyToChildren(_rTree
);
379 // returns NULL, if not a localized value
380 static std::auto_ptr
<SubtreeChange
> expanded(ValueChange
const& _aNode
, rtl::OUString
const & _aSourceLocale
);
382 //--------------------------------------------------------------------------
384 void ExpandTreeForLocale::substitute(std::auto_ptr
<INode
> _aExpanded
)
386 m_rParent
.removeChild(_aExpanded
->getName());
387 m_rParent
.addChild(_aExpanded
);
390 //--------------------------------------------------------------------------
391 void ExpandTreeForLocale::handle(ISubtree
& _rNode
)
393 expand(_rNode
,m_aSourceLocale
);
396 //--------------------------------------------------------------------------
397 void ExpandTreeForLocale::handle(ValueNode
& _rNode
)
399 std::auto_ptr
<ISubtree
> aExpanded
= expanded(_rNode
,m_aSourceLocale
);
402 substitute( base_ptr(aExpanded
) );
405 //--------------------------------------------------------------------------
407 std::auto_ptr
<ISubtree
> ExpandTreeForLocale::expanded(ValueNode
const& _aNode
, rtl::OUString
const & _aSourceLocale
)
409 if (!_aNode
.isLocalized()) return std::auto_ptr
<ISubtree
>();
411 OTreeNodeFactory
& rFactory
= getDefaultTreeNodeFactory();
413 node::Attributes aValueAttributes
= _aNode
.getAttributes();
415 aValueAttributes
.setLocalized(false);
416 if (aValueAttributes
.state() == node::isMerged
)
417 aValueAttributes
.setState( node::isReplaced
);
420 std::auto_ptr
<ValueNode
> aValue
= _aNode
.isNull()
421 ? rFactory
.createNullValueNode(_aSourceLocale
,_aNode
.getValueType(),aValueAttributes
)
422 : rFactory
.createValueNode(_aSourceLocale
,_aNode
.getValue(),aValueAttributes
);
424 std::auto_ptr
<ISubtree
> aRet
= rFactory
.createSetNode( _aNode
.getName(),
425 toTemplateName(_aNode
.getValueType()),
426 TEMPLATE_MODULE_LOCALIZED_VALUE
,
427 _aNode
.getAttributes() );
429 aRet
->addChild(base_ptr(aValue
));
434 //--------------------------------------------------------------------------
435 //--------------------------------------------------------------------------
437 void ExpandChangesForLocale::substitute(std::auto_ptr
<Change
> _aExpanded
)
439 m_rParent
.removeChange(_aExpanded
->getNodeName());
440 m_rParent
.addChange(_aExpanded
);
443 //--------------------------------------------------------------------------
445 void ExpandChangesForLocale::handle(SubtreeChange
& _rNode
)
447 expand(_rNode
,m_aSourceLocale
);
450 //--------------------------------------------------------------------------
451 void ExpandChangesForLocale::handle(ValueChange
& _rNode
)
453 std::auto_ptr
<SubtreeChange
> aExpanded
= expanded(_rNode
,m_aSourceLocale
);
456 substitute( base_ptr( aExpanded
) );
459 //--------------------------------------------------------------------------
460 void ExpandChangesForLocale::handle(AddNode
& _rNode
)
462 rtl::Reference
< data::TreeSegment
> seg(_rNode
.getNewTree());
463 std::auto_ptr
<INode
> pAdded(data::convertTree(seg
.is() ? seg
->fragment
: 0, false));
464 if (pAdded
.get() != NULL
)
466 std::auto_ptr
<INode
> pExpanded
;
467 if (ISubtree
* pAddedTree
= pAdded
->asISubtree())
469 ExpandTreeForLocale::expand(*pAddedTree
,m_aSourceLocale
);
472 else if(ValueNode
* pAddedValue
= pAdded
->asValueNode())
474 pExpanded
= base_ptr(ExpandTreeForLocale::expanded(*pAddedValue
,m_aSourceLocale
));
477 OSL_ENSURE(false, "Cannot expand unknown Node type (found in AddNode)");
482 rtl::Reference
< data::TreeSegment
> aExpanded
= data::TreeSegment::create( _rNode
.getNodeName(),pExpanded
);
483 std::auto_ptr
<AddNode
> aExpandedAdd( new AddNode( aExpanded
, _rNode
.getNodeName(), _rNode
.isToDefault() ) );
485 if (_rNode
.isReplacing()) aExpandedAdd
->setReplacing();
487 substitute( base_ptr( aExpandedAdd
) );
491 OSL_ENSURE(false, "Cannot expand AddNode without content");
494 //--------------------------------------------------------------------------
495 void ExpandChangesForLocale::handle(RemoveNode
& )
500 //--------------------------------------------------------------------------
501 std::auto_ptr
<SubtreeChange
> ExpandChangesForLocale::expanded(ValueChange
const& _aNode
, rtl::OUString
const & _aSourceLocale
)
503 std::auto_ptr
<SubtreeChange
> aRet
;
504 if (_aNode
.isLocalizedValue())
506 OTreeNodeFactory
& rNodeFactory
= getDefaultTreeNodeFactory();
507 OTreeChangeFactory
& rFactory
= getDefaultTreeChangeFactory();
509 node::Attributes aValueAttributes
= _aNode
.getAttributes();
511 aValueAttributes
.setLocalized(false);
512 if (aValueAttributes
.state() == node::isMerged
)
513 aValueAttributes
.setState( node::isReplaced
);
516 rtl::OUString
const sTemplateName
= toTemplateName(_aNode
.getValueType());
518 std::auto_ptr
<ValueNode
> aValue
= _aNode
.getNewValue().hasValue()
519 ? rNodeFactory
.createValueNode(sTemplateName
,_aNode
.getNewValue(),aValueAttributes
)
520 : rNodeFactory
.createNullValueNode(sTemplateName
,_aNode
.getValueType(),aValueAttributes
);
522 rtl::Reference
< data::TreeSegment
> aValueSegment
= data::TreeSegment::create(_aSourceLocale
, base_ptr(aValue
));
524 std::auto_ptr
<AddNode
> aAddValue
= rFactory
.createAddNodeChange(aValueSegment
,_aSourceLocale
,_aNode
.isToDefault());
525 aAddValue
->setReplacing();
527 aRet
= rFactory
.createSetNodeChange( _aNode
.getNodeName(),
529 TEMPLATE_MODULE_LOCALIZED_VALUE
,
530 _aNode
.getAttributes() );
532 aRet
->addChange(base_ptr(aAddValue
));
537 //--------------------------------------------------------------------------
538 } // anonymous namespace
539 //--------------------------------------------------------------------------
541 //--------------------------------------------------------------------------
542 //..........................................................................
543 } // namespace configmgr
544 //..........................................................................