Intergen tool
authorJustin Dickow <jjdickow@gmail.com>
Tue, 15 Jul 2014 15:54:41 +0000 (11:54 -0400)
committerJustin Dickow <jjdickow@gmail.com>
Tue, 15 Jul 2014 15:54:41 +0000 (11:54 -0400)
Signed-off-by: Justin Dickow <jjdickow@gmail.com>
25 files changed:
tools/intergen/GenerateInterfaceLibrary.cmake
tools/intergen/cppgen/CMakeLists.txt
tools/intergen/cppgen/include/cppgen/message_interface.h
tools/intergen/cppgen/include/cppgen/naming_convention.h
tools/intergen/cppgen/include/cppgen/struct_type_constructor.h
tools/intergen/cppgen/include/cppgen/struct_type_dbus_serializer.h
tools/intergen/cppgen/include/cppgen/struct_type_from_json_method.h
tools/intergen/cppgen/include/cppgen/struct_type_is_initialized_method.h
tools/intergen/cppgen/include/cppgen/struct_type_report_erros_method.h [new file with mode: 0644]
tools/intergen/cppgen/include/cppgen/type_name_code_generator.h
tools/intergen/cppgen/src/cppgen/declaration_generator.cc
tools/intergen/cppgen/src/cppgen/definition_generator.cc
tools/intergen/cppgen/src/cppgen/message_interface.cc
tools/intergen/cppgen/src/cppgen/naming_convention.cc
tools/intergen/cppgen/src/cppgen/struct_type_constructor.cc
tools/intergen/cppgen/src/cppgen/struct_type_dbus_serializer.cc
tools/intergen/cppgen/src/cppgen/struct_type_from_json_method.cc
tools/intergen/cppgen/src/cppgen/struct_type_is_initialized_method.cc
tools/intergen/cppgen/src/cppgen/struct_type_is_valid_method.cc
tools/intergen/cppgen/src/cppgen/struct_type_report_erros_method.cc [new file with mode: 0644]
tools/intergen/cppgen/src/cppgen/type_name_code_generator.cc
tools/intergen/model/include/model/composite_type.h
tools/intergen/model/src/model/composite_type.cc
tools/intergen/model/src/model/function.cc
tools/intergen/model/src/model/type_registry.cc

index 021e030..8414722 100644 (file)
@@ -1,11 +1,8 @@
-find_package(DBus)
-
 set(INTERGEN_CMD ${CMAKE_BINARY_DIR}/tools/intergen/bin/intergen)
 set(GENERATED_LIB_DEPENDENCIES jsoncpp)
 set(GENERATED_LIB_HEADER_DEPENDENCIES
   ${CMAKE_SOURCE_DIR}/src/components/rpc_base/include
   ${CMAKE_SOURCE_DIR}/src/thirdPartyLibs/jsoncpp/include
-  ${DBUS_INCLUDE_DIRS}
 )
 
 # Generates interface library from given xml file and builds it
@@ -26,6 +23,8 @@ function (GenerateInterfaceLibrary xml_file_name generated_interface_names)
   endif()
   if (GenerateInterfaceLibrary_DBUS_SUPPORT)
     set(NEED_DBUS "-d")
+    find_package(DBus)
+    list(APPEND GENERATED_LIB_HEADER_DEPENDENCIES ${DBUS_INCLUDE_DIRS})
   endif()
 
   foreach(interface_name ${generated_interface_names})
index 3ba1fef..c6e052a 100644 (file)
@@ -31,6 +31,7 @@ set (SOURCES
   src/cppgen/struct_type_from_json_method.cc
   src/cppgen/struct_type_is_initialized_method.cc
   src/cppgen/struct_type_is_valid_method.cc
+  src/cppgen/struct_type_report_erros_method.cc
   src/cppgen/type_name_code_generator.cc
 )
 
@@ -61,6 +62,7 @@ set (HEADERS
   include/cppgen/struct_type_from_json_method.h
   include/cppgen/struct_type_is_initialized_method.h
   include/cppgen/struct_type_is_valid_method.h
+  include/cppgen/struct_type_report_erros_method.h
   include/cppgen/type_name_code_generator.h
 )
 
index ab309c8..8cc2d10 100644 (file)
@@ -71,6 +71,7 @@ class MessageInterface: public CppClass {
   virtual const MethodsList& methods();
  private:
   // Fields
+  Method constructor_;
   Method handle_with_method_;
   InterfaceStringIdMethod interface_string_id_method_;
   std::vector<const Method*> methods_;
index b2dc2f9..3aef239 100644 (file)
@@ -85,6 +85,10 @@ std::string UpperCamelCaseInterfaceName(const Interface& interface);
 // Currently it just lower_case_interface_name
 std::string InterfaceNamespaceName(const Interface& interface);
 
+// Produces new name (generally for struct fields) if it
+// conflicts with known keywords
+std::string AvoidKeywords(const std::string& name);
+
 }  // namespace codegen
 
 #endif /* NAMING_CONVENTION_H_ */
index 5497ad4..a9f5ffe 100644 (file)
@@ -44,7 +44,8 @@ class TypePreferences;
  */
 class StructTypeDefaultConstructor : public CppStructConstructor {
  public:
-  StructTypeDefaultConstructor(const Struct* strct);
+  StructTypeDefaultConstructor(const Struct* strct,
+                               const std::string& base_class_name);
   ~StructTypeDefaultConstructor();
  private:
 };
@@ -57,7 +58,8 @@ class StructTypeDefaultConstructor : public CppStructConstructor {
 class StructTypeMandatoryConstructor : public CppStructConstructor {
  public:
   StructTypeMandatoryConstructor(const TypePreferences* preferences,
-                                 const Struct* strct);
+                                 const Struct* strct,
+                                 const std::string& base_class_name);
   ~StructTypeMandatoryConstructor();
  private:
   // CppFunction pure virtual methods implementation
index f4a2fa1..64872f3 100644 (file)
@@ -58,7 +58,8 @@ class StructTypeFromDbusReaderConstructor : public CppStructConstructor {
  public:
   StructTypeFromDbusReaderConstructor(const TypePreferences* preferences,
                                       const Struct* strct,
-                                      bool substructure);
+                                      bool substructure,
+                                      const std::string& base_class_name);
   ~StructTypeFromDbusReaderConstructor();
  private:
   // CppFunction interface
index b6b460a..270fe30 100644 (file)
@@ -44,9 +44,14 @@ class Struct;
  */
 class StructTypeFromJsonConstructor : public CppStructConstructor {
  public:
-  StructTypeFromJsonConstructor(const Struct* strct);
+  StructTypeFromJsonConstructor(const Struct* strct,
+                                const std::string& base_class_name);
   ~StructTypeFromJsonConstructor();
  private:
+  // CppFunction pure virtual methods implementation
+  virtual void DefineBody(std::ostream* os) const;
+ private:
+  // Fields
   const Struct* strct_;
 };
 
index 631e880..48e2d76 100644 (file)
@@ -49,6 +49,25 @@ class StructTypeIsInitializedMethod : public CppFunction {
  private:
   // CppFunction pure virtual methods implementation
   virtual void DefineBody(std::ostream* os) const;
+ private:
+  // Fields
+  const Struct* strct_;
+};
+
+/**
+ * @brief Generates bool empty() method for struct types
+ * this method has no is_ prefix to support stl style
+ * that is dictated by maps and arrays
+ */
+class StructTypeStructEmptyMethod : public CppFunction {
+ public:
+  StructTypeStructEmptyMethod(const Struct* strct);
+  ~StructTypeStructEmptyMethod();
+ private:
+  // CppFunction pure virtual methods implementation
+  virtual void DefineBody(std::ostream* os) const;
+ private:
+  // Fields
   const Struct* strct_;
 };
 
diff --git a/tools/intergen/cppgen/include/cppgen/struct_type_report_erros_method.h b/tools/intergen/cppgen/include/cppgen/struct_type_report_erros_method.h
new file mode 100644 (file)
index 0000000..3dd851c
--- /dev/null
@@ -0,0 +1,53 @@
+/* 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 CPPGEN_STRUCT_TYPE_REPORT_ERROS_METHOD_H
+#define CPPGEN_STRUCT_TYPE_REPORT_ERROS_METHOD_H
+
+#include "cppgen/cpp_function.h"
+
+namespace codegen {
+class Struct;
+
+class StructTypeReportErrosMethod: public CppFunction {
+ public:
+  StructTypeReportErrosMethod(const Struct* strct);
+ private:
+  // CppFunction pure virtual methods implementation
+  virtual void DefineBody(std::ostream* os) const;
+ private:
+  // Fields
+  const Struct* strct_;
+};
+
+} // namespace codegen
+
+#endif // CPPGEN_STRUCT_TYPE_REPORT_ERROS_METHOD_H
index bc23fb0..5fd7576 100644 (file)
@@ -90,12 +90,6 @@ class TypeNameGenerator: public TypeCodeGenerator {
 class RpcTypeNameGenerator: public TypeCodeGenerator {
  public:
   // Types
-  // Availability class to wrap type into
-  enum Availability {
-    kUnspecified,
-    kMandatory,
-    kOptional
-  };
  public:
   // Generates name of type that is able to validate given primitive value
   // |interface| specifies the interface where code is currently
@@ -106,7 +100,7 @@ class RpcTypeNameGenerator: public TypeCodeGenerator {
   RpcTypeNameGenerator(const Interface* interface,
                        const TypePreferences* preferences,
                        const Type* type,
-                       Availability availability);
+                       bool optional);
   ~RpcTypeNameGenerator();
   // Generated type name
   std::string result() const;
index 9be58a4..46e4591 100644 (file)
 #include "cppgen/literal_generator.h"
 #include "cppgen/message_handle_with_method.h"
 #include "cppgen/module_manager.h"
+#include "cppgen/naming_convention.h"
 #include "cppgen/struct_type_constructor.h"
 #include "cppgen/struct_type_dbus_serializer.h"
 #include "cppgen/struct_type_from_json_method.h"
 #include "cppgen/struct_type_is_initialized_method.h"
 #include "cppgen/struct_type_is_valid_method.h"
+#include "cppgen/struct_type_report_erros_method.h"
 #include "cppgen/type_name_code_generator.h"
 #include "model/composite_type.h"
 #include "model/constant.h"
@@ -142,7 +144,15 @@ void DeclarationGenerator::GenerateCodeForStruct(const Struct* strct) {
   CppFile& header_file = module_manager_->HeaderForStruct(*strct);
   DeclareExternalTypes(*preferences_, &header_file.global_namespace());
   ostream& o = header_file.types_ns().os();
-  DeclareStructureBegin(o, strct->name(), "",
+  std::string base_class_name = "CompositeType";
+  if (strct->frankenstruct()) {
+    base_class_name = RpcTypeNameGenerator(
+                        &strct->interface(),
+                        preferences_,
+                        strct->frankenstruct(),
+                        false).result();
+  }
+  DeclareStructureBegin(o, strct->name(), base_class_name,
                         Comment(strct->description()));
   {
     Section pub("public", &o);
@@ -150,25 +160,29 @@ void DeclarationGenerator::GenerateCodeForStruct(const Struct* strct) {
   }
   {
     Section pub("public", &o);
-    StructTypeDefaultConstructor(strct).Declare(&o, true);
-    StructTypeMandatoryConstructor mandatory_constructor(preferences_, strct);
+    StructTypeDefaultConstructor(strct, base_class_name).Declare(&o, true);
+    StructTypeMandatoryConstructor mandatory_constructor(preferences_,
+                                                         strct,
+                                                         base_class_name);
     if (mandatory_constructor.has_mandatory_parameters()) {
       mandatory_constructor.Declare(&o, true);
     }
     CppStructDestructor(strct->name()).Declare(&o, true);
     if (preferences_->generate_json) {
-      StructTypeFromJsonConstructor(strct).Declare(&o , true);
+      StructTypeFromJsonConstructor(strct, base_class_name).Declare(&o , true);
       StructTypeToJsonMethod(strct).Declare(&o , true);
     }
     if (preferences_->generate_dbus) {
       StructTypeFromDbusReaderConstructor(
-            preferences_, strct, true).Declare(&o, true);
+            preferences_, strct, true, base_class_name).Declare(&o, true);
       StructTypeToDbusWriterMethod(strct, true).Declare(&o , true);
       StructTypeDbusMessageSignatureMethod(preferences_,
                                            strct, true).Declare(&o, true);
     }
     StructTypeIsValidMethod(strct).Declare(&o, true);
     StructTypeIsInitializedMethod(strct).Declare(&o, true);
+    StructTypeStructEmptyMethod(strct).Declare(&o, true);
+    StructTypeReportErrosMethod(strct).Declare(&o, true);
   }
   {
     Section priv("private", &o);
@@ -187,7 +201,7 @@ void DeclarationGenerator::GenerateCodeForTypedef(const Typedef* tdef) {
           RpcTypeNameGenerator(&tdef->interface(),
                                preferences_,
                                tdef->type(),
-                               RpcTypeNameGenerator::kUnspecified).result(),
+                               false).result(),
           tdef->name())
       << '\n';
 }
@@ -211,15 +225,21 @@ void DeclarationGenerator::GenerateCodeForStructField(
     CppFile* header_file,
     Namespace* name_space) {
   ostream& o = name_space->os();
-  RpcTypeNameGenerator::Availability availability =
-      field.default_value() || field.is_mandatory() ?
-          RpcTypeNameGenerator::kMandatory : RpcTypeNameGenerator::kOptional;
+  // Field is considered optional if it has mandatory=false attribute and
+  // if it does NOT have default values. Fields that have default values are
+  // always available no mater if they present in input or not
+  bool field_is_optional = false;
+  if (!field.is_mandatory()) {
+    if (field.default_value() == NULL) {
+      field_is_optional = true;
+    }
+  }
   header_file->IncludeType(*field.type());
   o << RpcTypeNameGenerator(&strct.interface(),
                             preferences_,
                             field.type(),
-                            availability).result();
-  o << " " << field.name() << ";";
+                            field_is_optional).result();
+  o << " " << AvoidKeywords(field.name()) << ";";
   if (!field.description().empty()) {
     o << " " << Comment(field.description());
   }
@@ -238,7 +258,8 @@ void DeclarationGenerator::GenerateCodeForRequest(const Request& request,
   DeclareExternalTypes(*preferences_, &header_file->global_namespace());
   Namespace& requests_ns = header_file->requests_ns();
   ostream& o = requests_ns.os();
-  DeclareStructureBegin(o, request.name(), "Request",
+  const char* base_class_name = "Request";
+  DeclareStructureBegin(o, request.name(), base_class_name,
                         Comment(request.description()));
   {
     Section pub("public", &o);
@@ -250,26 +271,30 @@ void DeclarationGenerator::GenerateCodeForRequest(const Request& request,
   }
   {
     Section pub("public", &o);
-    StructTypeDefaultConstructor(&request).Declare(&o, true);
-    StructTypeMandatoryConstructor mandatory_constructor(preferences_, &request);
+    StructTypeDefaultConstructor(&request, base_class_name).Declare(&o, true);
+    StructTypeMandatoryConstructor mandatory_constructor(preferences_,
+                                                         &request,
+                                                         base_class_name);
     if (mandatory_constructor.has_mandatory_parameters()) {
       mandatory_constructor.Declare(&o, true);
     }
     CppStructDestructor(request.name()).Declare(&o, true);
 
     if (preferences_->generate_json) {
-      StructTypeFromJsonConstructor(&request).Declare(&o , true);
+      StructTypeFromJsonConstructor(&request, base_class_name).Declare(&o , true);
       StructTypeToJsonMethod(&request).Declare(&o , true);
     }
     if (preferences_->generate_dbus) {
-      StructTypeFromDbusReaderConstructor(preferences_,
-                                          &request, false).Declare(&o, true);
+      StructTypeFromDbusReaderConstructor(preferences_, &request, false,
+                                          base_class_name).Declare(&o, true);
       StructTypeToDbusWriterMethod(&request, false).Declare(&o , true);
       StructTypeDbusMessageSignatureMethod(preferences_,
                                            &request, false).Declare(&o, true);
     }
     StructTypeIsValidMethod(&request).Declare(&o, true);
     StructTypeIsInitializedMethod(&request).Declare(&o, true);
+    StructTypeStructEmptyMethod(&request).Declare(&o, true);
+    StructTypeReportErrosMethod(&request).Declare(&o, true);
     MessageHandleWithMethod(request.name()).Declare(&o, true);
     FunctionIdMethod(&request).Define(&o, true);
     FunctionStringIdMethod(&request).Define(&o, true);
@@ -287,7 +312,8 @@ void DeclarationGenerator::GenerateCodeForResponse(const Response& response) {
   DeclareExternalTypes(*preferences_, &header_file.global_namespace());
   Namespace& responses_ns = header_file.responses_ns();
   ostream& o = responses_ns.os();
-  DeclareStructureBegin(o, response.name(), "Response",
+  const char* base_class_name = "Response";
+  DeclareStructureBegin(o, response.name(), base_class_name,
                         Comment(response.description()));
   {
     Section pub("public", &o);
@@ -297,20 +323,22 @@ void DeclarationGenerator::GenerateCodeForResponse(const Response& response) {
   }
   {
     Section pub("public", &o);
-    StructTypeDefaultConstructor(&response).Declare(&o, true);
-    StructTypeMandatoryConstructor mandatory_constructor(preferences_, &response);
+    StructTypeDefaultConstructor(&response, base_class_name).Declare(&o, true);
+    StructTypeMandatoryConstructor mandatory_constructor(preferences_,
+                                                         &response,
+                                                         base_class_name);
     if (mandatory_constructor.has_mandatory_parameters()) {
       mandatory_constructor.Declare(&o, true);
     }
     CppStructDestructor(response.name()).Declare(&o, true);
     if (preferences_->generate_json) {
-      StructTypeFromJsonConstructor(&response).Declare(&o, true);
+      StructTypeFromJsonConstructor(&response, base_class_name).Declare(&o, true);
       StructTypeToJsonMethod(&response).Declare(&o , true);
 
     }
     if (preferences_->generate_dbus) {
-      StructTypeFromDbusReaderConstructor(preferences_,
-                                          &response, false).Declare(&o, true);
+      StructTypeFromDbusReaderConstructor(preferences_, &response, false,
+                                          base_class_name).Declare(&o, true);
       StructTypeToDbusWriterMethod(&response, false).Declare(&o , true);
 
       StructTypeDbusMessageSignatureMethod(preferences_,
@@ -318,6 +346,8 @@ void DeclarationGenerator::GenerateCodeForResponse(const Response& response) {
     }
     StructTypeIsValidMethod(&response).Declare(&o, true);
     StructTypeIsInitializedMethod(&response).Declare(&o, true);
+    StructTypeStructEmptyMethod(&response).Declare(&o, true);
+    StructTypeReportErrosMethod(&response).Declare(&o, true);
     MessageHandleWithMethod(response.name()).Declare(&o, true);
     FunctionIdMethod(&response).Define(&o, true);
     FunctionStringIdMethod(&response).Define(&o, true);
@@ -336,7 +366,8 @@ void DeclarationGenerator::GenerateCodeForNotification(
   DeclareExternalTypes(*preferences_, &header_file.global_namespace());
   Namespace& notifications_ns = header_file.notifications_ns();
   ostream& o = notifications_ns.os();
-  DeclareStructureBegin(o, notification.name(), "Notification",
+  const char* base_class_name = "Notification";
+  DeclareStructureBegin(o, notification.name(), base_class_name,
                         Comment(notification.description()));
   {
     Section pub("public", &o);
@@ -346,25 +377,29 @@ void DeclarationGenerator::GenerateCodeForNotification(
   }
   {
     Section pub("public", &o);
-    StructTypeDefaultConstructor(&notification).Declare(&o, true);
-    StructTypeMandatoryConstructor mandatory_constructor(preferences_, &notification);
+    StructTypeDefaultConstructor(&notification, base_class_name).Declare(&o, true);
+    StructTypeMandatoryConstructor mandatory_constructor(preferences_,
+                                                         &notification,
+                                                         base_class_name);
     if (mandatory_constructor.has_mandatory_parameters()) {
       mandatory_constructor.Declare(&o, true);
     }
     CppStructDestructor(notification.name()).Declare(&o, true);
     if (preferences_->generate_json) {
-      StructTypeFromJsonConstructor(&notification).Declare(&o , true);
+      StructTypeFromJsonConstructor(&notification, base_class_name).Declare(&o , true);
       StructTypeToJsonMethod(&notification).Declare(&o , true);
     }
     if (preferences_->generate_dbus) {
-      StructTypeFromDbusReaderConstructor(preferences_,
-                                          &notification, false).Declare(&o , true);
+      StructTypeFromDbusReaderConstructor(preferences_, &notification, false,
+                                          base_class_name).Declare(&o , true);
       StructTypeToDbusWriterMethod(&notification, false).Declare(&o , true);
       StructTypeDbusMessageSignatureMethod(preferences_,
                                            &notification, false).Declare(&o, true);
     }
     StructTypeIsValidMethod(&notification).Declare(&o, true);
     StructTypeIsInitializedMethod(&notification).Declare(&o, true);
+    StructTypeStructEmptyMethod(&notification).Declare(&o, true);
+    StructTypeReportErrosMethod(&notification).Declare(&o, true);
     MessageHandleWithMethod(notification.name()).Declare(&o, true);
     FunctionIdMethod(&notification).Define(&o, true);
     FunctionStringIdMethod(&notification).Define(&o, true);
index e822be4..e2ad0de 100644 (file)
@@ -44,6 +44,8 @@
 #include "cppgen/struct_type_from_json_method.h"
 #include "cppgen/struct_type_is_initialized_method.h"
 #include "cppgen/struct_type_is_valid_method.h"
+#include "cppgen/struct_type_report_erros_method.h"
+#include "cppgen/type_name_code_generator.h"
 #include "model/composite_type.h"
 #include "utils/safeformat.h"
 
@@ -75,25 +77,37 @@ void DefinitionGenerator::GenerateCodeForStruct(const Struct* strct) {
   CppFile& source_file = module_manager_->SourceForStruct(*strct);
   ostream& o = source_file.types_ns().os();
   o << Comment(format("{0} methods", strct->name())) << endl;
-  StructTypeDefaultConstructor(strct).Define(&o, false);
-  StructTypeMandatoryConstructor mandatory_constructor(preferences_, strct);
+  std::string base_class_name = "CompositeType";
+  if (strct->frankenstruct()) {
+    base_class_name = RpcTypeNameGenerator(
+                        &strct->interface(),
+                        preferences_,
+                        strct->frankenstruct(),
+                        false).result();
+  }
+  StructTypeDefaultConstructor(strct, base_class_name).Define(&o, false);
+  StructTypeMandatoryConstructor mandatory_constructor(preferences_,
+                                                       strct,
+                                                       base_class_name);
   if (mandatory_constructor.has_mandatory_parameters()){
     mandatory_constructor.Define(&o, false);
   }
   CppStructDestructor(strct->name()).Define(&o, false);
   if (preferences_->generate_json) {
-    StructTypeFromJsonConstructor(strct).Define(&o , false);
+    StructTypeFromJsonConstructor(strct, base_class_name).Define(&o , false);
     StructTypeToJsonMethod(strct).Define(&o , false);
   }
   if (preferences_->generate_dbus) {
-    StructTypeFromDbusReaderConstructor(preferences_,
-                                        strct, true).Define(&o , false);
+    StructTypeFromDbusReaderConstructor(preferences_, strct, true,
+                                        base_class_name).Define(&o , false);
     StructTypeToDbusWriterMethod(strct, true).Define(&o , false);
     StructTypeDbusMessageSignatureMethod(preferences_,
                                          strct, true).Define(&o, false);
   }
   StructTypeIsValidMethod(strct).Define(&o, false);
   StructTypeIsInitializedMethod(strct).Define(&o, false);
+  StructTypeStructEmptyMethod(strct).Define(&o, false);
+  StructTypeReportErrosMethod(strct).Define(&o, false);
   o << endl;
 
   Namespace& val_ns = module_manager_->SourceForValidator().types_ns();
@@ -110,19 +124,22 @@ void DefinitionGenerator::GenerateCodeForResponse(const Response& response) {
   CppFile& source_file = module_manager_->SourceForResponse(response);
   ostream& o = source_file.responses_ns().os();
   o << Comment(format("{0} response methods", response.name())) << endl;
-  StructTypeDefaultConstructor(&response).Define(&o, false);
-  StructTypeMandatoryConstructor mandatory_constructor(preferences_, &response);
+  const char* base_class_name = "Response";
+  StructTypeDefaultConstructor(&response, base_class_name).Define(&o, false);
+  StructTypeMandatoryConstructor mandatory_constructor(preferences_,
+                                                       &response,
+                                                       base_class_name);
   if (mandatory_constructor.has_mandatory_parameters()){
     mandatory_constructor.Define(&o, false);
   }
   CppStructDestructor(response.name()).Define(&o, false);
   if (preferences_->generate_json) {
-    StructTypeFromJsonConstructor(&response).Define(&o , false);
+    StructTypeFromJsonConstructor(&response, base_class_name).Define(&o , false);
     StructTypeToJsonMethod(&response).Define(&o , false);
   }
   if (preferences_->generate_dbus) {
-    StructTypeFromDbusReaderConstructor(preferences_,
-                                        &response, false).Define(&o , false);
+    StructTypeFromDbusReaderConstructor(preferences_, &response, false,
+                                        base_class_name).Define(&o , false);
     StructTypeToDbusWriterMethod(&response, false).Define(&o , false);
     StructTypeDbusMessageSignatureMethod(preferences_,
                                          &response, false).Define(&o, false);
@@ -130,6 +147,8 @@ void DefinitionGenerator::GenerateCodeForResponse(const Response& response) {
   MessageHandleWithMethod(response.name()).Define(&o, false);
   StructTypeIsValidMethod(&response).Define(&o, false);
   StructTypeIsInitializedMethod(&response).Define(&o, false);
+  StructTypeStructEmptyMethod(&response).Define(&o, false);
+  StructTypeReportErrosMethod(&response).Define(&o, false);
   o << endl;
 
   Namespace& val_ns = module_manager_->SourceForValidator().responses_ns();
@@ -141,19 +160,22 @@ void DefinitionGenerator::GenerateCodeForNotification(
   CppFile& source_file = module_manager_->SourceForNotification(notification);
   ostream& o = source_file.notifications_ns().os();
   o << Comment(format("{0} notification methods", notification.name())) << endl;
-  StructTypeDefaultConstructor(&notification).Define(&o, false);
-  StructTypeMandatoryConstructor mandatory_constructor(preferences_, &notification);
+  const char* base_class_name = "Notification";
+  StructTypeDefaultConstructor(&notification, base_class_name).Define(&o, false);
+  StructTypeMandatoryConstructor mandatory_constructor(preferences_,
+                                                       &notification,
+                                                       base_class_name);
   if (mandatory_constructor.has_mandatory_parameters()){
     mandatory_constructor.Define(&o, false);
   }
   CppStructDestructor(notification.name()).Define(&o, false);
   if (preferences_->generate_json) {
-    StructTypeFromJsonConstructor(&notification).Define(&o , false);
+    StructTypeFromJsonConstructor(&notification, base_class_name).Define(&o , false);
     StructTypeToJsonMethod(&notification).Define(&o , false);
   }
   if (preferences_->generate_dbus) {
-    StructTypeFromDbusReaderConstructor(preferences_,
-                                        &notification, false).Define(&o, false);
+    StructTypeFromDbusReaderConstructor(preferences_, &notification, false,
+                                        base_class_name).Define(&o, false);
     StructTypeToDbusWriterMethod(&notification, false).Define(&o , false);
     StructTypeDbusMessageSignatureMethod(preferences_,
                                          &notification, false).Define(&o, false);
@@ -161,6 +183,8 @@ void DefinitionGenerator::GenerateCodeForNotification(
   MessageHandleWithMethod(notification.name()).Define(&o, false);
   StructTypeIsValidMethod(&notification).Define(&o, false);
   StructTypeIsInitializedMethod(&notification).Define(&o, false);
+  StructTypeStructEmptyMethod(&notification).Define(&o, false);
+  StructTypeReportErrosMethod(&notification).Define(&o, false);
   o << endl;
 
   Namespace& val_ns = module_manager_->SourceForValidator().notifications_ns();
@@ -172,25 +196,30 @@ void DefinitionGenerator::GenerateCodeForRequest(const Request& request,
                                                  CppFile* source_file) {
   ostream& o = source_file->requests_ns().os();
   o << Comment(format("{0} request methods", request.name())) << endl;
-  StructTypeDefaultConstructor(&request).Define(&o, false);
-  StructTypeMandatoryConstructor mandatory_constructor(preferences_, &request);
+  const char* base_class_name = "Request";
+  StructTypeDefaultConstructor(&request, base_class_name).Define(&o, false);
+  StructTypeMandatoryConstructor mandatory_constructor(preferences_,
+                                                       &request,
+                                                       base_class_name);
   if (mandatory_constructor.has_mandatory_parameters()){
     mandatory_constructor.Define(&o, false);
   }
   CppStructDestructor(request.name()).Define(&o, false);
   if (preferences_->generate_json) {
-    StructTypeFromJsonConstructor(&request).Define(&o , false);
+    StructTypeFromJsonConstructor(&request, base_class_name).Define(&o , false);
     StructTypeToJsonMethod(&request).Define(&o , false);
   }
   if (preferences_->generate_dbus) {
-    StructTypeFromDbusReaderConstructor(preferences_,
-                                        &request, false).Define(&o , false);
+    StructTypeFromDbusReaderConstructor(preferences_, &request, false,
+                                        base_class_name).Define(&o , false);
     StructTypeToDbusWriterMethod(&request, false).Define(&o , false);
     StructTypeDbusMessageSignatureMethod(preferences_,
                                          &request, false).Define(&o, false);
   }
   StructTypeIsValidMethod(&request).Define(&o, false);
   StructTypeIsInitializedMethod(&request).Define(&o, false);
+  StructTypeStructEmptyMethod(&request).Define(&o, false);
+  StructTypeReportErrosMethod(&request).Define(&o, false);
   MessageHandleWithMethod(request.name()).Define(&o, false);
   o << endl;
 
index 96705cb..cd68380 100644 (file)
@@ -54,13 +54,20 @@ void InterfaceStringIdMethod::DefineBody(std::ostream* os) const {
 MessageInterface::MessageInterface(const Interface* interface,
                                    FunctionMessage::MessageType message_type)
   : CppClass(Capitalize(FunctionMessage::MessageTypeToString(message_type))),
+    constructor_(this, CppClass::kPublic, name(), "", Method::kExplicit),
     handle_with_method_(this, kPublic,
                         "HandleWith", "void",
                         Method::kVirtual|Method::kAbstract),
     interface_string_id_method_(this, interface){
-  Add(Superclass("rpc::" + name() + "Base", kPublic));
+  std::string superclass_name = "rpc::" + name() + "Base";
+  Add(Superclass(superclass_name, kPublic));
+  constructor_.Add(Method::Parameter("init_state", "InitializationState"));
+  constructor_.Add(Method::Initializer(superclass_name, "init_state"));
+
   handle_with_method_.Add(Method::Parameter(
                             "handler", "Handler*"));
+
+  methods_.push_back(&constructor_);
   methods_.push_back(&handle_with_method_);
   methods_.push_back(&interface_string_id_method_);
 }
index 757cf7d..668577e 100644 (file)
@@ -35,6 +35,7 @@
 #include <algorithm>
 #include <cctype>
 #include <memory>
+#include <set>
 
 #include "model/interface.h"
 #include "utils/string_utils.h"
@@ -221,5 +222,77 @@ std::string Capitalize(const std::string& str) {
   return res;
 }
 
+std::string AvoidKeywords(const std::string& name) {
+  static const char* keywords_init[] = {
+    "asm",
+    "bool",
+    "catch",
+    "class",
+    "const_cast",
+    "default",
+    "delete",
+    "dynamic_cast",
+    "explicit",
+    "false",
+    "final",
+    "friend",
+    "inline",
+    "mutable",
+    "namespace",
+    "new",
+    "operator",
+    "override",
+    "private",
+    "protected",
+    "public",
+    "reinterpret_cast",
+    "static_cast",
+    "template",
+    "this",
+    "throw",
+    "true",
+    "try",
+    "typeid",
+    "typename",
+    "using",
+    "virtual",
+    // std map functions to avoid collisions in frankenstruct
+    "at",
+    "begin",
+    "cbegin",
+    "cend",
+    "clear",
+    "count",
+    "crbegin",
+    "crend",
+    "emplace",
+    "emplace_hint",
+    "empty",
+    "end",
+    "equal_range",
+    "erase",
+    "find",
+    "get_allocator",
+    "insert",
+    "key_comp",
+    "lower_bound",
+    "max_size",
+    "rbegin",
+    "rend",
+    "size",
+    "swap",
+    "upper_bound",
+    "value_comp",
+  };
+  static const std::set<std::string> keywords(
+      keywords_init,
+      keywords_init + sizeof(keywords_init) / sizeof(keywords_init[0]));
+  if (keywords.count(name) != 0) {
+    return name + "_";
+  } else {
+    return name;
+  }
+}
+
 }  // namespace codegen
 
index aeabc83..33256c7 100644 (file)
@@ -35,6 +35,7 @@
 #include <string>
 
 #include "cppgen/literal_generator.h"
+#include "cppgen/naming_convention.h"
 #include "cppgen/type_name_code_generator.h"
 #include "model/composite_type.h"
 #include "model/constant.h"
@@ -43,8 +44,13 @@ using std::string;
 
 namespace codegen {
 
-StructTypeDefaultConstructor::StructTypeDefaultConstructor(const Struct* strct)
+StructTypeDefaultConstructor::StructTypeDefaultConstructor(
+    const Struct* strct,
+    const std::string& base_class_name)
     : CppStructConstructor(strct->name()) {
+  if (!strct->frankenstruct()) {
+    Add(Initializer(base_class_name, "kUninitialized"));
+  }
 }
 
 StructTypeDefaultConstructor::~StructTypeDefaultConstructor() {
@@ -52,19 +58,26 @@ StructTypeDefaultConstructor::~StructTypeDefaultConstructor() {
 
 StructTypeMandatoryConstructor::StructTypeMandatoryConstructor(
     const TypePreferences* preferences,
-    const Struct* strct)
+    const Struct* strct,
+    const std::string& base_class_name)
     : CppStructConstructor(strct->name()) {
+  // Pass kUnitialized to CompositeType constructor
+  // there is no actual difference which value to pick
+  if (!strct->frankenstruct()) {
+    Add(Initializer(base_class_name, "kUninitialized"));
+  }
   const Struct::FieldsList& fields = strct->fields();
   for (Struct::FieldsList::const_iterator i = fields.begin(), end =
       fields.end(); i != end; ++i) {
     const Struct::Field& field = *i;
     if (field.default_value() || field.is_mandatory()) {
-      Add(Parameter(field.name(),
+      Add(Parameter(AvoidKeywords(field.name()),
                     TypeNameGenerator(
                       &strct->interface(),
                       preferences,
                       field.type()).result()));
-      Add(Initializer(field.name(), field.name()));
+      Add(Initializer(AvoidKeywords(field.name()),
+                      AvoidKeywords(field.name())));
     }
   }
 }
index 58c11be..5040652 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "cppgen/struct_type_dbus_serializer.h"
 
+#include "cppgen/naming_convention.h"
 #include "cppgen/type_name_code_generator.h"
 #include "model/composite_type.h"
 #include "utils/safeformat.h"
@@ -61,13 +62,19 @@ void StructTypeDbusMessageSignatureMethod::DefineBody(std::ostream* os) const {
     }
     for (Struct::FieldsList::const_iterator i = fields.begin(),
          end = fields.end(); i != end; ++i) {
-      RpcTypeNameGenerator::Availability availability =
-          i->default_value() || i->is_mandatory() ?
-              RpcTypeNameGenerator::kMandatory : RpcTypeNameGenerator::kOptional;
+      // Field is considered optional if it has mandatory=false attribute and
+      // if it does NOT have default values. Fields that have default values are
+      // always available no mater if they present in input or not
+      bool field_is_optional = false;
+      if (!i->is_mandatory()) {
+        if (i->default_value() == NULL) {
+          field_is_optional = true;
+        }
+      }
       std::string field_type = RpcTypeNameGenerator(&strct_->interface(),
                                                     preferences_,
                                                     i->type(),
-                                                    availability).result();
+                                                    field_is_optional).result();
       strmfmt(*os, "rpc::DbusSignature< {0} >({1});\n",
               field_type, parameters_[0].name);
 
@@ -81,19 +88,26 @@ void StructTypeDbusMessageSignatureMethod::DefineBody(std::ostream* os) const {
 StructTypeFromDbusReaderConstructor::StructTypeFromDbusReaderConstructor(
     const TypePreferences* preferences,
     const Struct* strct,
-    bool substructure)
+    bool substructure,
+    const std::string& base_class_name)
     : CppStructConstructor(strct->name()),
       preferences_(preferences),
       strct_(strct),
       substructure_(substructure) {
   Add(Parameter("reader__", "dbus::MessageReader*"));
+  std::string base_initializer = "reader__";
+  if (!strct->frankenstruct()) {
+    base_initializer = "InitHelper(true)";
+  }
+  Add(Initializer(base_class_name, base_initializer));
   // In case of non-substructure use initializer list to initialize fields
   // From MessageReader passed in
   if (!substructure_) {
     const Struct::FieldsList& fields = strct->fields();
     for (Struct::FieldsList::const_iterator i = fields.begin(), end = fields.end();
          i != end; ++i) {
-      Add(Initializer(i->name(), "reader__"));
+      Add(Initializer(AvoidKeywords(i->name()),
+                      "reader__"));
     }
   }
 }
@@ -110,13 +124,19 @@ void StructTypeFromDbusReaderConstructor::DefineBody(std::ostream* os) const {
     *os << "dbus::MessageReader subreader__ = reader__->TakeStructReader();\n";
     for (Struct::FieldsList::const_iterator i = fields.begin(), end = fields.end();
          i != end; ++i) {
-      RpcTypeNameGenerator::Availability availability =
-          i->default_value() || i->is_mandatory() ?
-              RpcTypeNameGenerator::kMandatory : RpcTypeNameGenerator::kOptional;
+      // Field is considered optional if it has mandatory=false attribute and
+      // if it does NOT have default values. Fields that have default values are
+      // always available no mater if they present in input or not
+      bool field_is_optional = false;
+      if (!i->is_mandatory()) {
+        if (i->default_value() == NULL) {
+          field_is_optional = true;
+        }
+      }
       std::string field_type = RpcTypeNameGenerator(&strct_->interface(),
                                                     preferences_,
                                                     i->type(),
-                                                    availability).result();
+                                                    field_is_optional).result();
       strmfmt(*os, "{0} = {1}(&subreader__);\n", i->name(), field_type);
     }
   }
index bf76804..1cdb354 100644 (file)
@@ -34,6 +34,7 @@
 
 
 #include "cppgen/literal_generator.h"
+#include "cppgen/naming_convention.h"
 #include "model/composite_type.h"
 #include "utils/safeformat.h"
 
@@ -42,28 +43,47 @@ using typesafe_format::format;
 
 namespace codegen {
 
-StructTypeFromJsonConstructor::StructTypeFromJsonConstructor(const Struct* strct)
+StructTypeFromJsonConstructor::StructTypeFromJsonConstructor(
+    const Struct* strct,
+    const std::string& base_class_name)
     : CppStructConstructor(strct->name()),
       strct_(strct) {
-  Add(Parameter("value", "const Json::Value*"));
+  Add(Parameter("value__", "const Json::Value*"));
+  std::string base_initializer = parameters_[0].name;
+  if (!strct->frankenstruct()) {
+    base_initializer =
+      format("InitHelper({0}, &Json::Value::isObject)", parameters_[0].name);
+  }
+  Add(Initializer(base_class_name, base_initializer));
   const Struct::FieldsList& fields = strct_->fields();
   for (Struct::FieldsList::const_iterator i = fields.begin(), end =
       fields.end(); i != end; ++i) {
     std::string initializer =
-        format("CompositeType::ValueMember({0}, \"{1}\")",
+        format("impl::ValueMember({0}, \"{1}\")",
                parameters_[0].name,
                i->name());
     if (i->default_value()) {
       std::string def_value = LiteralGenerator(*i->default_value()).result();
       initializer += (", " + def_value);
     }
-    Add(Initializer(i->name(), initializer));
+    Add(Initializer(AvoidKeywords(i->name()), initializer));
   }
 }
 
 StructTypeFromJsonConstructor::~StructTypeFromJsonConstructor() {
 }
 
+void StructTypeFromJsonConstructor::DefineBody(std::ostream* os) const {
+  if (strct_->frankenstruct()) {
+    for (Struct::FieldsList::const_iterator i = strct_->fields().begin(),
+         end = strct_->fields().end(); i != end; ++i) {
+      const Struct::Field& field = *i;
+      strmfmt(*os, "erase(\"{0}\");\n",
+              field.name());
+    }
+  }
+}
+
 StructTypeToJsonMethod::StructTypeToJsonMethod(const Struct* strct)
     : CppFunction(strct->name(), "ToJsonValue", "Json::Value", kConst),
       strct_(strct) {
@@ -73,14 +93,18 @@ StructTypeToJsonMethod::~StructTypeToJsonMethod() {
 }
 
 void StructTypeToJsonMethod::DefineBody(std::ostream* os) const {
-  *os << "Json::Value result__(Json::objectValue);" << '\n';
+  if (strct_->frankenstruct()) {
+    strmfmt(*os, "Json::Value result__(Frankenbase::{0}());\n",
+            name_);
+  } else {
+    *os << "Json::Value result__(Json::objectValue);" << '\n';
+  }
   const Struct::FieldsList& fields = strct_->fields();
   for (Struct::FieldsList::const_iterator i = fields.begin(), end =
       fields.end(); i != end; ++i) {
     const Struct::Field& field = *i;
-    strmfmt(*os, "CompositeType::WriteJsonField(\"{0}\", {0}, &result__);",
-            field.name())
-        << '\n';
+    strmfmt(*os, "impl::WriteJsonField(\"{0}\", {1}, &result__);\n",
+            field.name(), AvoidKeywords(field.name()));
   }
   *os << "return result__;" << '\n';
 }
index effae08..d51aa7b 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <ostream>
 
+#include "cppgen/naming_convention.h"
 #include "model/composite_type.h"
 #include "utils/safeformat.h"
 
@@ -52,15 +53,32 @@ StructTypeIsInitializedMethod::~StructTypeIsInitializedMethod() {
 }
 
 void StructTypeIsInitializedMethod::DefineBody(std::ostream* os) const {
+  if (strct_->frankenstruct()) {
+    strmfmt(*os, "if (Frankenbase::{0}()) return true;\n",
+            name_);
+  }
+  *os << "return (initialization_state__ != kUninitialized) || (!struct_empty());\n";
+}
+
+StructTypeStructEmptyMethod::StructTypeStructEmptyMethod(const Struct* strct)
+    : CppFunction(strct->name(), "struct_empty", "bool", kConst),
+      strct_(strct) {
+}
+
+StructTypeStructEmptyMethod::~StructTypeStructEmptyMethod() {
+}
+
+void StructTypeStructEmptyMethod::DefineBody(std::ostream* os) const {
   const Struct::FieldsList& fields = strct_->fields();
   for (size_t i = 0; i != fields.size(); ++i) {
     const Struct::Field& field = fields[i];
-    strmfmt(*os, "if ({0}.is_initialized()) return true;\n", field.name());
+    strmfmt(*os, "if ({0}.is_initialized()) return false;\n",
+            AvoidKeywords(field.name()));
     if ((i % 2) == 1) {
       *os << endl;
     }
   }
-  *os << "return false;\n";
+  *os << "return true;\n";
 }
 
 }  // namespace codegen
index 3a9874e..001f9a0 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <ostream>
 
+#include "cppgen/naming_convention.h"
 #include "cppgen/generator_preferences.h"
 #include "model/composite_type.h"
 #include "utils/safeformat.h"
@@ -52,10 +53,23 @@ StructTypeIsValidMethod::~StructTypeIsValidMethod() {
 }
 
 void StructTypeIsValidMethod::DefineBody(std::ostream* os) const {
+  if (strct_->frankenstruct()) {
+    strmfmt(*os, "if (!Frankenbase::{0}()) return false;\n",
+            name_);
+  }
   const Struct::FieldsList& fields = strct_->fields();
+  bool struct_can_be_valid_empty = true;
+  for (size_t i = 0; i != fields.size(); ++i) {
+    if (fields[i].is_mandatory()) {
+      struct_can_be_valid_empty = false;
+    }
+  }
+  if (struct_can_be_valid_empty) {
+    *os << "if (struct_empty()) return initialization_state__ == kInitialized;\n";
+  }
   for (size_t i = 0; i != fields.size(); ++i) {
-    const Struct::Field& field = fields[i];
-    strmfmt(*os, "if (!{0}.is_valid()) return false;\n", field.name());
+    strmfmt(*os, "if (!{0}.is_valid()) return false;\n",
+            AvoidKeywords(fields[i].name()));
   }
   *os << "return "<< func_names::kAdditionalValidation << "();\n";
 }
diff --git a/tools/intergen/cppgen/src/cppgen/struct_type_report_erros_method.cc b/tools/intergen/cppgen/src/cppgen/struct_type_report_erros_method.cc
new file mode 100644 (file)
index 0000000..5b509e9
--- /dev/null
@@ -0,0 +1,76 @@
+/* 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.
+ */
+
+#include "cppgen/struct_type_report_erros_method.h"
+
+#include "cppgen/naming_convention.h"
+#include "model/composite_type.h"
+#include "utils/safeformat.h"
+#include "utils/string_utils.h"
+
+using typesafe_format::strmfmt;
+
+namespace codegen {
+
+StructTypeReportErrosMethod::StructTypeReportErrosMethod(const Struct* strct)
+  : CppFunction(strct->name(), "ReportErrors", "void", kConst),
+    strct_(strct) {
+  Add(Parameter("report__", "rpc::ValidationReport*"));
+}
+
+void StructTypeReportErrosMethod::DefineBody(std::ostream* os) const {
+  if (strct_->frankenstruct()) {
+    strmfmt(*os, "Frankenbase::{0}({1});\n",
+            name_, parameters_[0].name);
+  } else {
+    *os << "if (struct_empty()) {\n";
+    {
+      Indent ind(*os);
+      strmfmt(*os, "rpc::CompositeType::ReportErrors({0});\n", parameters_[0].name);
+    }
+    *os << "}\n";
+  }
+  const Struct::FieldsList& fields = strct_->fields();
+  for (size_t i = 0; i != fields.size(); ++i) {
+    const Struct::Field& field = fields[i];
+    strmfmt(*os, "if (!{0}.is_valid()) {\n", AvoidKeywords(field.name()));
+    {
+      Indent ind(*os);
+      strmfmt(*os, "{0}.ReportErrors(&{2}->ReportSubobject(\"{1}\"));\n",
+              AvoidKeywords(field.name()),
+              field.name(),
+              parameters_[0].name);
+    }
+    *os << "}\n";
+  }
+}
+
+} // namespace cppgen
index a8aac2c..08eedbc 100644 (file)
@@ -179,22 +179,14 @@ void TypeNameGenerator::GenerateCodeForTypedef(const Typedef* tdef) {
 RpcTypeNameGenerator::RpcTypeNameGenerator(const Interface* interface,
                                            const TypePreferences* preferences,
                                            const Type* type,
-                                           Availability availability)
+                                           bool optional)
     : interface_(interface),
       preferences_(preferences) {
-  bool wrap_with_availability = availability != kUnspecified;
-  // Arrays, map and typedefs of arrays and maps doesn't need to be marked as
-  // optional or mandatory because their minimal size indicates whether
-  // container contents is optional
-  if (TypeProperties(type).is_container()) {
-    wrap_with_availability = false;
-  }
-
-  if (wrap_with_availability && (availability == kOptional)) {
+  if (optional) {
     os_ << "Optional< ";
   }
   type->Apply(this);
-  if (wrap_with_availability && (availability == kOptional)) {
+  if (optional) {
     os_ << " >";
   }
 }
@@ -239,13 +231,17 @@ void RpcTypeNameGenerator::GenerateCodeForEnum(const Enum* enm) {
 void RpcTypeNameGenerator::GenerateCodeForArray(const Array* array) {
   os_ << "Array< ";
   array->type()->Apply(this);
-  strmfmt(os_, ", {0}, {1} >", array->range().min(), array->range().max());
+  strmfmt(os_, ", {0}, {1} >",
+          array->range().min(),
+          array->range().max());
 }
 
 void RpcTypeNameGenerator::GenerateCodeForMap(const Map* map) {
   os_ << "Map< ";
   map->type()->Apply(this);
-  strmfmt(os_, ", {0}, {1} >", map->range().min(), map->range().max());
+  strmfmt(os_, ", {0}, {1} >",
+          map->range().min(),
+          map->range().max());
 }
 
 void RpcTypeNameGenerator::GenerateCodeForNullable(
index 5ec76e4..ae60a53 100644 (file)
@@ -155,10 +155,14 @@ class Struct : public Type {
  public:
   // Methods
   Struct(const Interface* interface,
-         const std::string& name, Scope scope,
+         const std::string& name,
+         const Type* frankenmap,
+         Scope scope,
          const Description& description);
   ~Struct();
   const Interface& interface() const;
+  // Returns frankenstruct type if this struct is frankenstruct
+  const Type* frankenstruct() const;
   const std::string& name() const;
   const Description& description() const;
   const FieldsList& fields() const;
@@ -174,6 +178,7 @@ class Struct : public Type {
   // Fields
   const Interface* interface_;
   std::string name_;
+  const Type* frankenmap_;
   Scope scope_;
   Description description_;
   FieldsList fields_;
index f499560..57e89cc 100644 (file)
@@ -228,10 +228,12 @@ bool Enum::AddConstant(const std::string& name, const int64_t value,
  */
 Struct::Struct(const Interface* interface,
                const std::string& name,
+               const Type* frankenmap,
                Scope scope,
                const Description& description)
     : interface_(interface),
       name_(name),
+      frankenmap_(frankenmap),
       scope_(scope),
       description_(description) {
   assert(interface_);
@@ -285,6 +287,10 @@ const Interface& Struct::interface() const {
   return *interface_;
 }
 
+const Type* Struct::frankenstruct() const {
+  return frankenmap_;
+}
+
 const std::string& Struct::name() const {
   return name_;
 }
index 1826b10..9c9765e 100644 (file)
@@ -77,7 +77,7 @@ FunctionMessage::FunctionMessage(const Interface* interface,
                                  const Enum::Constant* id,
                                  MessageType message_type,
                                  const Description& description, Scope scope)
-    : Struct(interface, name, scope, description),
+    : Struct(interface, name, NULL, scope, description), // Functions can not be frankenmaps
       interface_(interface),
       id_(id),
       message_type_(message_type) {
index 94a75b4..fa173eb 100644 (file)
@@ -124,11 +124,7 @@ const TypeRegistry::TypedefList& TypeRegistry::typedefs() const {
 
 // static
 bool TypeRegistry::IsMandatoryParam(const pugi::xml_node& param) {
-  bool mandatory = param.attribute("mandatory").as_bool("true");
-  if (param.attribute("array").as_bool(false)) {
-    mandatory = param.attribute("minsize").as_int(0) > 0;
-  }
-  return mandatory;
+  return param.attribute("mandatory").as_bool("true");
 }
 
 bool TypeRegistry::AddEnums(const pugi::xml_node& xml) {
@@ -190,12 +186,23 @@ bool TypeRegistry::AddStruct(const pugi::xml_node& xml_struct) {
     return true;
   }
   std::string name = xml_struct.attribute("name").value();
+  const Type* frankenmap = NULL;
+  if (!xml_struct.attribute("type").empty()) {
+    if (!GetContainer(xml_struct,
+                      &frankenmap,
+                      false,
+                      false)) {
+      std::cerr << "Invalid frankenstruct: " << name << std::endl;
+      return false;
+    }
+  }
   Description description = CollectDescription(xml_struct);
   if (IsRegisteredStruct(name)) {
     std::cerr << "Duplicate structure: " << name << std::endl;
     return false;
   }
-  structs_.push_back(new Struct(interface_, name, scope, description));
+  structs_.push_back(new Struct(interface_, name, frankenmap,
+                                scope, description));
   struct_by_name_[name] = structs_.back();
   if (!AddStructureFields(structs_.back(), xml_struct)) {
     return false;
@@ -250,7 +257,7 @@ bool TypeRegistry::GetContainer(const pugi::xml_node& params, const Type** type,
         return true;
       }
     } else {
-      std::cerr << "Incorrect array size range: " << minsize_str << ", "
+      std::cerr << "Incorrect container size range: " << minsize_str << ", "
                 << maxsize_str << std::endl;
     }
   }