THRIFT-5837 Delphi implementation for THRIFT-5835
Client: Delphi
Patch: Jens Geyer

This closes #3068
diff --git a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
index 6703832..ca371f7 100644
--- a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
@@ -118,8 +118,7 @@
   void generate_delphi_property(ostream& out,
                                 bool struct_is_exception,
                                 t_field* tfield,
-                                bool isPublic,
-                                std::string fieldPrefix = "");
+                                bool isPublic);
   void generate_delphi_isset_reader_writer_definition(ostream& out, t_field* tfield, bool is_xception);
   void generate_delphi_property_reader_definition(ostream& out,
                                                   t_field* tfield,
@@ -141,9 +140,7 @@
                                             t_field* tfield,
                                             std::string fieldPrefix,
                                             bool is_xception_class,
-                                            bool is_union,
-                                            bool is_xception_factory,
-                                            std::string xception_factory_name);
+                                            bool is_union);
   void generate_delphi_clear_union_value(ostream& out,
                                          std::string cls_prefix,
                                          std::string name,
@@ -151,40 +148,30 @@
                                          t_field* tfield,
                                          std::string fieldPrefix,
                                          bool is_xception_class,
-                                         bool is_union,
-                                         bool is_xception_factory,
-                                         std::string xception_factory_name);
+                                         bool is_union);
   void generate_delphi_isset_reader_writer_impl(ostream& out,
-                                         std::string cls_prefix,
-                                         std::string name,
-                                         t_type* type,
-                                         t_field* tfield,
-                                         std::string fieldPrefix,
-                                         bool is_xception);
+                                                std::string cls_prefix,
+                                                std::string name,
+                                                t_type* type,
+                                                t_field* tfield,
+                                                std::string fieldPrefix,
+                                                bool is_xception_class);
   void generate_delphi_struct_writer_impl(ostream& out,
                                           std::string cls_prefix,
                                           t_struct* tstruct,
-                                          bool is_exception,
-                                          bool is_x_factory);
-  void generate_delphi_struct_result_writer_impl(ostream& out,
-                                                 std::string cls_prefix,
-                                                 t_struct* tstruct,
-                                                 bool is_exception,
-                                                 bool is_x_factory);
+                                          bool is_exception);
 
   void generate_delphi_struct_tostring_impl(ostream& out,
                                             std::string cls_prefix,
                                             t_struct* tstruct,
-                                            bool is_exception,
-                                            bool is_x_factory);
+                                            bool is_exception);
 
   void add_delphi_uses_list(string unitname);
 
   void generate_delphi_struct_reader_impl(ostream& out,
                                           std::string cls_prefix,
                                           t_struct* tstruct,
-                                          bool is_exception,
-                                          bool is_x_factory);
+                                          bool is_exception);
   void generate_delphi_create_exception_impl(ostream& out,
                                              string cls_prefix,
                                              t_struct* tstruct,
@@ -200,12 +187,14 @@
                          std::ostream& out,
                          std::string name,
                          t_type* type,
-                         t_const_value* value);
+                         t_const_value* value,
+                         bool is_const_class);
   void initialize_field(std::ostream& vars,
                         std::ostream& out,
                         std::string name,
                         t_type* type,
-                        t_const_value* value);
+                        t_const_value* value,
+                        bool is_const_class);
   void finalize_field(std::ostream& out,
                       std::string name,
                       t_type* type,
@@ -213,7 +202,6 @@
                       std::string cls_nm = "");
   std::string render_const_value(std::ostream& local_vars,
                                  std::ostream& out,
-                                 std::string name,
                                  t_type* type,
                                  t_const_value* value,
                                  bool guidAsLiteral);
@@ -225,32 +213,27 @@
                              std::string cls_nm = "");
   std::string make_constants_classname();
 
-  void generate_delphi_struct(t_struct* tstruct, bool is_exception);
+  void generate_delphi_struct(t_struct* tstruct);
+  void generate_delphi_exception(t_struct* tstruct);
   void generate_delphi_struct_impl(ostream& out,
                                    std::string cls_prefix,
                                    t_struct* tstruct,
-                                   bool is_exception,
-                                   bool is_result = false,
-                                   bool is_x_factory = false);
+                                   bool is_result, 
+                                   bool is_const_class);
+  void generate_delphi_exception_impl(ostream& out,
+                                      std::string cls_prefix,
+                                      t_struct* tstruct);
   void print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct);
   void generate_delphi_struct_type_factory(ostream& out,
                                            std::string cls_prefix,
-                                           t_struct* tstruct,
-                                           bool is_exception,
-                                           bool is_result = false,
-                                           bool is_x_factory = false);
+                                           t_struct* tstruct);
   void generate_delphi_struct_type_factory_registration(ostream& out,
                                                         std::string cls_prefix,
-                                                        t_struct* tstruct,
-                                                        bool is_exception,
-                                                        bool is_result = false,
-                                                        bool is_x_factory = false);
+                                                        t_struct* tstruct);
   void generate_delphi_struct_definition(std::ostream& out,
-                                         t_struct* tstruct,
-                                         bool is_xception = false,
-                                         bool in_class = false,
-                                         bool is_result = false,
-                                         bool is_x_factory = false);
+                                         t_struct* tstruct);
+  void generate_delphi_exception_definition(std::ostream& out,
+                                            t_struct* tstruct);
 
   void generate_function_helpers(t_function* tfunction);
   void generate_service_interface(t_service* tservice);
@@ -327,9 +310,7 @@
 
   std::string type_name(t_type* ttype,
                         bool b_cls = false,
-                        bool b_no_postfix = false,
-                        bool b_exception_factory = false,
-                        bool b_full_exception_factory = false);
+                        bool b_no_postfix = false);
   std::string normalize_clsnm(std::string name,
                               std::string prefix,
                               bool b_no_check_keyword = false);
@@ -339,7 +320,6 @@
 
   std::string base_type_name(t_base_type* tbase);
   std::string declare_field(t_field* tfield,
-                            bool init = false,
                             std::string prefix = "",
                             bool is_xception_class = false);
   std::string function_signature(t_function* tfunction,
@@ -369,10 +349,7 @@
   void generate_delphi_docstring_comment(std::ostream& out, string contents);
 
   bool type_can_be_null(t_type* ttype) {
-    while (ttype->is_typedef()) {
-      ttype = ((t_typedef*)ttype)->get_type();
-    }
-
+    ttype = ttype->get_true_type();
     return ttype->is_container() || ttype->is_struct() || ttype->is_xception();
   }
 
@@ -426,10 +403,10 @@
   };
 
   // reserved exception class method names (lowercase!)
-  const std::string DELPHI_RESERVED_METHOD_EXCEPTION[23] = {
+  const std::string DELPHI_RESERVED_METHOD_EXCEPTION[24] = {
     "setinnerexception", "setstackinfo", "getstacktrace", "raisingexception", "createfmt", "createres",
     "createresfmt", "createhelp", "createfmthelp", "createreshelp", "createresfmthelp", "getbaseexception",
-    "baseexception", "helpcontext", "innerexception", "message", "stacktrace", "stackinfo",
+    "baseexception", "helpcontext", "innerexception", "exceptiondata", "message", "stacktrace", "stackinfo",
     "getexceptionstackinfoproc", "getstackinfostringproc", "cleanupstackinfoproc", "raiseouterexception",
     "throwouterexception"
   };
@@ -830,11 +807,11 @@
   has_forward = true;
   pdebug("forward declaration of %s\n", type_name(tstruct).c_str());
 
-  string what = tstruct->is_xception() ? "class" : "interface";
-
   indent_up();
-  indent(s_forward_decr) << type_name(tstruct, tstruct->is_xception(), true) << " = " << what << ";"
-                         << '\n';
+  indent(s_forward_decr) << type_name(tstruct, false, true) << " = interface;" << '\n';
+  if( tstruct->is_xception()) {
+    indent(s_forward_decr) << type_name(tstruct, true, true) << " = class;" << '\n';
+  }
   indent_down();
 
   add_defined_type(tstruct);
@@ -1070,7 +1047,8 @@
                      code,
                      prop_name((*c_iter)->get_name(), false, "F"),
                      (*c_iter)->get_type(),
-                     (*c_iter)->get_value());
+                     (*c_iter)->get_value(),
+                     true);
   }
   indent_down_impl();
 
@@ -1114,7 +1092,8 @@
                        code,
                        constants_class + "." + prop_name((*c_iter)->get_name(), false, "F"),
                        (*c_iter)->get_type(),
-                       (*c_iter)->get_value());
+                       (*c_iter)->get_value(),
+                       true);
     }
   }
   indent_down_impl();
@@ -1175,7 +1154,7 @@
       if (field_type == nullptr) {
         throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
       }
-      string val = render_const_value(vars, out, name, field_type, v_iter->second, false);
+      string val = render_const_value(vars, out, field_type, v_iter->second, false);
       indent_impl(out) << cls_prefix << normalize_name(name) << "."
                        << prop_name(v_iter->first->get_string(), type->is_xception())
                        << " := " << val << ";" << '\n';
@@ -1186,8 +1165,8 @@
     const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
     map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string key = render_const_value(vars, out, name, ktype, v_iter->first, false);
-      string val = render_const_value(vars, out, name, vtype, v_iter->second, false);
+      string key = render_const_value(vars, out, ktype, v_iter->first, false);
+      string val = render_const_value(vars, out, vtype, v_iter->second, false);
       indent_impl(out) << cls_prefix << normalize_name(name) << "[" << key << "]"
                        << " := " << val << ";" << '\n';
     }
@@ -1202,7 +1181,7 @@
     const vector<t_const_value*>& val = value->get_list();
     vector<t_const_value*>::const_iterator v_iter;
     for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
-      string val = render_const_value(vars, out, name, etype, *v_iter, false);
+      string val = render_const_value(vars, out, etype, *v_iter, false);
       indent_impl(out) << cls_prefix << normalize_name(name) << ".Add(" << val << ");" << '\n';
     }
   }
@@ -1217,10 +1196,7 @@
 }
 
 bool t_delphi_generator::const_needs_var(t_type* type) {
-  t_type* truetype = type;
-  while (truetype->is_typedef()) {
-    truetype = ((t_typedef*)truetype)->get_type();
-  }
+  t_type* truetype = type->get_true_type();
 
   if(!truetype->is_base_type()) {
     return true;
@@ -1247,7 +1223,7 @@
                 << '\n';
   } else {
     std::ostringstream vars; // dummy
-    string v2 = render_const_value(vars, out, name, type, value, true);
+    string v2 = render_const_value(vars, out, type, value, true);
     indent(out) << "const " << name << " = " << v2 << ";" << '\n';
   }
 }
@@ -1256,23 +1232,20 @@
                                            std::ostream& out,
                                            string name,
                                            t_type* type,
-                                           t_const_value* value) {
-  t_type* truetype = type;
-  while (truetype->is_typedef()) {
-    truetype = ((t_typedef*)truetype)->get_type();
-  }
+                                           t_const_value* value,
+                                           bool is_const_class) {
+  t_type* truetype = type->get_true_type();
 
   if (truetype->is_base_type()) {
-    if(const_needs_var(type)) {
-      string the_value = render_const_value( vars, out, name, type, value, false);
+    if(const_needs_var(type) || (!is_const_class)) {
+      string the_value = render_const_value( vars, out, type, value, false);
       indent_impl(out) << name << " := " << the_value << ";" << '\n';
     }
   } else if (truetype->is_enum()) {
     indent_impl(out) << name << " := " << type_name(type) << "." << value->get_identifier_name()
                      << ";" << '\n';
   } else {
-    string typname;
-    typname = type_name(truetype, true, false, type->is_xception(), type->is_xception());
+    string typname = type_name(truetype, true, false/*, type->is_xception(), type->is_xception()*/);
     indent_impl(out) << name << " := " << typname << ".Create;" << '\n';
     print_const_def_value(vars, out, name, truetype, value);
   }
@@ -1282,8 +1255,9 @@
                                           std::ostream& out,
                                           string name,
                                           t_type* type,
-                                          t_const_value* value) {
-  print_const_value(vars, out, name, type, value);
+                                          t_const_value* value,
+                                          bool is_const_class) {
+  print_const_value(vars, out, name, type, value, is_const_class);
 }
 
 void t_delphi_generator::finalize_field(std::ostream& out,
@@ -1300,16 +1274,10 @@
 
 string t_delphi_generator::render_const_value(ostream& vars,
                                               ostream& out,
-                                              string name,
                                               t_type* type,
                                               t_const_value* value,
                                               bool guidAsLiteral) {
-  (void)name;
-
-  t_type* truetype = type;
-  while (truetype->is_typedef()) {
-    truetype = ((t_typedef*)truetype)->get_type();
-  }
+  t_type* truetype = type->get_true_type();
 
   std::ostringstream render;
 
@@ -1360,7 +1328,7 @@
   } else {
     string t = tmp("tmp");
     vars << "  " << t << " : " << type_name(type) << ";" << '\n';
-    print_const_value(vars, out, t, type, value);
+    print_const_value(vars, out, t, type, value, true);
     render << t;
   }
 
@@ -1368,54 +1336,53 @@
 }
 
 void t_delphi_generator::generate_struct(t_struct* tstruct) {
-  generate_delphi_struct(tstruct, false);
+  generate_delphi_struct(tstruct);
 }
 
 void t_delphi_generator::generate_xception(t_struct* txception) {
-  generate_delphi_struct(txception, true);
+  generate_delphi_exception(txception);
 }
 
-void t_delphi_generator::generate_delphi_struct(t_struct* tstruct, bool is_exception) {
+void t_delphi_generator::generate_delphi_struct(t_struct* tstruct) {
   indent_up();
-  generate_delphi_struct_definition(s_struct, tstruct, is_exception);
+  generate_delphi_struct_definition(s_struct, tstruct);
   indent_down();
 
   add_defined_type(tstruct);
 
-  generate_delphi_struct_impl(s_struct_impl, "", tstruct, is_exception);
+  generate_delphi_struct_impl(s_struct_impl, "", tstruct, false, false/*?*/);
   if (register_types_) {
-    generate_delphi_struct_type_factory(s_type_factory_funcs, "", tstruct, is_exception);
-    generate_delphi_struct_type_factory_registration(s_type_factory_registration,
-                                                     "",
-                                                     tstruct,
-                                                     is_exception);
+    generate_delphi_struct_type_factory(s_type_factory_funcs, "", tstruct);
+    generate_delphi_struct_type_factory_registration(s_type_factory_registration, "", tstruct);
   }
 }
 
+void t_delphi_generator::generate_delphi_exception(t_struct* tstruct) {
+  // generate exception data class first
+  generate_delphi_struct(tstruct);
+
+  indent_up();
+  generate_delphi_exception_definition(s_struct, tstruct);
+  indent_down();
+
+  add_defined_type(tstruct);
+
+  generate_delphi_exception_impl(s_struct_impl, "", tstruct);
+  /*
+  if (register_types_) {
+    generate_delphi_exception_type_factory(s_type_factory_funcs, "", tstruct);
+    generate_delphi_exception_type_factory_registration(s_type_factory_registration, "", tstruct);
+  }
+  */
+}
+
 void t_delphi_generator::generate_delphi_struct_impl(ostream& out,
                                                      string cls_prefix,
                                                      t_struct* tstruct,
-                                                     bool is_exception,
                                                      bool is_result,
-                                                     bool is_x_factory) {
+                                                     bool is_const_class) {
 
-  if (is_exception && (!is_x_factory)) {
-    generate_delphi_struct_impl(out, cls_prefix, tstruct, is_exception, is_result, true);
-  }
-
-  string cls_nm;
-
-  string exception_factory_name;
-
-  if (is_exception) {
-    exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory";
-  }
-
-  if (is_exception) {
-    cls_nm = type_name(tstruct, true, (!is_x_factory), is_x_factory, true);
-  } else {
-    cls_nm = type_name(tstruct, true, false);
-  }
+  string cls_nm = type_name(tstruct, true, false);
 
   std::ostringstream vars, code;
 
@@ -1424,26 +1391,22 @@
 
   indent_up_impl();
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = (*m_iter)->get_type();
-    while (t->is_typedef()) {
-      t = ((t_typedef*)t)->get_type();
-    }
+    t_type* truetype = (*m_iter)->get_type()->get_true_type();
     if ((*m_iter)->get_value() != nullptr) {
       initialize_field(vars,
                        code,
-                       prop_name((*m_iter)->get_name(), is_exception, ""),
-                       t,
-                       (*m_iter)->get_value());
+                       prop_name((*m_iter)->get_name(), false, "F"),
+                       truetype,
+                       (*m_iter)->get_value(),
+					   is_const_class);
       if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-        indent_impl(code) << prop_name((*m_iter), is_exception, "F__isset_") << " := True;"
-                          << '\n';
+        indent_impl(code) << prop_name((*m_iter), false, "F__isset_") << " := True;" << '\n';
       }
     }
   }
   indent_down_impl();
 
-  indent_impl(out) << "constructor " << cls_prefix << cls_nm << "."
-                   << "Create;" << '\n';
+  indent_impl(out) << "constructor " << cls_prefix << cls_nm << ".Create;" << '\n';
 
   if (!vars.str().empty()) {
     out << "var" << '\n';
@@ -1452,11 +1415,7 @@
 
   indent_impl(out) << "begin" << '\n';
   indent_up_impl();
-  if (is_exception && (!is_x_factory)) {
-    indent_impl(out) << "inherited Create('');" << '\n';
-  } else {
-    indent_impl(out) << "inherited;" << '\n';
-  }
+  indent_impl(out) << "inherited;" << '\n';
 
   if (!code.str().empty()) {
     out << code.str();
@@ -1465,7 +1424,78 @@
   indent_down_impl();
   indent_impl(out) << "end;" << '\n' << '\n';
 
-  if ((members.size() > 0) && is_exception && (!is_x_factory)) {
+  indent_impl(out) << "destructor " << cls_prefix << cls_nm << ".Destroy;" << '\n';
+  indent_impl(out) << "begin" << '\n';
+  indent_up_impl();
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = (*m_iter)->get_type()->get_true_type();
+    finalize_field(out, prop_name(*m_iter, false), t, (*m_iter)->get_value());
+  }
+
+  indent_impl(out) << "inherited;" << '\n';
+  indent_down_impl();
+  indent_impl(out) << "end;" << '\n' << '\n';
+
+  if (tstruct->is_union()) {
+    indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".ClearUnionValues;" << '\n';
+    indent_impl(out) << "begin" << '\n';
+    indent_up_impl();
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      t_type* t = (*m_iter)->get_type()->get_true_type();
+
+      generate_delphi_clear_union_value(out,
+                                        cls_prefix,
+                                        cls_nm,
+                                        t,
+                                        *m_iter,
+                                        "F",
+                                        false,
+                                        tstruct->is_union());
+    }
+    indent_down_impl();
+    indent_impl(out) << "end;" << '\n' << '\n';
+  }
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    t_type* t = (*m_iter)->get_type()->get_true_type();
+    generate_delphi_property_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", false);
+    generate_delphi_property_writer_impl(out,
+                                         cls_prefix,
+                                         cls_nm,
+                                         t,
+                                         *m_iter,
+                                         "F",
+                                         false,
+                                         tstruct->is_union());
+    if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+      generate_delphi_isset_reader_writer_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", false);
+    }
+  }
+
+  generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, false);
+  generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, false);
+  generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, false);
+}
+
+void t_delphi_generator::generate_delphi_exception_impl(ostream& out, 
+                                                        string cls_prefix,
+                                                        t_struct* tstruct) {
+
+  string cls_nm = type_name(tstruct, true, true/*, false, true*/);
+
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  indent_impl(out) << "constructor " << cls_prefix << cls_nm << ".Create;" << '\n';
+  indent_impl(out) << "begin" << '\n';
+  indent_up_impl();
+  indent_impl(out) << "inherited Create('');" << '\n';
+  indent_impl(out) << "FData := " << type_name(tstruct, true, false) << ".Create;" << '\n';
+  indent_down_impl();
+  indent_impl(out) << "end;" << '\n' << '\n';
+
+  if (members.size() > 0) {
     indent_impl(out) << "constructor " << cls_prefix << cls_nm << "."
                      << "Create(" << constructor_argument_list(tstruct, indent_impl()) << ");"
                      << '\n';
@@ -1473,7 +1503,7 @@
     indent_up_impl();
     indent_impl(out) << "Create;" << '\n';
     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      string propname = prop_name((*m_iter)->get_name(), is_exception);
+      string propname = prop_name((*m_iter)->get_name(), true);
       string param_name = constructor_param_name((*m_iter)->get_name());
       indent_impl(out) << propname << " := " << param_name << ";" << '\n';
     }
@@ -1482,113 +1512,76 @@
     indent_impl(out) << "end;" << '\n' << '\n';
   }
 
+  indent_impl(out) << "constructor " << cls_prefix << cls_nm << "."
+                   << "Create(const aData: " << type_name(tstruct, false, false) << ");"
+                   << '\n';
+  indent_impl(out) << "begin" << '\n';
+  indent_up_impl();
+  indent_impl(out) << "inherited Create('');" << '\n';
+  indent_impl(out) << "if aData <> nil" << '\n';
+  indent_impl(out) << "then FData := aData" << '\n';
+  indent_impl(out) << "else ASSERT(FALSE,'Invalid argument');" << '\n';
+  indent_impl(out) << "UpdateMessageProperty;" << '\n';
+  indent_down_impl();
+  indent_impl(out) << "end;" << '\n' << '\n';
+
   indent_impl(out) << "destructor " << cls_prefix << cls_nm << "."
                    << "Destroy;" << '\n';
   indent_impl(out) << "begin" << '\n';
   indent_up_impl();
 
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = (*m_iter)->get_type();
-    while (t->is_typedef()) {
-      t = ((t_typedef*)t)->get_type();
-    }
-    finalize_field(out, prop_name(*m_iter, is_exception), t, (*m_iter)->get_value());
+    t_type* t = (*m_iter)->get_type()->get_true_type();
+    finalize_field(out, prop_name(*m_iter, true), t, (*m_iter)->get_value());
   }
 
   indent_impl(out) << "inherited;" << '\n';
   indent_down_impl();
   indent_impl(out) << "end;" << '\n' << '\n';
 
-  if (is_exception && (!is_x_factory)) {
-    indent_impl(out) << "function " << cls_prefix << cls_nm << "." << exception_factory_name
-                     << ": I" << exception_factory_name << ";" << '\n';
-    indent_impl(out) << "begin" << '\n';
-    indent_up_impl();
-    indent_impl(out) << "if F" << exception_factory_name << " = nil" << '\n';
-    indent_impl(out) << "then F" << exception_factory_name << " := T" << exception_factory_name << "Impl.Create;" << '\n' << '\n';
-    indent_impl(out) << "result := F" << exception_factory_name << ";" << '\n';
-    indent_down_impl();
-    indent_impl(out) << "end;" << '\n' << '\n';
-    indent_impl(out) << "function " << cls_prefix << cls_nm << ".QueryInterface(const IID: TGUID; out Obj): HRESULT;" << '\n';
-    indent_impl(out) << "begin" << '\n';
-    indent_up_impl();
-    indent_impl(out) << "if GetInterface(IID, Obj)" << '\n';
-    indent_impl(out) << "then result := S_OK" << '\n';
-    indent_impl(out) << "else result := E_NOINTERFACE;" << '\n';
-    indent_down_impl();
-    indent_impl(out) << "end;" << '\n' << '\n';
-    indent_impl(out) << "function " << cls_prefix << cls_nm << "._AddRef: Integer;" << '\n';
-    indent_impl(out) << "begin" << '\n';
-    indent_up_impl();
-    indent_impl(out) << "result := -1;    // not refcounted" << '\n';
-    indent_down_impl();
-    indent_impl(out) << "end;" << '\n' << '\n';
-    indent_impl(out) << "function " << cls_prefix << cls_nm << "._Release: Integer;" << '\n';
-    indent_impl(out) << "begin" << '\n';
-    indent_up_impl();
-    indent_impl(out) << "result := -1;    // not refcounted" << '\n';
-    indent_down_impl();
-    indent_impl(out) << "end;" << '\n' << '\n';
-  }
-
-  if (tstruct->is_union()) {
-    indent_impl(out) << "procedure " << cls_prefix << cls_nm << "."
-                     << "ClearUnionValues;" << '\n';
-    indent_impl(out) << "begin" << '\n';
-    indent_up_impl();
-    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      t_type* t = (*m_iter)->get_type();
-      while (t->is_typedef()) {
-        t = ((t_typedef*)t)->get_type();
-      }
-
-      generate_delphi_clear_union_value(out,
-                                        cls_prefix,
-                                        cls_nm,
-                                        t,
-                                        *m_iter,
-                                        "F",
-                                        is_exception,
-                                        tstruct->is_union(),
-                                        is_x_factory,
-                                        exception_factory_name);
-    }
-    indent_down_impl();
-    indent_impl(out) << "end;" << '\n' << '\n';
-  }
+  // non-refcounted IUnknown impl
+  indent_impl(out) << "function " << cls_prefix << cls_nm << ".QueryInterface(const IID: TGUID; out Obj): HRESULT;" << '\n';
+  indent_impl(out) << "begin" << '\n';
+  indent_up_impl();
+  indent_impl(out) << "if GetInterface(IID, Obj)" << '\n';
+  indent_impl(out) << "then result := S_OK" << '\n';
+  indent_impl(out) << "else result := E_NOINTERFACE;" << '\n';
+  indent_down_impl();
+  indent_impl(out) << "end;" << '\n' << '\n';
+  indent_impl(out) << "function " << cls_prefix << cls_nm << "._AddRef: Integer;" << '\n';
+  indent_impl(out) << "begin" << '\n';
+  indent_up_impl();
+  indent_impl(out) << "result := -1;    // not refcounted" << '\n';
+  indent_down_impl();
+  indent_impl(out) << "end;" << '\n' << '\n';
+  indent_impl(out) << "function " << cls_prefix << cls_nm << "._Release: Integer;" << '\n';
+  indent_impl(out) << "begin" << '\n';
+  indent_up_impl();
+  indent_impl(out) << "result := -1;    // not refcounted" << '\n';
+  indent_down_impl();
+  indent_impl(out) << "end;" << '\n' << '\n';
 
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    t_type* t = (*m_iter)->get_type();
-    while (t->is_typedef()) {
-      t = ((t_typedef*)t)->get_type();
-    }
-    generate_delphi_property_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception);
+    t_type* t = (*m_iter)->get_type()->get_true_type();
+    generate_delphi_property_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "", true);
     generate_delphi_property_writer_impl(out,
                                          cls_prefix,
                                          cls_nm,
                                          t,
                                          *m_iter,
-                                         "F",
-                                         is_exception,
-                                         tstruct->is_union(),
-                                         is_x_factory,
-                                         exception_factory_name);
+                                         "",
+                                         true,
+                                         tstruct->is_union());
     if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-      generate_delphi_isset_reader_writer_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception);
+      generate_delphi_isset_reader_writer_impl(out, cls_prefix, cls_nm, t, *m_iter, "", true);
     }
   }
 
-  generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, is_exception, is_x_factory);
-  if (is_result) {
-    generate_delphi_struct_result_writer_impl(out, cls_prefix, tstruct, is_exception, is_x_factory);
-  } else {
-    generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, is_exception, is_x_factory);
-  }
-  generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, is_exception, is_x_factory);
+  generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, true);
+  generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, true);
+  generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, true);
 
-  if (is_exception && is_x_factory) {
-    generate_delphi_create_exception_impl(out, cls_prefix, tstruct, is_exception);
-  }
+  generate_delphi_create_exception_impl(out, cls_prefix, tstruct, true);
 }
 
 void t_delphi_generator::print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct) {
@@ -1600,17 +1593,8 @@
 
 void t_delphi_generator::generate_delphi_struct_type_factory(ostream& out,
                                                              string cls_prefix,
-                                                             t_struct* tstruct,
-                                                             bool is_exception,
-                                                             bool is_result,
-                                                             bool is_x_factory) {
+                                                             t_struct* tstruct) {
   (void)cls_prefix;
-  if (is_exception)
-    return;
-  if (is_result)
-    return;
-  if (is_x_factory)
-    return;
 
   string struct_intf_name = type_name(tstruct);
   string cls_nm = type_name(tstruct, true, false);
@@ -1629,17 +1613,8 @@
 
 void t_delphi_generator::generate_delphi_struct_type_factory_registration(ostream& out,
                                                                           string cls_prefix,
-                                                                          t_struct* tstruct,
-                                                                          bool is_exception,
-                                                                          bool is_result,
-                                                                          bool is_x_factory) {
+                                                                          t_struct* tstruct) {
   (void)cls_prefix;
-  if (is_exception)
-    return;
-  if (is_result)
-    return;
-  if (is_x_factory)
-    return;
 
   string struct_intf_name = type_name(tstruct);
 
@@ -1649,12 +1624,8 @@
   out << '\n';
 }
 
-void t_delphi_generator::generate_delphi_struct_definition(ostream& out,
-                                                           t_struct* tstruct,
-                                                           bool is_exception,
-                                                           bool in_class,
-                                                           bool is_result,
-                                                           bool is_x_factory) {
+void t_delphi_generator::generate_delphi_struct_definition(ostream& out, 
+                                                           t_struct* tstruct) {
   bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
   string struct_intf_name;
   string struct_name;
@@ -1662,121 +1633,77 @@
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter;
 
-  string exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory";
+  struct_intf_name = type_name(tstruct, false, false);
+  struct_name = type_name(tstruct, true);
 
-  if (is_exception) {
-    struct_intf_name = type_name(tstruct, false, false, true);
+  generate_delphi_doc(out, tstruct);
+  if(rtti_) {
+    indent(out) << "{$TYPEINFO ON}" << '\n';
+    indent(out) << "{$RTTI EXPLICIT METHODS([vcPublic, vcPublished]) PROPERTIES([vcPublic, vcPublished])}" << '\n';
+    indent(out) << struct_intf_name << " = interface(IBaseWithTypeInfo)" << '\n';
   } else {
-    struct_intf_name = type_name(tstruct);
+    indent(out) << struct_intf_name << " = interface(IBase)" << '\n';
+  }
+  indent_up();
+
+  generate_guid(out);
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    generate_delphi_property_reader_definition(out, *m_iter, false);
+    generate_delphi_property_writer_definition(out, *m_iter, false);
   }
 
-  if (is_exception) {
-    struct_name = type_name(tstruct, true, (!is_x_factory), is_x_factory);
-  } else {
-    struct_name = type_name(tstruct, true);
-  }
-
-  if ((!is_exception) || is_x_factory) {
-
-    generate_delphi_doc(out, tstruct);
-    if(rtti_) {
-      indent(out) << "{$TYPEINFO ON}" << '\n';
-      indent(out) << "{$RTTI EXPLICIT METHODS([vcPublic, vcPublished]) PROPERTIES([vcPublic, vcPublished])}" << '\n';
-      indent(out) << struct_intf_name << " = interface(IBaseWithTypeInfo)" << '\n';
-    } else {
-      indent(out) << struct_intf_name << " = interface(IBase)" << '\n';
-    }
-    indent_up();
-
-    generate_guid(out);
-
+  if (members.size() > 0) {
+    out << '\n';
     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      generate_delphi_property_reader_definition(out, *m_iter, is_exception);
-      generate_delphi_property_writer_definition(out, *m_iter, is_exception);
+      generate_property(out, *m_iter, true, false);
     }
 
-    if (is_x_factory) {
-      out << '\n';
-      indent(out) << "// Create Exception Object" << '\n';
-      indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << '\n';
-    }
-
-    if (members.size() > 0) {
-      out << '\n';
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        generate_property(out, *m_iter, true, is_exception);
+    out << '\n';
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+        generate_delphi_isset_reader_writer_definition(out, *m_iter, false);
       }
     }
 
-    if (members.size() > 0) {
-      out << '\n';
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-          generate_delphi_isset_reader_writer_definition(out, *m_iter, is_exception);
-        }
+    out << '\n';
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+        isset_name = prop_name(*m_iter, false, "__isset_");
+        indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";"
+                    << '\n';
       }
     }
-
-    if (members.size() > 0) {
-      out << '\n';
-      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-        if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-          isset_name = prop_name(*m_iter, is_exception, "__isset_");
-          indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";"
-                      << '\n';
-        }
-      }
-    }
-
-    indent_down();
-    indent(out) << "end;"
-                << render_deprecation_attribute(tstruct->annotations_, " {", "}")
-                << '\n';
-    if(rtti_) {
-      indent(out) << "{$IFNDEF TYPEINFO_WAS_ON} {$TYPEINFO OFF} {$ENDIF}" << '\n';
-    }
-    indent(out) << '\n';
   }
 
+  indent_down();
+  indent(out) << "end;"
+              << render_deprecation_attribute(tstruct->annotations_, " {", "}")
+              << '\n';
+  if(rtti_) {
+    indent(out) << "{$IFNDEF TYPEINFO_WAS_ON} {$TYPEINFO OFF} {$ENDIF}" << '\n';
+  }
+  indent(out) << '\n';
+
   generate_delphi_doc(out, tstruct);
   indent(out) << struct_name << " = ";
   if (is_final) {
     out << "sealed ";
   }
-  out << "class(";
-  if (is_exception && (!is_x_factory)) {
-    out << "TException, IInterface, IBase, ISupportsToString";
-  } else {
-    out << "TInterfacedObject, IBase, ISupportsToString, " << struct_intf_name;
-  }
-  out << ")" << '\n';
-
-  if (is_exception && (!is_x_factory)) {
-    indent(out) << "public" << '\n';
-    indent_up();
-    indent(out) << "type" << '\n';
-    indent_up();
-    generate_delphi_struct_definition(out, tstruct, is_exception, in_class, is_result, true);
-    indent_down();
-    indent_down();
-  }
+  out << "class(TInterfacedObject, IBase, ISupportsToString, " << struct_intf_name << ")" << '\n';
 
   indent(out) << "private" << '\n';
   indent_up();
 
-  if (is_exception && (!is_x_factory)) {
-    indent(out) << "F" << exception_factory_name << " :" << struct_intf_name << ";" << '\n' << '\n';
-  }
-
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    indent(out) << declare_field(*m_iter, false, "F", is_exception) << '\n';
+    indent(out) << declare_field(*m_iter, "F", false) << '\n';
   }
 
   if (members.size() > 0) {
     indent(out) << '\n';
     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
       if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-        isset_name = prop_name(*m_iter, is_exception, "F__isset_");
+        isset_name = prop_name(*m_iter, false, "F__isset_");
         indent(out) << isset_name << ": System.Boolean;" << '\n';
       }
     }
@@ -1785,8 +1712,8 @@
   indent(out) << '\n';
 
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    generate_delphi_property_reader_definition(out, *m_iter, is_exception);
-    generate_delphi_property_writer_definition(out, *m_iter, is_exception);
+    generate_delphi_property_reader_definition(out, *m_iter, false);
+    generate_delphi_property_writer_definition(out, *m_iter, false);
   }
 
   if (tstruct->is_union()) {
@@ -1799,72 +1726,134 @@
     out << '\n';
     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
       if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-        isset_name = prop_name(*m_iter, is_exception, "__isset_");
+        isset_name = prop_name(*m_iter, false, "__isset_");
         indent(out) << "function Get" << isset_name << ": System.Boolean;" << '\n';
         indent(out) << "procedure Set" << isset_name << "( const value : System.Boolean);" << '\n';
       }
     }
   }
 
-  if (is_exception && (!is_x_factory)) {
-    out << '\n';
-    indent_down();
-    indent(out) << "strict protected" << '\n';
-    indent_up();
-    indent(out) << "function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;" << '\n';
-    indent(out) << "function _AddRef: Integer; stdcall;" << '\n';
-    indent(out) << "function _Release: Integer; stdcall;" << '\n';
-    out << '\n';
-  }
-
   indent_down();
   indent(out) << "public" << '\n';
   indent_up();
-
-  if ((members.size() > 0) && is_exception && (!is_x_factory)) {
-    indent(out) << "constructor Create; overload;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n';
-    indent(out) << "constructor Create(" << constructor_argument_list(tstruct, indent())
-                << "); overload;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n';
-  } else {
-    indent(out) << "constructor Create;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n';
-  }
-
+  indent(out) << "constructor Create;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n';
   indent(out) << "destructor Destroy; override;" << '\n';
 
   out << '\n';
   indent(out) << "function ToString: string; override;" << '\n';
 
-  if (is_exception && (!is_x_factory)) {
-    out << '\n';
-    indent(out) << "// Exception Factory" << '\n';
-    indent(out) << "function " << exception_factory_name << ": " << struct_intf_name << ";" << '\n';
-  }
-
   out << '\n';
   indent(out) << "// IBase" << '\n';
   indent(out) << "procedure Read( const iprot: IProtocol);" << '\n';
   indent(out) << "procedure Write( const oprot: IProtocol);" << '\n';
 
-  if (is_exception && is_x_factory) {
+  if (members.size() > 0) {
     out << '\n';
-    indent(out) << "// Create Exception Object" << '\n';
-    indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << '\n';
+    indent(out) << "// Properties" << '\n';
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      generate_property(out, *m_iter, true, false);
+    }
+
+    out << '\n';
+    indent(out) << "// isset" << '\n';
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+        isset_name = prop_name(*m_iter, false, "__isset_");
+        indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";"
+                    << '\n';
+      }
+    }
   }
 
+  indent_down();
+  indent(out) << "end;" << '\n' << '\n';
+}
+
+void t_delphi_generator::generate_delphi_exception_definition(ostream& out, 
+                                                              t_struct* tstruct) {
+  bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
+  string struct_intf_name;
+  string struct_name;
+  string isset_name;
+  const vector<t_field*>& members = tstruct->get_members();
+  vector<t_field*>::const_iterator m_iter;
+
+  struct_intf_name = type_name(tstruct, false, false);
+  struct_name = type_name(tstruct, true, true);
+
+  generate_delphi_doc(out, tstruct);
+  indent(out) << struct_name << " = ";
+  if (is_final) {
+    out << "sealed ";
+  }
+  out << "class(TException, IInterface, IBase, ISupportsToString)" << '\n';
+
+  indent(out) << "private" << '\n';
+  indent_up();
+  indent(out) << "FData : " << struct_intf_name << ';' << '\n';
+  indent(out) << '\n';
+
+  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+    generate_delphi_property_reader_definition(out, *m_iter, true);
+    generate_delphi_property_writer_definition(out, *m_iter, true);
+  }
+
+  if (members.size() > 0) {
+    out << '\n';
+    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+      if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+        isset_name = prop_name(*m_iter, true, "__isset_");
+        indent(out) << "function Get" << isset_name << ": System.Boolean;" << '\n';
+        indent(out) << "procedure Set" << isset_name << "( const value : System.Boolean);" << '\n';
+      }
+    }
+  }
+
+  out << '\n';
+  indent_down();
+  indent(out) << "strict protected" << '\n';
+  indent_up();
+  indent(out) << "// non-refcounted instance" << '\n';
+  indent(out) << "function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;" << '\n';
+  indent(out) << "function _AddRef: Integer; stdcall;" << '\n';
+  indent(out) << "function _Release: Integer; stdcall;" << '\n';
+  out << '\n';
+
+  indent_down();
+  indent(out) << "public" << '\n';
+  indent_up();
+
+  indent(out) << "constructor Create; overload;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n';
+  if (members.size() > 0) {
+    indent(out) << "constructor Create(" << constructor_argument_list(tstruct, indent())
+                << "); overload;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n';
+  }
+  indent(out) << "constructor Create( const aData: " << struct_intf_name
+                << "); overload;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n';
+
+  indent(out) << "destructor Destroy; override;" << '\n';
+
+  out << '\n';
+  indent(out) << "property ExceptionData : " << struct_intf_name << " read FData;" << '\n';
+  indent(out) << "function ToString: string; override;" << '\n';
+
+  out << '\n';
+  indent(out) << "// IBase" << '\n';
+  indent(out) << "procedure Read( const iprot: IProtocol);" << '\n';
+  indent(out) << "procedure Write( const oprot: IProtocol);" << '\n';
+
   if (members.size() > 0) {
     out << '\n';
     indent(out) << "// Properties" << '\n';
     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-      generate_property(out, *m_iter, true, is_exception);
+      generate_property(out, *m_iter, true, true);
     }
-  }
 
-  if (members.size() > 0) {
     out << '\n';
     indent(out) << "// isset" << '\n';
     for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
       if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
-        isset_name = prop_name(*m_iter, is_exception, "__isset_");
+        isset_name = prop_name(*m_iter, true, "__isset_");
         indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";"
                     << '\n';
       }
@@ -1957,11 +1946,11 @@
 
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
     t_struct* ts = (*f_iter)->get_arglist();
-    generate_delphi_struct_definition(s_service, ts, false, true);
+    generate_delphi_struct_definition(s_service, ts);
     generate_delphi_struct_impl(s_service_impl,
                                 normalize_clsnm(service_name_, "T") + ".",
                                 ts,
-                                false);
+                                false, false);
     generate_function_helpers(*f_iter);
   }
 }
@@ -2076,7 +2065,7 @@
            // Delphi forces us to specify a type with IFuture<T>, so we use Integer=0 for void methods
           indent_impl(s_service_impl) << "result := TTask.Future<System.Integer>(function: System.Integer" << '\n';
         } else {
-          string rettype = type_name(ttype, false, true, false, true);
+          string rettype = type_name(ttype, false, true/*, false, true*/);
           indent_impl(s_service_impl) << "result := TTask.Future<" << rettype << ">(function: " << rettype << '\n';
         }
         indent_impl(s_service_impl) << "begin" << '\n';
@@ -2227,8 +2216,10 @@
         indent_impl(s_service_impl) << "if (" << retvar << "." << prop_name(*x_iter, false, "__isset_")
                                     << ") then begin" << '\n';
         indent_up_impl();
-        indent_impl(s_service_impl) << exceptvar << " := " << retvar << "." << prop_name(*x_iter)
-                                    << ".CreateException;" << '\n';
+        indent_impl(s_service_impl) << exceptvar
+                                    << " := " << type_name((*x_iter)->get_type(),true,true/*,false,true*/)
+                                    << ".Create(" << retvar << "." << prop_name(*x_iter) << ");"
+                                    << '\n';
         indent_impl(s_service_impl) << "raise " << exceptvar << ";" << '\n';
         indent_down_impl();
         indent_impl(s_service_impl) << "end;" << '\n';
@@ -2434,18 +2425,21 @@
     result.append(&success);
   }
 
+  int num_excepts = 0;
   t_struct* xs = tfunction->get_xceptions();
   const vector<t_field*>& fields = xs->get_members();
   vector<t_field*>::const_iterator f_iter;
   for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
     result.append(*f_iter);
+    ++num_excepts;
   }
+  result.set_method_xcepts(num_excepts > 0);
 
-  generate_delphi_struct_definition(s_service, &result, false, true, true);
+  generate_delphi_struct_definition(s_service, &result);
   generate_delphi_struct_impl(s_service_impl,
                               normalize_clsnm(service_name_, "T") + ".",
                               &result,
-                              false);
+                              true, false);
 }
 
 void t_delphi_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
@@ -2543,10 +2537,7 @@
                                 << " do begin" << '\n';
     indent_up_impl();
     if (!tfunction->is_oneway()) {
-      string factory_name = normalize_clsnm((*x_iter)->get_type()->get_name(), "", true)
-                            + "Factory";
-      indent_impl(s_service_impl) << "ret." << prop_name(*x_iter) << " := E." << factory_name << ";"
-                                  << '\n';
+      indent_impl(s_service_impl) << "ret." << prop_name(*x_iter) << " := E.ExceptionData;" << '\n';
     }
     indent_down_impl();
     indent_impl(s_service_impl) << "end;" << '\n';
@@ -2616,10 +2607,7 @@
                                                     t_field* tfield,
                                                     string prefix,
                                                     ostream& local_vars) {
-  t_type* type = tfield->get_type();
-  while (type->is_typedef()) {
-    type = ((t_typedef*)type)->get_type();
-  }
+  t_type* type = tfield->get_type()->get_true_type();
 
   if (type->is_void()) {
     throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
@@ -2695,11 +2683,7 @@
                                                      string prefix) {
   string typ_name;
 
-  if (tstruct->is_xception()) {
-    typ_name = type_name(tstruct, true, false, true, true);
-  } else {
-    typ_name = type_name(tstruct, true, false);
-  }
+  typ_name = type_name(tstruct, true, false);
 
   indent_impl(out) << prefix << name << " := " << typ_name << ".Create;" << '\n';
   indent_impl(out) << prefix << name << ".Read(iprot);" << '\n';
@@ -2819,10 +2803,7 @@
                                                   ostream& local_vars) {
   (void)local_vars;
 
-  t_type* type = tfield->get_type();
-  while (type->is_typedef()) {
-    type = ((t_typedef*)type)->get_type();
-  }
+  t_type* type = tfield->get_type()->get_true_type();
 
   string name = prefix + prop_name(tfield, is_xception);
 
@@ -2999,22 +2980,21 @@
                                            t_field* tfield,
                                            bool isPublic,
                                            bool is_xception) {
-  generate_delphi_property(out, is_xception, tfield, isPublic, "Get");
+  generate_delphi_property(out, is_xception, tfield, isPublic);
 }
 
 void t_delphi_generator::generate_delphi_property(ostream& out,
                                                   bool struct_is_xception,
                                                   t_field* tfield,
-                                                  bool isPublic,
-                                                  std::string fieldPrefix) {
+                                                  bool isPublic) {
   (void)isPublic;
 
   t_type* ftype = tfield->get_type();
   bool is_xception = ftype->is_xception();
   generate_delphi_doc(out, tfield);
   indent(out) << "property " << prop_name(tfield, struct_is_xception) << ": "
-              << type_name(ftype, false, true, is_xception, true)
-              << " read " << prop_name(tfield, struct_is_xception, fieldPrefix)
+              << type_name(ftype, false, true/*, false, true*/)
+              << " read " << prop_name(tfield, struct_is_xception, "Get")
               << " write " << prop_name(tfield, struct_is_xception, "Set")
               << ";"
               << render_deprecation_attribute(tfield->annotations_, " {", "}")
@@ -3050,9 +3030,7 @@
 
 string t_delphi_generator::type_name(t_type* ttype,
                                      bool b_cls,
-                                     bool b_no_postfix,
-                                     bool b_exception_factory,
-                                     bool b_full_exception_factory) {
+                                     bool b_no_postfix) {
 
   if (ttype->is_typedef()) {
     t_typedef* tdef = (t_typedef*)ttype;
@@ -3060,9 +3038,7 @@
       if (tdef->get_type() != nullptr) {
         return type_name(tdef->get_type(),
                          b_cls,
-                         b_no_postfix,
-                         b_exception_factory,
-                         b_full_exception_factory);
+                         b_no_postfix);
       } else {
         throw "unresolved forward declaration: " + tdef->get_symbolic();
       }
@@ -3117,20 +3093,12 @@
 
   string nm = normalize_clsnm(ttype->get_name(), type_prefix);
 
-  if (b_exception_factory) {
-    nm = normalize_clsnm(ttype->get_name(), type_prefix, true) + "Factory";
-  }
-
   if (b_cls) {
     if (!b_no_postfix) {
       nm = nm + "Impl";
     }
   }
 
-  if (b_exception_factory && b_full_exception_factory) {
-    return type_name(ttype, true, true, false, false) + "." + nm;
-  }
-
   return nm;
 }
 
@@ -3217,16 +3185,14 @@
 }
 
 string t_delphi_generator::declare_field(t_field* tfield,
-                                         bool init,
                                          std::string prefix,
                                          bool is_xception_class) {
-  (void)init;
-
   t_type* ftype = tfield->get_type();
   bool is_xception = ftype->is_xception();
 
   string result = prop_name(tfield, is_xception_class, prefix) + ": "
-                  + type_name(ftype, false, true, is_xception, true) + ";";
+                  + type_name(ftype, false, true) + ";";
+
   return result;
 }
 
@@ -3251,7 +3217,7 @@
     } else {
       signature = "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "Async("
                 + argument_list(tfunction->get_arglist()) + "): IFuture<"
-                + type_name(ttype, false, true, is_xception, true) + ">;";
+                + type_name(ttype, false, true/*, is_xception, true*/) + ">;";
     }
   } else {
     if (is_void(ttype)) {
@@ -3260,7 +3226,7 @@
     } else {
       signature = "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "("
                 + argument_list(tfunction->get_arglist()) + "): "
-                + type_name(ttype, false, true, is_xception, true) + ";";
+                + type_name(ttype, false, true/*, is_xception, true*/) + ";";
     }
   }
 
@@ -3289,7 +3255,7 @@
     tt = (*f_iter)->get_type();
     result += input_arg_prefix(tt); // const?
     result += normalize_name((*f_iter)->get_name()) + ": "
-              + type_name(tt, false, true, tt->is_xception(), true);
+              + type_name(tt, false, true/*, tt->is_xception(), true*/);
   }
   return result;
 }
@@ -3326,7 +3292,7 @@
     tt = (*f_iter)->get_type();
     line += input_arg_prefix(tt); // const?
     line += constructor_param_name((*f_iter)->get_name()) + ": "
-            + type_name(tt, false, true, tt->is_xception(), true);
+            + type_name(tt, false, true/*, tt->is_xception(), true*/);
   }
 
   if (line.size() > 0) {
@@ -3345,9 +3311,7 @@
 }
 
 string t_delphi_generator::type_to_enum(t_type* type) {
-  while (type->is_typedef()) {
-    type = ((t_typedef*)type)->get_type();
-  }
+  type = type->get_true_type();
 
   if (type->is_base_type()) {
     t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
@@ -3387,9 +3351,7 @@
 }
 
 string t_delphi_generator::empty_value(t_type* type) {
-  while (type->is_typedef()) {
-    type = ((t_typedef*)type)->get_type();
-  }
+  type = type->get_true_type();
 
   if (type->is_base_type()) {
     t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
@@ -3436,7 +3398,7 @@
   bool is_xception = ftype->is_xception();
 
   indent(out) << "procedure " << prop_name(tfield, is_xception_class, "Set")
-              << "( const Value: " << type_name(ftype, false, true, is_xception, true) << ");"
+              << "( const Value: " << type_name(ftype, false, true/*, false, true*/) << ");"
               << render_deprecation_attribute(tfield->annotations_, " ", ";")
               << '\n';
 }
@@ -3448,7 +3410,7 @@
   bool is_xception = ftype->is_xception();
 
   indent(out) << "function " << prop_name(tfield, is_xception_class, "Get") << ": "
-              << type_name(ftype, false, true, is_xception, true) << ";" 
+              << type_name(ftype, false, true/*, false*/) << ";" 
               << render_deprecation_attribute(tfield->annotations_, " ", ";")
               << '\n';
 }
@@ -3456,8 +3418,8 @@
 void t_delphi_generator::generate_delphi_isset_reader_writer_definition(ostream& out,
                                                                  t_field* tfield,
                                                                  bool is_xception) {
-  indent(out) << "function " << prop_name(tfield, is_xception,"Get__isset_") << ": System.Boolean;" << '\n';
-  indent(out) << "procedure " << prop_name(tfield, is_xception, "Set__isset_") << "( const value : System.Boolean);" << '\n';
+  indent(out) << "function " << prop_name(tfield, false,"Get__isset_") << ": System.Boolean;" << '\n';
+  indent(out) << "procedure " << prop_name(tfield, false, "Set__isset_") << "( const value : System.Boolean);" << '\n';
 }
 
 void t_delphi_generator::generate_delphi_clear_union_value(ostream& out,
@@ -3467,25 +3429,20 @@
                                                            t_field* tfield,
                                                            std::string fieldPrefix,
                                                            bool is_xception_class,
-                                                           bool is_union,
-                                                           bool is_xception_factory,
-                                                           std::string xception_factory_name) {
+                                                           bool is_union) {
   (void)cls_prefix;
   (void)name;
   (void)type;
   (void)is_union;
-  (void)is_xception_factory;
-  (void)xception_factory_name;
 
   t_type* ftype = tfield->get_type();
   bool is_xception = ftype->is_xception();
 
-  indent_impl(out) << "if " << prop_name(tfield, is_xception_class,"F__isset_") << " then begin"
-                   << '\n';
+  indent_impl(out) << "if " << prop_name(tfield, is_xception_class,"F__isset_") << " then begin" << '\n';
   indent_up_impl();
   indent_impl(out) << prop_name(tfield, is_xception_class,"F__isset_") << " := False;" << '\n';
   indent_impl(out) << prop_name(tfield, is_xception_class,fieldPrefix) << " := "
-                   << "Default( " << type_name(ftype, false, true, is_xception, true) << ");"
+                   << "Default( " << type_name(ftype, false, true/*, is_xception, true*/) << ");"
                    << '\n';
   indent_down_impl();
   indent_impl(out) << "end;" << '\n';
@@ -3498,9 +3455,7 @@
                                                               t_field* tfield,
                                                               std::string fieldPrefix,
                                                               bool is_xception_class,
-                                                              bool is_union,
-                                                              bool is_xception_factory,
-                                                              std::string xception_factory_name) {
+                                                              bool is_union) {
   (void)type;
 
   t_type* ftype = tfield->get_type();
@@ -3508,21 +3463,20 @@
 
   indent_impl(out) << "procedure " << cls_prefix << name << "."
                    << prop_name(tfield, is_xception_class,"Set")
-                   << "( const Value: " << type_name(ftype, false, true, is_xception, true) << ");"
+                   << "( const Value: " << type_name(ftype, false, true) << ");"
                    << '\n';
   indent_impl(out) << "begin" << '\n';
   indent_up_impl();
   if (is_union) {
     indent_impl(out) << "ClearUnionValues;" << '\n';
   }
-  if (tfield->get_req() != t_field::T_REQUIRED) {
-    indent_impl(out) << prop_name(tfield, is_xception_class,"F__isset_") << " := True;" << '\n';
-  }
-  indent_impl(out) << prop_name(tfield, is_xception_class,fieldPrefix) << " := Value;" << '\n';
-
-  if (is_xception_class && (!is_xception_factory)) {
-    indent_impl(out) << xception_factory_name << "." << prop_name(tfield, is_xception_class)
-                     << " := Value;" << '\n';
+  if(is_xception_class) {
+    indent_impl(out) << "FData." << prop_name(tfield, false, fieldPrefix) << " := Value;" << '\n';
+  } else {
+    if (tfield->get_req() != t_field::T_REQUIRED) {
+      indent_impl(out) << prop_name(tfield, is_xception_class, "F__isset_") << " := True;" << '\n';
+    }
+    indent_impl(out) << prop_name(tfield, is_xception_class, fieldPrefix) << " := Value;" << '\n';
   }
 
   indent_down_impl();
@@ -3543,11 +3497,14 @@
 
   indent_impl(out) << "function " << cls_prefix << name << "."
                    << prop_name(tfield, is_xception_class,"Get") << ": "
-                   << type_name(ftype, false, true, is_xception, true) << ";" << '\n';
+                   << type_name(ftype, false, true) << ";" << '\n';
   indent_impl(out) << "begin" << '\n';
   indent_up_impl();
-  indent_impl(out) << "Result := " << prop_name(tfield, is_xception_class,fieldPrefix) << ";"
-                   << '\n';
+  if(is_xception_class) {
+    indent_impl(out) << "Result := FData." << prop_name(tfield, false, fieldPrefix) << ";" << '\n';
+  } else {
+    indent_impl(out) << "Result := " << prop_name(tfield, is_xception_class, fieldPrefix) << ";" << '\n';    
+  }
   indent_down_impl();
   indent_impl(out) << "end;" << '\n' << '\n';
 }
@@ -3558,16 +3515,20 @@
                                                            t_type* type,
                                                            t_field* tfield,
                                                            std::string fieldPrefix,
-                                                           bool is_xception) {
+                                                           bool is_xception_class) {
   (void)type;
 
-  string isset_name = prop_name(tfield, is_xception, "__isset_");
+  string isset_name = prop_name(tfield, false, "__isset_");
 
   indent_impl(out) << "function " << cls_prefix << name << "."
                    << "Get" << isset_name << ": System.Boolean;" << '\n';
   indent_impl(out) << "begin" << '\n';
   indent_up_impl();
-  indent_impl(out) << "Result := " << fieldPrefix << isset_name << ";" << '\n';
+  if(is_xception_class) {
+    indent_impl(out) << "Result := FData." << fieldPrefix << isset_name << ";" << '\n';
+  } else {
+    indent_impl(out) << "Result := " << fieldPrefix << isset_name << ";" << '\n';
+  }
   indent_down_impl();
   indent_impl(out) << "end;" << '\n' << '\n';
 
@@ -3575,7 +3536,11 @@
                    << "Set" << isset_name << "( const value: System.Boolean);" << '\n';
   indent_impl(out) << "begin" << '\n';
   indent_up_impl();
-  indent_impl(out) << fieldPrefix << isset_name << " := value;" << '\n';
+  if(is_xception_class) {
+    indent_impl(out) << "FData." << fieldPrefix << isset_name << " := value;" << '\n';
+  } else {
+    indent_impl(out) << fieldPrefix << isset_name << " := value;" << '\n';
+  }
   indent_down_impl();
   indent_impl(out) << "end;" << '\n' << '\n';
 }
@@ -3587,47 +3552,13 @@
   (void)cls_prefix;
 
   string exception_cls_nm = type_name(tstruct, true, true);
-  string cls_nm = type_name(tstruct, true, false, is_exception, is_exception);
-
-  indent_impl(out) << "function " << cls_nm << ".CreateException: " << exception_cls_nm << ";"
-                   << '\n';
-
-  indent_impl(out) << "begin" << '\n';
-  indent_up_impl();
-
-  indent_impl(out) << "Result := " << exception_cls_nm << ".Create;" << '\n';
-  string factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory";
-  indent_impl(out) << "Result.F" << factory_name << " := Self;" << '\n';
-
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  string propname;
-
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    propname = prop_name(*f_iter, is_exception);
-    if ((*f_iter)->get_req() != t_field::T_REQUIRED) {
-      indent_impl(out) << "if " << prop_name(*f_iter, is_exception,"__isset_") << " then begin" << '\n';
-      indent_up_impl();
-    }
-    indent_impl(out) << "Result." << propname << " := " << propname << ";" << '\n';
-    if ((*f_iter)->get_req() != t_field::T_REQUIRED) {
-      indent_down_impl();
-      indent_impl(out) << "end;" << '\n';
-    }
-  }
-
-  indent_impl(out) << "Result.UpdateMessageProperty;" << '\n';
-
-  indent_down_impl();
-  indent_impl(out) << "end;" << '\n' << '\n';
+  string cls_nm = type_name(tstruct, true, false/*, is_exception, is_exception*/);
 }
 
 void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out,
                                                             string cls_prefix,
                                                             t_struct* tstruct,
-                                                            bool is_exception,
-                                                            bool is_x_factory) {
+                                                            bool is_exception) {
 
   ostringstream local_vars;
   ostringstream code_block;
@@ -3746,7 +3677,7 @@
     }
   }
 
-  if( is_exception && (!is_x_factory)) {
+  if( is_exception) {
     code_block << '\n';
     indent_impl(code_block) << "UpdateMessageProperty;" << '\n';
   }
@@ -3755,10 +3686,9 @@
 
   string cls_nm;
 
-  cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory);
+  cls_nm = type_name(tstruct, true, is_exception);
 
-  indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Read( const iprot: IProtocol);"
-                   << '\n';
+  indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Read( const iprot: IProtocol);" << '\n';
   indent_impl(out) << "var" << '\n';
   indent_up_impl();
   indent_impl(out) << "field_ : TThriftField;" << '\n';
@@ -3768,76 +3698,10 @@
   out << code_block.str();
 }
 
-void t_delphi_generator::generate_delphi_struct_result_writer_impl(ostream& out,
-                                                                   string cls_prefix,
-                                                                   t_struct* tstruct,
-                                                                   bool is_exception,
-                                                                   bool is_x_factory) {
-
-  ostringstream local_vars;
-  ostringstream code_block;
-
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_sorted_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  indent_impl(code_block) << "begin" << '\n';
-  indent_up_impl();
-
-  indent_impl(local_vars) << "tracker : IProtocolRecursionTracker;" << '\n';
-  indent_impl(code_block) << "tracker := oprot.NextRecursionLevel;" << '\n';
-
-  indent_impl(code_block) << "Thrift.Protocol.Init( struc, '" << name << "');" << '\n';
-  indent_impl(code_block) << "oprot.WriteStructBegin(struc);" << '\n';
-
-  if (fields.size() > 0) {
-    indent_impl(code_block) << "Thrift.Protocol.Init( field_);" << '\n';
-    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-      indent_impl(code_block) << "if (" << prop_name(*f_iter, is_exception,"__isset_") << ") then"
-                              << '\n';
-      indent_impl(code_block) << "begin" << '\n';
-      indent_up_impl();
-      indent_impl(code_block) << "field_.Name := '" << (*f_iter)->get_name() << "';" << '\n';
-      indent_impl(code_block) << "field_.Type_  := " << type_to_enum((*f_iter)->get_type()) << ";"
-                              << '\n';
-      indent_impl(code_block) << "field_.ID := " << (*f_iter)->get_key() << ";" << '\n';
-      indent_impl(code_block) << "oprot.WriteFieldBegin(field_);" << '\n';
-      generate_serialize_field(code_block, is_exception, *f_iter, "Self.", local_vars);
-      indent_impl(code_block) << "oprot.WriteFieldEnd();" << '\n';
-      indent_down_impl();
-    }
-  }
-
-  indent_impl(code_block) << "oprot.WriteFieldStop();" << '\n';
-  indent_impl(code_block) << "oprot.WriteStructEnd();" << '\n';
-
-  indent_down_impl();
-  indent_impl(code_block) << "end;" << '\n' << '\n';
-
-  string cls_nm;
-
-  cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory);
-
-  indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Write( const oprot: IProtocol);"
-                   << '\n';
-  indent_impl(out) << "var" << '\n';
-  indent_up_impl();
-  indent_impl(out) << "struc : TThriftStruct;" << '\n';
-
-  if (fields.size() > 0) {
-    indent_impl(out) << "field_ : TThriftField;" << '\n';
-  }
-
-  out << local_vars.str();
-  indent_down_impl();
-  out << code_block.str();
-}
-
 void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out,
                                                             string cls_prefix,
                                                             t_struct* tstruct,
-                                                            bool is_exception,
-                                                            bool is_x_factory) {
+                                                            bool is_exception) {
 
   ostringstream local_vars;
   ostringstream code_block;
@@ -3906,7 +3770,7 @@
 
   string cls_nm;
 
-  cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory);
+  cls_nm = type_name(tstruct, true, is_exception);
 
   indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Write( const oprot: IProtocol);"
                    << '\n';
@@ -3924,8 +3788,7 @@
 void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out,
                                                               string cls_prefix,
                                                               t_struct* tstruct,
-                                                              bool is_exception,
-                                                              bool is_x_factory) {
+                                                              bool is_exception) {
 
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
@@ -3933,7 +3796,7 @@
   string cls_nm;
 
   if (is_exception) {
-    cls_nm = type_name(tstruct, true, (!is_x_factory), is_x_factory, true);
+    cls_nm = type_name(tstruct, true, true/*, false, true*/);
   } else {
     cls_nm = type_name(tstruct, true, false);
   }
@@ -3998,10 +3861,7 @@
                        << '\n';
     }
 
-    t_type* ttype = (*f_iter)->get_type();
-    while (ttype->is_typedef()) {
-      ttype = ((t_typedef*)ttype)->get_type();
-    }
+    t_type* ttype = (*f_iter)->get_type()->get_true_type();
 
     if (ttype->is_xception() || ttype->is_struct()) {
       indent_impl(out) << "if (Self." << prop_name((*f_iter), is_exception) << " = nil) then " << tmp_sb
@@ -4009,7 +3869,7 @@
                        << prop_name((*f_iter), is_exception) << ".ToString());" << '\n';
     } else if (ttype->is_enum()) {
       indent_impl(out) << tmp_sb << ".Append(EnumUtils<"
-                       << type_name(ttype, false, true, false, false)
+                       << type_name(ttype, false, true)
                        << ">.ToString( System.Ord( Self."
                        << prop_name((*f_iter), is_exception) << ")));" << '\n';
     } else if (ttype->is_uuid()) {
@@ -4048,9 +3908,7 @@
 }
 
 bool t_delphi_generator::is_void(t_type* type) {
-  while (type->is_typedef()) {
-    type = ((t_typedef*)type)->get_type();
-  }
+  type = type->get_true_type();
 
   if (type->is_base_type()) {
     t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
diff --git a/lib/delphi/test/serializer/SerializerData.dpr b/lib/delphi/test/serializer/SerializerData.dpr
index 92ed00b..637e4ed 100644
--- a/lib/delphi/test/serializer/SerializerData.dpr
+++ b/lib/delphi/test/serializer/SerializerData.dpr
@@ -40,6 +40,8 @@
   Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
   System_ in 'gen-delphi\System_.pas',
   SysUtils_ in 'gen-delphi\SysUtils_.pas',
+  test.ExceptionStruct in 'gen-delphi\test.ExceptionStruct.pas',
+  test.SimpleException in 'gen-delphi\test.SimpleException.pas',
   DebugProtoTest in 'gen-delphi\DebugProtoTest.pas',
   TestSerializer.Data in 'TestSerializer.Data.pas';
 
@@ -69,11 +71,26 @@
 end;
 
 
+function CreateBatchGetResponse : IBatchGetResponse; stdcall;
+begin
+  result := Fixtures.CreateBatchGetResponse;
+end;
+
+
+function CreateSimpleException : IError; stdcall;
+begin
+  result := Fixtures.CreateSimpleException;
+end;
+
+
 exports
   CreateOneOfEach,
   CreateNesting,
   CreateHolyMoley,
-  CreateCompactProtoTestStruct;
+  CreateCompactProtoTestStruct,
+  CreateBatchGetResponse,
+  CreateSimpleException;
+
 
 begin
   IsMultiThread := TRUE;
diff --git a/lib/delphi/test/serializer/SerializerData.dproj b/lib/delphi/test/serializer/SerializerData.dproj
index cfc27f8..cdad312 100644
--- a/lib/delphi/test/serializer/SerializerData.dproj
+++ b/lib/delphi/test/serializer/SerializerData.dproj
@@ -1,22 +1,4 @@
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
-   http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
--->
-	<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+	<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 		<PropertyGroup>
 			<ProjectGuid>{B523D1D7-2C9A-4B39-A6CF-69EF536D5079}</ProjectGuid>
 			<MainSource>SerializerData.dpr</MainSource>
@@ -85,6 +67,8 @@
 			<DCCReference Include="..\..\src\Thrift.TypeRegistry.pas"/>
 			<DCCReference Include="gen-delphi\System_.pas"/>
 			<DCCReference Include="gen-delphi\SysUtils_.pas"/>
+			<DCCReference Include="gen-delphi\test.ExceptionStruct.pas"/>
+			<DCCReference Include="gen-delphi\test.SimpleException.pas"/>
 			<DCCReference Include="gen-delphi\DebugProtoTest.pas"/>
 			<DCCReference Include="TestSerializer.Data.pas"/>
 			<BuildConfiguration Include="Release">
@@ -100,10 +84,12 @@
 			</BuildConfiguration>
 		</ItemGroup>
 		<Import Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')" Project="$(BDS)\Bin\CodeGear.Delphi.Targets"/>
-		<Import Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')" Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj"/>
+		<Import Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\8.0\UserTools.proj')" Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\8.0\UserTools.proj"/>
 		<PropertyGroup>
-			<PreBuildEvent><![CDATA[thrift.exe -r -gen delphi:com_types ..\keywords\ReservedKeywords.thrift
-thrift.exe -r -gen delphi:com_types ..\..\..\..\test\DebugProtoTest.thrift]]></PreBuildEvent>
+			<PreBuildEvent><![CDATA[thrift.exe -r -gen delphi:com_types,rtti ..\keywords\ReservedKeywords.thrift
+thrift.exe -r -gen delphi:com_types ..\..\..\..\test\DebugProtoTest.thrift
+thrift.exe -r -gen delphi:com_types ..\..\..\..\test\ExceptionStruct.thrift
+thrift.exe -r -gen delphi:com_types SimpleException.thrift]]></PreBuildEvent>
 		</PropertyGroup>
 		<ProjectExtensions>
 			<Borland.Personality>Delphi.Personality.12</Borland.Personality>
@@ -140,6 +126,9 @@
 					<Source>
 						<Source Name="MainSource">SerializerData.dpr</Source>
 					</Source>
+					<Parameters>
+						<Parameters Name="HostApplication">bin\Debug\Win32\TestSerializer.exe</Parameters>
+					</Parameters>
 				</Delphi.Personality>
 				<Platforms>
 					<Platform value="Win32">True</Platform>
diff --git a/lib/delphi/test/serializer/SimpleException.thrift b/lib/delphi/test/serializer/SimpleException.thrift
new file mode 100644
index 0000000..c13876c
--- /dev/null
+++ b/lib/delphi/test/serializer/SimpleException.thrift
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+namespace * test.SimpleException
+
+exception Error {
+  1: i32    ErrorCode = 42
+  /** test name collision with Exception class */
+  2: Error  InnerException                  
+  /** test name collisions with Thrift Delphi implementation details */
+  3: uuid   ExceptionData = '00000000-4444-CCCC-ffff-0123456789ab'    
+}
+
+
+
+// EOF
diff --git a/lib/delphi/test/serializer/TestSerializer.Data.pas b/lib/delphi/test/serializer/TestSerializer.Data.pas
index 24f850d..ddf4ba2 100644
--- a/lib/delphi/test/serializer/TestSerializer.Data.pas
+++ b/lib/delphi/test/serializer/TestSerializer.Data.pas
@@ -27,6 +27,8 @@
   ComObj,
   Thrift.Protocol,
   Thrift.Collections,
+  test.ExceptionStruct,
+  test.SimpleException,
   DebugProtoTest;
 
 
@@ -37,6 +39,8 @@
     class function CreateNesting : INesting;
     class function CreateHolyMoley : IHolyMoley;
     class function CreateCompactProtoTestStruct : ICompactProtoTestStruct;
+    class function CreateBatchGetResponse : IBatchGetResponse;
+    class function CreateSimpleException : IError;
 
   // These byte arrays are serialized versions of the above structs.
   // They were serialized in binary protocol using thrift 0.6.x and are used to
@@ -359,6 +363,51 @@
 end;
 
 
+class function Fixtures.CreateBatchGetResponse : IBatchGetResponse;
+var
+  data : IGetRequest;
+  error : ISomeException;
+const
+  REQUEST_ID = '123';
+begin
+  data := TGetRequestImpl.Create;
+  data.Id := REQUEST_ID;
+  data.Data := TThriftBytesImpl.Create( TEncoding.UTF8.GetBytes( #0#1#2#3#4#5#6#7#8));
+
+  error := TSomeExceptionImpl.Create;
+  error.Error := TErrorCode.GenericError;
+
+  result := TBatchGetResponseImpl.Create;
+  result.Responses := TThriftDictionaryImpl<WideString, IGetRequest>.Create;
+  result.Responses.Add( REQUEST_ID, data);
+  result.Errors := TThriftDictionaryImpl<WideString, ISomeException>.Create;
+  result.Errors.Add( REQUEST_ID, error);
+end;
+
+
+class function Fixtures.CreateSimpleException : IError;
+var i : Integer;
+    inner : IError;
+    guid : TGuid;
+const
+  IDL_GUID_VALUE : TGuid = '{00000000-4444-CCCC-ffff-0123456789ab}';
+begin
+  result := nil;
+  for i := 0 to 4 do begin
+    inner := result;
+    result := TErrorImpl.Create;
+
+    // validate const values set in IDL
+    ASSERT( result.ErrorCode = 42);  // IDL default value
+    ASSERT( IsEqualGUID( result.ExceptionData, IDL_GUID_VALUE));
+
+    // set fresh, but reproducible values
+    FillChar( guid, SizeOf(guid), i);
+    result.ErrorCode := i;
+    result.ExceptionData := guid;
+    result.InnerException := inner;
+  end;
+end;
 
 
 end.
diff --git a/lib/delphi/test/serializer/TestSerializer.Tests.pas b/lib/delphi/test/serializer/TestSerializer.Tests.pas
index e6a309e..466fb26 100644
--- a/lib/delphi/test/serializer/TestSerializer.Tests.pas
+++ b/lib/delphi/test/serializer/TestSerializer.Tests.pas
@@ -41,6 +41,8 @@
   Thrift.WinHTTP,
   Thrift.TypeRegistry,
   System_,
+  test.ExceptionStruct,
+  test.SimpleException,
   DebugProtoTest;
 
 {$TYPEINFO ON}
@@ -82,8 +84,11 @@
     procedure Test_Serializer_Deserializer;
     procedure Test_COM_Types;
     procedure Test_ThriftBytesCTORs;
-    procedure Test_OneOfEach(     const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
-    procedure Test_CompactStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
+
+    procedure Test_OneOfEach(       const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
+    procedure Test_CompactStruct(   const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
+    procedure Test_ExceptionStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
+    procedure Test_SimpleException( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
 
   public
     constructor Create;
@@ -100,6 +105,8 @@
 function CreateNesting : INesting; stdcall; external SERIALIZERDATA_DLL;
 function CreateHolyMoley : IHolyMoley; stdcall; external SERIALIZERDATA_DLL;
 function CreateCompactProtoTestStruct : ICompactProtoTestStruct; stdcall; external SERIALIZERDATA_DLL;
+function CreateBatchGetResponse : IBatchGetResponse; stdcall; external SERIALIZERDATA_DLL;
+function CreateSimpleException : IError; stdcall; external SERIALIZERDATA_DLL;
 
 
 { TTestSerializer }
@@ -266,6 +273,105 @@
 end;
 
 
+procedure TTestSerializer.Test_ExceptionStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
+var tested, correct : IBatchGetResponse;
+    bytes   : TBytes;
+    corrDP, testDP : TPair<WideString, IGetRequest>;
+    corrEP, testEP : TPair<WideString, ISomeException>;
+begin
+  // write
+  tested := CreateBatchGetResponse;
+  case method of
+    mt_Bytes:  bytes := Serialize( tested, factory);
+    mt_Stream: begin
+      stream.Size := 0;
+      Serialize( tested, factory, stream);
+    end
+  else
+    ASSERT( FALSE);
+  end;
+
+  // init + read
+  correct := TBatchGetResponseImpl.Create;
+  case method of
+    mt_Bytes:  Deserialize( bytes, tested, factory);
+    mt_Stream: begin
+      stream.Position := 0;
+      Deserialize( stream, tested, factory);
+    end
+  else
+    ASSERT( FALSE);
+  end;
+
+  // check
+  correct := CreateBatchGetResponse;
+
+  // rewrite the following test if not
+  ASSERT( tested.Responses.Count = 1);
+  ASSERT( correct.Responses.Count = tested.Responses.Count);
+  for corrDP in correct.Responses do begin
+    for testDP in tested.Responses do begin
+      ASSERT( corrDP.Key = testDP.Key);
+      ASSERT( corrDP.Value.Id = testDP.Value.Id);
+      ASSERT( corrDP.Value.Data.Count = testDP.Value.Data.Count);
+    end;
+  end;
+
+  // rewrite the following test if not
+  ASSERT( tested.Errors.Count = 1);
+  ASSERT( correct.Errors.Count = tested.Errors.Count);
+  for corrEP in correct.Errors do begin
+    for testEP in tested.Errors do begin
+      ASSERT( corrEP.Key = testEP.Key);
+      ASSERT( corrEP.Value.Error = testEP.Value.Error);
+    end;
+  end;
+end;
+
+
+procedure TTestSerializer.Test_SimpleException( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
+var tested, correct : IError;
+    bytes   : TBytes;
+begin
+  // write
+  tested := CreateSimpleException;
+  case method of
+    mt_Bytes:  bytes := Serialize( tested, factory);
+    mt_Stream: begin
+      stream.Size := 0;
+      Serialize( tested, factory, stream);
+    end
+  else
+    ASSERT( FALSE);
+  end;
+
+  // init + read
+  correct := TErrorImpl.Create;
+  case method of
+    mt_Bytes:  Deserialize( bytes, tested, factory);
+    mt_Stream: begin
+      stream.Position := 0;
+      Deserialize( stream, tested, factory);
+    end
+  else
+    ASSERT( FALSE);
+  end;
+
+  // check
+  correct := CreateSimpleException;
+  while correct <> nil do begin
+    // validate
+    ASSERT( correct.ErrorCode = tested.ErrorCode);
+    ASSERT( IsEqualGUID( correct.ExceptionData, tested.ExceptionData));
+
+    // iterate
+    correct := correct.InnerException;
+    tested  := tested.InnerException;
+    ASSERT( (tested <> nil) xor (correct = nil));  // both or none
+  end;
+end;
+
+
 procedure TTestSerializer.Test_Serializer_Deserializer;
 var factory : TFactoryPair;
     stream  : TFileStream;
@@ -279,8 +385,10 @@
       for factory in FProtocols do begin
         Writeln('- '+UserFriendlyName(factory));
 
-        Test_OneOfEach(     method, factory, stream);
-        Test_CompactStruct( method, factory, stream);
+        Test_OneOfEach(       method, factory, stream);
+        Test_CompactStruct(   method, factory, stream);
+        Test_ExceptionStruct( method, factory, stream);
+        Test_SimpleException( method, factory, stream);
       end;
 
       Writeln;
diff --git a/lib/delphi/test/serializer/TestSerializer.dpr b/lib/delphi/test/serializer/TestSerializer.dpr
index b78c0db..8c2f64d 100644
--- a/lib/delphi/test/serializer/TestSerializer.dpr
+++ b/lib/delphi/test/serializer/TestSerializer.dpr
@@ -44,6 +44,8 @@
   System_ in 'gen-delphi\System_.pas',
   SysUtils_ in 'gen-delphi\SysUtils_.pas',
   DebugProtoTest in 'gen-delphi\DebugProtoTest.pas',
+  test.ExceptionStruct in 'gen-delphi\test.ExceptionStruct.pas',
+  test.SimpleException in 'gen-delphi\test.SimpleException.pas',
   TestSerializer.Tests in 'TestSerializer.Tests.pas';
 
 
diff --git a/lib/delphi/test/serializer/TestSerializer.dproj b/lib/delphi/test/serializer/TestSerializer.dproj
index 383e04a..5ea2b79 100644
--- a/lib/delphi/test/serializer/TestSerializer.dproj
+++ b/lib/delphi/test/serializer/TestSerializer.dproj
@@ -1,22 +1,4 @@
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
-   http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
--->
-	<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+	<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 		<PropertyGroup>
 			<ProjectGuid>{9282EDD8-7C12-41B0-8172-61C6BFA6E238}</ProjectGuid>
 			<MainSource>TestSerializer.dpr</MainSource>
@@ -85,6 +67,8 @@
 			<DCCReference Include="gen-delphi\System_.pas"/>
 			<DCCReference Include="gen-delphi\SysUtils_.pas"/>
 			<DCCReference Include="gen-delphi\DebugProtoTest.pas"/>
+			<DCCReference Include="gen-delphi\test.ExceptionStruct.pas"/>
+			<DCCReference Include="gen-delphi\test.SimpleException.pas"/>
 			<DCCReference Include="TestSerializer.Tests.pas"/>
 			<BuildConfiguration Include="Debug">
 				<Key>Cfg_2</Key>
@@ -99,10 +83,12 @@
 			</BuildConfiguration>
 		</ItemGroup>
 		<Import Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')" Project="$(BDS)\Bin\CodeGear.Delphi.Targets"/>
-		<Import Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')" Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj"/>
+		<Import Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\8.0\UserTools.proj')" Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\8.0\UserTools.proj"/>
 		<PropertyGroup>
 			<PreBuildEvent><![CDATA[thrift.exe -r -gen delphi:com_types,rtti ..\keywords\ReservedKeywords.thrift
-thrift.exe -r -gen delphi:com_types ..\..\..\..\test\DebugProtoTest.thrift]]></PreBuildEvent>
+thrift.exe -r -gen delphi:com_types ..\..\..\..\test\DebugProtoTest.thrift
+thrift.exe -r -gen delphi:com_types ..\..\..\..\test\ExceptionStruct.thrift
+thrift.exe -r -gen delphi:com_types SimpleException.thrift]]></PreBuildEvent>
 		</PropertyGroup>
 		<ProjectExtensions>
 			<Borland.Personality>Delphi.Personality.12</Borland.Personality>