text: // MusicXML Class Library
  // Copyright (c) by Matthew James Briggs
  // Distributed under the MIT License
  
  #include "mx/core/elements/EndingAttributes.h"
  #include "mx/core/FromXElement.h"
  #include <iostream>
  
  namespace mx
  {
      namespace core
      {
          EndingAttributes::EndingAttributes()
          :number( "1" )
          ,type( StartStopDiscontinue::start )
          ,printObject()
          ,defaultX()
          ,defaultY()
          ,relativeX()
          ,relativeY()
          ,fontFamily()
          ,fontStyle( FontStyle::normal )
          ,fontSize( FontSize{ CssFontSize::medium } )
          ,fontWeight( FontWeight::normal )
          ,endLength()
          ,textX()
          ,textY()
          ,hasNumber( true )
          ,hasType( true )
          ,hasPrintObject( false )
          ,hasDefaultX( false )
          ,hasDefaultY( false )
          ,hasRelativeX( false )
          ,hasRelativeY( false )
          ,hasFontFamily( false )
          ,hasFontStyle( false )
          ,hasFontSize( false )
          ,hasFontWeight( false )
          ,hasEndLength( false )
          ,hasTextX( false )
          ,hasTextY( false )
          {}
  
  
          bool EndingAttributes::hasValues() const
          {
              return hasNumber ||
              hasType ||
              hasPrintObject ||
              hasDefaultX ||
              hasDefaultY ||
              hasRelativeX ||
              hasRelativeY ||
              hasFontFamily ||
              hasFontStyle ||
              hasFontSize ||
              hasFontWeight ||
              hasEndLength ||
              hasTextX ||
              hasTextY;
          }
  
  
          std::ostream& EndingAttributes::toStream( std::ostream& os ) const
          {
              if ( hasValues() )
              {
                  streamAttribute( os, number, "number", hasNumber );
                  streamAttribute( os, type, "type", hasType );
                  streamAttribute( os, printObject, "print-object", hasPrintObject );
                  streamAttribute( os, defaultX, "default-x", hasDefaultX );
                  streamAttribute( os, defaultY, "default-y", hasDefaultY );
                  streamAttribute( os, relativeX, "relative-x", hasRelativeX );
                  streamAttribute( os, relativeY, "relative-y", hasRelativeY );
                  streamAttribute( os, fontFamily, "font-family", hasFontFamily );
                  streamAttribute( os, fontStyle, "font-style", hasFontStyle );
                  streamAttribute( os, fontSize, "font-size", hasFontSize );
                  streamAttribute( os, fontWeight, "font-weight", hasFontWeight );
                  streamAttribute( os, endLength, "end-length", hasEndLength );
                  streamAttribute( os, textX, "text-x", hasTextX );
                  streamAttribute( os, textY, "text-y", hasTextY );
              }
              return os;
          }
  
  
          bool EndingAttributes::fromXElementImpl( std::ostream& message, xml::XElement& xelement )
          {
              const char* const className = "EndingAttributes";
              bool isSuccess = true;
              bool isNumberFound = false;
              bool isTypeFound = false;
          
              auto it = xelement.attributesBegin();
              auto endIter = xelement.attributesEnd();
          
              for( ; it != endIter; ++it )
              {
                  if( parseAttribute( message, it, className, isSuccess, number, isNumberFound, "number" ) )
                  {
                      number.setUseSpaceBetweenItems( it->getValue().find( " " ) != std::string::npos );
                      continue;
                  }
                  if( parseAttribute( message, it, className, isSuccess, type, isTypeFound, "type", &parseStartStopDiscontinue ) ) { continue; }
                  if( parseAttribute( message, it, className, isSuccess, printObject, hasPrintObject, "print-object", &parseYesNo ) ) { continue; }
                  if( parseAttribute( message, it, className, isSuccess, defaultX, hasDefaultX, "default-x" ) ) { continue; }
                  if( parseAttribute( message, it, className, isSuccess, defaultY, hasDefaultY, "default-y" ) ) { continue; }
                  if( parseAttribute( message, it, className, isSuccess, relativeX, hasRelativeX, "relative-x" ) ) { continue; }
                  if( parseAttribute( message, it, className, isSuccess, relativeY, hasRelativeY, "relative-y" ) ) { continue; }
                  if( parseAttribute( message, it, className, isSuccess, fontFamily, hasFontFamily, "font-family" ) ) { continue; }
                  if( parseAttribute( message, it, className, isSuccess, fontStyle, hasFontStyle, "font-style", &parseFontStyle ) ) { continue; }
                  if( parseAttribute( message, it, className, isSuccess, fontSize, hasFontSize, "font-size" ) ) { continue; }
                  if( parseAttribute( message, it, className, isSuccess, fontWeight, hasFontWeight, "font-weight", &parseFontWeight ) ) { continue; }
                  if( parseAttribute( message, it, className, isSuccess, endLength, hasEndLength, "end-length" ) ) { continue; }
                  if( parseAttribute( message, it, className, isSuccess, textX, hasTextX, "text-x" ) ) { continue; }
                  if( parseAttribute( message, it, className, isSuccess, textY, hasTextY, "text-y" ) ) { continue; }
              }
          
              if( !isNumberFound )
              {
                  isSuccess = false;
                  message << className << ": 'number' is a required attribute but was not found" << std::endl;
              }
              if( !isTypeFound )
              {
                  isSuccess = false;
                  message << className << ": 'number' is a required attribute but was not found" << std::endl;
              }
          
              MX_RETURN_IS_SUCCESS;
          }
  
      }
  }
  