text: // balxml_encoder.h                                                   -*-C++-*-
  
  // ----------------------------------------------------------------------------
  //                                   NOTICE
  //
  // This component is not up to date with current BDE coding standards, and
  // should not be used as an example for new development.
  // ----------------------------------------------------------------------------
  
  #ifndef INCLUDED_BALXML_ENCODER
  #define INCLUDED_BALXML_ENCODER
  
  #include <bsls_ident.h>
  BSLS_IDENT("$Id: $")
  
  //@PURPOSE: Provide an XML encoder utility.
  //
  //@CLASSES:
  //  balxml::Encoder: XML encoder utility class
  //
  //@SEE_ALSO: balxml_decoder, balber_berencoder
  //
  //@DESCRIPTION: This component provides a class for encoding value-semantic
  // objects in XML format.  In particular, the 'balxml::Encoder' 'class'
  // contains a parameterized 'encode' function that encodes a specified
  // value-semantic object into a specified stream.  There are three overloaded
  // versions of this function:
  //
  //: o writes to an 'bsl::streambuf'
  //: o writes to an 'bsl::ostream'
  //: o writes to an 'balxml::Formatter'
  //
  // The 'encode' function encodes objects in XML format, which is a very useful
  // format for debugging.  For more efficient performance, a binary encoding
  // (such as BER) should be used.
  //
  // This component can be used with types supported by the 'bdlat' framework.
  // In particular, types generated by the 'bas_codegen.pl' tool can be used.
  //
  ///Usage
  ///-----
  // The following snippets of code illustrate the usage of this component.
  // Suppose we have an XML schema inside a file named 'employee.xsd':
  //..
  //  <?xml version='1.0' encoding='UTF-8'?>
  //  <xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'
  //             xmlns:test='http://bloomberg.com/schemas/test'
  //             targetNamespace='http://bloomberg.com/schemas/test'
  //             elementFormDefault='unqualified'>
  //
  //      <xs:complexType name='Address'>
  //          <xs:sequence>
  //              <xs:element name='street' type='xs:string'/>
  //              <xs:element name='city'   type='xs:string'/>
  //              <xs:element name='state'  type='xs:string'/>
  //          </xs:sequence>
  //      </xs:complexType>
  //
  //      <xs:complexType name='Employee'>
  //          <xs:sequence>
  //              <xs:element name='name'        type='xs:string'/>
  //              <xs:element name='homeAddress' type='test:Address'/>
  //              <xs:element name='age'         type='xs:int'/>
  //          </xs:sequence>
  //      </xs:complexType>
  //  </xs:schema>
  //..
  // Using the 'bas_codegen.pl' tool, we generate C++ classes for this schema as
  // follows:
  //..
  //  $ bas_codegen.pl -m msg -p test employee.xsd
  //..
  // This tool will generate the header and implementation files for the
  // 'test_messages' components in the current directory.
  //
  // Now suppose we wanted to encode information about a particular employee
  // using XML encoding to the standard output, and using the 'PRETTY' option for
  // formatting the output.  The following function will do this:
  //..
  //  #include <test_messages.h>
  //
  //  #include <balxml_encoder.h>
  //  #include <balxml_encodingstyle.h>
  //
  //  #include <bsl_iostream.h>
  //  #include <bsl_sstream.h>
  //
  //  using namespace BloombergLP;
  //
  //  void usageExample()
  //  {
  //      test::Employee bob;
  //
  //      bob.name()                 = "Bob";
  //      bob.homeAddress().street() = "Some Street";
  //      bob.homeAddress().city()   = "Some City";
  //      bob.homeAddress().state()  = "Some State";
  //      bob.age()                  = 21;
  //
  //      balxml::EncoderOptions options;
  //      options.setEncodingStyle(balxml::EncodingStyle::BAEXML_PRETTY);
  //
  //      balxml::Encoder encoder(&options, &bsl::cerr, &bsl::cerr);
  //
  //      const bsl::string EXPECTED_OUTPUT =
  //       "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
  //       "<Employee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
  //       "    <name>Bob</name>\n"
  //       "    <homeAddress>\n"
  //       "        <street>Some Street</street>\n"
  //       "        <city>Some City</city>\n"
  //       "        <state>Some State</state>\n"
  //       "    </homeAddress>\n"
  //       "    <age>21</age>\n"
  //       "</Employee>\n";
  //
  //      bsl::ostringstream os;
  //      const int rc = encoder.encodeToStream(os, bob);
  //
  //      assert(0 == rc);
  //      assert(EXPECTED_OUTPUT == os.str());
  //  }
  //..
  
  #include <balscm_version.h>
  
  #include <balxml_encoderoptions.h>
  #include <balxml_encodingstyle.h>
  #include <balxml_errorinfo.h>      // for Severity
  #include <balxml_formatter.h>
  #include <balxml_typesprintutil.h>
  
  #include <bdlat_arrayfunctions.h>
  #include <bdlat_choicefunctions.h>
  #include <bdlat_nullablevaluefunctions.h>
  #include <bdlat_sequencefunctions.h>
  #include <bdlat_typecategory.h>
  #include <bdlat_typename.h>
  
  #include <bdlsb_memoutstreambuf.h>
  
  #include <bslma_allocator.h>
  #include <bslma_default.h>
  #include <bslma_usesbslmaallocator.h>
  
  #include <bslmf_nestedtraitdeclaration.h>
  
  #include <bsls_assert.h>
  #include <bsls_objectbuffer.h>
  #include <bsls_review.h>
  
  #include <bsl_ostream.h>
  #include <bsl_string.h>
  #include <bsl_vector.h>
  
  namespace BloombergLP {
  namespace balxml {
  
  class Encoder_Context;
  
                                 // =============
                                 // class Encoder
                                 // =============
  
  class Encoder {
      // This 'class' contains the parameterized 'encode' functions that encode
      // 'bdlat' types in XML format.
  
      // FRIENDS
      friend class Encoder_Context;
  
    private:
      // PRIVATE TYPES
      class MemOutStream : public bsl::ostream
      {
          // This class provides stream for logging using
          // 'bdlsb::MemOutStreamBuf' as a streambuf.  The logging stream is
          // created on demand, i.e., during the first attempt to log message.
          bdlsb::MemOutStreamBuf d_sb;
  
          // Not implemented:
          MemOutStream(const MemOutStream&);
          MemOutStream& operator=(const MemOutStream&);
  
        public:
          // CREATORS
          MemOutStream(bslma::Allocator *basicAllocator = 0);
              // Create a new stream using the optionally specified
              // 'basicAllocator'.
  
          virtual ~MemOutStream();
              // Destroy this stream and release memory back to the allocator.
              //
              // Although the compiler should generate this destructor
              // implicitly, xlC 8 breaks when the destructor is called by name
              // unless it is explicitly declared.
  
          // MANIPULATORS
          void reset();
              // Reset the internal streambuf to empty.
  
          // ACCESSORS
          const char *data() const;
              // Return a pointer to the memory containing the formatted values
              // formatted to this stream.  The data is not null-terminated
              // unless a null character was appended onto this stream.
  
          int length() const;
              // Return the length of the formatted data, including null
              // characters appended to the stream, if any.
      };
  
    private:
      // DATA
      const EncoderOptions            *d_options;        // held, not owned
      bslma::Allocator                *d_allocator;      // held, not owned
  
      bsls::ObjectBuffer<MemOutStream> d_logArea;
          // placeholder for MemOutStream
  
      MemOutStream                    *d_logStream;
          // if not zero, log stream was created at the moment of first logging
          // and must be destroyed
  
      ErrorInfo::Severity              d_severity;       // error severity
  
      bsl::ostream                    *d_errorStream;    // held, not owned
      bsl::ostream                    *d_warningStream;  // held, not owned
  
      // PRIVATE MANIPULATORS
      ErrorInfo::Severity logError(const char               *text,
                                   const bslstl::StringRef&  tag,
                                   int                       formattingMode,
                                   int                       index = -1);
  
      bsl::ostream& logStream();
          // Return the stream for logging.  Note the if stream has not been
          // created yet, it will be created during this call.
  
    public:
      // TRAITS
      BSLMF_NESTED_TRAIT_DECLARATION(Encoder, bslma::UsesBslmaAllocator);
  
      // CREATORS
      Encoder(const EncoderOptions *options, bslma::Allocator *basicAllocator);
  
      Encoder(const EncoderOptions *options,
              bsl::ostream         *errorStream   = 0,
              bsl::ostream         *warningStream = 0,
              bslma::Allocator     *basicAllocator = 0);
          // Construct a encoder object using the specified 'options'.  Errors
          // and warnings will be rendered to the optionally specified
          // 'errorStream' and 'warningStream' respectively.
  
      ~Encoder();
          // Destroy this object.  This destruction has no effect on objects
          // pointed-to by the pointers provided at construction.
  
      template <class TYPE>
      int encode(bsl::streambuf *buffer, const TYPE& object);
          // Encode the specified non-modifiable 'object' to the specified
          // 'buffer'.  Return 0 on success, and a non-zero value otherwise.
          // Note that the encoder will use encoder options, error and warning
          // streams specified at the construction time.
  
      template <class TYPE>
      int encodeToStream(bsl::ostream& stream, const TYPE& object);
          // Encode the specified non-modifiable 'object' to the specified
          // 'stream'.  Return 0 on success, and a non-zero value otherwise.
          // Note that the encoder will use encoder options, error and warning
          // streams specified at the construction time.
  
      template <class TYPE>
      bsl::ostream& encode(bsl::ostream& stream, const TYPE& object);
          // Encode the specified non-modifiable 'object' to the specified
          // 'stream'.  Return a reference to 'stream'.  If an encoding error is
          // detected, 'stream.fail()' will be true on return.  Note that the
          // encoder will use encoder options, error and warning streams
          // specified at the construction time.  IMPORTANT: The use of
          // 'stream.fail()' to communicate errors to the caller has two
          // consequences: 1) if 'stream' is the same as the 'errorStream'
          // passed to the constructor, then the error message may be suppressed
          // (because of the output/error stream becoming invalidated) and 2) it
          // is important to call 'stream.clear()' after testing the stream
          // state.  To avoid these issues, we recommend that you use use
          // 'encodeToStream', above, instead of this version of 'encode'.
  
      template <class TYPE>
      int encode(Formatter& formatter, const TYPE& object);
          // Encode the specified non-modifiable 'object' to the specified
          // 'formatter'.  Return 0 on success, and a non-zero value otherwise.
          // Note that encoder will use encoder options, error and warning
          // streams specified at the construction time.
  
      //ACCESSORS
      const EncoderOptions *options() const;
          // Return the encoder options.
  
      bool isCompact() const;
          // Return 'true' if the encoding style in the encoder options is
          // defined as 'EncodingStyle::BAEXML_COMPACT', and 'false' otherwise.
  
      bsl::ostream *errorStream() const;
          // Return pointer to the error stream.
  
      bsl::ostream *warningStream() const;
          // Return pointer to the warning stream.
  
      ErrorInfo::Severity  errorSeverity() const;
          // Return the severity of the most severe warning or error encountered
          // during the last call to the 'encode' method.  The severity is reset
          // each time 'encode' is called.
  
      bslstl::StringRef loggedMessages() const;
          // Return a string containing any error, warning, or trace messages
          // that were logged during the last call to the 'encode' method.  The
          // log is reset each time 'encode' is called.
  };
  
  // ---- Anything below this line is implementation specific.  Do not use.  ----
  
                             // ======================
                             // struct Encoder_Context
                             // ======================
  
  class Encoder_Context {
      // This 'struct' contains state that is maintained during encoding.  It
      // also contains methods for switching between pretty formatting and
      // compact formatting, based on the encoding options.
  
      // DATA
      Formatter  *d_formatter;
      Encoder    *d_encoder;
  
      // NOT IMPLEMENTED
      Encoder_Context(const Encoder_Context& other);
      Encoder_Context& operator=(const Encoder_Context& other);
  
    public:
      // CREATORS
      Encoder_Context(Formatter *formatter, Encoder *encoder);
  
      // MANIPULATORS
      template <class NAME_TYPE, class VALUE_TYPE>
      void addAttribute(const NAME_TYPE& name, const VALUE_TYPE& value);
  
      template<class NAME_TYPE, class VALUE_TYPE>
      void addAttribute(const NAME_TYPE&  name,
                        const VALUE_TYPE& value,
                        int               formattingMode);
  
      template <class NAME_TYPE>
      void closeElement(const NAME_TYPE& name);
  
      void invalidate();
  
      ErrorInfo::Severity logError(const char               *text,
                                   const bslstl::StringRef&  tag,
                                   int                       formattingMode,
                                   int                       index = -1);
  
      template <class NAME_TYPE>
      void openElement(const NAME_TYPE& name);
  
      bsl::ostream& rawOutputStream();
  
      // ACCESSORS
      const EncoderOptions& encoderOptions() const;
  
      int status() const;
  };
  
                    // =======================================
                    // struct Encoder_OptionsCompatibilityUtil
                    // =======================================
  
  struct Encoder_OptionsCompatibilityUtil {
      // Component-private 'struct'.  Do not use.
      //
      // This struct provides a namespace for a suite of functions used to
      // compute the options for the underlying XML formatter used by the
      // encoder, given the encoder's options.
  
    private:
      // PRIVATE CLASS METHODS
      static int getFormatterInitialIndentLevel(
                                           const EncoderOptions& encoderOptions);
          // Return the value of the 'InitialIndentLevel' field for a
          // 'FormatterOptions' object that corresponds to the specified
          // 'encoderOptions', which is 0 if the 'EncodingStyle' of
          // 'encoderOptions' is 'EncodingStyle::e_COMPACT', and is the value of
          // 'InitialIndentLevel' of 'encoderOptions' otherwise.
  
      static int getFormatterSpacesPerLevel(
                                           const EncoderOptions& encoderOptions);
          // Return the value of the 'SpacesPerLevel' field for a
          // 'FormatterOptions' object that corresponds to the specified
          // 'encoderOptions', which is 0 if the 'EncodingStyle' of
          // 'encoderOptions' is 'EncodingStyle::e_COMPACT', and is the value of
          // 'SpacesPerLevel' of 'encoderOptions' otherwise.
  
      static int getFormatterWrapColumn(const EncoderOptions& encoderOptions);
          // Return the value of the 'WrapColumn' field for a
          // 'FormatterOptions' object that corresponds to the specified
          // 'encoderOptions', which is -1 if the 'EncodingStyle' of
          // 'encoderOptions' is 'EncodingStyle::e_COMPACT', and is the value of
          // 'WrapColumn' of 'encoderOptions' otherwise.
  
    public:
      // CLASS METHODS
      static void getFormatterOptions(
                                  int                   *formatterIndentLevel,
                                  int                   *formatterSpacesPerLevel,
                                  int                   *formatterWrapColumn,
                                  EncoderOptions        *formatterOptions,
                                  const EncoderOptions&  encoderOptions);
          // Load to the specified 'formatterIndentLevel',
          // 'formatterSpacesPerLevel', and 'formatterWrapColumn', the number of
          // spaces to indent the first element in the XML document, the number
          // of spaces to use for indenting each level of nesting in the
          // document, and the maximum horizontal column number after which the
          // encoder should insert a line break, respectively, based on the
          // specified 'encoderOptions'.  Load to the specified
          // 'formatterOptions' the options that the formatter should use to emit
          // XML, based on the 'encoderOptions'.  The behavior is undefined
          // unless 'formatterOptions' has the default value.
  };
  
                           // ==========================
                           // class Encoder_EncodeObject
                           // ==========================
  
  class Encoder_EncodeObject {
      // Component-private class.  Do not use.
      //
      // This struct encodes an object *with* enclosing tags.  Compared to the
      // 'EncoderUtil_EncodeValue' class below, this class prefixes the value
      // with an opening tag, and suffixes the value with a closing tag.  In
      // pseudocode, this is equivalent to:
      //..
      //  openTag()
      //  Encoder_EncodeValue()
      //  closeTag()
      //..
      // There is an overloaded version of 'bsl::vector<char>' because, based on
      // the formatting mode, this class needs to switch between encoding the
      // value in a single tag (i.e., when using BASE64, TEXT, IS_LIST or HEX)
      // and encoding the value in multiple tags (i.e., when repetition is used).
  
      // PRIVATE TYPES
      struct CanBeListOrRepetition { };
      struct CanBeRepetitionOnly   { };
  
      // PRIVATE DATA MEMBERS
      Encoder_Context *d_context_p;
  
    public:
      // IMPLEMENTATION MANIPULATORS
      template <class TYPE>
      int executeImp(const TYPE&               object,
                     const bslstl::StringRef&  tag,
                     int                       formattingMode,
                     bdlat_TypeCategory::Array);
  
      template <class TYPE>
      int executeImp(const TYPE&                       object,
                     const bslstl::StringRef&          tag,
                     int                               formattingMode,
                     bdlat_TypeCategory::NullableValue);
  
      template <class TYPE>
      int executeImp(const TYPE&                     object,
                     const bslstl::StringRef&        tag,
                     int                             formattingMode,
                     bdlat_TypeCategory::DynamicType);
  
      template <class TYPE, class ANY_CATEGORY>
      int executeImp(const TYPE&              object,
                     const bslstl::StringRef& tag,
                     int                      formattingMode,
                     ANY_CATEGORY);
  
      int executeImp(const bsl::vector<char>&  object,
                     const bslstl::StringRef&  tag,
                     int                       formattingMode,
                     bdlat_TypeCategory::Array);
  
      template <class TYPE>
      int executeArrayListImp(const TYPE& object, const bslstl::StringRef& tag);
  
      template <class TYPE>
      int executeArrayRepetitionImp(const TYPE&              object,
                                    const bslstl::StringRef& tag,
                                    int                      formattingMode);
  
    private:
      // NOT IMPLEMENTED
      Encoder_EncodeObject(const Encoder_EncodeObject&);
      Encoder_EncodeObject& operator=(const Encoder_EncodeObject&);
  
    public:
      // CREATORS
      explicit Encoder_EncodeObject(Encoder_Context *context);
  
      // Using compiler generated destructor:
      //  ~Encoder_EncodeObject();
  
      // MANIPULATORS
      template <class TYPE, class INFO_TYPE>
      int operator()(const TYPE& object, const INFO_TYPE& info);
  
      template <class TYPE>
      int execute(const TYPE&              object,
                  const bslstl::StringRef& tag,
                  int                      formattingMode);
  };
  
                           // =========================
                           // class Encoder_EncodeValue
                           // =========================
  
  class Encoder_EncodeValue {
      // Component-private class.  Do not use.
      //
      // This class just encodes a value *without* any enclosing tags.
  
      // PRIVATE DATA MEMBERS
      Encoder_Context *d_context_p;
  
    public:
      // IMPLEMENTATION MANIPULATORS
      template <class TYPE>
      int executeImp(const TYPE&                  object,
                     int                          formattingMode,
                     bdlat_TypeCategory::Sequence);
  
      template <class TYPE>
      int executeImp(const TYPE&                object,
                     int                        formattingMode,
                     bdlat_TypeCategory::Choice);
  
      template <class TYPE>
      int executeImp(const TYPE&                     object,
                     int                             formattingMode,
                     bdlat_TypeCategory::DynamicType);
  
      template <class TYPE, class ANY_CATEGORY>
      int executeImp(const TYPE& object, int formattingMode, ANY_CATEGORY);
  
    private:
      // NOT IMPLEMENTED
      Encoder_EncodeValue(const Encoder_EncodeValue&);
      Encoder_EncodeValue& operator=(const Encoder_EncodeValue&);
  
    public:
      // CREATORS
      explicit Encoder_EncodeValue(Encoder_Context *context);
  
      // Using compiler generated destructor:
      //  ~Encoder_EncodeValue();
  
      // MANIPULATORS
      template <class TYPE, class INFO_TYPE>
      int operator()(const TYPE& object, const INFO_TYPE& info);
  
      template <class TYPE>
      int execute(const TYPE& object, int formattingMode);
  };
  
                        // ===============================
                        // class Encoder_SequenceFirstPass
                        // ===============================
  
  class Encoder_SequenceFirstPass {
      // Component private class.  Do not use.
      //
      // This class is used as the first pass when encoding elements of a
      // sequence.  It basically does two things:
      //     o encode elements with the
      //       'bdlat_FormattingMode::e_IS_ATTRIBUTE' flag using the
      //       'Formatter::addAttribute' method.
      //     o looks for an element with the
      //       'bdlat_FormattingMode::e_IS_SIMPLE_CONTENT' flag and, if
      //       found, provides accessors to obtain the 'id' of the element.
      //       Note that the behavior is undefined unless there is only one
      //       element with 'IS_SIMPLE_CONTENT' flag and, if this element exist,
      //       all other elements must have 'IS_ATTRIBUTE' flag.
  
      // PRIVATE DATA MEMBERS
      Encoder_Context   *d_context_p;        // held, not owned
      bool                      d_hasSubElements;   // true if an element with
                                                    // neither 'IS_ATTRIBUTE' nor
                                                    // 'IS_SIMPLE_CONTENT' is
                                                    // found
      bdlb::NullableValue<int>  d_simpleContentId;  // the 'id' of the element
                                                    // with 'IS_SIMPLE_CONTENT'
                                                    // flag, if found
  
    public:
      // IMPLEMENTATION MANIPULATORS
      template <class TYPE>
      int addAttributeImp(const TYPE&                       object,
                          const bslstl::StringRef&          name,
                          int                               formattingMode,
                          bdlat_TypeCategory::NullableValue);
      template <class TYPE>
      int addAttributeImp(const TYPE&                     object,
                          const bslstl::StringRef&        name,
                          int                             formattingMode,
                          bdlat_TypeCategory::DynamicType);
      template <class TYPE, class ANY_CATEGORY>
      int addAttributeImp(const TYPE&              object,
                          const bslstl::StringRef& name,
                          int                      formattingMode,
                          ANY_CATEGORY);
          // Add an attribute with the specified 'name', the value of the
          // specified 'object', using the specified 'formattingMode'.  Note that
          // the last argument is used for overloading purposes only.
  
      template <class TYPE>
      int addAttribute(const TYPE&              object,
                       const bslstl::StringRef& name,
                       int                      formattingMode);
          // Add an attribute with the specified 'name', the value of the
          // specified 'object', using the specified 'formattingMode'.
  
    private:
      // NOT IMPLEMENTED
      Encoder_SequenceFirstPass(const Encoder_SequenceFirstPass&);
      Encoder_SequenceFirstPass& operator=(const Encoder_SequenceFirstPass&);
  
    public:
      // CREATORS
      explicit Encoder_SequenceFirstPass(Encoder_Context *context);
          // Create a visitor for first pass for sequences.
  
      // Generated by compiler:
      //  ~Encoder_SequenceFirstPass();
  
      // MANIPULATORS
      template <class TYPE, class INFO_TYPE>
      int operator()(const TYPE& object, const INFO_TYPE& info);
          // Called back when an element is visited.
  
      // ACCESSORS
      const bool& hasSubElements() const;
          // Return true if a sub-element is found, and false otherwise.
  
      const bdlb::NullableValue<int>& simpleContentId() const;
          // Return a null value if there is no element with 'IS_SIMPLE_CONTENT'
          // flag, or a non-null value with the integer 'id' of the element
          // otherwise.
  };
  
                        // ================================
                        // class Encoder_SequenceSecondPass
                        // ================================
  
  class Encoder_SequenceSecondPass {
      // Component-private class.  Do not use.
      //
      // This class is used as the second pass when encoding elements of a
      // sequence.  It basically calls 'EncoderUtil_EncodeObject' for elements
      // that do not have 'IS_ATTRIBUTE' flag.  Note that the behavior is
      // undefined if there is an element with the 'IS_SIMPLE_CONTENT' flag.
  
      // DATA
      Encoder_EncodeObject d_encodeObjectFunctor;
          // functor used to encode sub-elements
  
      // NOT IMPLEMENTED
      Encoder_SequenceSecondPass(const Encoder_SequenceSecondPass&);
      Encoder_SequenceSecondPass& operator=(const Encoder_SequenceSecondPass&);
  
    public:
      // CREATORS
      explicit
      Encoder_SequenceSecondPass(Encoder_Context *context);
          // Create a visitor for the second pass for sequences.
  
      // Generated by compiler:
      //  ~Encoder_SequenceSecondPass();
  
      // MANIPULATORS
      template <class TYPE, class INFO_TYPE>
      int operator()(const TYPE& object, const INFO_TYPE& info);
          // Called back when an element is visited.
  };
  
  // ============================================================================
  //                               PROXY CLASSES
  // ============================================================================
  
                    // ========================================
                    // struct Encoder_EncodeObject_executeProxy
                    // ========================================
  
  struct Encoder_EncodeObject_executeProxy {
      // Component-private struct.  Do not use.
  
      // DATA MEMBERS
      Encoder_EncodeObject *d_instance_p;
      const bslstl::StringRef       *d_tag_p;
      int                          d_formattingMode;
  
      // CREATORS
  
      // Creators have been omitted to allow simple static initialization of this
      // struct.
  
      // FUNCTIONS
      template <class TYPE>
      inline
      int operator()(const TYPE& object)
      {
          return d_instance_p->execute(object, *d_tag_p, d_formattingMode);
      }
  };
  
                  // ===========================================
                  // struct Encoder_EncodeObject_executeImpProxy
                  // ===========================================
  
  struct Encoder_EncodeObject_executeImpProxy {
      // Component-private struct.  Do not use.
  
      // DATA
      Encoder_EncodeObject *d_instance_p;
      const bslstl::StringRef       *d_tag_p;
      int                          d_formattingMode;
  
      // CREATORS
  
      // Creators have been omitted to allow simple static initialization of this
      // struct.
  
      // FUNCTIONS
      template <class TYPE>
      inline
      int operator()(const TYPE&, bslmf::Nil)
      {
          BSLS_ASSERT_SAFE(0);
          return -1;
      }
  
      template <class TYPE, class ANY_CATEGORY>
      inline
      int operator()(const TYPE& object, ANY_CATEGORY category)
      {
          return d_instance_p->executeImp(object,
                                          *d_tag_p,
                                          d_formattingMode,
                                          category);
      }
  };
  
                   // ==========================================
                   // struct Encoder_EncodeValue_executeImpProxy
                   // ==========================================
  
  struct Encoder_EncodeValue_executeImpProxy {
      // Component-private struct.  Do not use.
  
      // DATA MEMBERS
      Encoder_EncodeValue *d_instance_p;
      int                         d_formattingMode;
  
      // CREATORS
  
      // Creators have been omitted to allow simple static initialization of this
      // struct.
  
      // FUNCTIONS
      template <class TYPE>
      inline
      int operator()(const TYPE&, bslmf::Nil)
      {
          BSLS_ASSERT_SAFE(0);
          return -1;
      }
  
      template <class TYPE, class ANY_CATEGORY>
      inline
      int operator()(const TYPE& object, ANY_CATEGORY category)
      {
          return d_instance_p->executeImp(object, d_formattingMode, category);
      }
  };
  
               // ==================================================
               // struct Encoder_SequenceFirstPass_addAttributeProxy
               // ==================================================
  
  struct Encoder_SequenceFirstPass_addAttributeProxy {
      // Component-private struct.  Do not use.
  
      // DATA MEMBERS
      Encoder_SequenceFirstPass *d_instance_p;
      const bslstl::StringRef            *d_name_p;
      int                               d_formattingMode;
  
      // CREATORS
  
      // Creators have been omitted to allow simple static initialization of this
      // struct.
  
      // FUNCTIONS
      template <class TYPE>
      inline
      int operator()(const TYPE& object)
      {
          return d_instance_p->addAttribute(object, *d_name_p, d_formattingMode);
      }
  };
  
             // =====================================================
             // struct Encoder_SequenceFirstPass_addAttributeImpProxy
             // =====================================================
  
  struct Encoder_SequenceFirstPass_addAttributeImpProxy {
      // Component-private struct.  Do not use.
  
      // DATA MEMBERS
      Encoder_SequenceFirstPass *d_instance_p;
      const bslstl::StringRef            *d_name_p;
      int                               d_formattingMode;
  
      // CREATORS
  
      // Creators have been omitted to allow simple static initialization of this
      // struct.
  
      // FUNCTIONS
      template <class TYPE>
      inline
      int operator()(const TYPE&, bslmf::Nil)
      {
          BSLS_ASSERT_SAFE(0);
          return -1;
      }
  
      template <class TYPE, class ANY_CATEGORY>
      inline
      int operator()(const TYPE& object, ANY_CATEGORY category)
      {
          return d_instance_p->addAttributeImp(object,
                                               *d_name_p,
                                               d_formattingMode,
                                               category);
      }
  };
  }  // close package namespace
  
  // ============================================================================
  //                            INLINE DEFINITIONS
  // ============================================================================
  
  namespace balxml {
  
                         // ------------------------------
                         // class BerEncoder::MemOutStream
                         // ------------------------------
  
  inline
  Encoder::MemOutStream::MemOutStream(bslma::Allocator *basicAllocator)
  : bsl::ostream(0)
  , d_sb(bslma::Default::allocator(basicAllocator))
  {
      rdbuf(&d_sb);
  }
  
  // MANIPULATORS
  inline
  void Encoder::MemOutStream::reset()
  {
      d_sb.reset();
  }
  
  // ACCESSORS
  inline
  const char *Encoder::MemOutStream::data() const
  {
      return d_sb.data();
  }
  
  inline
  int Encoder::MemOutStream::length() const
  {
      return (int)d_sb.length();
  }
  
                                 // -------------
                                 // class Encoder
                                 // -------------
  
  inline
  bool Encoder::isCompact() const
  {
      return EncodingStyle::e_COMPACT == d_options->encodingStyle();
  }
  
  inline
  const EncoderOptions *Encoder::options() const
  {
      return d_options;
  }
  
  inline
  bsl::ostream *Encoder::errorStream() const
  {
      return d_errorStream;
  }
  
  inline
  bsl::ostream *Encoder::warningStream() const
  {
      return d_warningStream;
  }
  
  inline
  ErrorInfo::Severity Encoder::errorSeverity() const
  {
      return d_severity;
  }
  
  inline
  bslstl::StringRef Encoder::loggedMessages() const
  {
      if (d_logStream) {
          return bslstl::StringRef(d_logStream->data(), d_logStream->length());
                                                                        // RETURN
      }
      return bslstl::StringRef();
  }
  
  inline
  bsl::ostream& Encoder::logStream()
  {
      if (0 == d_logStream) {
          d_logStream = new(d_logArea.buffer()) MemOutStream(d_allocator);
      }
      return *d_logStream;
  }
  
  template <class TYPE>
  inline
  int Encoder::encode(bsl::streambuf *buffer, const TYPE& object)
  {
      int indentLevel    = 0;
      int spacesPerLevel = 0;
      int wrapColumn     = 0;
  
      EncoderOptions formatterEncoderOptions;
      Encoder_OptionsCompatibilityUtil::getFormatterOptions(
          &indentLevel,
          &spacesPerLevel,
          &wrapColumn,
          &formatterEncoderOptions,
          *d_options);
  
      Formatter formatter(buffer,
                          formatterEncoderOptions,
                          indentLevel,
                          spacesPerLevel,
                          wrapColumn);
  
      const int rc = encode(formatter, object);
  
      buffer->pubsync();
  
      return rc;
  }
  
  template <class TYPE>
  inline
  int Encoder::encodeToStream(bsl::ostream& stream, const TYPE& object)
  {
      return encode(stream.rdbuf(), object);
  }
  
  template <class TYPE>
  inline
  bsl::ostream& Encoder::encode(bsl::ostream& stream, const TYPE& object)
  {
      int indentLevel    = 0;
      int spacesPerLevel = 0;
      int wrapColumn     = 0;
  
      EncoderOptions formatterEncoderOptions;
      Encoder_OptionsCompatibilityUtil::getFormatterOptions(
          &indentLevel,
          &spacesPerLevel,
          &wrapColumn,
          &formatterEncoderOptions,
          *d_options);
  
      Formatter formatter(stream,
                          formatterEncoderOptions,
                          indentLevel,
                          spacesPerLevel,
                          wrapColumn);
  
      encode(formatter, object);
  
      stream.flush();
  
      return stream;
  }
  
  template <class TYPE>
  int Encoder::encode(Formatter& formatter, const TYPE& object)
  {
      d_severity = ErrorInfo::e_NO_ERROR;
      if (d_logStream != 0) {
          d_logStream->reset();
      }
  
      Encoder_Context context(&formatter,this);
  
      if (d_options->outputXMLHeader()) {
          formatter.addHeader();
      }
  
      const char *tag = d_options->tag().empty()
                      ? bdlat_TypeName::xsdName(object,
                                                d_options->formattingMode())
                      : d_options->tag().c_str();
  
      context.openElement(tag);
  
      if (!d_options->objectNamespace().empty()) {
  
          context.addAttribute("xmlns", d_options->objectNamespace());
  
          if (d_options->outputXSIAlias()) {
              // Only declare the "xsi" namespace and schema location if an
              // object namespace was provided because only then can validation
              // happen.
              context.addAttribute("xmlns:xsi",
                                   "http://www.w3.org/2001/XMLSchema-instance");
  
              if (!d_options->schemaLocation().empty()) {
                  context.addAttribute("xsi:schemaLocation",
                                       d_options->objectNamespace()
                                       + " "
                                       + d_options->schemaLocation());
              }
          }
      }
      else if (d_options->outputXSIAlias()) {
          context.addAttribute("xmlns:xsi",
                               "http://www.w3.org/2001/XMLSchema-instance");
      }
  
      Encoder_EncodeValue encodeValue(&context);
  
      int rc = 0;
      if (0 != encodeValue.execute(object,d_options->formattingMode())) {
  
          logError("Failed to encode", tag, d_options->formattingMode());
  
          context.invalidate();
          rc = -1;
      }
      else {
          context.closeElement(tag);
      }
  
      switch (d_severity) {
        case ErrorInfo::e_NO_ERROR: {
        } break;
        case ErrorInfo::e_WARNING: {
          if (d_warningStream) {
              *d_warningStream << loggedMessages();
          }
        } break;
        default: {
          if (d_errorStream) {
              *d_errorStream << loggedMessages();
          }
        } break;
      }
      return rc;
  }
  
                             // ---------------------
                             // class Encoder_Context
                             // ---------------------
  
  // MANIPULATORS
  template <class NAME_TYPE, class VALUE_TYPE>
  inline
  void Encoder_Context::addAttribute(const NAME_TYPE&  name,
                                     const VALUE_TYPE& value)
  {
      d_formatter->addAttribute(name,
                                value,
                                bdlat_FormattingMode::e_DEFAULT);
  }
  
  template <class NAME_TYPE, class VALUE_TYPE>
  inline
  void Encoder_Context::addAttribute(const NAME_TYPE&  name,
                                     const VALUE_TYPE& value,
                                     int               formattingMode)
  {
      d_formatter->addAttribute(name, value, formattingMode);
  }
  
  template <class NAME_TYPE>
  inline
  void Encoder_Context::closeElement(const NAME_TYPE& name)
  {
      d_formatter->closeElement(name);
  }
  
  inline
  void Encoder_Context::invalidate()
  {
      rawOutputStream().setstate(bsl::ios_base::failbit);
  }
  
  inline
  ErrorInfo::Severity Encoder_Context::logError(
                                        const char               *text,
                                        const bslstl::StringRef&  tag,
                                        int                       formattingMode,
                                        int                       index)
  {
      return d_encoder->logError(text, tag, formattingMode, index);
  }
  
  template <class NAME_TYPE>
  inline
  void Encoder_Context::openElement(const NAME_TYPE& name)
  {
      d_formatter->openElement(name);
  }
  
  inline
  bsl::ostream& Encoder_Context::rawOutputStream()
  {
      return d_formatter->rawOutputStream();
  }
  
  // ACCESSORS
  inline
  const EncoderOptions& Encoder_Context::encoderOptions() const
  {
      return *d_encoder->options();
  }
  
  inline
  int Encoder_Context::status() const
  {
      return d_formatter->status();
  }
  
                           // --------------------------
                           // class Encoder_EncodeObject
                           // --------------------------
  
  // IMPLEMENTATION MANIPULATORS
  template <class TYPE>
  inline
  int Encoder_EncodeObject::executeImp(const TYPE&               object,
                                       const bslstl::StringRef&  tag,
                                       int                       formattingMode,
                                       bdlat_TypeCategory::Array)
  {
      if (formattingMode & bdlat_FormattingMode::e_LIST) {
          return executeArrayListImp(object, tag);                      // RETURN
      }
      // else { return ... } removed, to prevent warning with gcc-4.1.1 (reach
      // end of non-void function), instead, have unconditional:
  
      return executeArrayRepetitionImp(object, tag, formattingMode);
  }
  
  template <class TYPE>
  inline
  int Encoder_EncodeObject::executeImp(
                                const TYPE&                       object,
                                const bslstl::StringRef&          tag,
                                int                               formattingMode,
                                bdlat_TypeCategory::NullableValue)
  {
      enum { k_SUCCESS = 0 };
  
      if (bdlat_NullableValueFunctions::isNull(object)) {
          if (formattingMode & bdlat_FormattingMode::e_NILLABLE) {
              if (!d_context_p->encoderOptions().objectNamespace().empty()
               && d_context_p->encoderOptions().outputXSIAlias()) {
                  // Only add the "xsi:nil" attribute if an object namespace was
                  // provided because only then can validation happen.
                  d_context_p->openElement(tag);
                  d_context_p->addAttribute("xsi:nil", "true");
                  d_context_p->closeElement(tag);
              }
          }
  
          return d_context_p->status();                                 // RETURN
      }
  
      Encoder_EncodeObject_executeProxy proxy = {
          this,
          &tag,
          formattingMode
      };
  
      return bdlat_NullableValueFunctions::accessValue(object, proxy);
  }
  
  template <class TYPE>
  inline
  int Encoder_EncodeObject::executeImp(
                                  const TYPE&                     object,
                                  const bslstl::StringRef&        tag,
                                  int                             formattingMode,
                                  bdlat_TypeCategory::DynamicType)
  {
      Encoder_EncodeObject_executeImpProxy proxy = {
          this,
          &tag,
          formattingMode
      };
  
      return bdlat_TypeCategoryUtil::accessByCategory(object, proxy);
  }
  
  template <class TYPE, class ANY_CATEGORY>
  int Encoder_EncodeObject::executeImp(const TYPE&              object,
                                       const bslstl::StringRef& tag,
                                       int                      formattingMode,
                                       ANY_CATEGORY)
  {
      enum { k_FAILURE = -1 };
  
      bool isUntagged = formattingMode & bdlat_FormattingMode::e_UNTAGGED;
  
      if (!isUntagged) {
          d_context_p->openElement(tag);
      }
  
      Encoder_EncodeValue encodeValue(d_context_p);
  
      if (0 != encodeValue.execute(object, formattingMode)) {
          d_context_p->logError("Unable to encode value", tag, formattingMode);
          return k_FAILURE;                                             // RETURN
      }
  
      if (!isUntagged) {
          d_context_p->closeElement(tag);
      }
  
      int ret = d_context_p->status();
  
      if (ret) {
          d_context_p->logError("Formatter was invalidated for",
                                tag,
                                formattingMode);
      }
  
      return ret;
  }
  
  template <class TYPE>
  int Encoder_EncodeObject::executeArrayListImp(const TYPE&              object,
                                                const bslstl::StringRef& tag)
  {
      d_context_p->openElement(tag);
  
      TypesPrintUtil::printList(d_context_p->rawOutputStream(),
                                object,
                                &d_context_p->encoderOptions());
  
      d_context_p->closeElement(tag);
  
      int ret = d_context_p->status();
  
      if (ret) {
  
          d_context_p->logError(
              "Error while encoding list for",
              tag,
              EncoderOptions::DEFAULT_INITIALIZER_FORMATTING_MODE);
      }
  
      return ret;
  }
  
  template <class TYPE>
  int Encoder_EncodeObject::executeArrayRepetitionImp(
                                         const TYPE&              object,
                                         const bslstl::StringRef& tag,
                                         int                      formattingMode)
  {
      enum { k_SUCCESS = 0, k_FAILURE = -1 };
  
      const int size = (int)bdlat_ArrayFunctions::size(object);
  
      Encoder_EncodeObject_executeProxy proxy = { this, &tag, formattingMode };
  
      for (int i = 0; i < size; ++i) {
          if (0 != bdlat_ArrayFunctions::accessElement(object, proxy, i)) {
  
              d_context_p->logError(
                  "Error while encoding array element",
                  tag,
                  formattingMode,
                  i);
  
              return k_FAILURE;                                         // RETURN
          }
      }
  
      return k_SUCCESS;
  }
  
  // CREATORS
  inline
  Encoder_EncodeObject::Encoder_EncodeObject(Encoder_Context *context)
  : d_context_p(context)
  {
      BSLS_ASSERT(d_context_p);
  }
  
  // MANIPULATORS
  template <class TYPE, class INFO_TYPE>
  inline
  int Encoder_EncodeObject::operator()(const TYPE& object, const INFO_TYPE& info)
  {
      bslstl::StringRef name(info.name(), info.nameLength());
  
      return execute(object, name, info.formattingMode());
  }
  
  template <class TYPE>
  inline
  int Encoder_EncodeObject::execute(const TYPE&              object,
                                    const bslstl::StringRef& tag,
                                    int                      formattingMode)
  {
      typedef typename bdlat_TypeCategory::Select<TYPE>::Type TypeCategory;
  
      return executeImp(object, tag, formattingMode, TypeCategory());
  }
  
                           // -------------------------
                           // class Encoder_EncodeValue
                           // -------------------------
  
  // IMPLEMENTATION MANIPULATORS
  template <class TYPE>
  inline
  int Encoder_EncodeValue::executeImp(
                                     const TYPE&                  object,
                                     int                          formattingMode,
                                     bdlat_TypeCategory::Sequence)
  {
      enum { k_SUCCESS = 0, k_FAILURE = -1 };
  
  #if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
      int type = formattingMode & bdlat_FormattingMode::e_TYPE_MASK;
  
      BSLS_ASSERT_SAFE(bdlat_FormattingMode::e_DEFAULT == type);
  #else
      (void) formattingMode;
  #endif
  
      Encoder_SequenceFirstPass firstPass(d_context_p);
  
      if (0 != bdlat_SequenceFunctions::accessAttributes(object, firstPass)) {
          return k_FAILURE;                                             // RETURN
      }
  
      if (!firstPass.simpleContentId().isNull()) {
          Encoder_EncodeValue encodeValue(d_context_p);
  
          return bdlat_SequenceFunctions::accessAttribute(
                                            object,
                                            encodeValue,
                                            firstPass.simpleContentId().value());
                                                                        // RETURN
      }
  
      if (firstPass.hasSubElements()) {
          Encoder_SequenceSecondPass secondPass(d_context_p);
  
          return bdlat_SequenceFunctions::accessAttributes(object, secondPass);
                                                                        // RETURN
      }
  
      return k_SUCCESS;
  }
  
  template <class TYPE>
  inline
  int Encoder_EncodeValue::executeImp(const TYPE&                object,
                                      int                        formattingMode,
                                      bdlat_TypeCategory::Choice)
  {
      enum { k_FAILURE = -1 };
  
  #if defined(BSLS_ASSERT_SAFE_IS_ACTIVE)
      int type = formattingMode & bdlat_FormattingMode::e_TYPE_MASK;
  
      BSLS_ASSERT_SAFE(bdlat_FormattingMode::e_DEFAULT == type);
  #endif
  
      if (bdlat_ChoiceFunctions::k_UNDEFINED_SELECTION_ID
                                 == bdlat_ChoiceFunctions::selectionId(object)) {
  
          d_context_p->logError("Undefined selection is not allowed ",
                                "???",
                                formattingMode);
          return k_FAILURE;                                             // RETURN
      }
  
      Encoder_EncodeObject encodeObject(d_context_p);
  
      return bdlat_ChoiceFunctions::accessSelection(object, encodeObject);
  }
  
  template <class TYPE>
  inline
  int Encoder_EncodeValue::executeImp(
                                  const TYPE&                     object,
                                  int                             formattingMode,
                                  bdlat_TypeCategory::DynamicType)
  {
      Encoder_EncodeValue_executeImpProxy proxy = { this, formattingMode };
  
      return bdlat_TypeCategoryUtil::accessByCategory(object, proxy);
  }
  
  template <class TYPE, class ANY_CATEGORY>
  inline
  int Encoder_EncodeValue::executeImp(const TYPE&  object,
                                      int          formattingMode,
                                      ANY_CATEGORY)
  {
      TypesPrintUtil::print(d_context_p->rawOutputStream(),
                            object,
                            formattingMode,
                            &d_context_p->encoderOptions());
  
      return d_context_p->status();
  }
  
  // CREATORS
  inline
  Encoder_EncodeValue::Encoder_EncodeValue(Encoder_Context *context)
  : d_context_p(context)
  {
      BSLS_ASSERT(d_context_p);
  }
  
  // MANIPULATORS
  template <class TYPE, class INFO_TYPE>
  inline
  int Encoder_EncodeValue::operator()(const TYPE& object, const INFO_TYPE& info)
  {
      typedef typename bdlat_TypeCategory::Select<TYPE>::Type TypeCategory;
  
      return executeImp(object, info.formattingMode(), TypeCategory());
  }
  
  template <class TYPE>
  inline
  int Encoder_EncodeValue::execute(const TYPE& object, int formattingMode)
  {
      typedef typename bdlat_TypeCategory::Select<TYPE>::Type TypeCategory;
  
      return executeImp(object, formattingMode, TypeCategory());
  }
  
                        // -------------------------------
                        // class Encoder_SequenceFirstPass
                        // -------------------------------
  
  // IMPLEMENTATION MANIPULATORS
  template <class TYPE>
  inline
  int Encoder_SequenceFirstPass::addAttributeImp(
                                const TYPE&                       object,
                                const bslstl::StringRef&          name,
                                int                               formattingMode,
                                bdlat_TypeCategory::NullableValue)
  {
      enum { k_SUCCESS = 0 };
  
      if (bdlat_NullableValueFunctions::isNull(object)) {
          return k_SUCCESS;                                             // RETURN
      }
  
      Encoder_SequenceFirstPass_addAttributeProxy proxy = {
          this,
          &name,
          formattingMode
      };
  
      return bdlat_NullableValueFunctions::accessValue(object, proxy);
  }
  
  template <class TYPE>
  inline
  int Encoder_SequenceFirstPass::addAttributeImp(
                                  const TYPE&                     object,
                                  const bslstl::StringRef&        name,
                                  int                             formattingMode,
                                  bdlat_TypeCategory::DynamicType)
  {
      Encoder_SequenceFirstPass_addAttributeImpProxy proxy = {
          this,
          &name,
          formattingMode
      };
  
      return bdlat_TypeCategoryUtil::accessByCategory(object, proxy);
  
  }
  
  template <class TYPE, class ANY_CATEGORY>
  inline
  int Encoder_SequenceFirstPass::addAttributeImp(
                                         const TYPE&              object,
                                         const bslstl::StringRef& name,
                                         int                      formattingMode,
                                         ANY_CATEGORY)
  {
      d_context_p->addAttribute(name, object, formattingMode);
  
      int ret = d_context_p->status();
  
      if (ret) {
          d_context_p->logError("Failed to encode attribute",
                                name,
                                formattingMode);
      }
  
      return ret;
  }
  
  template <class TYPE>
  inline
  int Encoder_SequenceFirstPass::addAttribute(
                                         const TYPE&              object,
                                         const bslstl::StringRef& name,
                                         int                      formattingMode)
  {
      typedef typename bdlat_TypeCategory::Select<TYPE>::Type TypeCategory;
  
      return addAttributeImp(object, name, formattingMode, TypeCategory());
  }
  
  // CREATORS
  inline
  Encoder_SequenceFirstPass::Encoder_SequenceFirstPass(Encoder_Context *context)
  : d_context_p(context)
  , d_hasSubElements(false)
  {
      BSLS_ASSERT(d_context_p);
      BSLS_ASSERT(d_simpleContentId.isNull());
  
      // {DRQS 153551134<GO>}: gcc can occasionally mis-diagnose
      // 'd_simpleContentId' as uninitialized.  This workaround avoids that
      // problem (which can cause build failures if '-Wmaybe-uninitialized' and
      // '-Werror' are set).  See also {DRQS 75130685<GO>} and {DRQS
      // 115347303<GO>}.
      d_simpleContentId.makeValue(0);
      d_simpleContentId.reset();
  }
  
  // MANIPULATORS
  template <class TYPE, class INFO_TYPE>
  int Encoder_SequenceFirstPass::operator()(const TYPE&      object,
                                            const INFO_TYPE& info)
  {
      enum { k_SUCCESS = 0 };
  
      int  formattingMode  = info.formattingMode();
      bool isSimpleContent = formattingMode
                           & bdlat_FormattingMode::e_SIMPLE_CONTENT;
      bool isAttribute     = formattingMode & bdlat_FormattingMode::e_ATTRIBUTE;
  
      if (isSimpleContent) {
          BSLS_ASSERT(!isAttribute);
          BSLS_ASSERT(!d_hasSubElements);
          BSLS_ASSERT(d_simpleContentId.isNull());
  
          d_simpleContentId.makeValue(info.id());
      }
      else if (isAttribute) {
          bslstl::StringRef name(info.name(), info.nameLength());
  
          return addAttribute(object, name, formattingMode);            // RETURN
      }
      else {
          BSLS_ASSERT(d_simpleContentId.isNull());
  
          d_hasSubElements = true;
      }
  
      return k_SUCCESS;
  }
  
  // ACCESSORS
  inline
  const bool& Encoder_SequenceFirstPass::hasSubElements() const
  {
      return d_hasSubElements;
  }
  
  inline
  const bdlb::NullableValue<int>&
  Encoder_SequenceFirstPass::simpleContentId() const
  {
      return d_simpleContentId;
  }
  
                        // --------------------------------
                        // class Encoder_SequenceSecondPass
                        // --------------------------------
  
  // CREATORS
  inline
  Encoder_SequenceSecondPass::Encoder_SequenceSecondPass(
                                                        Encoder_Context* context)
  : d_encodeObjectFunctor(context)
  {
  }
  
  // MANIPULATORS
  template <class TYPE, class INFO_TYPE>
  int Encoder_SequenceSecondPass::operator()(const TYPE&      object,
                                             const INFO_TYPE& info)
  {
      enum { k_SUCCESS = 0 };
  
      int formattingMode = info.formattingMode();
  
      BSLS_ASSERT(
                 !(formattingMode & bdlat_FormattingMode::e_SIMPLE_CONTENT));
  
      if (!(formattingMode & bdlat_FormattingMode::e_ATTRIBUTE)) {
          return d_encodeObjectFunctor(object, info);                   // RETURN
      }
  
      return k_SUCCESS;
  }
  
  }  // close package namespace
  }  // close enterprise namespace
  
  #endif
  
  // ----------------------------------------------------------------------------
  // Copyright 2015 Bloomberg Finance L.P.
  //
  // Licensed 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.
  // ----------------------------- END-OF-FILE ----------------------------------
  