)
set (SOURCES
- src/rpc_base/rpc_base.cc
+ src/rpc_base/rpc_base.cc
)
set (HEADERS
- include/rpc_base/rpc_message.h
+ include/rpc_base/gtest_support.h
+ include/rpc_base/rpc_base_dbus_inl.h
include/rpc_base/rpc_base.h
include/rpc_base/rpc_base_inl.h
+ include/rpc_base/rpc_base_json_inl.h
+ include/rpc_base/rpc_message.h
+ include/rpc_base/validation_report.h
)
add_library(rpc_base ${HEADERS} ${SOURCES})
--- /dev/null
+/**
+ * Copyright (c) 2014, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RPC_BASE_GTEST_SUPPORT_H_
+#define RPC_BASE_GTEST_SUPPORT_H_
+
+#include <gtest/gtest.h>
+
+#include "rpc_base/validation_report.h"
+
+// A predicate-formatter for asserting that intergen generated
+// object is valid
+template<typename T>
+::testing::AssertionResult AssertRpcObjValid(const char* obj_expr,
+ const T& obj) {
+ if (obj.is_valid())
+ return ::testing::AssertionSuccess();
+
+ rpc::ValidationReport report(obj_expr);
+ obj.ReportErrors(&report);
+
+ return ::testing::AssertionFailure()
+ << obj_expr << " failed validation. Violations are:\n"
+ << rpc::PrettyFormat(report);
+}
+
+#define ASSERT_RPCTYPE_VALID(object) \
+ ASSERT_PRED_FORMAT1(AssertRpcObjValid, object)
+
+#define EXPECT_RPCTYPE_VALID(object) \
+ EXPECT_PRED_FORMAT1(AssertRpcObjValid, object)
+
+#endif /* RPC_BASE_GTEST_SUPPORT_H_ */
} // namespace dbus
namespace rpc {
+class ValidationReport;
+
template<typename T> class Range;
class PrimitiveType;
class CompositeType;
template<typename T, size_t minsize, size_t maxsize> class Array;
template<typename T, size_t minsize, size_t maxsize> class Map;
template<typename T> class Nullable;
-template<typename T> class Mandatory;
template<typename T> class Optional;
template<typename T>
public:
bool is_initialized() const;
bool is_valid() const;
+ void ReportErrors(ValidationReport* report) const;
protected:
enum ValueState {
kUninitialized,
kInvalid,
kValid
};
- PrimitiveType(ValueState value_state);
+ explicit PrimitiveType(ValueState value_state);
+ static ValueState InitHelper(bool is_next);
static ValueState InitHelper(const Json::Value* value,
bool (Json::Value::*type_check)() const);
protected:
};
/*
- * Helper class for all composite types (arrays and all user-defined types)
+ * Base class for all composite types (arrays and all user-defined types)
*/
class CompositeType {
public:
- static const Json::Value* ValueMember(const Json::Value* value,
- const char* member_name);
- template<class T>
- static void WriteJsonField(const char* field_name,
- const T& field,
- Json::Value* json_value);
- template<class T>
- static void WriteJsonField(const char* field_name,
- const Nullable<T>& field,
- Json::Value* json_value);
- template<class T>
- static void WriteJsonField(const char* field_name,
- const Optional<T>& field,
- Json::Value* json_value);
- template<typename T, size_t minsize, size_t maxsize>
- static void WriteJsonField(const char* field_name,
- const Map<T, minsize, maxsize>& field,
- Json::Value* json_value);
- template<typename T, size_t minsize, size_t maxsize>
- static void WriteJsonField(const char* field_name,
- const Array<T, minsize, maxsize>& field,
- Json::Value* json_value);
+ void mark_initialized();
+ void ReportErrors(ValidationReport* report) const;
+ protected:
+ enum InitializationState {
+ kUninitialized,
+ kInitialized,
+ kInvalidInitialized
+ };
+ explicit CompositeType(InitializationState init_state);
+ static InitializationState InitHelper(bool is_next);
+ static InitializationState InitHelper(const Json::Value* value,
+ bool (Json::Value::*type_check)() const);
+ protected:
+ InitializationState initialization_state__;
};
/*
};
template<typename T, size_t minsize, size_t maxsize>
-class Array : public std::vector<T> {
+class Array : public std::vector<T>, public CompositeType {
public:
// Types
typedef std::vector<T> ArrayType;
bool is_valid() const;
bool is_initialized() const;
- bool is_null() const;
- void set_to_null();
- private:
- bool marked_as_null_;
+ void ReportErrors(ValidationReport* report) const;
};
template<typename T, size_t minsize, size_t maxsize>
-class Map : public std::map<std::string, T> {
+class Map : public std::map<std::string, T>, public CompositeType {
public:
// Types
+ typedef Map<T, minsize, maxsize> Frankenbase;
typedef std::map<std::string, T> MapType;
public:
// Methods
bool is_valid() const;
bool is_initialized() const;
- bool is_null() const;
- void set_to_null();
- private:
- bool marked_as_null_;
+ void ReportErrors(ValidationReport* report) const;
};
template<typename T>
public:
// Methods
Nullable();
+ explicit Nullable(dbus::MessageReader* reader);
// Need const and non-const versions to beat all-type accepting constructor
explicit Nullable(Json::Value* value);
explicit Nullable(const Json::Value* value);
bool is_initialized() const;
bool is_null() const;
void set_to_null();
+ void ReportErrors(ValidationReport* report) const;
private:
bool marked_null_;
};
explicit Optional(const U& value);
template<typename U>
Optional(const Json::Value* value,const U& def_value);
+ Json::Value ToJsonValue() const;
void ToDbusWriter(dbus::MessageWriter* writer) const;
bool is_valid() const;
bool is_initialized() const;
+ void ReportErrors(ValidationReport* report) const;
private:
T value_;
};
// Template methods implementation
#include "rpc_base_inl.h"
+#include "rpc_base_json_inl.h"
#endif /* VALIDATED_TYPES_H_ */
#include "rpc_base/rpc_base.h"
namespace rpc {
+
+// static
+inline PrimitiveType::ValueState PrimitiveType::InitHelper(bool is_next) {
+ return is_next ? kValid : kInvalid;
+}
+
+// static
+inline CompositeType::InitializationState CompositeType::InitHelper(bool is_next) {
+ return is_next ? kInitialized : kUninitialized;
+}
+
namespace impl {
};
template<typename T>
-struct DbusSignatureHelper<Mandatory<T> > {
+struct DbusSignatureHelper<Optional<T> > {
static void DbusSignature(std::string* signature) {
+ (*signature) += DBUS_STRUCT_BEGIN_CHAR;
+ (*signature) += rpc::impl::DbusTypeCode<bool>();
rpc::impl::DbusSignatureHelper<T>::DbusSignature(signature);
+ (*signature) += DBUS_STRUCT_END_CHAR;
}
};
template<typename T>
-struct DbusSignatureHelper<Optional<T> > {
+struct DbusSignatureHelper<Nullable<T> > {
static void DbusSignature(std::string* signature) {
(*signature) += DBUS_STRUCT_BEGIN_CHAR;
(*signature) += rpc::impl::DbusTypeCode<bool>();
return available ? value : T();
}
+// Helper Nullable type initialization functipon
+template<typename T>
+bool TakeNullable(dbus::MessageReader* reader) {
+ dbus::MessageReader struct_reader = reader->TakeStructReader();
+ bool is_null = struct_reader.TakeBool();
+ return is_null;
+}
+
} // namespace impl
// Type constructors
inline Boolean::Boolean(dbus::MessageReader* reader)
- : PrimitiveType(true, reader->NextIsBool()),
+ : PrimitiveType(InitHelper(reader->NextIsBool())),
value_(reader->TakeBool()) {
}
template<typename T, T minval, T maxval>
inline Integer<T, minval, maxval>::Integer(dbus::MessageReader* reader)
- : PrimitiveType(true, impl::NextIs<IntType>(*reader)),
+ : PrimitiveType(InitHelper(impl::NextIs<IntType>(*reader))),
value_(impl::Take<IntType>(reader)) {
- if (valid_) {
- valid_ = range_.Includes(value_);
+ if (is_valid()) {
+ value_state_ = range_.Includes(value_) ? kValid : kInvalid;
}
}
template<int64_t minnum, int64_t maxnum, int64_t minden, int64_t maxden>
inline Float<minnum, maxnum, minden, maxden>::Float(dbus::MessageReader* reader)
- : PrimitiveType(true, reader->NextIsDouble()),
+ : PrimitiveType(InitHelper(reader->NextIsDouble())),
value_(reader->TakeDouble()) {
- if (valid_) {
- valid_ = range_.Includes(value_);
+ if (is_valid()) {
+ value_state_ = range_.Includes(value_) ? kValid : kInvalid;
}
}
template<size_t minlen, size_t maxlen>
inline String<minlen, maxlen>::String(dbus::MessageReader* reader)
- : PrimitiveType(true, reader->NextIsString()),
+ : PrimitiveType(InitHelper(reader->NextIsString())),
value_(reader->TakeString()) {
- if (valid_) {
- valid_ = length_range_.Includes(value_.length());
+ if (is_valid()) {
+ value_state_ = length_range_.Includes(value_.length()) ? kValid : kInvalid;
}
}
template<typename T>
inline Enum<T>::Enum(dbus::MessageReader* reader)
- : PrimitiveType(true, reader->NextIsInt32()),
+ : PrimitiveType(InitHelper(reader->NextIsInt32())),
value_(EnumType(reader->TakeInt32())) {
- if (valid_) {
- valid_ = IsValidEnum(value_);
+ if (is_valid()) {
+ value_state_ = IsValidEnum(value_) ? kValid : kInvalid;
}
}
template<typename T, size_t minsize, size_t maxsize>
-inline Array<T, minsize, maxsize>::Array(dbus::MessageReader* reader) {
+inline Array<T, minsize, maxsize>::Array(dbus::MessageReader* reader)
+ : CompositeType(InitHelper(reader->NextIsArray())) {
dbus::MessageReader array_reader = reader->TakeArrayReader();
if (array_reader.has_failed()) {
push_back(T());
}
template<typename T, size_t minsize, size_t maxsize>
-inline Map<T, minsize, maxsize>::Map(dbus::MessageReader* reader) {
+inline Map<T, minsize, maxsize>::Map(dbus::MessageReader* reader)
+ : CompositeType(InitHelper(reader->NextIsStruct())) {
// Map key-value pairs are serialized into array
dbus::MessageReader array_reader = reader->TakeArrayReader();
if (array_reader.has_failed()) {
}
template<typename T>
+inline Nullable<T>::Nullable(dbus::MessageReader* reader)
+ : T(reader),
+ marked_null_(impl::TakeNullable<T>(reader)){
+}
+
+template<typename T>
inline Optional<T>::Optional(dbus::MessageReader* reader)
: value_(impl::TakeOptional<T>(reader)){
}
#include "rpc_base.h"
#include <cassert>
+#include <cstdio>
+
+#include "rpc_base/validation_report.h"
namespace rpc {
return min() <= val && val <= max();
}
+
+/*
+ * PrimitiveType base class
+ */
inline PrimitiveType::PrimitiveType(ValueState value_state)
: value_state_(value_state) {
}
return value_state_ == kValid;
}
+inline void PrimitiveType::ReportErrors(ValidationReport* report) const {
+ switch (value_state_) {
+ case kUninitialized: {
+ report->set_validation_info("value is not initialized");
+ break;
+ }
+ case kInvalid: {
+ report->set_validation_info("value initialized incorrectly");
+ break;
+ }
+ case kValid: {
+ // No error
+ break;
+ }
+ default: {
+ assert(!"Unexpected value state");
+ break;
+ }
+ }
+}
+
+/*
+ * CompositeType base class
+ */
+inline void CompositeType::mark_initialized() {
+ initialization_state__ = kInitialized;
+}
+
+inline CompositeType::CompositeType(InitializationState init_state)
+ : initialization_state__(init_state) {
+}
+
+inline void CompositeType::ReportErrors(ValidationReport* report) const {
+ switch (initialization_state__) {
+ case kUninitialized: {
+ report->set_validation_info("object is not initialized");
+ break;
+ }
+ case kInvalidInitialized: {
+ report->set_validation_info("object initialized incorrectly");
+ break;
+ }
+ case kInitialized: {
+ // No error
+ break;
+ }
+ default:
+ assert(!"Unexpected initialization state");
+ break;
+ }
+}
+
/*
* Boolean class
*/
template<typename T>
Enum<T>::Enum(EnumType value)
- : PrimitiveType(IsValidEnum(value_) ? kValid : kInvalid),
+ : PrimitiveType(IsValidEnum(value) ? kValid : kInvalid),
value_(value) {
}
*/
template<typename T, size_t minsize, size_t maxsize>
Array<T, minsize, maxsize>::Array()
- : marked_as_null_(false) {
+ : CompositeType(kUninitialized) {
}
template<typename T, size_t minsize, size_t maxsize>
template<typename U>
Array<T, minsize, maxsize>::Array(const U& value)
: ArrayType(value.begin(), value.end()),
- marked_as_null_(false) {
+ CompositeType(kUninitialized) {
}
template<typename T, size_t minsize, size_t maxsize>
template<typename T, size_t minsize, size_t maxsize>
bool Array<T, minsize, maxsize>::is_valid() const {
- if (is_null()) {
+ // Empty array might be valid only if marked initialized
+ if (this->empty() && (initialization_state__ != kInitialized)) {
return false;
}
- if (!Range<size_t>(minsize, maxsize).Includes(this->size()))
+ // Array size must be within allowed range
+ if (!Range<size_t>(minsize, maxsize).Includes(this->size())) {
return false;
+ }
+ // All array elements must be valid
for (typename ArrayType::const_iterator i = this->begin();
i != this->end(); ++i) {
if (!i->is_valid())
template<typename T, size_t minsize, size_t maxsize>
bool Array<T, minsize, maxsize>::is_initialized() const {
- return is_null() || !this->empty();
-}
-
-template<typename T, size_t minsize, size_t maxsize>
-bool Array<T, minsize, maxsize>::is_null() const {
- return marked_as_null_;
+ // Array that is not empty is initialized for sure
+ if (!this->empty()) {
+ return true;
+ }
+ // Empty array is initialized if not marked as unitialized
+ if (initialization_state__ != kUninitialized) {
+ return true;
+ }
+ return false;
}
template<typename T, size_t minsize, size_t maxsize>
-void Array<T, minsize, maxsize>::set_to_null() {
- marked_as_null_ = true;
+void Array<T, minsize, maxsize>::ReportErrors(ValidationReport* report) const {
+ if (this->empty()) {
+ CompositeType::ReportErrors(report);
+ } else {
+ if (!Range<size_t>(minsize, maxsize).Includes(this->size())) {
+ report->set_validation_info("array has invalid size");
+ } else {
+ // No error
+ }
+ }
+ for (size_t i = 0; i != this->size(); ++i) {
+ const T& elem = this->operator [](i);
+ if (!elem.is_valid()) {
+ char elem_idx[32] = {};
+ snprintf(elem_idx, 32, "[%zu]", i);
+ ValidationReport& elem_report =
+ report->ReportSubobject(elem_idx);
+ elem.ReportErrors(&elem_report);
+ }
+ }
}
/*
*/
template<typename T, size_t minsize, size_t maxsize>
Map<T, minsize, maxsize>::Map()
- : marked_as_null_(false) {
+ : CompositeType(kUninitialized) {
}
template<typename T, size_t minsize, size_t maxsize>
template<typename U>
Map<T, minsize, maxsize>::Map(const U& value)
- : marked_as_null_(false) {
+ : CompositeType(kUninitialized) {
for (typename U::const_iterator i = value.begin(), e = value.end(); i != e;
++i) {
// Explicitly convert that value to T because all rpc_types have explicit
template<typename T, size_t minsize, size_t maxsize>
bool Map<T, minsize, maxsize>::is_valid() const {
- if (is_null())
+ // Empty map might be valid only if marked initialized
+ if (this->empty() && (initialization_state__ != kInitialized)) {
return false;
- if (!Range<size_t>(minsize, maxsize).Includes(this->size()))
+ }
+ // Maps size must be within allowed range
+ if (!Range<size_t>(minsize, maxsize).Includes(this->size())) {
return false;
+ }
+ // All map elements must be valid
for (typename Map::const_iterator i = this->begin();
i != this->end(); ++i) {
if (!i->second.is_valid())
template<typename T, size_t minsize, size_t maxsize>
bool Map<T, minsize, maxsize>::is_initialized() const {
- return is_null() || !this->empty();
-}
-
-template<typename T, size_t minsize, size_t maxsize>
-bool Map<T, minsize, maxsize>::is_null() const {
- return marked_as_null_;
+ // Map that is not empty is initialized for sure
+ if (!this->empty()) {
+ return true;
+ }
+ // Empty map might be initialized only if not marked as unitialized
+ if (initialization_state__ != kUninitialized) {
+ return true;
+ }
+ return false;
}
template<typename T, size_t minsize, size_t maxsize>
-void Map<T, minsize, maxsize>::set_to_null() {
- marked_as_null_ = true;
+void Map<T, minsize, maxsize>::ReportErrors(ValidationReport* report) const {
+ if (this->empty()) {
+ CompositeType::ReportErrors(report);
+ } else {
+ if (!Range<size_t>(minsize, maxsize).Includes(this->size())) {
+ report->set_validation_info("map has invalid size");
+ } else {
+ // No error
+ }
+ }
+ for (typename Map::const_iterator i = this->begin();
+ i != this->end(); ++i) {
+ if (!i->second.is_valid()) {
+ std::string elem_name = "[\"" + i->first + "\"]";
+ ValidationReport& elem_report = report->ReportSubobject(elem_name);
+ i->second.ReportErrors(&elem_report);
+ }
+ }
}
/*
marked_null_ = true;
}
+template<typename T>
+void Nullable<T>::ReportErrors(ValidationReport* report) const {
+ if (marked_null_) {
+ // No error
+ } else {
+ T::ReportErrors(report);
+ }
+}
+
/*
* Optional class
*/
return value_.is_initialized();
}
+template<typename T>
+void Optional<T>::ReportErrors(ValidationReport* report) const {
+ if (!is_initialized()) {
+ // No error
+ } else {
+ value_.ReportErrors(report);
+ }
+}
+
} // namespace rpc
}
}
-/*
- * Composite type
- */
+// static
+inline CompositeType::InitializationState CompositeType::InitHelper(
+ const Json::Value* value,
+ bool (Json::Value::*type_check)() const) {
+ if (!value) {
+ return kUninitialized;
+ } else if ((value->*type_check)()) {
+ // Some value type checks return true when initialized with null
+ if (value->isNull()) {
+ return kInvalidInitialized;
+ } else {
+ return kInitialized;
+ }
+ } else {
+ return kInvalidInitialized;
+ }
+}
+namespace impl {
// static
-inline const Json::Value* CompositeType::ValueMember(const Json::Value* value,
- const char* member_name) {
+inline const Json::Value* ValueMember(const Json::Value* value,
+ const char* member_name) {
if (value && value->isMember(member_name)) {
return &(*value)[member_name];
}
return NULL;
}
-// static
template<class T>
-void CompositeType::WriteJsonField(const char* field_name,
+inline void WriteJsonField(const char* field_name,
const T& field,
Json::Value* json_value) {
- (*json_value)[field_name] = field.ToJsonValue();
-}
-
-// static
-template<class T>
-void CompositeType::WriteJsonField(const char* field_name,
- const Nullable<T>& field,
- Json::Value* json_value) {
- if (field.is_null()) {
- (*json_value)[field_name] = Json::Value::null;
- } else {
- const T& non_nulable = field;
- WriteJsonField(field_name, non_nulable, json_value);
- }
-}
-
-// static
-template<typename T, size_t minsize, size_t maxsize>
-void CompositeType::WriteJsonField(const char* field_name,
- const Map<T, minsize, maxsize>& field,
- Json::Value* json_value) {
if (field.is_initialized()) {
(*json_value)[field_name] = field.ToJsonValue();
}
}
-// static
-template<typename T, size_t minsize, size_t maxsize>
-void CompositeType::WriteJsonField(const char* field_name,
- const Array<T, minsize, maxsize>& field,
- Json::Value* json_value) {
- if (field.is_initialized()) {
- (*json_value)[field_name] = field.ToJsonValue();
- }
-}
-
-template<class T>
-void CompositeType::WriteJsonField(const char* field_name,
- const Optional<T>& field,
- Json::Value* json_value) {
- if (field.is_initialized()) {
- WriteJsonField(field_name, *field, json_value);
- }
-}
+} // namespace impl
inline Boolean::Boolean(const Json::Value* value)
: PrimitiveType(InitHelper(value, &Json::Value::isBool)),
// Non-const version
template<typename T, size_t minsize, size_t maxsize>
Array<T, minsize, maxsize>::Array(Json::Value* value)
- : marked_as_null_(value && value->isNull()) {
- if (value && !marked_as_null_) {
+ : CompositeType(InitHelper(value, &Json::Value::isArray)) {
+ if (value) {
if (value->isArray()) {
this->reserve(value->size());
for (Json::Value::iterator i = value->begin(); i != value->end(); ++i) {
push_back(&*i);
}
} else {
- // In case of non-array value initialize array with non-initialized value
- // so it handled as initialized but invalid
- push_back(T());
+ // Array is empty, empty initialized or uninitialized
+ // depending on InitHelper result
}
}
}
// Const version, must be identical to the non-const version
template<typename T, size_t minsize, size_t maxsize>
Array<T, minsize, maxsize>::Array(const Json::Value* value)
- : marked_as_null_(value && value->isNull()) {
- if (value && !marked_as_null_) {
+ : CompositeType(InitHelper(value, &Json::Value::isArray)) {
+ if (value) {
if (value->isArray()) {
this->reserve(value->size());
for (Json::Value::const_iterator i = value->begin(); i != value->end(); ++i) {
push_back(&*i);
}
} else {
- // In case of non-array value initialize array with non-initialized value
- // so it handled as initialized but invalid
- push_back(T());
+ // Array is empty, empty initialized or uninitialized
+ // depending on InitHelper result
}
}
}
template<typename T, size_t minsize, size_t maxsize>
Json::Value Array<T, minsize, maxsize>::ToJsonValue() const {
- if (is_null()) {
- return Json::Value::null;
- }
Json::Value array(Json::arrayValue);
array.resize(this->size());
for (size_t i = 0; i != this->size(); ++i) {
// Non-const version
template<typename T, size_t minsize, size_t maxsize>
Map<T, minsize, maxsize>::Map(Json::Value* value)
- : marked_as_null_(value && value->isNull()) {
- if (value && !marked_as_null_) {
+ : CompositeType(InitHelper(value, &Json::Value::isObject)) {
+ if (value) {
if (value->isObject()) {
for (Json::Value::iterator i = value->begin(); i != value->end(); ++i) {
this->insert(typename MapType::value_type(i.key().asString(), T(&*i)));
}
} else {
- // In case of non-array value initialize array with null value
- // so it handled as initialized but invalid
- this->insert(typename MapType::value_type("", T()));
+ // Map is empty, empty initialized or uninitialized
+ // depending on InitHelper result
}
}
}
template<typename T, size_t minsize, size_t maxsize>
Map<T, minsize, maxsize>::Map(const Json::Value* value)
- : marked_as_null_(value && value->isNull()) {
- if (value && !marked_as_null_) {
+ : CompositeType(InitHelper(value, &Json::Value::isObject)) {
+ if (value) {
if (value->isObject()) {
for (Json::Value::const_iterator i = value->begin(); i != value->end(); ++i) {
this->insert(typename MapType::value_type(i.key().asString(), T(&*i)));
}
} else {
- // In case of non-array value initialize array with null value
- // so it handled as initialized but invalid
- this->insert(typename MapType::value_type("", T()));
+ // Map is empty, empty initialized or uninitialized
+ // depending on InitHelper result
}
}
}
template<typename T, size_t minsize, size_t maxsize>
Json::Value Map<T, minsize, maxsize>::ToJsonValue() const {
- if (is_null()) {
- return Json::Value::null;
- }
Json::Value map(Json::objectValue);
for (typename MapType::const_iterator i = this->begin(); i != this->end(); ++i) {
map[i->first] = i->second.ToJsonValue();
: value_(value, def_value) {
}
+template<typename T>
+inline Json::Value Optional<T>::ToJsonValue() const {
+ return value_.ToJsonValue();
+}
+
} // namespace rpc
#endif /* VALIDATED_TYPES_JSON_INL_H_ */
};
// Base class for all interface-specific requests
-class RequestBase : public Message {
+class RequestBase : public Message, public CompositeType {
public:
+ explicit RequestBase(InitializationState init_state): CompositeType(init_state) {}
// Message interface
MessageType message_type() const { return kRequest; }
virtual ~RequestBase() {}
};
// Base class for all interface-specific responses
-class ResponseBase : public Message {
+class ResponseBase : public Message, public CompositeType {
public:
+ ResponseBase(InitializationState init_state): CompositeType(init_state) {}
// Message interface
MessageType message_type() const { return kResponse; }
virtual ~ResponseBase() {}
};
// Base class for all interface-specific notifications
-class NotificationBase : public Message {
+class NotificationBase : public Message, public CompositeType {
public:
+ explicit NotificationBase(InitializationState init_state): CompositeType(init_state) {}
MessageType message_type() const { return kNotification; }
// Message interface
virtual ~NotificationBase() {}
--- /dev/null
+/**
+ * Copyright (c) 2014, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RPC_BASE_VALIDATION_REPORT_H_
+#define RPC_BASE_VALIDATION_REPORT_H_
+
+#include <string>
+#include <list>
+
+namespace rpc {
+
+class ValidationReport;
+typedef std::list<ValidationReport> ValidationReports;
+
+class ValidationReport {
+ public:
+ explicit ValidationReport(const std::string& object_name);
+ const std::string& object_name() const;
+ const std::string& validation_info() const;
+ void set_validation_info(const std::string& info);
+ const ValidationReports& subobject_reports() const;
+ ValidationReport& ReportSubobject(const std::string& object_name);
+private:
+ std::string object_name_;
+ std::string validation_info_;
+ ValidationReports subobject_reports_;
+};
+
+std::string PrettyFormat(const ValidationReport& report);
+
+// Implementation
+
+namespace impl {
+inline void PrettyFormat(const ValidationReport& report,
+ const std::string& parent_path,
+ std::string* result) {
+ std::string object_path = parent_path;
+ if (!object_path.empty() && report.object_name()[0] != '[') {
+ object_path.append(".");
+ }
+ object_path.append(report.object_name());
+ if (!report.validation_info().empty()) {
+ result->append(object_path);
+ result->append(": ");
+ result->append(report.validation_info());
+ result->append("\n");
+ }
+ const ValidationReports& subreports = report.subobject_reports();
+ for (ValidationReports::const_iterator i = subreports.begin(),
+ end = subreports.end(); i != end; ++i) {
+ PrettyFormat(*i, object_path, result);
+ }
+}
+} // namespace impl
+
+inline ValidationReport::ValidationReport(const std::string& object_name)
+ : object_name_(object_name) {
+}
+
+inline const std::string& ValidationReport::object_name() const {
+ return object_name_;
+}
+
+inline const std::string& ValidationReport::validation_info() const {
+ return validation_info_;
+}
+
+inline void ValidationReport::set_validation_info(const std::string& info) {
+ validation_info_ = info;
+}
+
+inline const std::list<ValidationReport>& ValidationReport::subobject_reports() const {
+ return subobject_reports_;
+}
+
+inline ValidationReport& ValidationReport::ReportSubobject(
+ const std::string& object_name) {
+ subobject_reports_.push_back(ValidationReport(object_name));
+ return subobject_reports_.back();
+}
+
+inline std::string PrettyFormat(const ValidationReport& report) {
+ std::string result;
+ impl::PrettyFormat(report, "", &result);
+ return result;
+}
+
+} // namespace rpc
+
+#endif /* RPC_BASE_VALIDATION_REPORT_H_ */