VariantJsonCompressor.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2012-2016, High Performance Humanoid Technologies (H2T),
5 * Karlsruhe Institute of Technology (KIT), all rights reserved.
6 *
7 * ArmarX is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * ArmarX is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * @author Simon Ottenhaus (simon dot ottenhaus at kit dot edu)
20 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
21 * GNU General Public License
22 */
23
25
26#include <Ice/ObjectFactory.h>
27
29
32
34
35namespace armarx
36{
40
43 const std::string& variantBaseTypeName,
44 const Ice::CommunicatorPtr& communicator)
45 {
46 StructuralJsonParser parser(json, false, true);
47 parser.parse();
48 if (parser.iserr())
49 {
50 return ParseResult("JSON parse error: " + parser.geterr(), ParseResult::eSytaxError);
51 }
52
53 ContainerTypePtr containerInfo =
55 ParseResult result = CheckUserInput(parser.parsedJson, containerInfo, communicator);
56 if (result.iserr())
57 {
58 JPathNavigator nav(parser.parsedJson);
59 nav = nav.selectSingleNode("type");
60 if (nav.isString())
61 {
62 std::string type = nav.asString();
66 {
67 return ParseResult("Input might be in old format. Try importing.\n" +
68 result.geterr(),
69 result.getErrorType());
70 }
71 }
72 }
73 return result;
74 }
75
77 VariantJsonCompressor::FormatUserInput(std::string& json, int indenting)
78 {
79 StructuralJsonParser parser(json, false, true);
80 parser.parse();
81 if (parser.iserr())
82 {
83 return ParseResult("JSON parse error: " + parser.geterr(), ParseResult::eSytaxError);
84 }
85 json = parser.parsedJson->toJsonString(indenting);
86 return ParseResult::Success();
87 }
88
91 const ContainerTypePtr& containerInfo,
92 const Ice::CommunicatorPtr& communicator)
93 {
94 JPathNavigator nav(json);
95 if (containerInfo->subType)
96 {
97 if (containerInfo->typeId == SingleTypeVariantList::getTypePrefix())
98 {
99 if (!nav.isArray())
100 {
101 return ParseResult::Error(
102 "Unexpected JSON data type. Expected array at " +
103 nav.getData()->getLexerStartOffset().toLongString(),
105 }
106 for (JPathNavigator child : nav.select("*"))
107 {
108 ParseResult r =
109 CheckUserInput(child.getData(), containerInfo->subType, communicator);
110 if (r.iserr())
111 {
112 return r;
113 }
114 }
115 return ParseResult::Success();
116 }
117 else if (containerInfo->typeId == StringValueMap::getTypePrefix())
118 {
119 if (!nav.isObject())
120 {
121 return ParseResult::Error(
122 "Unexpected JSON data type. Expected object at " +
123 nav.getData()->getLexerStartOffset().toLongString(),
125 }
126 for (JPathNavigator child : nav.select("*"))
127 {
128 ParseResult r =
129 CheckUserInput(child.getData(), containerInfo->subType, communicator);
130 if (r.iserr())
131 {
132 return r;
133 }
134 }
135 return ParseResult::Success();
136 }
137 else
138 {
139 return ParseResult::Error("Unknown container type: " + containerInfo->typeId +
140 ". At " +
141 nav.getData()->getLexerStartOffset().toLongString(),
143 }
144 }
145 else if (VariantType::IsBasicType(Variant::hashTypeName(containerInfo->typeId)))
146 {
147 VariantTypeId type = Variant::hashTypeName(containerInfo->typeId);
148 if (type == VariantType::Bool && !nav.isBool())
149 {
150 return ParseResult::Error("Cannot parse Variant: Expected bool at " +
151 nav.getData()->getLexerStartOffset().toLongString(),
153 }
154 else if (type == VariantType::String && !nav.isString())
155 {
156 return ParseResult::Error("Cannot parse Variant: Expected string at " +
157 nav.getData()->getLexerStartOffset().toLongString(),
159 }
160 else if (type == VariantType::Float && !nav.isNumber())
161 {
162 return ParseResult::Error("Cannot parse Variant: Expected number at " +
163 nav.getData()->getLexerStartOffset().toLongString(),
165 }
166 else if (type == VariantType::Double && !nav.isNumber())
167 {
168 return ParseResult::Error("Cannot parse Variant: Expected number at " +
169 nav.getData()->getLexerStartOffset().toLongString(),
171 }
172 else if (type == VariantType::Int && !nav.isInt())
173 {
174 return ParseResult::Error("Cannot parse Variant: Expected int at " +
175 nav.getData()->getLexerStartOffset().toLongString(),
177 }
178 else if (type == VariantType::Long && !nav.isInt())
179 {
180 return ParseResult::Error("Cannot parse Variant: Expected int at " +
181 nav.getData()->getLexerStartOffset().toLongString(),
183 }
184
185 return ParseResult::Success();
186 }
187 else
188 {
189 Ice::ValueFactoryPtr factory =
190 communicator->getValueFactoryManager()->find(containerInfo->typeId);
191 SerializablePtr obj =
192 SerializablePtr::dynamicCast(factory->create(containerInfo->typeId));
193 static Ice::Current c;
194
195 JSONObjectPtr jsonObject = new JSONObject();
196 jsonObject->fromString(json->toJsonString(0));
197 try
198 {
199 obj->deserialize(jsonObject, c);
200 }
201 catch (const UserException& ex)
202 {
203 return ParseResult::Error(std::string("Cannot parse Variant: ") + ex.ice_id() +
204 ": " + ex.reason + ". At " +
205 nav.getData()->getLexerStartOffset().toLongString(),
207 }
208 catch (LocalException& ex)
209 {
210 return ParseResult::Error(std::string("Cannot parse Variant: ") + ex.name() + ": " +
211 ex.getReason() + ". At " +
212 nav.getData()->getLexerStartOffset().toLongString(),
214 }
215
216 VariantDataPtr variant = VariantDataPtr::dynamicCast(obj);
217 if (variant == 0)
218 {
219 return ParseResult::Error(
220 "Cannot cast Variant. Expected: " + containerInfo->typeId +
221 ". Is: " + obj->ice_id() + ". At " +
222 nav.getData()->getLexerStartOffset().toLongString(),
224 }
225 return ParseResult::Success();
226 }
227 }
228
229 std::string
230 VariantJsonCompressor::Compress(const std::string& json,
231 const std::string& variantBaseTypeName,
232 int indenting)
233 {
234 JsonDataPtr compressed = CompressToJson(json, variantBaseTypeName);
235 return compressed->toJsonString(indenting);
236 }
237
240 const std::string& variantBaseTypeName)
241 {
242 StructuralJsonParser parser(json, false, true);
243 parser.parse();
244 if (parser.iserr())
245 {
246 throw VariantJsonException("Invalid json: ") << parser.geterr();
247 }
248
249 ContainerTypePtr containerInfo =
251 return Compress(parser.parsedJson, containerInfo);
252 }
253
254 std::string
255 VariantJsonCompressor::Decompress(const std::string& json,
256 const std::string& variantBaseTypeName)
257 {
258 StructuralJsonParser parser(json, false, true);
259 parser.parse();
260 if (parser.iserr())
261 {
262 throw VariantJsonException("Invalid json: ") << parser.geterr();
263 }
264
265 ContainerTypePtr containerInfo =
267 JsonDataPtr decompressed = Decompress(parser.parsedJson, containerInfo);
268 return decompressed->toJsonString(0);
269 }
270
271 std::string
273 const std::string& variantBaseTypeName)
274 {
275 int typeId = Variant::hashTypeName(variantBaseTypeName);
276
277 JsonObjectPtr variant(new JsonObject);
278 variant->add("typeName", variantBaseTypeName);
279
280 if (typeId == VariantType::Int)
281 {
282 variant->add("value", JsonValue::CreateRaw(JsonValue::eNumber, value));
283 }
284 else if (typeId == VariantType::Long)
285 {
286 variant->add("value", JsonValue::CreateRaw(JsonValue::eNumber, value));
287 }
288 else if (typeId == VariantType::Bool)
289 {
290 variant->add("value", JsonValue::CreateRaw(JsonValue::eBool, value));
291 }
292 else if (typeId == VariantType::Float)
293 {
294 variant->add("value", JsonValue::CreateRaw(JsonValue::eNumber, value));
295 }
296 else if (typeId == VariantType::Double)
297 {
298 variant->add("value", JsonValue::CreateRaw(JsonValue::eNumber, value));
299 }
300 else if (typeId == VariantType::String)
301 {
302 variant->add("value", JsonValue::CreateRaw(JsonValue::eString, value));
303 }
304 else
305 {
306 throw VariantJsonException("Unsupported Basic Type: ") << variantBaseTypeName;
307 }
308
310 o->add("type", JsonValue(SingleVariant::getTypePrefix()));
311 o->add("variant", variant);
312 return o->toJsonString(0);
313 }
314
317 const ContainerTypePtr& containerInfo)
318 {
319 if (containerInfo->subType)
320 {
321 JPathNavigator nav(json);
322 if (containerInfo->typeId == SingleTypeVariantList::getTypePrefix())
323 {
324 JsonArrayPtr array(new JsonArray);
325 if (!nav.isArray())
326 {
327 throw VariantJsonException("Wrong JSON data type. Expected array at ")
328 << nav.getData()->getLexerStartOffset().toLongString();
329 }
330 for (JPathNavigator child : nav.select("*"))
331 {
332 array->add(Decompress(child.getData(), containerInfo->subType));
333 }
334 JsonObjectPtr o(new JsonObject);
335 o->add("array", array);
336 o->add("type", JsonValue(containerInfo->typeId));
337 return o;
338 }
339 else if (containerInfo->typeId == StringValueMap::getTypePrefix())
340 {
341 JsonObjectPtr map(new JsonObject);
342 if (!nav.isObject())
343 {
344 throw VariantJsonException("Wrong JSON data type. Expected object at ")
345 << nav.getData()->getLexerStartOffset().toLongString();
346 }
347 for (JPathNavigator child : nav.select("*"))
348 {
349 map->add(child.getKey(), Decompress(child.getData(), containerInfo->subType));
350 }
351 JsonObjectPtr o(new JsonObject);
352 o->add("map", map);
353 o->add("type", JsonValue(containerInfo->typeId));
354 return o;
355 }
356 else
357 {
358 throw VariantJsonException("Unknown container type: ") << containerInfo->typeId;
359 }
360 }
361 else
362 {
363 JsonObjectPtr variant(new JsonObject);
364 variant->add("typeName", containerInfo->typeId);
365 variant->add("value", json->clone());
366 JsonObjectPtr o(new JsonObject);
367 o->add("type", JsonValue(SingleVariant::getTypePrefix()));
368 o->add("variant", variant);
369 return o;
370 }
371 }
372
375 const ContainerTypePtr& containerInfo)
376 {
377 if (containerInfo->subType)
378 {
379 if (containerInfo->typeId == SingleTypeVariantList::getTypePrefix())
380 {
381 JsonArrayPtr a(new JsonArray);
382 for (JPathNavigator child : nav.select("array/*"))
383 {
384 a->add(Compress(child.getData(), containerInfo->subType));
385 }
386 return a;
387 }
388 else if (containerInfo->typeId == StringValueMap::getTypePrefix())
389 {
390 JsonObjectPtr o(new JsonObject);
391 for (JPathNavigator child : nav.select("map/*"))
392 {
393 o->add(child.getKey(), Compress(child.getData(), containerInfo->subType));
394 }
395 return o;
396 }
397 else
398 {
399 throw VariantJsonException("Unknown container type: ") << containerInfo->typeId;
400 }
401 }
402 else
403 {
404 std::string typeName = nav.selectSingleNode("variant/typeName").asString();
405 if (typeName != containerInfo->typeId)
406 {
407 throw VariantJsonException("typeName mismatch. expected: ")
408 << containerInfo->typeId << ". is: " << typeName;
409 }
410
411 return nav.selectSingleNode("variant/value").getData();
412 }
413 }
414} // namespace armarx
constexpr T c
int parse(FILE *, bool)
Definition Parser.cpp:585
static JsonValuePtr CreateRaw(Type type, const std::string &value)
static ParseResult Error(const std::string &error, ErrorType errorType)
ErrorType getErrorType()
static ParseResult Success()
std::string geterr()
static std::string getTypePrefix()
static std::string getTypePrefix()
static ContainerTypePtr FromString(const std::string &typeStr)
static std::string Compress(const std::string &json, const std::string &variantBaseTypeName, int indenting=2)
static std::string Decompress(const std::string &json, const std::string &variantBaseTypeName)
static JsonDataPtr CompressToJson(const std::string &json, const std::string &variantBaseTypeName)
static ParseResult CheckUserInput(const std::string &json, const std::string &variantBaseTypeName, const Ice::CommunicatorPtr &communicator)
static ParseResult FormatUserInput(std::string &json, int indenting=2)
static std::string DecompressBasicVariant(const std::string &value, const std::string &variantBaseTypeName)
static int hashTypeName(const std::string &typeName)
Compute and return a hash value for a given type name.
Definition Variant.cpp:813
::IceInternal::Handle<::Ice::Communicator > CommunicatorPtr
Definition IceManager.h:49
const VariantTypeId String
Definition Variant.h:921
const VariantTypeId Int
Definition Variant.h:917
const VariantTypeId Long
Definition Variant.h:918
const VariantTypeId Bool
Definition Variant.h:916
bool IsBasicType(VariantTypeId id)
Definition Variant.cpp:893
const VariantTypeId Double
Definition Variant.h:920
const VariantTypeId Float
Definition Variant.h:919
double a(double t, double a0, double j)
Definition CtrlUtil.h:45
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::shared_ptr< JsonObject > JsonObjectPtr
Definition JsonObject.h:34
std::shared_ptr< JsonData > JsonDataPtr
Definition JsonData.h:31
std::shared_ptr< JsonArray > JsonArrayPtr
Definition JsonArray.h:32
IceInternal::Handle< JSONObject > JSONObjectPtr
Definition JSONObject.h:34
Ice::Int VariantTypeId
Definition Variant.h:43