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 
24 #include "VariantJsonCompressor.h"
25 
26 #include <Ice/ObjectFactory.h>
27 
29 
32 
33 #include "VariantJsonException.h"
34 
35 namespace armarx
36 {
38  {
39  }
40 
42  VariantJsonCompressor::CheckUserInput(const std::string& json,
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 =
54  ::armarx::VariantContainerType::FromString(variantBaseTypeName);
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 
239  VariantJsonCompressor::CompressToJson(const std::string& json,
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 =
250  ::armarx::VariantContainerType::FromString(variantBaseTypeName);
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 =
266  ::armarx::VariantContainerType::FromString(variantBaseTypeName);
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 
309  JsonObjectPtr o(new JsonObject);
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 
374  VariantJsonCompressor::Compress(const JPathNavigator& nav,
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
armarx::JsonValue::eNumber
@ eNumber
Definition: JsonValue.h:42
armarx::ParseResult::eSytaxError
@ eSytaxError
Definition: ParseResult.h:40
armarx::VariantType::Float
const VariantTypeId Float
Definition: Variant.h:919
armarx::JPathNavigator::isString
bool isString() const
Definition: JPathNavigator.cpp:61
armarx::ParseResult
Definition: ParseResult.h:33
armarx::ParseResult::iserr
bool iserr()
Definition: ParseResult.cpp:34
JSONObject.h
armarx::JPathNavigator::asString
std::string asString() const
Definition: JPathNavigator.cpp:224
armarx::SingleVariant::getTypePrefix
static std::string getTypePrefix()
Definition: VariantContainer.cpp:159
armarx::JsonArrayPtr
std::shared_ptr< JsonArray > JsonArrayPtr
Definition: JsonArray.h:32
armarx::VariantJsonCompressor::FormatUserInput
static ParseResult FormatUserInput(std::string &json, int indenting=2)
Definition: VariantJsonCompressor.cpp:77
StructuralJsonParser.h
IceStorm::Parser::parse
int parse(FILE *, bool)
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
armarx::VariantType::Bool
const VariantTypeId Bool
Definition: Variant.h:916
armarx::JsonArray
Definition: JsonArray.h:34
armarx::JPathNavigator
Definition: JPathNavigator.h:35
armarx::JsonValue
Definition: JsonValue.h:34
armarx::JsonValue::eString
@ eString
Definition: JsonValue.h:41
IceInternal::Handle<::Ice::Communicator >
armarx::VariantType::Double
const VariantTypeId Double
Definition: Variant.h:920
armarx::VariantJsonCompressor::VariantJsonCompressor
VariantJsonCompressor()
Definition: VariantJsonCompressor.cpp:37
armarx::VariantJsonException
Definition: VariantJsonException.h:30
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:855
armarx::VariantJsonCompressor::CheckUserInput
static ParseResult CheckUserInput(const std::string &json, const std::string &variantBaseTypeName, const Ice::CommunicatorPtr &communicator)
Definition: VariantJsonCompressor.cpp:42
JPathNavigator.h
armarx::JSONObjectPtr
IceInternal::Handle< JSONObject > JSONObjectPtr
Definition: JSONObject.h:34
armarx::ParseResult::getErrorType
ErrorType getErrorType()
Definition: ParseResult.cpp:46
armarx::VariantType::Long
const VariantTypeId Long
Definition: Variant.h:918
armarx::ParseResult::eVariantParseError
@ eVariantParseError
Definition: ParseResult.h:42
armarx::VariantJsonCompressor::Decompress
static std::string Decompress(const std::string &json, const std::string &variantBaseTypeName)
Definition: VariantJsonCompressor.cpp:255
armarx::JsonValue::eBool
@ eBool
Definition: JsonValue.h:43
armarx::VariantTypeId
Ice::Int VariantTypeId
Definition: Variant.h:43
armarx::VariantType::IsBasicType
bool IsBasicType(VariantTypeId id)
Definition: Variant.cpp:893
armarx::VariantJsonCompressor::CompressToJson
static JsonDataPtr CompressToJson(const std::string &json, const std::string &variantBaseTypeName)
Definition: VariantJsonCompressor.cpp:239
IceStorm::parser
Parser * parser
Definition: Parser.cpp:34
armarx::JsonObject
Definition: JsonObject.h:36
VariantJsonCompressor.h
armarx::VariantJsonCompressor::DecompressBasicVariant
static std::string DecompressBasicVariant(const std::string &value, const std::string &variantBaseTypeName)
Definition: VariantJsonCompressor.cpp:272
armarx::VariantType::Int
const VariantTypeId Int
Definition: Variant.h:917
armarx::Variant::hashTypeName
static int hashTypeName(const std::string &typeName)
Compute and return a hash value for a given type name.
Definition: Variant.cpp:813
armarx::ParseResult::geterr
std::string geterr()
Definition: ParseResult.cpp:40
armarx::JPathNavigator::selectSingleNode
JPathNavigator selectSingleNode(const std::string &expr) const
Definition: JPathNavigator.cpp:122
armarx::ParseResult::Error
static ParseResult Error(const std::string &error, ErrorType errorType)
Definition: ParseResult.cpp:70
armarx::JsonDataPtr
std::shared_ptr< JsonData > JsonDataPtr
Definition: JsonData.h:31
armarx::VariantType::String
const VariantTypeId String
Definition: Variant.h:921
armarx::ParseResult::eContainerMismatch
@ eContainerMismatch
Definition: ParseResult.h:41
armarx::VariantJsonCompressor::Compress
static std::string Compress(const std::string &json, const std::string &variantBaseTypeName, int indenting=2)
Definition: VariantJsonCompressor.cpp:230
armarx::StructuralJsonParser
Definition: StructuralJsonParser.h:35
armarx::JsonValue::CreateRaw
static JsonValuePtr CreateRaw(Type type, const std::string &value)
Definition: JsonValue.cpp:107
armarx::VariantContainerType::FromString
static ContainerTypePtr FromString(const std::string &typeStr)
Definition: VariantContainer.cpp:281
armarx::ParseResult::Success
static ParseResult Success()
Definition: ParseResult.cpp:64
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
VariantJsonException.h
armarx::JsonObjectPtr
std::shared_ptr< JsonObject > JsonObjectPtr
Definition: JsonObject.h:34
armarx::StringValueMap::getTypePrefix
static std::string getTypePrefix()
Definition: StringValueMap.cpp:190
armarx::SingleTypeVariantList::getTypePrefix
static std::string getTypePrefix()
Definition: SingleTypeVariantList.cpp:218