{%- import "interface_macros.tmpl" as interface_macros %}
{%- import "struct_macros.tmpl" as struct_macros %}
{%- set class_name = interface.name %}
{%- set proxy_name = interface.name ~ "Proxy" %}
{%- set namespace_as_string = "%s"|format(module_namespace|replace(".","::")) %}
{%- set namespace_as_string_with_variant = namespace_as_string ~ ("::" ~ variant if variant) %}
{%- set qualified_class_name = ("::" ~ namespace_as_string_with_variant if namespace_as_string_with_variant) ~ "::" ~ class_name %}
{%- macro alloc_params(struct, params, message, method_number, is_response) %}
{# Allow people to search for deserialization error strings #}
// Validation for {{class_name}}.{{method_number}}
bool success = true;
{%- for param in struct.packed.packed_fields_in_ordinal_order %}
{%- if param|is_nullable_value_kind_packed_field %}
{%- if param|is_primary_nullable_value_kind_packed_field %}
{{param.original_field.kind|cpp_wrapper_call_type}} p_{{param.original_field.name}}{};
{%- endif %}
{%- else %}
{{param.field.kind|cpp_wrapper_call_type}} p_{{param.field.name}}{ {{- param.field|default_value -}} };
{%- endif %}
{%- endfor %}
{{struct.name}}DataView input_data_view({{params}}, {{message}});
{{struct_macros.deserialize(struct, "input_data_view", "p_%s", "success")}}
if (!success) {
ReportValidationErrorForMessage(
{{message}},
mojo::internal::VALIDATION_ERROR_DESERIALIZATION_FAILED,
{{class_name}}::Name_, {{method_number}}, {{is_response}});
return false;
}
{%- endmacro %}
{%- macro pass_params(parameters) %}
{%- for param in parameters %}
{%- if param.kind|is_non_const_ref_kind %}
p_{{param.name}}
{%- else %}
std::move(p_{{param.name}})
{%- endif %}
{%- if not loop.last %}, {% endif %}
{%- endfor %}
{%- endmacro %}
{%- macro feature_enabled_helper(iface) %}
{%- set feature=iface.runtime_feature|get_qualified_name_for_feature %}
// static
bool {{iface.name}}::RuntimeFeature_IsEnabled_(bool expected) {
bool enabled = base::FeatureList::IsEnabled({{feature}});
#if DCHECK_IS_ON()
if (expected) {
DCHECK(enabled) << "RuntimeFeature {{feature}} for {{iface.name}} is not enabled";
}
#endif
return enabled;
}
{%- endmacro %}
{%- macro check_feature_for_method(method) %}
{%- if method.runtime_feature %}
{%- set feature_cpp = method.runtime_feature|get_qualified_name_for_feature %}
CHECK(base::FeatureList::IsEnabled({{feature_cpp}}));
{%- endif %}
{%- endmacro %}
{#--- Function with signature of GenericValidationInfo.request_validator ---#}
{%- macro define_validate_with_runtime_feature(class_name, method) %}
{%- set feature_cpp = method.runtime_feature|get_qualified_name_for_feature %}
bool ValidateWithRuntimeFeature_{{class_name}}_{{method.name}}(
const void* data, mojo::internal::ValidationContext* validation_context) {
if (!base::FeatureList::IsEnabled({{feature_cpp}})) {
return false;
}
return internal::{{class_name}}_{{method.name}}_Params_Data::Validate(
data, validation_context);
}
{%- endmacro %}
{%- macro request_validator(class_name, method) %}
{%- if method.runtime_feature -%}
&ValidateWithRuntimeFeature_{{class_name}}_{{method.name}}
{%- else -%}
&internal::{{class_name}}_{{method.name}}_Params_Data::Validate
{%- endif -%}
{%- endmacro -%}
{#--- Begin #}
const char {{class_name}}::Name_[] = "{{module_namespace}}.{{class_name}}";
{%- if interface.uuid %}
constexpr base::Token {{class_name}}::Uuid_;
{%- endif %}
{#--- Constants #}
{%- for constant in interface.constants %}
{%- if constant.kind|is_string_kind %}
const char {{interface.name}}::{{constant.name}}[] = {{constant|constant_value}};
{%- else %}
constexpr {{constant.kind|cpp_pod_type}} {{interface.name}}::{{constant.name}};
{%- endif %}
{%- endfor %}
{{interface.name}}::IPCStableHashFunction {{interface.name}}::MessageToMethodInfo_(mojo::Message& message) {
#if !BUILDFLAG(IS_FUCHSIA)
{%- if interface.methods %}
switch (static_cast<messages::{{interface.name}}>(message.name())) {
{%- for method in interface.methods %}
case messages::{{interface.name}}::k{{method.name}}: {
return &{{interface.name}}::{{method.name}}_Sym::IPCStableHash;
}
{%- endfor %}
}
{%- endif %}
#endif // !BUILDFLAG(IS_FUCHSIA)
return nullptr;
}
const char* {{interface.name}}::MessageToMethodName_(mojo::Message& message) {
#if BUILDFLAG(MOJO_TRACE_ENABLED)
{%- if interface.methods %}
bool is_response = message.has_flag(mojo::Message::kFlagIsResponse);
if (!is_response) {
switch (static_cast<messages::{{interface.name}}>(message.name())) {
{%- for method in interface.methods %}
case messages::{{interface.name}}::k{{method.name}}:
return "Receive {{namespace_as_string}}::{{interface.name}}::{{method.name}}";
{%- endfor %}
}
} else {
switch (static_cast<messages::{{interface.name}}>(message.name())) {
{%- for method in interface.methods %}
case messages::{{interface.name}}::k{{method.name}}:
return "Receive reply {{namespace_as_string}}::{{interface.name}}::{{method.name}}";
{%- endfor %}
}
}
{%- endif %}
return "Receive unknown mojo message";
#else
bool is_response = message.has_flag(mojo::Message::kFlagIsResponse);
if (is_response) {
return "Receive mojo reply";
} else {
return "Receive mojo message";
}
#endif // BUILDFLAG(MOJO_TRACE_ENABLED)
}
#if !BUILDFLAG(IS_FUCHSIA)
{%- for method in interface.methods %}
uint32_t {{interface.name}}::{{method.name}}_Sym::IPCStableHash() {
// This method's address is used for indetifiying the mojo method name after
// symbolization. So each IPCStableHash should have a unique address.
// We cannot use NO_CODE_FOLDING() here - it relies on the uniqueness of
// __LINE__ value, which is not unique accross different mojo modules.
// The code below is very similar to NO_CODE_FOLDING, but it uses a unique
// hash instead of __LINE__.
constexpr uint32_t kHash = base::MD5Hash32Constexpr(
"(Impl){{namespace_as_string}}::{{interface.name}}::{{method.name}}");
const uint32_t hash = kHash;
base::debug::Alias(&hash);
return hash;
}
{%- endfor %}
# endif // !BUILDFLAG(IS_FUCHSIA)
{%- if interface.runtime_feature %}
{{feature_enabled_helper(interface)}}
{%- endif %}
{%- for method in interface.methods %}
{%- if method.sync %}
bool {{class_name}}::{{method.name}}({{interface_macros.declare_sync_method_params("", method)}}) {
NOTREACHED();
}
{%- endif %}
{%- endfor %}
{#--- ForwardToCallback definition #}
{%- for method in interface.methods -%}
{%- if method.response_parameters != None %}
{%- if method.sync %}
class {{class_name}}_{{method.name}}_HandleSyncResponse
: public mojo::MessageReceiver {
public:
{{class_name}}_{{method.name}}_HandleSyncResponse(
bool* result
{%- for param in method.response_parameters -%}
, {{param.kind|cpp_wrapper_call_type}}* out_{{param.name}}
{%- endfor %})
: result_(result)
{%- for param in method.response_parameters -%}
, out_{{param.name}}_(out_{{param.name}})
{%- endfor %} {
DCHECK(!*result_);
}
{{class_name}}_{{method.name}}_HandleSyncResponse(const {{class_name}}_{{method.name}}_HandleSyncResponse&) = delete;
{{class_name}}_{{method.name}}_HandleSyncResponse& operator=(const {{class_name}}_{{method.name}}_HandleSyncResponse&) = delete;
bool Accept(mojo::Message* message) override;
private:
bool* result_;
{%- for param in method.response_parameters %}
{{param.kind|cpp_wrapper_call_type}}* out_{{param.name}}_;
{%- endfor -%}
};
{%- endif %}
class {{class_name}}_{{method.name}}_ForwardToCallback
: public mojo::MessageReceiver {
public:
{{class_name}}_{{method.name}}_ForwardToCallback(
{{class_name}}::{{method.name}}Callback callback
) : callback_(std::move(callback)) {
}
{{class_name}}_{{method.name}}_ForwardToCallback(const {{class_name}}_{{method.name}}_ForwardToCallback&) = delete;
{{class_name}}_{{method.name}}_ForwardToCallback& operator=(const {{class_name}}_{{method.name}}_ForwardToCallback&) = delete;
bool Accept(mojo::Message* message) override;
private:
{{class_name}}::{{method.name}}Callback callback_;
};
{%- endif %}
{%- endfor %}
{{proxy_name}}::{{proxy_name}}(mojo::MessageReceiverWithResponder* receiver)
: receiver_(receiver) {
{%- if interface|has_estimate_size_methods %}
if (base::FeatureList::IsEnabled(mojo::features::kMojoPredictiveAllocation)) {
{%- for method in interface.methods %}
{%- if method.estimate_message_size %}
{%- set message_name =
"base::to_underlying(messages::%s::k%s)"|format(interface.name, method.name) %}
size_estimator_.EnablePredictiveAllocation({{message_name}});
{%- endif %}
{%- endfor %}
}
{%- endif %}
}
{#--- Proxy definitions #}
{%- for method in interface.methods %}
{%- set message_name =
"base::to_underlying(messages::%s::k%s)"|format(interface.name, method.name) %}
{%- set params_struct = method.param_struct %}
{%- set params_description =
"%s.%s request"|format(interface.name, method.name) %}
{%- set message_typename = "%s_%s_Message"|format(proxy_name, method.name) %}
{%- if method.sync %}
bool {{proxy_name}}::{{method.name}}(
{{interface_macros.declare_sync_method_params("param_", method)}}) {
#if BUILDFLAG(MOJO_TRACE_ENABLED)
{%- set event_name = "Call %s::%s::%s (sync)" % (namespace_as_string,
class_name, method.name) %}
{{interface_macros.trace_event(prefix="param_",
method_parameters=method.parameters,
method_name=event_name,
parameter_group="input_parameters",
trace_event_type='_BEGIN')}}
#else
{#- Output a minimal trace event if MOJO_TRACE_ENABLED is false. #}
{%- set event_name = "%s::%s" % (class_name, method.name) %}
{{interface_macros.trace_event(method_name=event_name)}}
#endif
{{check_feature_for_method(method)|indent(2)}}
const bool kExpectsResponse = true;
const bool kIsSync = true;
const bool kAllowInterrupt =
{% if method.allow_interrupt %}true{% else %}false{% endif %};
{%- if method.supports_urgent %}
const bool is_urgent = mojo::UrgentMessageScope::IsInUrgentScope();
{% else %}
const bool is_urgent = false;
{%- endif %}
{{interface_macros.build_message_flags(False, "kIsSync", "kAllowInterrupt",
"is_urgent", "kExpectsResponse",
"kFlags")}}
{{interface_macros.build_serialized_message(
message_name, method, "param_%s", params_struct, params_description,
"kFlags", "message")}}
#if defined(ENABLE_IPC_FUZZER)
message.set_interface_name({{class_name}}::Name_);
message.set_method_name("{{method.name}}");
#endif
bool result = false;
std::unique_ptr<mojo::MessageReceiver> responder(
new {{class_name}}_{{method.name}}_HandleSyncResponse(
&result
{%- for param in method.response_parameters -%}
, out_param_{{param.name}}
{%- endfor %}));
::mojo::internal::SendMojoMessage(*receiver_, message, std::move(responder));
#if BUILDFLAG(MOJO_TRACE_ENABLED)
{{interface_macros.trace_event(prefix="out_param_",
method_parameters=method.response_parameters,
method_name=event_name,
parameter_group="sync_response_parameters",
trace_event_type='_END',
dereference_parameters=True)}}
#endif
return result;
}
{%- endif %} {#- if method.sync #}
void {{proxy_name}}::{{method.name}}(
{{interface_macros.declare_request_params("in_", method)}}) {
#if BUILDFLAG(MOJO_TRACE_ENABLED)
{%- set event_name = "Send %s::%s::%s" % (namespace_as_string, class_name,
method.name) %}
{{interface_macros.trace_event(prefix="in_",
method_parameters=method.parameters,
method_name=event_name,
parameter_group="input_parameters")}}
#endif
{{check_feature_for_method(method)|indent(2)}}
{%- if method.response_parameters != None %}
const bool kExpectsResponse = true;
{%- else %}
const bool kExpectsResponse = false;
{%- endif %}
const bool kIsSync = false;
const bool kAllowInterrupt = true;
{%- if method.supports_urgent %}
const bool is_urgent = mojo::UrgentMessageScope::IsInUrgentScope();
{% else %}
const bool is_urgent = false;
{%- endif %}
{{interface_macros.build_message_flags(False, "kIsSync", "kAllowInterrupt",
"is_urgent", "kExpectsResponse",
"kFlags")}}
{{interface_macros.build_serialized_message(
message_name, method, "in_%s", params_struct, params_description,
"kFlags", "message", True)}}
#if defined(ENABLE_IPC_FUZZER)
message.set_interface_name({{class_name}}::Name_);
message.set_method_name("{{method.name}}");
#endif
{%- if method.estimate_message_size %}
size_estimator_.TrackPayloadSize({{message_name}}, message.payload_num_bytes());
{%- endif %}
{%- if method.response_parameters != None %}
std::unique_ptr<mojo::MessageReceiver> responder(
new {{class_name}}_{{method.name}}_ForwardToCallback(
std::move(callback)));
::mojo::internal::SendMojoMessage(*receiver_, message, std::move(responder));
{%- else %}
// This return value may be ignored as false implies the Connector has
// encountered an error, which will be visible through other means.
::mojo::internal::SendMojoMessage(*receiver_, message);
{%- endif %}
}
{%- endfor %}
{#--- ProxyToResponder definition #}
{%- for method in interface.methods -%}
{%- if method.response_parameters != None %}
{%- set message_name =
"base::to_underlying(messages::%s::k%s)"|format(interface.name, method.name) %}
{%- set response_params_struct = method.response_param_struct %}
{%- set params_description =
"%s.%s response"|format(interface.name, method.name) %}
{%- set response_message_typename =
"%s_%s_Response_Message"|format(interface.name, method.name) %}
class {{class_name}}_{{method.name}}_ProxyToResponder : public ::mojo::internal::ProxyToResponder {
public:
static {{class_name}}::{{method.name}}Callback CreateCallback(
::mojo::Message& message,
std::unique_ptr<mojo::MessageReceiverWithStatus> responder) {
std::unique_ptr<{{class_name}}_{{method.name}}_ProxyToResponder> proxy(
new {{class_name}}_{{method.name}}_ProxyToResponder(
message, std::move(responder)));
return base::BindOnce(&{{class_name}}_{{method.name}}_ProxyToResponder::Run,
std::move(proxy));
}
~{{class_name}}_{{method.name}}_ProxyToResponder() {
#if DCHECK_IS_ON()
if (responder_) {
// If we're being destroyed without being run, we want to ensure the
// binding endpoint has been closed. This checks for that asynchronously.
// We pass a bound generated callback to handle the response so that any
// resulting DCHECK stack will have useful interface type information.
// Instantiate a ScopedFizzleBlockShutdownTasks to allow this request to
// fizzle if this happens after shutdown and the endpoint is bound to a
// BLOCK_SHUTDOWN sequence.
base::ThreadPoolInstance::ScopedFizzleBlockShutdownTasks fizzler;
responder_->IsConnectedAsync(base::BindOnce(&OnIsConnectedComplete));
}
#endif
}
private:
{{class_name}}_{{method.name}}_ProxyToResponder(
::mojo::Message& message,
std::unique_ptr<mojo::MessageReceiverWithStatus> responder)
: ::mojo::internal::ProxyToResponder(message, std::move(responder)) {
}
#if DCHECK_IS_ON()
static void OnIsConnectedComplete(bool connected) {
DCHECK(!connected)
<< "{{class_name}}::{{method.name}}Callback was destroyed without "
<< "first either being run or its corresponding binding being closed. "
<< "It is an error to drop response callbacks which still correspond "
<< "to an open interface pipe.";
}
#endif
void Run(
{{interface_macros.declare_params("in_", method.response_parameters)}});
};
bool {{class_name}}_{{method.name}}_ForwardToCallback::Accept(
mojo::Message* message) {
DCHECK(message->is_serialized());
internal::{{class_name}}_{{method.name}}_ResponseParams_Data* params =
reinterpret_cast<
internal::{{class_name}}_{{method.name}}_ResponseParams_Data*>(
message->mutable_payload());
{%- set desc = class_name~"::"~method.name~" response" %}
{{alloc_params(method.response_param_struct, "params", "message", method.sequential_ordinal, "true")}}
if (!callback_.is_null())
std::move(callback_).Run({{pass_params(method.response_parameters)}});
return true;
}
void {{class_name}}_{{method.name}}_ProxyToResponder::Run(
{{interface_macros.declare_params("in_", method.response_parameters)}}) {
#if BUILDFLAG(MOJO_TRACE_ENABLED)
{%- set event_name = "Send reply %s::%s::%s"
% (namespace_as_string, class_name, method.name) %}
{{interface_macros.trace_event(prefix="in_",
method_parameters=method.response_parameters,
method_name=event_name,
parameter_group="async_response_parameters",
dereference_parameters=False)}}
#endif
{{interface_macros.build_message_flags(True, "is_sync_", "true", "false",
"false", "kFlags")}}
{{interface_macros.build_serialized_message(
message_name, method, "in_%s", response_params_struct,
response_params_description, "kFlags", "message")}}
#if defined(ENABLE_IPC_FUZZER)
message.set_interface_name({{class_name}}::Name_);
message.set_method_name("{{method.name}}");
#endif
message.set_request_id(request_id_);
message.set_trace_nonce(trace_nonce_);
::mojo::internal::SendMojoMessage(*responder_, message);
// SendMojoMessage() fails silently if the responder connection is closed,
// or if the message is malformed.
//
// TODO(darin): If Accept() returns false due to a malformed message, that
// may be good reason to close the connection. However, we don't have a
// way to do that from here. We should add a way.
responder_ = nullptr;
}
{%- endif -%}
{%- if method.sync %}
bool {{class_name}}_{{method.name}}_HandleSyncResponse::Accept(
mojo::Message* message) {
DCHECK(message->is_serialized());
internal::{{class_name}}_{{method.name}}_ResponseParams_Data* params =
reinterpret_cast<internal::{{class_name}}_{{method.name}}_ResponseParams_Data*>(
message->mutable_payload());
{%- set desc = class_name~"::"~method.name~" response" %}
{{alloc_params(method.response_param_struct, "params", "message", method.sequential_ordinal, "true")}}
{%- for param in method.response_parameters %}
*out_{{param.name}}_ = std::move(p_{{param.name}});
{%- endfor %}
*result_ = true;
return true;
}
{%- endif %}
{%- endfor %}
{#--- StubDispatch definition #}
// static
bool {{class_name}}StubDispatch::Accept(
{{interface.name}}* impl,
mojo::Message* message) {
{%- if interface.methods %}
{%- if interface.dispatch_debug_alias %}
const uint64_t kDebugAliasSentinel0 = 0xC0FFEE42;
const uint64_t kMessageName = message->header()->name;
const uint64_t kDebugAliasSentinel1 = 0xDECAFBAD;
base::debug::Alias(&kDebugAliasSentinel0);
base::debug::Alias(&kMessageName);
base::debug::Alias(&kDebugAliasSentinel1);
{%- endif %}
switch (static_cast<messages::{{class_name}}>(message->header()->name)) {
{%- for method in interface.methods %}
case messages::{{class_name}}::k{{method.name}}: {
{%- if method.response_parameters == None %}
DCHECK(message->is_serialized());
internal::{{class_name}}_{{method.name}}_Params_Data* params =
reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>(
message->mutable_payload());
{%- set desc = class_name~"::"~method.name %}
{{alloc_params(method.param_struct, "params", "message", method.sequential_ordinal, "false")|
indent(4)}}
// A null |impl| means no implementation was bound.
DCHECK(impl);
impl->{{method.name}}({{pass_params(method.parameters)|indent(8, True)}});
return true;
{%- else %}
break;
{%- endif %}
}
{%- endfor %}
}
{%- endif %}
return false;
}
// static
bool {{class_name}}StubDispatch::AcceptWithResponder(
{{interface.name}}* impl,
mojo::Message* message,
std::unique_ptr<mojo::MessageReceiverWithStatus> responder) {
{%- if interface.methods %}
[[maybe_unused]] const bool message_is_sync =
message->has_flag(mojo::Message::kFlagIsSync);
[[maybe_unused]] const uint64_t request_id = message->request_id();
switch (static_cast<messages::{{class_name}}>(message->header()->name)) {
{%- for method in interface.methods %}
case messages::{{class_name}}::k{{method.name}}: {
{%- if method.response_parameters != None %}
internal::{{class_name}}_{{method.name}}_Params_Data* params =
reinterpret_cast<
internal::{{class_name}}_{{method.name}}_Params_Data*>(
message->mutable_payload());
{%- set desc = class_name~"::"~method.name %}
{{alloc_params(method.param_struct, "params", "message", method.sequential_ordinal, "false")|
indent(4)}}
{{class_name}}::{{method.name}}Callback callback =
{{class_name}}_{{method.name}}_ProxyToResponder::CreateCallback(
*message, std::move(responder));
// A null |impl| means no implementation was bound.
DCHECK(impl);
impl->{{method.name}}(
{%- if method.parameters -%}{{pass_params(method.parameters)|indent(8,True)}}, {% endif -%}std::move(callback));
return true;
{%- else %}
break;
{%- endif %}
}
{%- endfor %}
}
{%- endif %}
return false;
}
{#--- Feature validators for methods with [RuntimeFeature=] ---#}
{%- if interface.methods|selectattr('runtime_feature') %}
namespace {
{%- for method in interface.methods %}
{%- if method.runtime_feature %}
{{ define_validate_with_runtime_feature(class_name, method)}}
{%- endif %}
{%- endfor %}
} // namespace
{%- endif %}
{#--- Table of validation functions (packed or sparse) ---#}
{% if interface.methods and (interface | has_packed_method_ordinals) %}
static const mojo::internal::GenericValidationInfo k{{class_name}}ValidationInfo[] = {
{%- for i in range(interface.methods | map(attribute='ordinal') | max + 1) -%}
{%- set method = (interface.methods | selectattr('ordinal', 'equalto', i) | list)[0] %}
{%- if method %}
{ {{request_validator(class_name, method)}},
{%- if method.response_parameters != None %}
&internal::{{class_name}}_{{method.name}}_ResponseParams_Data::Validate},
{%- else %}
nullptr /* no response */},
{%- endif %}
{%- else %}
{nullptr, nullptr}, // nonexistent
{%- endif %}
{%- endfor %}
};
{%- elif interface.methods %}
static const std::pair<uint32_t, mojo::internal::GenericValidationInfo> k{{class_name}}ValidationInfo[] = {
{%- for method in interface.methods %}
{base::to_underlying(messages::{{class_name}}::k{{method.name}}),
{ {{request_validator(class_name, method)}},
{%- if method.response_parameters != None %}
&internal::{{class_name}}_{{method.name}}_ResponseParams_Data::Validate}},
{%- else %}
nullptr /* no response */}},
{%- endif %}
{%- endfor %}
};
{%- endif %}
{#--- Request validator definitions #}
bool {{class_name}}RequestValidator::Accept(mojo::Message* message) {
{#- Not simply Name_ because there is a mojom interface called MessageReceiver #}
const char* name = {{qualified_class_name}}::Name_;
{%- if not interface.methods %}
return mojo::internal::ValidateRequestGeneric(message, name, {});
{%- elif interface | has_packed_method_ordinals %}
return mojo::internal::ValidateRequestGenericPacked(message, name, k{{class_name}}ValidationInfo);
{%- else %}
return mojo::internal::ValidateRequestGeneric(message, name, k{{class_name}}ValidationInfo);
{%- endif %}
}
{#--- Response validator definitions #}
{% if interface|has_callbacks %}
bool {{class_name}}ResponseValidator::Accept(mojo::Message* message) {
const char* name = {{qualified_class_name}}::Name_;
{%- if interface | has_packed_method_ordinals %}
return mojo::internal::ValidateResponseGenericPacked(message, name, k{{class_name}}ValidationInfo);
{%- else %}
return mojo::internal::ValidateResponseGeneric(message, name, k{{class_name}}ValidationInfo);
{% endif %}
}
{%- endif -%}