1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <boost/property_tree/json_parser.hpp>
24 #include <com/sun/star/beans/NamedValue.hpp>
25 #include <com/sun/star/beans/PropertyValue.hpp>
26 #include <com/sun/star/lang/IllegalArgumentException.hpp>
27 #include <com/sun/star/reflection/XIdlField.hpp>
28 #include <com/sun/star/reflection/theCoreReflection.hpp>
29 #include <comphelper/sequenceashashmap.hxx>
30 #include <comphelper/processfactory.hxx>
31 #include <comphelper/propertysequence.hxx>
32 #include <sal/log.hxx>
33 #include <o3tl/string_view.hxx>
35 using namespace com::sun::star
;
39 uno::Any
jsonToUnoAny(const boost::property_tree::ptree
& aTree
)
44 uno::Reference
<reflection::XIdlField
> aField
;
45 boost::property_tree::ptree aNodeNull
, aNodeValue
, aNodeField
;
46 const std::string
& rType
= aTree
.get
<std::string
>("type", "");
47 const std::string
& rValue
= aTree
.get
<std::string
>("value", "");
48 uno::Sequence
<uno::Reference
<reflection::XIdlField
>> aFields
;
49 uno::Reference
<reflection::XIdlClass
> xIdlClass
50 = css::reflection::theCoreReflection::get(comphelper::getProcessComponentContext())
51 ->forName(OUString::fromUtf8(rType
.c_str()));
54 uno::TypeClass aTypeClass
= xIdlClass
->getTypeClass();
55 xIdlClass
->createObject(aAny
);
56 aFields
= xIdlClass
->getFields();
57 nFields
= aFields
.getLength();
58 aNodeValue
= aTree
.get_child("value", aNodeNull
);
59 if (nFields
> 0 && aNodeValue
!= aNodeNull
)
61 for (sal_Int32 itField
= 0; itField
< nFields
; ++itField
)
63 aField
= aFields
[itField
];
64 aNodeField
= aNodeValue
.get_child(aField
->getName().toUtf8().getStr(), aNodeNull
);
65 if (aNodeField
!= aNodeNull
)
67 aValue
= jsonToUnoAny(aNodeField
);
68 aField
->set(aAny
, aValue
);
72 else if (!rValue
.empty())
74 if (aTypeClass
== uno::TypeClass_VOID
)
76 else if (aTypeClass
== uno::TypeClass_BYTE
)
77 aAny
<<= static_cast<sal_Int8
>(o3tl::toInt32(rValue
));
78 else if (aTypeClass
== uno::TypeClass_BOOLEAN
)
79 aAny
<<= OString(rValue
.c_str()).toBoolean();
80 else if (aTypeClass
== uno::TypeClass_SHORT
)
81 aAny
<<= static_cast<sal_Int16
>(o3tl::toInt32(rValue
));
82 else if (aTypeClass
== uno::TypeClass_UNSIGNED_SHORT
)
83 aAny
<<= static_cast<sal_uInt16
>(o3tl::toUInt32(rValue
));
84 else if (aTypeClass
== uno::TypeClass_LONG
)
85 aAny
<<= o3tl::toInt32(rValue
);
86 else if (aTypeClass
== uno::TypeClass_UNSIGNED_LONG
)
87 aAny
<<= static_cast<sal_uInt32
>(o3tl::toInt32(rValue
));
88 else if (aTypeClass
== uno::TypeClass_FLOAT
)
89 aAny
<<= OString(rValue
.c_str()).toFloat();
90 else if (aTypeClass
== uno::TypeClass_DOUBLE
)
91 aAny
<<= o3tl::toDouble(rValue
);
92 else if (aTypeClass
== uno::TypeClass_STRING
)
93 aAny
<<= OUString::fromUtf8(rValue
.c_str());
100 namespace comphelper
{
102 SequenceAsHashMap::SequenceAsHashMap()
106 SequenceAsHashMap::SequenceAsHashMap(const css::uno::Any
& aSource
)
112 SequenceAsHashMap::SequenceAsHashMap(const css::uno::Sequence
< css::uno::Any
>& lSource
)
117 SequenceAsHashMap::SequenceAsHashMap(const css::uno::Sequence
< css::beans::PropertyValue
>& lSource
)
122 SequenceAsHashMap::SequenceAsHashMap(const css::uno::Sequence
< css::beans::NamedValue
>& lSource
)
127 void SequenceAsHashMap::operator<<(const css::uno::Any
& aSource
)
129 // An empty Any reset this instance!
130 if (!aSource
.hasValue())
136 css::uno::Sequence
< css::beans::NamedValue
> lN
;
143 css::uno::Sequence
< css::beans::PropertyValue
> lP
;
150 throw css::lang::IllegalArgumentException(
151 "Any contains wrong type.", css::uno::Reference
<css::uno::XInterface
>(),
156 void SequenceAsHashMap::operator<<(const css::uno::Sequence
< css::uno::Any
>& lSource
)
158 sal_Int32 c
= lSource
.getLength();
164 css::beans::PropertyValue lP
;
165 if (lSource
[i
] >>= lP
)
168 (lP
.Name
.isEmpty()) ||
169 (!lP
.Value
.hasValue())
171 throw css::lang::IllegalArgumentException(
172 "PropertyValue struct contains no useful information.",
173 css::uno::Reference
<css::uno::XInterface
>(), -1);
174 (*this)[lP
.Name
] = lP
.Value
;
178 css::beans::NamedValue lN
;
179 if (lSource
[i
] >>= lN
)
182 (lN
.Name
.isEmpty()) ||
183 (!lN
.Value
.hasValue())
185 throw css::lang::IllegalArgumentException(
186 "NamedValue struct contains no useful information.",
187 css::uno::Reference
<css::uno::XInterface
>(), -1);
188 (*this)[lN
.Name
] = lN
.Value
;
192 // ignore VOID Any ... but reject wrong filled ones!
193 if (lSource
[i
].hasValue())
194 throw css::lang::IllegalArgumentException(
195 "Any contains wrong type.",
196 css::uno::Reference
<css::uno::XInterface
>(), -1);
200 void SequenceAsHashMap::operator<<(const css::uno::Sequence
< css::beans::PropertyValue
>& lSource
)
204 sal_Int32 c
= lSource
.getLength();
205 const css::beans::PropertyValue
* pSource
= lSource
.getConstArray();
208 for (sal_Int32 i
=0; i
<c
; ++i
)
209 (*this)[pSource
[i
].Name
] = pSource
[i
].Value
;
212 void SequenceAsHashMap::operator<<(const css::uno::Sequence
< css::beans::NamedValue
>& lSource
)
216 sal_Int32 c
= lSource
.getLength();
217 const css::beans::NamedValue
* pSource
= lSource
.getConstArray();
220 for (sal_Int32 i
=0; i
<c
; ++i
)
221 (*this)[pSource
[i
].Name
] = pSource
[i
].Value
;
224 void SequenceAsHashMap::operator>>(css::uno::Sequence
< css::beans::PropertyValue
>& lDestination
) const
226 sal_Int32 c
= static_cast<sal_Int32
>(size());
227 lDestination
.realloc(c
);
228 css::beans::PropertyValue
* pDestination
= lDestination
.getArray();
231 for (const_iterator pThis
= begin();
235 pDestination
[i
].Name
= pThis
->first
.maString
;
236 pDestination
[i
].Value
= pThis
->second
;
241 void SequenceAsHashMap::operator>>(css::uno::Sequence
< css::beans::NamedValue
>& lDestination
) const
243 sal_Int32 c
= static_cast<sal_Int32
>(size());
244 lDestination
.realloc(c
);
245 css::beans::NamedValue
* pDestination
= lDestination
.getArray();
248 for (const_iterator pThis
= begin();
252 pDestination
[i
].Name
= pThis
->first
.maString
;
253 pDestination
[i
].Value
= pThis
->second
;
258 css::uno::Any
SequenceAsHashMap::getAsConstAny(bool bAsPropertyValueList
) const
260 css::uno::Any aDestination
;
261 if (bAsPropertyValueList
)
262 aDestination
<<= getAsConstPropertyValueList();
264 aDestination
<<= getAsConstNamedValueList();
268 css::uno::Sequence
< css::beans::NamedValue
> SequenceAsHashMap::getAsConstNamedValueList() const
270 css::uno::Sequence
< css::beans::NamedValue
> lReturn
;
275 css::uno::Sequence
< css::beans::PropertyValue
> SequenceAsHashMap::getAsConstPropertyValueList() const
277 css::uno::Sequence
< css::beans::PropertyValue
> lReturn
;
282 bool SequenceAsHashMap::match(const SequenceAsHashMap
& rCheck
) const
284 for (auto const& elem
: rCheck
)
286 const OUString
& sCheckName
= elem
.first
.maString
;
287 const css::uno::Any
& aCheckValue
= elem
.second
;
288 const_iterator pFound
= find(sCheckName
);
293 const css::uno::Any
& aFoundValue
= pFound
->second
;
294 if (aFoundValue
!= aCheckValue
)
301 void SequenceAsHashMap::update(const SequenceAsHashMap
& rUpdate
)
303 m_aMap
.reserve(std::max(size(), rUpdate
.size()));
304 for (auto const& elem
: rUpdate
.m_aMap
)
306 m_aMap
[elem
.first
] = elem
.second
;
310 std::vector
<css::beans::PropertyValue
> JsonToPropertyValues(const OString
& rJson
)
312 std::vector
<beans::PropertyValue
> aArguments
;
313 boost::property_tree::ptree aTree
, aNodeNull
, aNodeValue
;
314 std::stringstream
aStream(rJson
.getStr());
315 boost::property_tree::read_json(aStream
, aTree
);
317 for (const auto& rPair
: aTree
)
319 const std::string
& rType
= rPair
.second
.get
<std::string
>("type", "");
320 const std::string
& rValue
= rPair
.second
.get
<std::string
>("value", "");
322 beans::PropertyValue aValue
;
323 aValue
.Name
= OUString::fromUtf8(rPair
.first
.c_str());
324 if (rType
== "string")
325 aValue
.Value
<<= OUString::fromUtf8(rValue
.c_str());
326 else if (rType
== "boolean")
327 aValue
.Value
<<= OString(rValue
.c_str()).toBoolean();
328 else if (rType
== "float")
329 aValue
.Value
<<= OString(rValue
.c_str()).toFloat();
330 else if (rType
== "long")
331 aValue
.Value
<<= o3tl::toInt32(rValue
);
332 else if (rType
== "short")
333 aValue
.Value
<<= sal_Int16(o3tl::toInt32(rValue
));
334 else if (rType
== "unsigned short")
335 aValue
.Value
<<= sal_uInt16(o3tl::toUInt32(rValue
));
336 else if (rType
== "int64")
337 aValue
.Value
<<= o3tl::toInt64(rValue
);
338 else if (rType
== "int32")
339 aValue
.Value
<<= o3tl::toInt32(rValue
);
340 else if (rType
== "int16")
341 aValue
.Value
<<= sal_Int16(o3tl::toInt32(rValue
));
342 else if (rType
== "uint64")
343 aValue
.Value
<<= OString(rValue
.c_str()).toUInt64();
344 else if (rType
== "uint32")
345 aValue
.Value
<<= o3tl::toUInt32(rValue
);
346 else if (rType
== "uint16")
347 aValue
.Value
<<= sal_uInt16(o3tl::toUInt32(rValue
));
348 else if (rType
== "[]byte")
350 aNodeValue
= rPair
.second
.get_child("value", aNodeNull
);
351 if (aNodeValue
!= aNodeNull
&& aNodeValue
.size() == 0)
353 uno::Sequence
<sal_Int8
> aSeqByte(reinterpret_cast<const sal_Int8
*>(rValue
.c_str()),
355 aValue
.Value
<<= aSeqByte
;
358 else if (rType
== "[]any")
360 aNodeValue
= rPair
.second
.get_child("value", aNodeNull
);
361 if (aNodeValue
!= aNodeNull
&& !aNodeValue
.empty())
363 uno::Sequence
<uno::Any
> aSeq(aNodeValue
.size());
364 std::transform(aNodeValue
.begin(), aNodeValue
.end(), aSeq
.getArray(),
365 [](const auto& rSeqPair
) { return jsonToUnoAny(rSeqPair
.second
); });
366 aValue
.Value
<<= aSeq
;
370 SAL_WARN("comphelper", "JsonToPropertyValues: unhandled type '" << rType
<< "'");
371 aArguments
.push_back(aValue
);
376 } // namespace comphelper
378 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */