27 #include <SimoxUtility/algorithm/get_map_keys_values.h>
37 #include <IceUtil/Time.h>
40 #include <type_traits>
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),
67 template<
typename PropertyType>
inline
69 PropertyType* setterRef,
70 const std::string& propertyName,
71 PropertyType defaultValue,
72 const std::string& description,
75 propertyName(propertyName),
76 description(description),
77 defaultValue(defaultValue),
81 caseInsensitive(
true),
83 stringRemoveQuotes(
true),
93 template <
typename PropertyType>
inline
94 PropertyDefinition<PropertyType>&
96 const std::string& valueString,
103 propertyValuesMap[lowerCaseValueString] =
ValueEntry(valueString,
114 template <
typename PropertyType>
inline
117 const std::map<std::string, PropertyType>&
values)
126 template <
typename PropertyType>
127 template<
class T>
inline
128 std::enable_if_t < std::is_same_v<T, PropertyType>&& !std::is_same_v<T, std::string>,
PropertyDefinition<T>& >
138 template <
typename PropertyType>
142 this->factory = func;
148 template <
typename PropertyType>
152 if (this->caseInsensitive != isCaseInsensitive)
157 typename PropertyValuesMap::iterator valueIter =
158 propertyValuesMap.begin();
162 while (valueIter != propertyValuesMap.end())
164 key = valueIter->second.first;
166 if (isCaseInsensitive)
171 newPropertyValuesMap[key] = valueIter->second;
176 propertyValuesMap = newPropertyValuesMap;
177 this->caseInsensitive = isCaseInsensitive;
184 template <
typename PropertyType>
188 this->expandEnvVars = expand;
193 template <
typename PropertyType>
197 this->stringRemoveQuotes = removeQuotes;
202 template <
typename PropertyType>
205 const std::string& match_regex)
207 this->regex = match_regex;
213 template <
typename PropertyType>
217 if constexpr(std::is_arithmetic_v<PropertyType>)
219 this->
min = min_value;
225 ARMARX_WARNING <<
"Cannot use setMin() to " << min_value <<
" on a non-arithmetic type. Ignoring.";
231 template <
typename PropertyType>
235 if constexpr(std::is_arithmetic_v<PropertyType>)
237 this->
max = max_value;
243 ARMARX_WARNING <<
"Cannot use setMax() to " << max_value <<
" on a non-arithmetic type. Ignoring.";
248 template <
typename PropertyType>
252 return caseInsensitive;
256 template <
typename PropertyType>
260 return expandEnvVars;
264 template <
typename PropertyType>
268 return stringRemoveQuotes;
272 template <
typename PropertyType>
279 template <
typename PropertyType>
287 template <
typename PropertyType>
295 template <
typename PropertyType>
303 template <
typename PropertyType>
311 template <
typename PropertyType>
315 return propertyValuesMap;
319 template <
typename PropertyType>
327 throw armarx::LocalException(
"Required property '" + getPropertyName() +
"': default doesn't exist.");
334 template <
typename PropertyType>
340 template <
typename PropertyType>
344 std::vector<std::string> mapValues;
346 typename PropertyValuesMap::iterator it = propertyValuesMap.begin();
348 while (it != propertyValuesMap.end())
350 mapValues.push_back(it->second.first);
360 getDefaultAsString(),
361 (!isCaseInsensitive() ?
"yes" :
"no"),
362 (isRequired() ?
"yes" :
"no"),
369 template <
typename PropertyType>
372 if (not isRequired())
378 else if constexpr(std::is_same_v<PropertyType, IceUtil::Time>)
381 double time_count = time.toMicroSecondsDouble();
382 std::string unit =
"µs";
384 if (time_count >= 1000)
389 if (time_count >= 1000)
394 if (time_count >= 60)
399 if (time_count >= 60)
404 if (time_count >= 24)
406 return time.toDateTime();
416 else if constexpr(std::is_same_v<PropertyType, bool>)
418 return getDefaultValue() ?
"true" :
"false";
421 else if constexpr(std::is_floating_point_v<PropertyType>)
426 else if constexpr(std::is_integral_v<PropertyType>)
431 else if constexpr(std::is_same_v<PropertyType, std::string>)
433 if (getDefaultValue().
empty())
438 return getDefaultValue();
443 typename PropertyValuesMap::iterator it = propertyValuesMap.begin();
445 while (it != propertyValuesMap.end())
447 if (it->second.second == getDefaultValue())
449 return it->second.first;
455 return "Default value not mapped.";
460 return std::string();
464 template <
typename PropertyType>
468 return isRequired() ? getValueRequired(prefix, iceProperties) : getValueOptional(prefix, iceProperties);
472 template <
typename PropertyType>
476 if (setterRef !=
nullptr)
478 *setterRef = getValue(prefix, iceProperties);
487 template <
typename PropertyType>
492 if constexpr(std::is_same_v<PropertyType, bool>)
494 setCaseInsensitive(
true);
503 else if constexpr(std::is_same_v<PropertyType, armarx::MessageTypeT>)
505 setCaseInsensitive(
true);
516 else if constexpr(std::is_same_v<PropertyType, std::map<std::string, std::string>>)
521 else if constexpr(std::is_same_v<PropertyType, std::vector<std::string>>)
526 else if constexpr(std::is_same_v<PropertyType, IceUtil::Time>)
528 setCaseInsensitive(
true);
533 meta::properties::PDInitHookPlugin<PropertyType>::Init(*
this);
538 template <
typename PropertyType>
540 PropertyDefinition<PropertyType>::getValueRequired(
const std::string& prefix,
Ice::PropertiesPtr iceProperties)
544 checkRequirement(prefix, iceProperties);
546 const std::string keyValue = getPropertyValue(prefix, iceProperties);
547 const std::string
value = getRawPropertyValue(prefix, iceProperties);
549 if (matchRegex(
value))
556 return getFactory()(
value);
558 catch (
const armarx::LocalException& e)
563 catch (
const std::exception& e)
566 <<
"Unknown exception while constructing type out of value: "
572 <<
"Unknown exception while constructing type out of value.";
577 const PropertyValuesMap& propertyValuesMap = getValueMap();
579 if (!propertyValuesMap.empty())
581 auto valueIter = propertyValuesMap.find(keyValue);
582 if (valueIter != propertyValuesMap.end())
584 return processMappedValue(valueIter->second.second);
589 <<
"Mapped keys: " << simox::alg::get_keys(getValueMap());
594 if constexpr(std::is_same_v<PropertyType, bool>)
599 else if constexpr(std::is_arithmetic_v<PropertyType>)
603 PropertyType numericValue = PropertyDefinition_lexicalCastTo<PropertyType>(
value);
604 checkLimits(prefix, numericValue);
607 catch (
const std::bad_cast&)
613 else if constexpr(std::is_same_v<PropertyType, std::string>)
615 return processMappedValue(
value);
619 throw exceptions::local::UnmappedValueException(prefix + getPropertyName(),
value)
620 <<
"Mapped keys: " << simox::alg::get_keys(getValueMap());
625 prefix + getPropertyName(), getRawPropertyValue(prefix, iceProperties));
629 template <
typename PropertyType>
631 PropertyDefinition<PropertyType>::getValueOptional(
const std::string& prefix,
Ice::PropertiesPtr iceProperties)
635 if (!isSet(prefix, iceProperties))
637 return getDefaultValue();
641 return getValueRequired(prefix, iceProperties);
646 template <
typename PropertyType>
648 PropertyDefinition<PropertyType>::getPropertyValue(
const std::string& prefix,
Ice::PropertiesPtr iceProperties)
const
650 std::string
value = icePropertyGet(iceProperties, prefix + getPropertyName());
652 if (isCaseInsensitive())
661 template <
typename PropertyType>
663 PropertyDefinition<PropertyType>::getRawPropertyValue(
const std::string& prefix,
Ice::PropertiesPtr iceProperties)
const
665 return icePropertyGet(iceProperties, prefix + getPropertyName());
671 template <
typename PropertyType>
673 PropertyDefinition<PropertyType>::matchRegex(
const std::string&
value)
const
675 if (!getMatchRegex().
empty())
684 template <
typename PropertyType>
686 PropertyDefinition<PropertyType>::checkRequirement(
const std::string& prefix,
Ice::PropertiesPtr iceProperties)
692 if (!isSet(prefix, iceProperties))
701 template <
typename PropertyType>
709 template <
typename PropertyType>
710 template <
typename T>
718 template <
typename PropertyType>
720 PropertyDefinition<PropertyType>::processMappedValue(
const std::string&
value)
722 std::string result =
value;
723 if (expandEnvironmentVariables())
725 expandEnvironmentVariables(result, result);
729 removeQuotes(result, result);
735 template <
typename PropertyType>
751 size_t foundStart = output.find(
"${");
753 if (foundStart != std::string::npos)
756 size_t foundEnd = output.find(
"}", foundStart);
758 if (foundEnd != std::string::npos)
760 std::string envVar = output.substr(foundStart + 2, foundEnd - foundStart - 2);
761 std::string replacement;
762 char* envVarENV = getenv(envVar.c_str());
766 replacement = envVarENV;
770 std::cout <<
"WARNING: Could not expand environment variable: " << envVar << std::endl;
773 output.replace(foundStart, foundEnd - foundStart + 1, replacement);
777 std::cout <<
"ERROR: Found '${' but missing '}' in " <<
input << std::endl;
795 template <
typename PropertyType>
801 if (
input.size() < 2)
815 template <
typename PropertyType>
824 if ((dirtyValue < getMin()) || (dirtyValue > getMax()))
827 prefix + getPropertyName(),