27 #include <SimoxUtility/algorithm/get_map_keys_values.h>
38 #include <type_traits>
41 #include <IceUtil/Time.h>
45 template <
typename PropertyType>
47 PropertyType* setterRef,
48 const std::string& propertyName,
49 const std::string& description,
52 propertyName(propertyName),
53 description(description),
57 caseInsensitive(
true),
59 stringRemoveQuotes(
true),
66 template <
typename PropertyType>
68 PropertyType* setterRef,
69 const std::string& propertyName,
70 PropertyType defaultValue,
71 const std::string& description,
74 propertyName(propertyName),
75 description(description),
76 defaultValue(defaultValue),
80 caseInsensitive(
true),
82 stringRemoveQuotes(
true),
91 template <
typename PropertyType>
92 inline PropertyDefinition<PropertyType>&
99 propertyValuesMap[lowerCaseValueString] =
ValueEntry(valueString,
value);
109 template <
typename PropertyType>
120 template <
typename PropertyType>
122 inline std::enable_if_t<std::is_same_v<T, PropertyType> && !std::is_same_v<T, std::string>,
133 template <
typename PropertyType>
137 this->factory = func;
142 template <
typename PropertyType>
146 if (this->caseInsensitive != isCaseInsensitive)
151 typename PropertyValuesMap::iterator valueIter = propertyValuesMap.begin();
155 while (valueIter != propertyValuesMap.end())
157 key = valueIter->second.first;
159 if (isCaseInsensitive)
164 newPropertyValuesMap[key] = valueIter->second;
169 propertyValuesMap = newPropertyValuesMap;
170 this->caseInsensitive = isCaseInsensitive;
176 template <
typename PropertyType>
180 this->expandEnvVars = expand;
184 template <
typename PropertyType>
188 this->stringRemoveQuotes = removeQuotes;
192 template <
typename PropertyType>
196 this->regex = match_regex;
201 template <
typename PropertyType>
205 if constexpr (std::is_arithmetic_v<PropertyType>)
207 this->
min = min_value;
214 <<
" on a non-arithmetic type. Ignoring.";
219 template <
typename PropertyType>
223 if constexpr (std::is_arithmetic_v<PropertyType>)
225 this->
max = max_value;
232 <<
" on a non-arithmetic type. Ignoring.";
237 template <
typename PropertyType>
241 return caseInsensitive;
244 template <
typename PropertyType>
248 return expandEnvVars;
251 template <
typename PropertyType>
255 return stringRemoveQuotes;
258 template <
typename PropertyType>
265 template <
typename PropertyType>
272 template <
typename PropertyType>
279 template <
typename PropertyType>
286 template <
typename PropertyType>
293 template <
typename PropertyType>
297 return propertyValuesMap;
300 template <
typename PropertyType>
308 throw armarx::LocalException(
"Required property '" + getPropertyName() +
309 "': default doesn't exist.");
315 template <
typename PropertyType>
322 template <
typename PropertyType>
325 const std::string&
value)
327 std::vector<std::string> mapValues;
329 typename PropertyValuesMap::iterator it = propertyValuesMap.begin();
331 while (it != propertyValuesMap.end())
333 mapValues.push_back(it->second.first);
346 getDefaultAsString(),
347 (!isCaseInsensitive() ?
"yes" :
"no"),
348 (isRequired() ?
"yes" :
"no"),
354 template <
typename PropertyType>
358 if (not isRequired())
364 else if constexpr (std::is_same_v<PropertyType, IceUtil::Time>)
367 double time_count = time.toMicroSecondsDouble();
368 std::string unit =
"µs";
370 if (time_count >= 1000)
375 if (time_count >= 1000)
380 if (time_count >= 60)
385 if (time_count >= 60)
390 if (time_count >= 24)
392 return time.toDateTime();
402 else if constexpr (std::is_same_v<PropertyType, bool>)
404 return getDefaultValue() ?
"true" :
"false";
407 else if constexpr (std::is_floating_point_v<PropertyType>)
412 else if constexpr (std::is_integral_v<PropertyType>)
417 else if constexpr (std::is_same_v<PropertyType, std::string>)
419 if (getDefaultValue().
empty())
424 return getDefaultValue();
429 typename PropertyValuesMap::iterator it = propertyValuesMap.begin();
431 while (it != propertyValuesMap.end())
433 if (it->second.second == getDefaultValue())
435 return it->second.first;
441 return "Default value not mapped.";
446 return std::string();
449 template <
typename PropertyType>
454 return isRequired() ? getValueRequired(prefix, iceProperties)
455 : getValueOptional(prefix, iceProperties);
458 template <
typename PropertyType>
463 if (setterRef !=
nullptr)
465 *setterRef = getValue(prefix, iceProperties);
469 std::map<std::string, std::string>
474 template <
typename PropertyType>
479 if constexpr (std::is_same_v<PropertyType, bool>)
481 setCaseInsensitive(
true);
490 else if constexpr (std::is_same_v<PropertyType, armarx::MessageTypeT>)
492 setCaseInsensitive(
true);
503 else if constexpr (std::is_same_v<PropertyType, std::map<std::string, std::string>>)
508 else if constexpr (std::is_same_v<PropertyType, std::vector<std::string>>)
513 else if constexpr (std::is_same_v<PropertyType, IceUtil::Time>)
515 setCaseInsensitive(
true);
520 meta::properties::PDInitHookPlugin<PropertyType>::Init(*
this);
524 template <
typename PropertyType>
526 PropertyDefinition<PropertyType>::getValueRequired(
const std::string& prefix,
531 checkRequirement(prefix, iceProperties);
533 const std::string keyValue = getPropertyValue(prefix, iceProperties);
534 const std::string
value = getRawPropertyValue(prefix, iceProperties);
536 if (matchRegex(
value))
543 return getFactory()(
value);
545 catch (
const armarx::LocalException& e)
550 catch (
const std::exception& e)
553 <<
"Unknown exception while constructing type out of value: " << e.what();
558 <<
"Unknown exception while constructing type out of value.";
563 const PropertyValuesMap& propertyValuesMap = getValueMap();
565 if (!propertyValuesMap.empty())
567 auto valueIter = propertyValuesMap.find(keyValue);
568 if (valueIter != propertyValuesMap.end())
570 return processMappedValue(valueIter->second.second);
575 <<
"Mapped keys: " << simox::alg::get_keys(getValueMap());
580 if constexpr (std::is_same_v<PropertyType, bool>)
585 else if constexpr (std::is_arithmetic_v<PropertyType>)
589 PropertyType numericValue =
590 PropertyDefinition_lexicalCastTo<PropertyType>(
value);
591 checkLimits(prefix, numericValue);
594 catch (
const std::bad_cast&)
600 else if constexpr (std::is_same_v<PropertyType, std::string>)
602 return processMappedValue(
value);
606 throw exceptions::local::UnmappedValueException(prefix + getPropertyName(),
value)
607 <<
"Mapped keys: " << simox::alg::get_keys(getValueMap());
612 getRawPropertyValue(prefix, iceProperties));
615 template <
typename PropertyType>
617 PropertyDefinition<PropertyType>::getValueOptional(
const std::string& prefix,
622 if (!isSet(prefix, iceProperties))
624 return getDefaultValue();
628 return getValueRequired(prefix, iceProperties);
632 template <
typename PropertyType>
634 PropertyDefinition<PropertyType>::getPropertyValue(
const std::string& prefix,
637 std::string
value = icePropertyGet(iceProperties, prefix + getPropertyName());
639 if (isCaseInsensitive())
647 template <
typename PropertyType>
649 PropertyDefinition<PropertyType>::getRawPropertyValue(
const std::string& prefix,
652 return icePropertyGet(iceProperties, prefix + getPropertyName());
657 template <
typename PropertyType>
659 PropertyDefinition<PropertyType>::matchRegex(
const std::string&
value)
const
661 if (!getMatchRegex().
empty())
669 template <
typename PropertyType>
671 PropertyDefinition<PropertyType>::checkRequirement(
const std::string& prefix,
678 if (!isSet(prefix, iceProperties))
686 template <
typename PropertyType>
694 template <
typename PropertyType>
695 template <
typename T>
702 template <
typename PropertyType>
704 PropertyDefinition<PropertyType>::processMappedValue(
const std::string&
value)
706 std::string result =
value;
707 if (expandEnvironmentVariables())
709 expandEnvironmentVariables(result, result);
713 removeQuotes(result, result);
718 template <
typename PropertyType>
735 size_t foundStart = output.find(
"${");
737 if (foundStart != std::string::npos)
740 size_t foundEnd = output.find(
"}", foundStart);
742 if (foundEnd != std::string::npos)
744 std::string envVar = output.substr(foundStart + 2, foundEnd - foundStart - 2);
745 std::string replacement;
746 char* envVarENV = getenv(envVar.c_str());
750 replacement = envVarENV;
754 std::cout <<
"WARNING: Could not expand environment variable: " << envVar
758 output.replace(foundStart, foundEnd - foundStart + 1, replacement);
762 std::cout <<
"ERROR: Found '${' but missing '}' in " <<
input << std::endl;
777 template <
typename PropertyType>
783 if (
input.size() < 2)
795 template <
typename PropertyType>
798 PropertyType numericValue)
const
805 if ((dirtyValue < getMin()) || (dirtyValue > getMax()))
808 prefix + getPropertyName(), getMin(), getMax(), dirtyValue);