//%2003////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, 2001, 2002  BMC Software, Hewlett-Packard Development
// Company, L. P., IBM Corp., The Open Group, Tivoli Systems.
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L. P.;
// IBM Corp.; EMC Corporation, The Open Group.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//==============================================================================
//
// Author: Mike Brasher (mbrasher@bmc.com)
//
// Modified By: Carol Ann Krug Graves, Hewlett-Packard Company
//                  (carolann_graves@hp.com)
//              Nitin Upasani, Hewlett-Packard Company (Nitin_Upasani@hp.com)
//              Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
//              Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com)
//
//%/////////////////////////////////////////////////////////////////////////////
#include <Pegasus/Common/Config.h>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#if defined(PEGASUS_OS_TYPE_UNIX)
#include <errno.h>
#endif
#include "CIMName.h"
#include "XmlReader.h"
#include "XmlWriter.h"
#include "CIMQualifier.h"
#include "CIMQualifierDecl.h"
#include "CIMClass.h"
#include "CIMInstance.h"
#include "CIMObject.h"
#include "CIMParamValue.h"
#include "System.h"
#include "XmlConstants.h"
#ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
#include "OS400ConvertChar.h"
#endif
// l10n
#include <Pegasus/Common/MessageLoader.h>

#define PEGASUS_SINT64_MIN (PEGASUS_SINT64_LITERAL(0x8000000000000000))
#define PEGASUS_UINT64_MAX PEGASUS_UINT64_LITERAL(0xFFFFFFFFFFFFFFFF)

PEGASUS_USING_STD;
PEGASUS_NAMESPACE_BEGIN

static const Uint32 MESSAGE_SIZE = 128;

//------------------------------------------------------------------------------
//
// getXmlDeclaration()
//
//     <?xml version="1.0" encoding="utf-8"?>
//
//------------------------------------------------------------------------------

void XmlReader::getXmlDeclaration(
    XmlParser& parser, 
    const char*& xmlVersion,
    const char*& xmlEncoding)
{
    XmlEntry entry;

    if (!parser.next(entry) ||
	entry.type != XmlEntry::XML_DECLARATION ||
	strcmp(entry.text, "xml") != 0)
    {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "Expected <?xml ... ?> style declaration");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_XML_STYLE",
				 "Expected <?xml ... ?> style declaration");

      throw XmlValidationError(parser.getLine(), mlParms);

    }

    if (!entry.getAttributeValue("version", xmlVersion)) {

      // l10n

      // throw XmlValidationError(
      //   parser.getLine(), "missing xml.version attribute");

      MessageLoaderParms mlParms("Common.XmlReader.MISSING_XML_ATTRIBUTE",
				 "missing xml.version attribute");

      throw XmlValidationError(parser.getLine(), mlParms);
    }

    if (!entry.getAttributeValue("encoding", xmlEncoding))
    {
        // ATTN-RK-P3-20020403:  Is there a default encoding?
    }
}

//------------------------------------------------------------------------------
//
//  testXmlDeclaration ()
//
//------------------------------------------------------------------------------

Boolean XmlReader::testXmlDeclaration (
    XmlParser& parser,
    XmlEntry& entry)
{
    if (!parser.next (entry) ||
        entry.type != XmlEntry::XML_DECLARATION ||
        strcmp (entry.text, "xml") != 0)
    {
        parser.putBack (entry);
        return false;
    }

    return true;
}

//------------------------------------------------------------------------------
//
// expectStartTag()
//
//------------------------------------------------------------------------------

void XmlReader::expectStartTag(
    XmlParser& parser, 
    XmlEntry& entry,
    const char* tagName)
{
    if (!parser.next(entry) ||
	entry.type != XmlEntry::START_TAG ||
	strcmp(entry.text, tagName) != 0)
    {
      // l10n

      // char message[MESSAGE_SIZE];
      // sprintf(message, "Expected open of %s element", tagName);
      // throw XmlValidationError(parser.getLine(), message);

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_OPEN",
				 "Expected open of $0 element",
				 tagName);

      throw XmlValidationError(parser.getLine(), mlParms);
    }
}

//------------------------------------------------------------------------------
//
// expectEndTag()
//
//------------------------------------------------------------------------------

void XmlReader::expectEndTag(XmlParser& parser, const char* tagName)
{
    XmlEntry entry;

    if (!parser.next(entry) ||
	entry.type != XmlEntry::END_TAG ||
	strcmp(entry.text, tagName) != 0)
    {

      // l10n

      // char message[MESSAGE_SIZE];
      // sprintf(message, "Expected close of %s element, got %s instead",
      //     tagName,entry.text);
      // throw XmlValidationError(parser.getLine(), message);

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_CLOSE",
				 "Expected close of $0 element, got $1 instead",
				 tagName,entry.text);

      throw XmlValidationError(parser.getLine(), mlParms);
    }
}

//------------------------------------------------------------------------------
//
// expectStartTagOrEmptyTag()
//
//------------------------------------------------------------------------------

void XmlReader::expectStartTagOrEmptyTag(
    XmlParser& parser, 
    XmlEntry& entry,
    const char* tagName)
{
    if (!parser.next(entry) ||
	(entry.type != XmlEntry::START_TAG &&
	entry.type != XmlEntry::EMPTY_TAG) ||
	strcmp(entry.text, tagName) != 0)
    {
      // l10n
      
      // char message[MESSAGE_SIZE];
      // sprintf(message, 
      //   "Expected either open or open/close %s element", tagName);
      // throw XmlValidationError(parser.getLine(), message);

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_OPENCLOSE",
				 "Expected either open or open/close $0 element",
				 tagName);

      throw XmlValidationError(parser.getLine(), mlParms);
    }
}

//------------------------------------------------------------------------------
//
// expectContentOrCData()
//
//------------------------------------------------------------------------------

Boolean XmlReader::expectContentOrCData(
    XmlParser& parser, 
    XmlEntry& entry)
{
    if (!parser.next(entry) ||
	(entry.type != XmlEntry::CONTENT &&
	entry.type != XmlEntry::CDATA))
    {
      // l10n

      // throw XmlValidationError(parser.getLine(),
      //	       "Expected content of CDATA");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_CDATA",
				 "Expected content of CDATA");

      throw XmlValidationError(parser.getLine(), mlParms);

    }

    return true;
}

//------------------------------------------------------------------------------
//
// testStartTag()
//
//------------------------------------------------------------------------------

Boolean XmlReader::testStartTag(
    XmlParser& parser, 
    XmlEntry& entry,
    const char* tagName)
{
    if (!parser.next(entry) ||
	entry.type != XmlEntry::START_TAG ||
	strcmp(entry.text, tagName) != 0)
    {
	parser.putBack(entry);
	return false;
    }

    return true;
}

//------------------------------------------------------------------------------
//
// testEndTag()
//
//------------------------------------------------------------------------------

Boolean XmlReader::testEndTag(XmlParser& parser, const char* tagName)
{
    XmlEntry entry;

    if (!parser.next(entry) ||
	entry.type != XmlEntry::END_TAG ||
	strcmp(entry.text, tagName) != 0)
    {
	parser.putBack(entry);
	return false;
    }

    return true;
}

//------------------------------------------------------------------------------
//
// testStartTagOrEmptyTag()
//
//------------------------------------------------------------------------------

Boolean XmlReader::testStartTagOrEmptyTag(
    XmlParser& parser, 
    XmlEntry& entry,
    const char* tagName)
{
    if (!parser.next(entry) ||
	(entry.type != XmlEntry::START_TAG &&
	entry.type != XmlEntry::EMPTY_TAG) ||
	strcmp(entry.text, tagName) != 0)
    {
	parser.putBack(entry);
	return false;
    }

    return true;
}

//------------------------------------------------------------------------------
//
// testStartTagOrEmptyTag()
//
//------------------------------------------------------------------------------

Boolean XmlReader::testStartTagOrEmptyTag(
    XmlParser& parser, 
    XmlEntry& entry)
{
    if (!parser.next(entry) ||
	(entry.type != XmlEntry::START_TAG &&
	 entry.type != XmlEntry::EMPTY_TAG))
    {
	parser.putBack(entry);
	return false;
    }

    return true;
}

//------------------------------------------------------------------------------
//
// testContentOrCData()
//
//------------------------------------------------------------------------------

Boolean XmlReader::testContentOrCData(
    XmlParser& parser, 
    XmlEntry& entry)
{
    if (!parser.next(entry) ||
	(entry.type != XmlEntry::CONTENT &&
	entry.type != XmlEntry::CDATA))
    {
	parser.putBack(entry);
	return false;
    }

    return true;
}

//------------------------------------------------------------------------------
//
// getCimStartTag()
//
//     <!ELEMENT CIM (MESSAGE|DECLARATION)>
//     <!ATTRLIST CIM 
//         CIMVERSION CDATA #REQUIRED
//         DTDVERSION CDATA #REQUIRED>
//
//------------------------------------------------------------------------------

void XmlReader::getCimStartTag(
    XmlParser& parser, 
    const char*& cimVersion,
    const char*& dtdVersion)
{
    XmlEntry entry;
    XmlReader::expectStartTag(parser, entry, "CIM");

    if (!entry.getAttributeValue("CIMVERSION", cimVersion)) {

      // l10n

      // throw XmlValidationError(
      //   parser.getLine(), "missing CIM.CIMVERSION attribute");

      MessageLoaderParms mlParms("Common.XmlReader.MISSING_CIMVERSION_ATTRIBUTE",
				 "missing CIM.CIMVERSION attribute");

      throw XmlValidationError(parser.getLine(), mlParms);
    }

    if (!entry.getAttributeValue("DTDVERSION", dtdVersion)){

      // l10n
      
      // throw XmlValidationError(
      //   parser.getLine(), "missing CIM.DTDVERSION attribute");
      
      MessageLoaderParms mlParms("Common.XmlReader.MISSING_DTDVERSION_ATTRIBUTE",
				 "missing CIM.DTDVERSION attribute");
      
      throw XmlValidationError(parser.getLine(), mlParms);
    }
}

//------------------------------------------------------------------------------
//
// getCimNameAttribute()
//
//     <!ENTITY % CIMName "NAME CDATA #REQUIRED">
//
//------------------------------------------------------------------------------

CIMName XmlReader::getCimNameAttribute(
    Uint32 lineNumber, 
    const XmlEntry& entry,
    const char* elementName,
    Boolean acceptNull)
{
    String name;

    if (!entry.getAttributeValue("NAME", name))
      {

	// l10n

	// char buffer[MESSAGE_SIZE];
	// sprintf(buffer, "missing %s.NAME attribute", elementName);
	// throw XmlValidationError(lineNumber, buffer);

	char buffer[MESSAGE_SIZE];
	sprintf(buffer, "%s.NAME", elementName);
	MessageLoaderParms mlParms("Common.XmlReader.MISSING_ATTRIBUTE",
				   "missing $0 attribute",
				   buffer);

	throw XmlValidationError(lineNumber, mlParms);
    }

    if (acceptNull && name.size() == 0)
	return CIMName ();
    
    if (!CIMName::legal(name))
    {
#ifdef PEGASUS_SNIA_INTEROP_TEST
    // In testing, replace illegal CIMName with this value to avoid the
    // exception and let xml parsing continue.  THIS IS TEMP.    
    name = "BADNAMESUBSTITUTEDBYPEGASUSCLIENT";
#else

    // l10n

    // char buffer[MESSAGE_SIZE];
    // sprintf(buffer, "Illegal value for %s.NAME attribute", elementName);
    // throw XmlSemanticError(lineNumber, buffer);

    char buffer[MESSAGE_SIZE];
    sprintf(buffer, "%s.NAME", elementName);
    
    MessageLoaderParms mlParms("Common.XmlReader.ILLEGAL_VALUE_FOR_ATTRIBUTE",
			       "Illegal value for $0 attribute",
			       buffer);
    
    throw XmlSemanticError(lineNumber, mlParms);

#endif
    }
    return CIMName (name);
}

//------------------------------------------------------------------------------
//
// getClassNameAttribute()
//
//     <!ENTITY % CIMName "CLASSNAME CDATA #REQUIRED">
//
//------------------------------------------------------------------------------

String XmlReader::getClassNameAttribute(
    Uint32 lineNumber, 
    const XmlEntry& entry,
    const char* elementName)
{
    String name;

    if (!entry.getAttributeValue("CLASSNAME", name))
    {


      // l10n

      // char buffer[MESSAGE_SIZE];
      // sprintf(buffer, "missing %s.CLASSNAME attribute", elementName);
      // throw XmlValidationError(lineNumber, buffer);

      char buffer[MESSAGE_SIZE];
      sprintf(buffer, "%s.CLASSNAME", elementName);

      MessageLoaderParms mlParms("Common.XmlReader.MISSING_ATTRIBUTE",
				 "missing $0 attribute",
				 buffer);

      throw XmlValidationError(lineNumber, mlParms);

    }

    if (!CIMName::legal(name))
    {
      // l10n

      // char buffer[MESSAGE_SIZE];
      // sprintf(buffer, 
      //   "Illegal value for %s.CLASSNAME attribute", elementName);
      // throw XmlSemanticError(lineNumber, buffer);

      char buffer[MESSAGE_SIZE];
      sprintf(buffer, "%s.CLASSNAME", elementName);
      
      MessageLoaderParms mlParms("Common.XmlReader.ILLEGAL_VALUE_FOR_ATTRIBUTE",
				 "Illegal value for $0 attribute",
				 buffer);
      
      throw XmlSemanticError(lineNumber, mlParms);
      
    }

    return name;
}

//------------------------------------------------------------------------------
//
// getClassOriginAttribute()
//
//     <!ENTITY % ClassOrigin "CLASSORIGIN CDATA #IMPLIED">
//
//------------------------------------------------------------------------------

CIMName XmlReader::getClassOriginAttribute(
    Uint32 lineNumber, 
    const XmlEntry& entry,
    const char* tagName)
{
    String name;

    if (!entry.getAttributeValue("CLASSORIGIN", name))
	return CIMName();

    // KS 200209 This may be temp but we are adding test for form
    // CLASSNAME = "" for Wbemservices interoperability.  Returns same
    // as if attribute did not exist.
    if (name.size() == 0)
        return CIMName();
    
    if (!CIMName::legal(name))
    {
      // l10n

      // char buffer[MESSAGE_SIZE];
      // sprintf(buffer, 
      //    "Illegal value for %s.CLASSORIGIN attribute", tagName);
      // throw XmlSemanticError(lineNumber, buffer);

      char buffer[MESSAGE_SIZE];
      sprintf(buffer, "%s.CLASSORIGIN", tagName);
      
      MessageLoaderParms mlParms("Common.XmlReader.ILLEGAL_VALUE_FOR_ATTRIBUTE",
				 "Illegal value for $0 attribute",
				 buffer);
      
      throw XmlSemanticError(lineNumber, mlParms);
    }

    return name;
}

//------------------------------------------------------------------------------
//
// getReferenceClassAttribute()
//
//     <!ENTITY % ReferenceClass "REFERENCECLASS CDATA #IMPLIED">
//
//------------------------------------------------------------------------------

CIMName XmlReader::getReferenceClassAttribute(
    Uint32 lineNumber, 
    const XmlEntry& entry,
    const char* elementName)
{
    String name;

    if (!entry.getAttributeValue("REFERENCECLASS", name))
	return CIMName();

    if (!CIMName::legal(name))
    {
#ifdef PEGASUS_SNIA_INTEROP_TEST
    name = "PEGASUS_SUBSTITUED_THIS_FOR_BAD_NAME";
    return name;
#endif 

    // l10n

    // char buffer[MESSAGE_SIZE];
    // sprintf(buffer, 
    //     "Illegal value for %s.REFERENCECLASS attribute", elementName);
    // throw XmlSemanticError(lineNumber, buffer);

    char buffer[MESSAGE_SIZE];
    sprintf(buffer, "%s.REFERENCECLASS", elementName);
    
    MessageLoaderParms mlParms("Common.XmlReader.ILLEGAL_VALUE_FOR_ATTRIBUTE",
			       "Illegal value for $0 attribute",
			       buffer);
    
    throw XmlSemanticError(lineNumber, mlParms);
    }

    return name;
}

//------------------------------------------------------------------------------
//
// getSuperClassAttribute()
//
//     <!ENTITY % SuperClass "SUPERCLASS CDATA #IMPLIED">
//
//------------------------------------------------------------------------------

CIMName XmlReader::getSuperClassAttribute(
    Uint32 lineNumber, 
    const XmlEntry& entry,
    const char* tagName)
{
    String superClass;

    if (!entry.getAttributeValue("SUPERCLASS", superClass))
	return CIMName();

    if (!CIMName::legal(superClass))
    {

      // l10n

      // char buffer[MESSAGE_SIZE];
      // sprintf(
      //   buffer, "Illegal value for %s.SUPERCLASS attribute", tagName);
      // throw XmlSemanticError(lineNumber, buffer);
      
      char buffer[MESSAGE_SIZE];
      sprintf(buffer, "%s.SUPERCLASS", tagName);
      
      MessageLoaderParms mlParms("Common.XmlReader.ILLEGAL_VALUE_FOR_ATTRIBUTE",
				 "Illegal value for $0 attribute",
				 buffer);
      
      throw XmlSemanticError(lineNumber, mlParms);
    }

    return superClass;
}

//------------------------------------------------------------------------------
//
// getCimTypeAttribute()
//
// This method can be used to get a TYPE attribute or a PARAMTYPE attribute.
// The only significant difference is that PARAMTYPE may specify a value of
// "reference" type.  This method recognizes these attributes by name, and
// does not allow a "TYPE" attribute to be of "reference" type.
//
//     <!ENTITY % CIMType "TYPE (boolean|string|char16|uint8|sint8|uint16
//         |sint16|uint32|sint32|uint64|sint64|datetime|real32|real64)">
//
//     <!ENTITY % ParamType "PARAMTYPE (boolean|string|char16|uint8|sint8
//         |uint16|sint16|uint32|sint32|uint64|sint64|datetime|real32|real64
//         |reference)">
//
//------------------------------------------------------------------------------

Boolean XmlReader::getCimTypeAttribute(
    Uint32 lineNumber, 
    const XmlEntry& entry, 
    CIMType& cimType,  // Output parameter
    const char* tagName,
    const char* attributeName,
    Boolean required)
{
    const char* typeName;

    if (!entry.getAttributeValue(attributeName, typeName))
    {
        if (required)
	{

	  // l10n

	  // char message[MESSAGE_SIZE];
	  // sprintf(message, "missing %s.%s attribute", tagName, attributeName);
	  // throw XmlValidationError(lineNumber, message);

	  char message[MESSAGE_SIZE];
	  sprintf(message, "%s.%s", tagName, attributeName);

	  MessageLoaderParms mlParms("Common.XmlReader.MISSING_ATTRIBUTE",
				     "missing $0 attribute",
				     message);
	  
	  throw XmlValidationError(lineNumber, mlParms);
	  
	}
	else
	  {
	    return false;
	  }
    }

    CIMType type = CIMTYPE_BOOLEAN;
    Boolean unrecognizedType = false;

    if (strcmp(typeName, "boolean") == 0)
	type = CIMTYPE_BOOLEAN;
    else if (strcmp(typeName, "string") == 0)
	type = CIMTYPE_STRING;
    else if (strcmp(typeName, "char16") == 0)
	type = CIMTYPE_CHAR16;
    else if (strcmp(typeName, "uint8") == 0)
	type = CIMTYPE_UINT8;
    else if (strcmp(typeName, "sint8") == 0)
	type = CIMTYPE_SINT8;
    else if (strcmp(typeName, "uint16") == 0)
	type = CIMTYPE_UINT16;
    else if (strcmp(typeName, "sint16") == 0)
	type = CIMTYPE_SINT16;
    else if (strcmp(typeName, "uint32") == 0)
	type = CIMTYPE_UINT32;
    else if (strcmp(typeName, "sint32") == 0)
	type = CIMTYPE_SINT32;
    else if (strcmp(typeName, "uint64") == 0)
	type = CIMTYPE_UINT64;
    else if (strcmp(typeName, "sint64") == 0)
	type = CIMTYPE_SINT64;
    else if (strcmp(typeName, "datetime") == 0)
	type = CIMTYPE_DATETIME;
    else if (strcmp(typeName, "real32") == 0)
	type = CIMTYPE_REAL32;
    else if (strcmp(typeName, "real64") == 0)
	type = CIMTYPE_REAL64;
    else if (strcmp(typeName, "reference") == 0)
	type = CIMTYPE_REFERENCE;
    else unrecognizedType = true;

    if (unrecognizedType ||
        ((type == CIMTYPE_REFERENCE) &&
         (strcmp(attributeName, "PARAMTYPE") != 0)))
    {
      // l10n

      // char message[MESSAGE_SIZE];
      // sprintf(message, "Illegal value for %s.%s attribute", tagName,
      //       attributeName);
      // throw XmlSemanticError(lineNumber, message);

      char buffer[MESSAGE_SIZE];
      sprintf(buffer, "%s.%s", tagName, attributeName);
      
      MessageLoaderParms mlParms("Common.XmlReader.ILLEGAL_VALUE_FOR_ATTRIBUTE",
				 "Illegal value for $0 attribute",
				 buffer);
      
      throw XmlSemanticError(lineNumber, mlParms);
    }

    cimType = type;
    return true;
}

//------------------------------------------------------------------------------
//
// getCimBooleanAttribute()
//
//------------------------------------------------------------------------------

Boolean XmlReader::getCimBooleanAttribute(
    Uint32 lineNumber,
    const XmlEntry& entry,
    const char* tagName,
    const char* attributeName,
    Boolean defaultValue,
    Boolean required)
{
    const char* tmp;

    if (!entry.getAttributeValue(attributeName, tmp))
    {
	if (!required)
	    return defaultValue;

	// l10n

	// char buffer[62];
	// sprintf(buffer, "missing required %s.%s attribute", 
	// attributeName, tagName);

	// throw XmlValidationError(lineNumber, buffer);

	char buffer[62];
	sprintf(buffer, "%s.%s", attributeName, tagName);

	MessageLoaderParms mlParms("Common.XmlReader.MISSING_REQUIRED_ATTRIBUTE",
				   "missing required $0 attribute",
				   buffer);
	
	throw XmlValidationError(lineNumber, mlParms);
    }

    if (strcmp(tmp, "true") == 0)
	return true;
    else if (strcmp(tmp, "false") == 0)
	return false;

    // l10n

    // char buffer[62];
    // sprintf(buffer, "Invalid %s.%s attribute value", attributeName, tagName);
    // throw XmlSemanticError(lineNumber, buffer);

    char buffer[62];
    sprintf(buffer, "%s.%s", attributeName, tagName);

    MessageLoaderParms mlParms("Common.XmlReader.INVALID_ATTRIBUTE",
			       "Invalid $0 attribute value",
			       buffer);

    throw XmlSemanticError(lineNumber, mlParms);

    return false;
}

//------------------------------------------------------------------------------
//
// SringToReal()
//
//	[ "+" | "-" ] *decimalDigit "." 1*decimalDigit 
//	    [ ( "e" | "E" ) [ "+" | "-" ] 1*decimalDigit ]
//
//------------------------------------------------------------------------------

Boolean XmlReader::stringToReal(const char* stringValue, Real64& x)
{
    //
    // Check the string against the DMTF-defined grammar
    //
    const char* p = stringValue;

    if (!*p)
	return false;

    // Skip optional sign:

    if (*p == '+' || *p  == '-')
	p++;

    // Skip optional first set of digits:

    while (isdigit(*p))
	p++;

    // Test required dot:

    if (*p++ != '.')
	return false;

    // One or more digits required:

    if (!isdigit(*p++))
	return false;

    while (isdigit(*p))
	p++;

    // If there is an exponent now:

    if (*p)
    {
	// Test exponent:

	if (*p != 'e' && *p != 'E')
	    return false;

	p++;

	// Skip optional sign:

	if (*p == '+' || *p  == '-')
	    p++;

	// One or more digits required:

	if (!isdigit(*p++))
	    return false;

	while (isdigit(*p))
	    p++;
    }

    if (*p)
	return false;

    //
    // Do the conversion
    //
    char* end;
    errno = 0;
    x = strtod(stringValue, &end);
    if (*end || (errno == ERANGE))
    {
        return false;
    }

    return true;
}

inline Uint8 _xmlReader_hexCharToNumeric(const char c)
{
    Uint8 n;

    if (isdigit(c))
        n = (c - '0');
    else if (isupper(c))
        n = (c - 'A' + 10);
    else // if (islower(c))
        n = (c - 'a' + 10);

    return n;
}

// See http://www.ietf.org/rfc/rfc2396.txt section 2
//
// Also see the "CIM Operations over HTTP" spec, section 3.3.2 and
// 3.3.3, for the treatment of non US-ASCII chars (UTF-8)
String XmlReader::decodeURICharacters(String uriString)
{
    Uint32 i;

    Array<Uint8> utf8Chars; 

    for (i=0; i<uriString.size(); i++)
    {
        if (uriString[i] == '%')
        {
            if (i+2 >= uriString.size())
            {
	      // l10n

	      // throw ParseError("Invalid URI encoding");

	      MessageLoaderParms mlParms("Common.XmlReader.INVALID_URI_ENCODING",
					 "Invalid URI encoding");

	      throw ParseError(MessageLoader::getMessage(mlParms));

            }

            Uint8 digit1 = _xmlReader_hexCharToNumeric(char(uriString[++i]));
            Uint8 digit2 = _xmlReader_hexCharToNumeric(char(uriString[++i]));
            if ( (digit1 > 15) || (digit2 > 15) )
            {
	      // l10n

	      // throw ParseError("Invalid URI encoding");

	      MessageLoaderParms mlParms("Common.XmlReader.INVALID_URI_ENCODING",
					 "Invalid URI encoding");

	      throw ParseError(MessageLoader::getMessage(mlParms));
            }

            Uint16 decodedChar = Uint16(digit1<<4) + Uint16(digit2);
            utf8Chars.append((Uint8)decodedChar);				
        }
        else
        {
            utf8Chars.append((Uint8)uriString[i]);	
        }
    }

    // If there was a string to decode...
    if (uriString.size() > 0)
    {
        // Convert UTF-8 to UTF-16 and return the String
        utf8Chars.append('\0');
        return String((char *)utf8Chars.getData(),STRING_FLAG_UTF8);
    }
    else
    {
        return String();
    }
}

//------------------------------------------------------------------------------
//
// stringToSignedInteger
//
//	[ "+" | "-" ] ( positiveDecimalDigit *decimalDigit | "0" )
//    or
//      [ "+" | "-" ] ( "0x" | "0X" ) 1*hexDigit
//
//------------------------------------------------------------------------------

Boolean XmlReader::stringToSignedInteger(
    const char* stringValue, 
    Sint64& x)
{
    x = 0;
    const char* p = stringValue;

    if (!p || !*p)
	return false;

    // Skip optional sign:

    Boolean negative = *p == '-';

    if (negative || *p == '+')
	p++;

    if (*p == '0')
    {
        if ( (p[1] == 'x') || (p[1] == 'X') )
        {
            // Convert a hexadecimal string

            // Skip over the "0x"
            p+=2;

            // At least one hexadecimal digit is required
            if (!isxdigit(*p))
                return false;

            // Build the Sint64 as a negative number, regardless of the
            // eventual sign (negative numbers can be bigger than positive ones)

            // Add on each digit, checking for overflow errors
            while (isxdigit(*p))
            {
                // Make sure we won't overflow when we multiply by 16
                if (x < PEGASUS_SINT64_MIN/16)
                {
                    return false;
                }
                x = x << 4;

                // Make sure we don't overflow when we add the next digit
                Sint64 newDigit = Sint64(_xmlReader_hexCharToNumeric(*p++));
                if (PEGASUS_SINT64_MIN - x > -newDigit)
                {
                    return false;
                }
                x = x - newDigit;
            }

            // If we found a non-hexadecimal digit, report an error
            if (*p)
                return false;

            // Return the integer to positive, if necessary, checking for an
            // overflow error
            if (!negative)
            {
                if (x == PEGASUS_SINT64_MIN)
                {
                    return false;
                }
                x = -x;
            }
            return true;
        }
        else
        {
            // A decimal string that starts with '0' must be exactly "0".
	    return p[1] == '\0';
        }
    }

    // Expect a positive decimal digit:

    // At least one decimal digit is required
    if (!isdigit(*p))
        return false;

    // Build the Sint64 as a negative number, regardless of the
    // eventual sign (negative numbers can be bigger than positive ones)

    // Add on each digit, checking for overflow errors
    while (isdigit(*p))
    {
        // Make sure we won't overflow when we multiply by 10
        if (x < PEGASUS_SINT64_MIN/10)
        {
            return false;
        }
        x = 10 * x;

        // Make sure we won't overflow when we add the next digit
        Sint64 newDigit = (*p++ - '0');
        if (PEGASUS_SINT64_MIN - x > -newDigit)
        {
            return false;
        }
        x = x - newDigit;
    }

    // If we found a non-decimal digit, report an error
    if (*p)
	return false;

    // Return the integer to positive, if necessary, checking for an
    // overflow error
    if (!negative)
    {
        if (x == PEGASUS_SINT64_MIN)
        {
            return false;
        }
        x = -x;
    }
    return true;
}

//------------------------------------------------------------------------------
//
// stringToUnsignedInteger
//
//	( positiveDecimalDigit *decimalDigit | "0" )
//    or
//      ( "0x" | "0X" ) 1*hexDigit
//
//------------------------------------------------------------------------------

Boolean XmlReader::stringToUnsignedInteger(
    const char* stringValue, 
    Uint64& x)
{
    x = 0;
    const char* p = stringValue;

    if (!p || !*p)
	return false;

    if (*p == '0')
    {
        if ( (p[1] == 'x') || (p[1] == 'X') )
        {
            // Convert a hexadecimal string

            // Skip over the "0x"
            p+=2;

            // At least one hexadecimal digit is required
            if (!*p)
                return false;

            // Add on each digit, checking for overflow errors
            while (isxdigit(*p))
            {
                // Make sure we won't overflow when we multiply by 16
                if (x > PEGASUS_UINT64_MAX/16)
                {
                    return false;
                }
                x = x << 4;

                // We can't overflow when we add the next digit
                Uint64 newDigit = Uint64(_xmlReader_hexCharToNumeric(*p++));
                if (PEGASUS_UINT64_MAX - x < newDigit)
                {
                    return false;
                }
                x = x + newDigit;
            }

            // If we found a non-hexadecimal digit, report an error
            if (*p)
                return false;

            return true;
        }
        else
        {
            // A decimal string that starts with '0' must be exactly "0".
	    return p[1] == '\0';
        }
    }

    // Expect a positive decimal digit:

    // Add on each digit, checking for overflow errors
    while (isdigit(*p))
    {
        // Make sure we won't overflow when we multiply by 10
        if (x > PEGASUS_UINT64_MAX/10)
        {
            return false;
        }
        x = 10 * x;

        // Make sure we won't overflow when we add the next digit
        Uint64 newDigit = (*p++ - '0');
        if (PEGASUS_UINT64_MAX - x < newDigit)
        {
            return false;
        }
        x = x + newDigit;
    }

    // If we found a non-decimal digit, report an error
    if (*p)
	return false;

    return true;
}

//------------------------------------------------------------------------------
//
// stringToValue()
//
// Return: CIMValue. If the string input is zero length creates a CIMValue
//         with value defined by the type.  Else the value is inserted.
//         
//         Note that this does not set the CIMValue Null if the string is empty.
//
//------------------------------------------------------------------------------

CIMValue XmlReader::stringToValue(
    Uint32 lineNumber, 
    const char* valueString, 
    CIMType type)
{
    // ATTN-B: accepting only UTF-8 for now! (affects string and char16):

    // Create value per type
    switch (type)
    {
	case CIMTYPE_BOOLEAN:
	{
	    if (System::strcasecmp(valueString, "TRUE") == 0)
		return CIMValue(true);
	    else if (System::strcasecmp(valueString, "FALSE") == 0)
		return CIMValue(false);
	    else {

	      // l10n

	      //  throw XmlSemanticError(
	      //	     lineNumber, "Invalid boolean value");

	      MessageLoaderParms mlParms("Common.XmlReader.INVALID_BOOLEAN_VALUE",
					 "Invalid boolean value");
	      
	      throw XmlSemanticError(lineNumber, mlParms);
	      
	    }
	}

	case CIMTYPE_STRING:
	{
	    return CIMValue(String(valueString, STRING_FLAG_UTF8));
	}

	case CIMTYPE_CHAR16:
	{

// remove this test, utf-8 can be up to 6 bytes per char
/*
	  if (strlen(valueString) != 1) {
	    // l10n

	    // throw XmlSemanticError(lineNumber, "Invalid char16 value");
	    
	    MessageLoaderParms mlParms("Common.XmlReader.INVALID_CHAR16_VALUE",
				       "Invalid char16 value");
	    
	    throw XmlSemanticError(lineNumber, mlParms);
	  }
*/
          // Converts UTF-8 to UTF-16
          String tmp(valueString, STRING_FLAG_UTF8);
          if (tmp.size() != 1)
          {
	    // l10n

	    // throw XmlSemanticError(lineNumber, "Invalid char16 value");
	    
	    MessageLoaderParms mlParms("Common.XmlReader.INVALID_CHAR16_VALUE",
				       "Invalid char16 value");
	    
	    throw XmlSemanticError(lineNumber, mlParms);
          }

	    return CIMValue(tmp[0]);
	}

	case CIMTYPE_UINT8:
	case CIMTYPE_UINT16:
	case CIMTYPE_UINT32:
	case CIMTYPE_UINT64:
	{
	    Uint64 x;

	    if (!stringToUnsignedInteger(valueString, x))
	    {

	      // l10n

	      // throw XmlSemanticError(
	      //   lineNumber, "Invalid unsigned integer value");

	      MessageLoaderParms mlParms("Common.XmlReader.INVALID_UI_VALUE",
					 "Invalid unsigned integer value");
	      
	      throw XmlSemanticError(lineNumber, mlParms);

	    }

	    switch (type)
	    {
		case CIMTYPE_UINT8:
                {
                    if (x >= (Uint64(1)<<8))
		    {

		      // l10n
		      
		      // throw XmlSemanticError(
		      //   lineNumber, "Uint8 value out of range");
		      
		      MessageLoaderParms mlParms("Common.XmlReader.U8_VALUE_OUT_OF_RANGE",
						 "Uint8 value out of range");
		      
		      throw XmlSemanticError(lineNumber, mlParms);	
		    }
		    return CIMValue(Uint8(x));
                }
		case CIMTYPE_UINT16:
                {
                    if (x >= (Uint64(1)<<16))
		    {

		      // l10n

		      // throw XmlSemanticError(
		      //	     lineNumber, "Uint16 value out of range");

		      MessageLoaderParms mlParms("Common.XmlReader.U16_VALUE_OUT_OF_RANGE",
						 "Uint16 value out of range");
		      
		      throw XmlSemanticError(lineNumber, mlParms);	

		    }
		    return CIMValue(Uint16(x));
                }
		case CIMTYPE_UINT32:
                {
                    if (x >= (Uint64(1)<<32))
		    {

		      // l10n

		      // throw XmlSemanticError(
		      //   lineNumber, "Uint32 value out of range");

		      MessageLoaderParms mlParms("Common.XmlReader.U32_VALUE_OUT_OF_RANGE",
						 "Uint32 value out of range");
		      
		      throw XmlSemanticError(lineNumber, mlParms);	
		    }
		    return CIMValue(Uint32(x));
                }
		case CIMTYPE_UINT64: return CIMValue(Uint64(x));
		default: break;
	    }
	}

	case CIMTYPE_SINT8:
	case CIMTYPE_SINT16:
	case CIMTYPE_SINT32:
	case CIMTYPE_SINT64:
	{
	    Sint64 x;

	    if (!stringToSignedInteger(valueString, x))
	    {

	      // l10n

	      // throw XmlSemanticError(
	      //   lineNumber, "Invalid signed integer value");

	      MessageLoaderParms mlParms("Common.XmlReader.INVALID_SI_VALUE",
					 "Invalid signed integer value");
	      
	      throw XmlSemanticError(lineNumber, mlParms);

	    }

	    switch (type)
	    {
		case CIMTYPE_SINT8:
                {
                    if(  (x >= (Sint64(1)<<7)) || (x < (-(Sint64(1)<<7))) )
		    {

		      // l10n

		      // throw XmlSemanticError(
		      //   lineNumber, "Sint8 value out of range");
		      
		      MessageLoaderParms mlParms("Common.XmlReader.S8_VALUE_OUT_OF_RANGE",
						 "Sint8 value out of range");
		      
		      throw XmlSemanticError(lineNumber, mlParms);	
		    }
		    return CIMValue(Sint8(x));
                }
		case CIMTYPE_SINT16:
                {
                    if(  (x >= (Sint64(1)<<15)) || (x < (-(Sint64(1)<<15))) )
		    {

		      // l10n

		      // throw XmlSemanticError(
		      //   lineNumber, "Sint16 value out of range");
		      
		      MessageLoaderParms mlParms("Common.XmlReader.S16_VALUE_OUT_OF_RANGE",
						 "Sint16 value out of range");
		      
		      throw XmlSemanticError(lineNumber, mlParms);	
		    }
		    return CIMValue(Sint16(x));
                }
		case CIMTYPE_SINT32:
                {
                    if(  (x >= (Sint64(1)<<31)) || (x < (-(Sint64(1)<<31))) )
		    {

		      // l10n

		      // throw XmlSemanticError(
		      //   lineNumber, "Sint32 value out of range");

		      MessageLoaderParms mlParms("Common.XmlReader.S32_VALUE_OUT_OF_RANGE",
						 "Sint32 value out of range");
		      
		      throw XmlSemanticError(lineNumber, mlParms);	
		    }
		    return CIMValue(Sint32(x));
                }
		case CIMTYPE_SINT64: return CIMValue(Sint64(x));
		default: break;
	    }
	}

	case CIMTYPE_DATETIME:
	{
	    CIMDateTime tmp;

	    try
	    {
            // KS 20021002 - Exception if no datatime value. Test for
            // zero length and leave the NULL value in the variable
            // Bugzilla 137  Adds the following if line.
            // Expect this to become permanent but test only for now
#ifdef PEGASUS_SNIA_INTEROP_TEST
            if (strlen(valueString) != 0)
#endif
                tmp.set(valueString);
	    }
	    catch (InvalidDateTimeFormatException&)
	    {

	      // l10n

	      // throw XmlSemanticError(lineNumber, "Invalid datetime value");

	      MessageLoaderParms mlParms("Common.XmlReader.INVALID_DATETIME_VALUE",
					 "Invalid datetime value");
	      
	      throw XmlSemanticError(lineNumber, mlParms);
	    }

	    return CIMValue(tmp);
	}

	case CIMTYPE_REAL32:
	{
	    Real64 x;

	    if (!stringToReal(valueString, x)) {

	      // l10n

	      // throw XmlSemanticError(lineNumber, "Invalid real number value");

	      MessageLoaderParms mlParms("Common.XmlReader.INVALID_RN_VALUE",
					 "Invalid real number value");
	      
	      throw XmlSemanticError(lineNumber, mlParms);
	    }
	    return CIMValue(Real32(x));
	}

	case CIMTYPE_REAL64:
	{
	    Real64 x;

	    if (!stringToReal(valueString, x)) {

	      // l10n

	      // throw XmlSemanticError(lineNumber, "Invalid real number value");

	      MessageLoaderParms mlParms("Common.XmlReader.INVALID_RN_VALUE",
					 "Invalid real number value");
	      
	      throw XmlSemanticError(lineNumber, mlParms);
	    }
	    return CIMValue(x);
	}

	default:
	    break;
    }

    // l10n

    // throw XmlSemanticError(lineNumber, "malformed XML");

    MessageLoaderParms mlParms("Common.XmlReader.MALFORMED_XML",
			       "malformed XML");
    
    throw XmlSemanticError(lineNumber, mlParms);

    return false;
}

//------------------------------------------------------------------------------
//
// skipElement()
//
//------------------------------------------------------------------------------
void XmlReader::skipElement(
    XmlParser& parser,
    XmlEntry& entry)
{
    const char * tag_name = entry.text;

    if (entry.type == XmlEntry::EMPTY_TAG)
    {
	return;
    }

    while (testStartTagOrEmptyTag(parser, entry))
    {
        skipElement(parser, entry); 
    }

    if (testContentOrCData(parser, entry))
    {
        ; // skip
    }

    expectEndTag(parser, tag_name);
    return;
}

//------------------------------------------------------------------------------
//
// getValueElement()
//
//     <!ELEMENT VALUE (#PCDATA)>
//
// Return: false if no value element.
//
//------------------------------------------------------------------------------

Boolean XmlReader::getValueElement(
    XmlParser& parser, 
    CIMType type, 
    CIMValue& value)
{
    // Get VALUE start tag: Return false if no VALUE start Tag

    XmlEntry entry;
    if (!testStartTagOrEmptyTag(parser, entry, "VALUE"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    const char* valueString = "";

    if (!empty)
    {
	if (testContentOrCData(parser, entry))
	    valueString = entry.text;

	expectEndTag(parser, "VALUE");
    }
#ifdef PEGASUS_SNIA_INTEROP_TEST
    // KS 20021004 - tries to put value in even if empty.
    // Think this is general problem with empty value
    // Need to check meaning of (#PCDATA) - Does it allow empty.
    // Bugzilla tbd
    if (!empty)
#endif
        value = stringToValue(parser.getLine(), valueString,type);
    
    return true;
}

//------------------------------------------------------------------------------
//
// getStringValueElement()
//
//     <!ELEMENT VALUE (#PCDATA)>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getStringValueElement(
    XmlParser& parser, 
    String& str,
    Boolean required)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "VALUE"))
    {
      if (required) {

	// l10n

	// throw XmlValidationError(parser.getLine(),"Expected VALUE element");

	MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_VALUE_ELEMENT",
				   "Expected VALUE element");
	
	throw XmlValidationError(parser.getLine(), mlParms);
	

      }
      return false;
    }

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    const char* valueString = "";

    if (!empty)
    {
	if (testContentOrCData(parser, entry))
	    valueString = entry.text;

	expectEndTag(parser, "VALUE");
    }

    str = String(valueString,STRING_FLAG_UTF8);
    return true;
}

//----------------------------------------------------------------------------
//
// getPropertyValue
//     Use: Decode property value from SetProperty request and
//     GetProperty response.
//
//     PropertyValue is one of:
//
//
//	<!ELEMENT VALUE.ARRAY (VALUE*)>
//
//	<!ELEMENT VALUE.REFERENCE (CLASSPATH|LOCALCLASSPATH|CLASSNAME|
//         <!ELEMENT VALUE.ARRAY (VALUE*)>
//
//         <!ELEMENT VALUE.REFERENCE (CLASSPATH|LOCALCLASSPATH|CLASSNAME|
//                           INSTANCEPATH|LOCALINSTANCEPATH|INSTANCENAME)>
//
//         <!ELEMENT VALUE.REFARRAY (VALUE.REFERENCE*)>
//
//----------------------------------------------------------------------------
Boolean XmlReader::getPropertyValue(
    XmlParser& parser, 
    CIMValue& cimValue)
{
    // Can not test for value type, so assume String
    const CIMType type = CIMTYPE_STRING;

    // Test for VALUE element
    if (XmlReader::getValueElement(parser, type, cimValue))
    {
	return true;
    }

    // Test for VALUE.ARRAY element
    if (XmlReader::getValueArrayElement(parser, type, cimValue))
    {
       return true;
    }

    // Test for VALUE.REFERENCE element
    CIMObjectPath reference;
    if (XmlReader::getValueReferenceElement(parser, reference))
    {
        cimValue.set(reference);
        return true;
    }

    // Test for VALUE.REFARRAY element
    if (XmlReader::getValueReferenceArrayElement(parser, cimValue))
    {
       return true;
    }

    return false;
}

//------------------------------------------------------------------------------
//
// stringArrayToValue()
//
//------------------------------------------------------------------------------

template<class T>
CIMValue StringArrayToValueAux(
    Uint32 lineNumber, 
    const Array<const char*>& stringArray,
    CIMType type,
    T*)
{
    Array<T> array;

    for (Uint32 i = 0, n = stringArray.size(); i < n; i++)
    {
	CIMValue value = XmlReader::stringToValue(
	    lineNumber, stringArray[i], type);

	T x;
	value.get(x);
	array.append(x);
    }

    return CIMValue(array);
}

CIMValue XmlReader::stringArrayToValue(
    Uint32 lineNumber, 
    const Array<const char*>& array, 
    CIMType type)
{
    switch (type)
    {
	case CIMTYPE_BOOLEAN: 
	    return StringArrayToValueAux(lineNumber, array, type, (Boolean*)0);

	case CIMTYPE_STRING:
	    return StringArrayToValueAux(lineNumber, array, type, (String*)0);

	case CIMTYPE_CHAR16:
	    return StringArrayToValueAux(lineNumber, array, type, (Char16*)0);

	case CIMTYPE_UINT8:
	    return StringArrayToValueAux(lineNumber, array, type, (Uint8*)0);

	case CIMTYPE_UINT16:
	    return StringArrayToValueAux(lineNumber, array, type, (Uint16*)0);

	case CIMTYPE_UINT32:
	    return StringArrayToValueAux(lineNumber, array, type, (Uint32*)0);

	case CIMTYPE_UINT64:
	    return StringArrayToValueAux(lineNumber, array, type, (Uint64*)0);

	case CIMTYPE_SINT8:
	    return StringArrayToValueAux(lineNumber, array, type, (Sint8*)0);

	case CIMTYPE_SINT16:
	    return StringArrayToValueAux(lineNumber, array, type, (Sint16*)0);

	case CIMTYPE_SINT32:
	    return StringArrayToValueAux(lineNumber, array, type, (Sint32*)0);

	case CIMTYPE_SINT64:
	    return StringArrayToValueAux(lineNumber, array, type, (Sint64*)0);

	case CIMTYPE_DATETIME:
	    return StringArrayToValueAux(lineNumber, array, type, (CIMDateTime*)0);

	case CIMTYPE_REAL32:
	    return StringArrayToValueAux(lineNumber, array, type, (Real32*)0);

	case CIMTYPE_REAL64:
	    return StringArrayToValueAux(lineNumber, array, type, (Real64*)0);

	default:
	    break;
    }

    // Unreachable:
    return CIMValue();
}

//------------------------------------------------------------------------------
//
// getValueArrayElement()
//
//     <!ELEMENT VALUE.ARRAY (VALUE*)>
//
//  Return: Boolean. Returns false if there is no VALUE.ARRAY start element
//
//------------------------------------------------------------------------------

Boolean XmlReader::getValueArrayElement(
    XmlParser& parser, 
    CIMType type, 
    CIMValue& value)
{
    // Clears any values from the Array. Assumes this is array CIMValue
    value.clear();

    // Get VALUE.ARRAY open tag:

    XmlEntry entry;
    Array<const char*> stringArray;

    // If no VALUE.ARRAY start tag, return false
    if (!testStartTagOrEmptyTag(parser, entry, "VALUE.ARRAY"))
	return false;

    if (entry.type != XmlEntry::EMPTY_TAG)
    {
        // For each VALUE element:

        while (testStartTagOrEmptyTag(parser, entry, "VALUE"))
        {
	    if (entry.type == XmlEntry::EMPTY_TAG)
	    {
	        stringArray.append("");
	        continue;
	    }

	    if (testContentOrCData(parser, entry))
	        stringArray.append(entry.text);
	    else
	        stringArray.append("");

	    expectEndTag(parser, "VALUE");
        }

        expectEndTag(parser, "VALUE.ARRAY");
    }

    value = stringArrayToValue(parser.getLine(), stringArray, type);
    return true;
}

//------------------------------------------------------------------------------
//
// getFlavor()
//
//     <!ENTITY % QualifierFlavor 
//         "OVERRIDABLE (true|false) 'true'
//         TOSUBCLASS (true|false) 'true'
//         TOINSTANCE (true|false)  'false'
//         TRANSLATABLE (true|false)  'false'">
//
//------------------------------------------------------------------------------

CIMFlavor XmlReader::getFlavor(
    XmlEntry& entry, 
    Uint32 lineNumber, 
    const char* tagName)
{
    // Get QUALIFIER.OVERRIDABLE

    Boolean overridable = getCimBooleanAttribute(
	lineNumber, entry, tagName, "OVERRIDABLE", true, false);

    // Get QUALIFIER.TOSUBCLASS

    Boolean toSubClass = getCimBooleanAttribute(
	lineNumber, entry, tagName, "TOSUBCLASS", true, false);

    // Get QUALIFIER.TOINSTANCE

    Boolean toInstance = getCimBooleanAttribute(
	lineNumber, entry, tagName, "TOINSTANCE", false, false);

    // Get QUALIFIER.TRANSLATABLE

    Boolean translatable = getCimBooleanAttribute(
	lineNumber, entry, tagName, "TRANSLATABLE", false, false);

    // Start with CIMFlavor::NONE.  Defaults are specified in the
    // getCimBooleanAttribute() calls above.
    CIMFlavor flavor = CIMFlavor (CIMFlavor::NONE);

    if (overridable)
        flavor.addFlavor (CIMFlavor::OVERRIDABLE);
    else
        flavor.addFlavor (CIMFlavor::DISABLEOVERRIDE);

    if (toSubClass)
        flavor.addFlavor (CIMFlavor::TOSUBCLASS);
    else
        flavor.addFlavor (CIMFlavor::RESTRICTED);

    if (toInstance)
        flavor.addFlavor (CIMFlavor::TOINSTANCE);

    if (translatable)
        flavor.addFlavor (CIMFlavor::TRANSLATABLE);

    return flavor;
}

//------------------------------------------------------------------------------
//
// getOptionalScope()
//
//     DTD:
//         <!ELEMENT SCOPE EMPTY>
//         <!ATTLIST SCOPE 
//              CLASS (true|false) 'false'
//              ASSOCIATION (true|false) 'false'
//              REFERENCE (true|false) 'false'
//              PROPERTY (true|false) 'false'
//              METHOD (true|false) 'false'
//              PARAMETER (true|false) 'false'
//              INDICATION (true|false) 'false'>
//
//------------------------------------------------------------------------------

CIMScope XmlReader::getOptionalScope(XmlParser& parser)
{
    XmlEntry entry;
    CIMScope scope;

    if (!parser.next(entry))
	return scope;    // No SCOPE element found; return the empty scope

    Boolean isEmptyTag = entry.type == XmlEntry::EMPTY_TAG;

    if ((!isEmptyTag && 
	entry.type != XmlEntry::START_TAG) ||
	strcmp(entry.text, "SCOPE") != 0)
    {
	// No SCOPE element found; return the empty scope
	parser.putBack(entry);
	return scope;
    }

    Uint32 line = parser.getLine();

    if (getCimBooleanAttribute(line, entry, "SCOPE", "CLASS", false, false))
	scope.addScope (CIMScope::CLASS);

    if (getCimBooleanAttribute(
	line, entry, "SCOPE", "ASSOCIATION", false, false))
	scope.addScope (CIMScope::ASSOCIATION);

    if (getCimBooleanAttribute(
	line, entry, "SCOPE", "REFERENCE", false, false))
	scope.addScope (CIMScope::REFERENCE);

    if (getCimBooleanAttribute(line, entry, "SCOPE", "PROPERTY", false, false))
	scope.addScope (CIMScope::PROPERTY);

    if (getCimBooleanAttribute(line, entry, "SCOPE", "METHOD", false, false))
	scope.addScope (CIMScope::METHOD);

    if (getCimBooleanAttribute(line, entry, "SCOPE", "PARAMETER", false, false))
	scope.addScope (CIMScope::PARAMETER);

    if (getCimBooleanAttribute(line, entry, "SCOPE", "INDICATION",false, false))
	scope.addScope (CIMScope::INDICATION);

    if (!isEmptyTag)
	expectEndTag(parser, "SCOPE");

    return scope;
}

//------------------------------------------------------------------------------
//
// getQualifierElement()
//
//     <!ELEMENT QUALIFIER (VALUE|VALUE.ARRAY)?>
//     <!ATTLIST QUALIFIER
//         %CIMName;
//         %CIMType; #REQUIRED
//         %Propagated;
//         %QualifierFlavor;>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getQualifierElement(
    XmlParser& parser, 
    CIMQualifier& qualifier)
{
    // Get QUALIFIER element:

    XmlEntry entry;
    if (!testStartTag(parser, entry, "QUALIFIER"))
	return false;

    // Get QUALIFIER.NAME attribute:

    CIMName name = getCimNameAttribute(parser.getLine(), entry, "QUALIFIER");

    // Get QUALIFIER.TYPE attribute:

    CIMType type;
    getCimTypeAttribute(parser.getLine(), entry, type, "QUALIFIER");

    // Get QUALIFIER.PROPAGATED

    Boolean propagated = getCimBooleanAttribute(
	parser.getLine(), entry, "QUALIFIER", "PROPAGATED", false, false);

    // Get flavor oriented attributes:

    CIMFlavor flavor = getFlavor(entry, parser.getLine(), "QUALIFIER");

    // Get VALUE or VALUE.ARRAY element:

    CIMValue value;

    if (!getValueElement(parser, type, value) &&
	!getValueArrayElement(parser, type, value))
    {
        value.setNullValue(type, false);
    }

    // Expect </QUALIFIER>:

    expectEndTag(parser, "QUALIFIER");

    // Build qualifier:

    qualifier = CIMQualifier(name, value, flavor, propagated);
    return true;
}

//------------------------------------------------------------------------------
//
// getQualifierElements()
//
//------------------------------------------------------------------------------

template<class CONTAINER>
void getQualifierElements(XmlParser& parser, CONTAINER& container)
{
    CIMQualifier qualifier;

    while (XmlReader::getQualifierElement(parser, qualifier))
    {
	try
	{
	    container.addQualifier(qualifier);
	}
	catch (AlreadyExistsException&)
	{

	  // l10n
	  
	  // throw XmlSemanticError(parser.getLine(), "duplicate qualifier");

	  MessageLoaderParms mlParms("Common.XmlReader.DUPLICATE_QUALIFIER",
				     "duplicate qualifier");
	  
	  throw XmlSemanticError(parser.getLine(), mlParms);
	}
    }
}

//------------------------------------------------------------------------------
//
// getPropertyElement()
//
//     <!ELEMENT PROPERTY (QUALIFIER*,VALUE?)>
//     <!ATTLIST PROPERTY
//         %CIMName;
//         %ClassOrigin;
//         %Propagated;
//         %CIMType; #REQUIRED>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getPropertyElement(XmlParser& parser, CIMProperty& property)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "PROPERTY"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    // Get PROPERTY.NAME attribute:

    CIMName name = getCimNameAttribute(parser.getLine(), entry, "PROPERTY");

    // Get PROPERTY.CLASSORIGIN attribute:

    CIMName classOrigin = 
	getClassOriginAttribute(parser.getLine(), entry, "PROPERTY");

    // Get PROPERTY.PROPAGATED

    Boolean propagated = getCimBooleanAttribute(
	parser.getLine(), entry, "PROPERTY", "PROPAGATED", false, false);

    // Get PROPERTY.TYPE attribute:

    CIMType type;
    getCimTypeAttribute(parser.getLine(), entry, type, "PROPERTY");

    // Create property: Sets type and !isarray

    CIMValue value(type, false);
    property = CIMProperty(name, value, 0, CIMName(), classOrigin, propagated);

    if (!empty)
    {
	// Get qualifiers:

	getQualifierElements(parser, property);

	// Get value:  Insert value if getValueElement exists (returns True)

	if (getValueElement(parser, type, value))
	    property.setValue(value);

	expectEndTag(parser, "PROPERTY");
    }

    return true;
}

//------------------------------------------------------------------------------
//
// getArraySizeAttribute()
//
//     Returns true if able to get array-size. Note that array size will
//     always be a positive integer.
//
//     <!ENTITY % ArraySize "ARRAYSIZE CDATA #IMPLIED">
//
//------------------------------------------------------------------------------

Boolean XmlReader::getArraySizeAttribute(
    Uint32 lineNumber,
    const XmlEntry& entry,
    const char* tagName,
    Uint32& value)
{
    const char* tmp;

    if (!entry.getAttributeValue("ARRAYSIZE", tmp))
	return false;

    Uint64 arraySize;

    if (!stringToUnsignedInteger(tmp, arraySize) || arraySize == 0)
    {
      // l10n
      
      // char message[128];
      // sprintf(message, "Illegal value for %s.%s", tagName, "ARRAYSIZE");
      // throw XmlSemanticError(lineNumber, message);

      char message[128];
      sprintf(message, "%s.%s", tagName, "ARRAYSIZE");
      
      MessageLoaderParms mlParms("Common.XmlReader.ILLEGAL_VALUE",
				 "Illegal value for $0",
				 message);
      
      throw XmlSemanticError(lineNumber, mlParms);
    }

    value = Uint32(arraySize);
    return true;
}

//------------------------------------------------------------------------------
//
// getPropertyArrayElement()
//
//     <!ELEMENT PROPERTY.ARRAY (QUALIFIER*,VALUE.ARRAY?)>
//     <!ATTLIST PROPERTY.ARRAY
//             %CIMName;
//             %CIMType; #REQUIRED
//             %ArraySize;
//             %ClassOrigin;
//             %Propagated;>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getPropertyArrayElement(
    XmlParser& parser, 
    CIMProperty& property)
{
    // Get PROPERTY element:

    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "PROPERTY.ARRAY"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    // Get PROPERTY.NAME attribute:

    CIMName name = 
	getCimNameAttribute(parser.getLine(), entry, "PROPERTY.ARRAY");

    // Get PROPERTY.TYPE attribute:

    CIMType type;
    getCimTypeAttribute(parser.getLine(), entry, type, "PROPERTY.ARRAY");

    // Get PROPERTY.ARRAYSIZE attribute:

    Uint32 arraySize = 0;
    getArraySizeAttribute(parser.getLine(), entry, "PROPERTY.ARRAY", arraySize);

    // Get PROPERTY.CLASSORIGIN attribute:

    CIMName classOrigin 
	= getClassOriginAttribute(parser.getLine(), entry, "PROPERTY.ARRAY");

    // Get PROPERTY.ARRAY.PROPAGATED

    Boolean propagated = getCimBooleanAttribute(
	parser.getLine(), entry, "PROPERTY.ARRAY", "PROPAGATED", false, false);

    // Create property:

    CIMValue value(type, true, arraySize);
    property = CIMProperty(
	name, value, arraySize, CIMName(), classOrigin, propagated);

    if (!empty)
    {
	// Get qualifiers:

	getQualifierElements(parser, property);

	// Get value:

	if (getValueArrayElement(parser, type, value))
	{
	    if (arraySize && arraySize != value.getArraySize())
	    {

	      // l10n

	      // throw XmlSemanticError(parser.getLine(),
	      //   "ARRAYSIZE attribute and value-array size are different");

	      MessageLoaderParms mlParms("Common.XmlReader.ARRAY_SIZE_DIFFERENT",
					 "ARRAYSIZE attribute and value-array size are different");
	      
	      throw XmlSemanticError(parser.getLine(), mlParms);
	    }

	    property.setValue(value);
	}

	expectEndTag(parser, "PROPERTY.ARRAY");
    }

    return true;
}

//------------------------------------------------------------------------------
//
// getHostElement()
//
//     <!ELEMENT HOST (#PCDATA)>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getHostElement(
    XmlParser& parser,
    String& host)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "HOST"))
	return false;
#ifdef PEGASUS_SNIA_INTEROP_TEST
    // Temp code to allow empty HOST field.
    // SNIA CIMOMs return empty field particularly on enumerateinstance.
    // Simply substitute a string for the empty.
	if (!parser.next(entry))
	    throw XmlException(XmlException::UNCLOSED_TAGS, parser.getLine());

	if (entry.type == XmlEntry::CONTENT)
	    host = String(entry.text,STRING_FLAG_UTF8);
	else
    {
	    parser.putBack(entry);
        host = "HOSTNAMEINSERTEDBYPEGASUSCLIENT";
    }

#else

    if (!parser.next(entry) || entry.type != XmlEntry::CONTENT)
    {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //	       "expected content of HOST element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_CONTENT_ELEMENT",
				 "expected content of HOST element");
      
      throw XmlValidationError(parser.getLine(), mlParms);
	
    }

    host = String(entry.text,STRING_FLAG_UTF8);
#endif
    expectEndTag(parser, "HOST");
    return true;
}

//------------------------------------------------------------------------------
//
// getNameSpaceElement()
//     
//     <!ELEMENT NAMESPACE EMPTY>
//     <!ATTLIST NAMESPACE %CIMName;>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getNameSpaceElement(
    XmlParser& parser,
    CIMName& nameSpaceComponent)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "NAMESPACE"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    nameSpaceComponent = getCimNameAttribute(
	parser.getLine(), entry, "NAMESPACE");

    if (!empty)
	expectEndTag(parser, "NAMESPACE");

    return true;
}

//------------------------------------------------------------------------------
//
// getLocalNameSpacePathElement()
//     
//     <!ELEMENT LOCALNAMESPACEPATH (NAMESPACE+)>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getLocalNameSpacePathElement(
    XmlParser& parser,
    String& nameSpace)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "LOCALNAMESPACEPATH"))
	return false;

    CIMName nameSpaceComponent;

    while (getNameSpaceElement(parser, nameSpaceComponent))
    {
	if (nameSpace.size())
	    nameSpace.append('/');

	nameSpace.append(nameSpaceComponent.getString());
    }

    if (!nameSpace.size())
    {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "Expected one or more NAMESPACE elements within "
      //   "LOCALNAMESPACEPATH element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_NAMESPACE_ELEMENTS",
				 "Expected one or more NAMESPACE elements within LOCALNAMESPACEPATH element");
      
      throw XmlValidationError(parser.getLine(), mlParms);
	

    }

    expectEndTag(parser, "LOCALNAMESPACEPATH");
    return true;
}

//------------------------------------------------------------------------------
//
// getNameSpacePathElement()
//
//     <!ELEMENT NAMESPACEPATH (HOST,LOCALNAMESPACEPATH)>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getNameSpacePathElement(
    XmlParser& parser,
    String& host,
    String& nameSpace)
{
    host.clear();
    nameSpace.clear();

    XmlEntry entry;

    if (!testStartTag(parser, entry, "NAMESPACEPATH"))
	return false;

    if (!getHostElement(parser, host)) {

      // l10n

      // throw XmlValidationError(parser.getLine(), "expected HOST element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_HOST_ELEMENT",
				 "expected HOST element");
      
      throw XmlValidationError(parser.getLine(), mlParms);
    }

    if (!getLocalNameSpacePathElement(parser, nameSpace))
    {

      // l10n

      // throw XmlValidationError(parser.getLine(), 
      //   "expected LOCALNAMESPACEPATH element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_LOCALNAMESPACEPATH_ELEMENT",
				 "expected LOCALNAMESPACEPATH element");
      
      throw XmlValidationError(parser.getLine(), mlParms);
    }

    expectEndTag(parser, "NAMESPACEPATH");

    return true;
}

//------------------------------------------------------------------------------
//
// getClassNameElement()
//
//     <!ELEMENT CLASSNAME EMPTY>
//     <!ATTLIST CLASSNAME %CIMName;>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getClassNameElement(
    XmlParser& parser,
    CIMName& className,
    Boolean required)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "CLASSNAME"))
    {
	if (required)
	{

	  // l10n

	  // throw XmlValidationError(parser.getLine(),
	  // "expected CLASSNAME element");

	  MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_CLASSNAME_ELEMENT",
				     "expected CLASSNAME element");
	  
	  throw XmlValidationError(parser.getLine(), mlParms);
	}
	else
	    return false;
    }
    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    className = getCimNameAttribute(
	parser.getLine(), entry, "CLASSNAME", false);

    if (!empty)
	expectEndTag(parser, "CLASSNAME");

    return true;
}

//------------------------------------------------------------------------------
//
// getValueTypeAttribute()
//
//     VALUETYPE (string|boolean|numeric) 'string'
//
//------------------------------------------------------------------------------

CIMKeyBinding::Type XmlReader::getValueTypeAttribute(
    Uint32 lineNumber, 
    const XmlEntry& entry,
    const char* elementName)
{
    String tmp;

    if (!entry.getAttributeValue("VALUETYPE", tmp))
	return CIMKeyBinding::STRING;

    if (String::equal(tmp, "string"))
	return CIMKeyBinding::STRING;
    else if (String::equal(tmp, "boolean"))
	return CIMKeyBinding::BOOLEAN;
    else if (String::equal(tmp, "numeric"))
	return CIMKeyBinding::NUMERIC;

    // char buffer[MESSAGE_SIZE];

    // sprintf(buffer, 
    // "Illegal value for %s.VALUETYPE attribute; "
    // "CIMValue must be one of \"string\", \"boolean\", or \"numeric\"",
    // elementName);

    // throw XmlSemanticError(lineNumber, buffer);


    char buffer[MESSAGE_SIZE];
    sprintf(buffer, "%s.VALUETYPE", elementName);
    
    MessageLoaderParms mlParms("Common.XmlReader.ILLEGAL_VALUE_FOR_CIMVALUE_ATTRIBUTE",
			       "Illegal value for $0 attribute; CIMValue must be one of \"string\", \"boolean\", or \"numeric\"", buffer);
    
    throw XmlSemanticError(lineNumber, mlParms);

    return CIMKeyBinding::BOOLEAN;
}

//------------------------------------------------------------------------------
//
// getKeyValueElement()
//
//     <!ELEMENT KEYVALUE (#PCDATA)>
//     <!ATTLIST KEYVALUE
//         VALUETYPE (string|boolean|numeric)  'string'>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getKeyValueElement(
    XmlParser& parser,
    CIMKeyBinding::Type& type,
    String& value)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "KEYVALUE"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    type = getValueTypeAttribute(parser.getLine(), entry, "KEYVALUE");

    value.clear();

    if (!empty)
    {
	if (!parser.next(entry))
	    throw XmlException(XmlException::UNCLOSED_TAGS, parser.getLine());

	if (entry.type == XmlEntry::CONTENT)
	    value = String(entry.text,STRING_FLAG_UTF8);
	else
	    parser.putBack(entry);

	expectEndTag(parser, "KEYVALUE");
    }

    return true;
}

//------------------------------------------------------------------------------
//
// getKeyBindingElement()
//
//     <!ELEMENT KEYBINDING (KEYVALUE|VALUE.REFERENCE)>
//     <!ATTLIST KEYBINDING
//         %CIMName;>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getKeyBindingElement(
    XmlParser& parser,
    CIMName& name,
    String& value,
    CIMKeyBinding::Type& type)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "KEYBINDING"))
	return false;

    name = getCimNameAttribute(parser.getLine(), entry, "KEYBINDING");

    if (!getKeyValueElement(parser, type, value))
    {
        CIMObjectPath reference;

        if (!getValueReferenceElement(parser, reference))
        {

	  // l10n

	  // throw XmlValidationError(parser.getLine(),
	  //          "Expected KEYVALUE or VALUE.REFERENCE element");

	  MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_KEYVALUE_OR_REFERENCE_ELEMENT",
				     "Expected KEYVALUE or VALUE.REFERENCE element");
	  
	  throw XmlValidationError(parser.getLine(), mlParms);
        }

        type = CIMKeyBinding::REFERENCE;
        value = reference.toString();
    }

    expectEndTag(parser, "KEYBINDING");
    return true;
}

//------------------------------------------------------------------------------
//
// getInstanceNameElement()
//
//     <!ELEMENT INSTANCENAME (KEYBINDING*|KEYVALUE?|VALUE.REFERENCE?)>
//     <!ATTLIST INSTANCENAME
//         %ClassName;>
//
// Note: An empty key name is used in the keyBinding when the INSTANCENAME is
// specified using a KEYVALUE or a VALUE.REFERENCE.
//
//------------------------------------------------------------------------------

Boolean XmlReader::getInstanceNameElement(
    XmlParser& parser,
    String& className,
    Array<CIMKeyBinding>& keyBindings)
{
    className.clear();
    keyBindings.clear();

    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "INSTANCENAME"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    className = getClassNameAttribute(parser.getLine(), entry, "INSTANCENAME");

    if (empty)
    {
        return true;
    }

    CIMName name;
    CIMKeyBinding::Type type;
    String value;
    CIMObjectPath reference;

    if (getKeyValueElement(parser, type, value))
    {
        // Use empty key name because none was specified
        keyBindings.append(CIMKeyBinding(name, value, type));
    }
    else if (getValueReferenceElement(parser, reference))
    {
        // Use empty key name because none was specified
        type = CIMKeyBinding::REFERENCE;
        value = reference.toString();
        keyBindings.append(CIMKeyBinding(name, value, type));
    }
    else
    {
	while (getKeyBindingElement(parser, name, value, type))
	    keyBindings.append(CIMKeyBinding(name, value, type));
    }

    expectEndTag(parser, "INSTANCENAME");

    return true;
}

Boolean XmlReader::getInstanceNameElement(
    XmlParser& parser,
    CIMObjectPath& instanceName)
{
    String className;
    Array<CIMKeyBinding> keyBindings;

    if (!XmlReader::getInstanceNameElement(parser, className, keyBindings))
	return false;

    instanceName.set(String(), CIMNamespaceName(), className, keyBindings);
    return true;
}

//------------------------------------------------------------------------------
//
// getInstancePathElement()
//
//     <!ELEMENT INSTANCEPATH (NAMESPACEPATH,INSTANCENAME)>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getInstancePathElement(
    XmlParser& parser,
    CIMObjectPath& reference)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "INSTANCEPATH"))
	return false;

    String host;
    String nameSpace;

    if (!getNameSpacePathElement(parser, host, nameSpace))
    {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "expected NAMESPACEPATH element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_NAMESPACEPATH_ELEMENT",
				 "expected NAMESPACEPATH element");
      
      throw XmlValidationError(parser.getLine(), mlParms);

    }

    String className;
    Array<CIMKeyBinding> keyBindings;

    if (!getInstanceNameElement(parser, className, keyBindings))
    {

      // l10n

      // throw XmlValidationError(parser.getLine(), 
      //   "expected INSTANCENAME element");


      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_INSTANCENAME_ELEMENT",
				 "expected INSTANCENAME element");
      
      throw XmlValidationError(parser.getLine(), mlParms);

    }

    reference.set(host, nameSpace, className, keyBindings);

    expectEndTag(parser, "INSTANCEPATH");
    return true;
}

//------------------------------------------------------------------------------
//
// getLocalInstancePathElement()
//
//     <!ELEMENT LOCALINSTANCEPATH (NAMESPACEPATH,INSTANCENAME)>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getLocalInstancePathElement(
    XmlParser& parser,
    CIMObjectPath& reference)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "LOCALINSTANCEPATH"))
	return false;

    String nameSpace;

    if (!getLocalNameSpacePathElement(parser, nameSpace))
    {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "expected LOCALNAMESPACEPATH element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_LOCALNAMESPACEPATH_ELEMENT",
				 "expected LOCALNAMESPACEPATH element");
      
      throw XmlValidationError(parser.getLine(), mlParms);

    }

    String className;
    Array<CIMKeyBinding> keyBindings;

    if (!getInstanceNameElement(parser, className, keyBindings))
    {

      // l10n

      // throw XmlValidationError(parser.getLine(), 
      //   "expected INSTANCENAME element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_INSTANCENAME_ELEMENT",
				 "expected INSTANCENAME element");
      
      throw XmlValidationError(parser.getLine(), mlParms);

    }

    reference.set(String(), nameSpace, className, keyBindings);

    expectEndTag(parser, "LOCALINSTANCEPATH");
    return true;
}

//------------------------------------------------------------------------------
//
// getClassPathElement()
//
//     <!ELEMENT CLASSPATH (NAMESPACEPATH,CLASSNAME)>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getClassPathElement(
    XmlParser& parser,
    CIMObjectPath& reference)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "CLASSPATH"))
	return false;

    String host;
    String nameSpace;

    if (!getNameSpacePathElement(parser, host, nameSpace))
    {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //    "expected NAMESPACEPATH element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_NAMESPACEPATH_ELEMENT",
				 "expected NAMESPACEPATH element");
      
      throw XmlValidationError(parser.getLine(), mlParms);

    }

    CIMName className;

    if (!getClassNameElement(parser, className))
    {

      // l10n

      // throw XmlValidationError(parser.getLine(), 
      //   "expected CLASSNAME element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_CLASSNAME_ELEMENT",
				 "expected CLASSNAME element");
      
      throw XmlValidationError(parser.getLine(), mlParms);

    }

    reference.set(host, nameSpace, className);

    expectEndTag(parser, "CLASSPATH");
    return true;
}

//------------------------------------------------------------------------------
//
// getLocalClassPathElement()
//
//     <!ELEMENT LOCALCLASSPATH (LOCALNAMESPACEPATH,CLASSNAME)>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getLocalClassPathElement(
    XmlParser& parser,
    CIMObjectPath& reference)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "LOCALCLASSPATH"))
	return false;

    String nameSpace;

    if (!getLocalNameSpacePathElement(parser, nameSpace))
    {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //    "expected LOCALNAMESPACEPATH element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_LOCALNAMESPACEPATH_ELEMENT",
				 "expected LOCALNAMESPACEPATH element");
      
      throw XmlValidationError(parser.getLine(), mlParms);

    }

    CIMName className;

    if (!getClassNameElement(parser, className))
    {

      // l10n

      // throw XmlValidationError(parser.getLine(), 
      //   "expected CLASSNAME element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_CLASSNAME_ELEMENT",
				 "expected CLASSNAME element");
      
      throw XmlValidationError(parser.getLine(), mlParms);

    }

    reference.set(String(), nameSpace, className);

    expectEndTag(parser, "LOCALCLASSPATH");

    return true;
}

//------------------------------------------------------------------------------
//
// getValueReferenceElement()
//
//     <!ELEMENT VALUE.REFERENCE (CLASSPATH|LOCALCLASSPATH|CLASSNAME|
//         INSTANCEPATH|LOCALINSTANCEPATH|INSTANCENAME)>
//
//
//------------------------------------------------------------------------------

Boolean XmlReader::getValueReferenceElement(
    XmlParser& parser,
    CIMObjectPath& reference)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "VALUE.REFERENCE"))
	return false;

    if (!parser.next(entry))
	throw XmlException(XmlException::UNCLOSED_TAGS, parser.getLine());

    if (entry.type != XmlEntry::START_TAG && 
	entry.type != XmlEntry::EMPTY_TAG)
    {

      // l10n

      // throw XmlValidationError(parser.getLine(), 
      //   "Expected one of the following start tags: "
      //    "CLASSPATH, LOCALCLASSPATH, CLASSNAME, INSTANCEPATH, "
      //    "LOCALINSTANCEPATH, INSTANCENAME");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_START_TAGS",
				 "Expected one of the following start tags: CLASSPATH, LOCALCLASSPATH, CLASSNAME, INSTANCEPATH, LOCALINSTANCEPATH, INSTANCENAME");
      
      throw XmlValidationError(parser.getLine(), mlParms);

    }

    if (strcmp(entry.text, "CLASSPATH") == 0)
    {
	parser.putBack(entry);
	getClassPathElement(parser, reference);
    }
    else if (strcmp(entry.text, "LOCALCLASSPATH") == 0)
    {
	parser.putBack(entry);
	getLocalClassPathElement(parser, reference);
    }
    else if (strcmp(entry.text, "CLASSNAME") == 0)
    {
	parser.putBack(entry);
	CIMName className;
	getClassNameElement(parser, className);
	reference.set(String(), CIMNamespaceName(), className);
    }
    else if (strcmp(entry.text, "INSTANCEPATH") == 0)
    {
	parser.putBack(entry);
	getInstancePathElement(parser, reference);
    }
    else if (strcmp(entry.text, "LOCALINSTANCEPATH") == 0)
    {
	parser.putBack(entry);
	getLocalInstancePathElement(parser, reference);
    }
    else if (strcmp(entry.text, "INSTANCENAME") == 0)
    {
	parser.putBack(entry);
	String className;
	Array<CIMKeyBinding> keyBindings;
	getInstanceNameElement(parser, className, keyBindings);
	reference.set(String(), CIMNamespaceName(), className, keyBindings);
    }

    expectEndTag(parser, "VALUE.REFERENCE");
    return true;
}

//------------------------------------------------------------------------------
//
// getValueReferenceArrayElement()
//
//     <!ELEMENT VALUE.REFARRAY (VALUE.REFERENCE*)>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getValueReferenceArrayElement(
    XmlParser& parser, 
    CIMValue& value)
{
    XmlEntry entry;
    Array<CIMObjectPath> referenceArray;
    CIMObjectPath reference;

    value.clear();

    // Get VALUE.REFARRAY open tag:

    if (!testStartTagOrEmptyTag(parser, entry, "VALUE.REFARRAY"))
	return false;

    if (entry.type != XmlEntry::EMPTY_TAG)
    {
        // For each VALUE.REFERENCE element:

        while (getValueReferenceElement(parser, reference))
        {
	    referenceArray.append(reference);
        }

        expectEndTag(parser, "VALUE.REFARRAY");
    }

    value.set(referenceArray);
    return true;
}

//------------------------------------------------------------------------------
//
// getPropertyReferenceElement()
//
//     <!ELEMENT PROPERTY.REFERENCE (QUALIFIER*,(VALUE.REFERENCE)?)>
//     <!ATTLIST PROPERTY.REFERENCE
//         %CIMName;
//         %ReferenceClass;
//         %ClassOrigin;
//         %Propagated;>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getPropertyReferenceElement(
    XmlParser& parser, 
    CIMProperty& property)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "PROPERTY.REFERENCE"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    // Get PROPERTY.NAME attribute:

    CIMName name = getCimNameAttribute(
	parser.getLine(), entry, "PROPERTY.REFERENCE");

    // Get PROPERTY.REFERENCECLASS attribute:

    CIMName referenceClass = getReferenceClassAttribute(
	parser.getLine(), entry, "PROPERTY.REFERENCE");

    // Get PROPERTY.CLASSORIGIN attribute:

    CIMName classOrigin = 
	getClassOriginAttribute(parser.getLine(), entry, "PROPERTY.REFERENCE");

    // Get PROPERTY.PROPAGATED

    Boolean propagated = getCimBooleanAttribute(parser.getLine(), entry, 
	"PROPERTY.REFERENCE", "PROPAGATED", false, false);

    // Create property:

    CIMValue value = CIMValue(CIMTYPE_REFERENCE, false, 0);
//    value.set(CIMObjectPath());
    property = CIMProperty(
	name, value, 0, referenceClass, classOrigin, propagated);

    if (!empty)
    {
	getQualifierElements(parser, property);

	CIMObjectPath reference;

	if (getValueReferenceElement(parser, reference))
	    property.setValue(reference);

	expectEndTag(parser, "PROPERTY.REFERENCE");
    }

    return true;
}

//------------------------------------------------------------------------------
//
// GetPropertyElements()
//
//------------------------------------------------------------------------------

template<class CONTAINER>
void GetPropertyElements(XmlParser& parser, CONTAINER& container)
{
    CIMProperty property;

    while (XmlReader::getPropertyElement(parser, property) ||
	XmlReader::getPropertyArrayElement(parser, property) ||
	XmlReader::getPropertyReferenceElement(parser, property))
    {
	try
	{
	    container.addProperty(property);
	}
	catch (AlreadyExistsException&)
	{

	  // l10n

	  // throw XmlSemanticError(parser.getLine(), "duplicate property");

	  MessageLoaderParms mlParms("Common.XmlReader.DUPLICATE_PROPERTY",
				     "duplicate property");
	  
	  throw XmlSemanticError(parser.getLine(), mlParms);
	}
    }
}

//------------------------------------------------------------------------------
//
// getParameterElement()
//
//     <!ELEMENT PARAMETER (QUALIFIER*)>
//     <!ATTLIST PARAMETER
//         %CIMName;
//         %CIMType; #REQUIRED>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getParameterElement(
    XmlParser& parser, 
    CIMParameter& parameter)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "PARAMETER"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    // Get PARAMETER.NAME attribute:

    CIMName name = getCimNameAttribute(parser.getLine(), entry, "PARAMETER");

    // Get PARAMETER.TYPE attribute:

    CIMType type;
    getCimTypeAttribute(parser.getLine(), entry, type, "PARAMETER");

    // Create parameter:

    parameter = CIMParameter(name, type);

    if (!empty)
    {
	getQualifierElements(parser, parameter);

	expectEndTag(parser, "PARAMETER");
    }

    return true;
}

//------------------------------------------------------------------------------
//
// getParameterArrayElement()
//
//     <!ELEMENT PARAMETER.ARRAY (QUALIFIER*)>
//     <!ATTLIST PARAMETER.ARRAY
//         %CIMName;
//         %CIMType; #REQUIRED
//         %ArraySize;>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getParameterArrayElement(
    XmlParser& parser, 
    CIMParameter& parameter)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "PARAMETER.ARRAY"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    // Get PARAMETER.ARRAY.NAME attribute:

    CIMName name = getCimNameAttribute(
	parser.getLine(), entry, "PARAMETER.ARRAY");

    // Get PARAMETER.ARRAY.TYPE attribute:

    CIMType type;
    getCimTypeAttribute(parser.getLine(), entry, type, "PARAMETER.ARRAY");

    // Get PARAMETER.ARRAYSIZE attribute:

    Uint32 arraySize = 0;
    getArraySizeAttribute(parser.getLine(), entry, "PARAMETER.ARRAY",arraySize);

    // Create parameter:

    parameter = CIMParameter(name, type, true, arraySize);

    if (!empty)
    {
	getQualifierElements(parser, parameter);

	expectEndTag(parser, "PARAMETER.ARRAY");
    }

    return true;
}

//------------------------------------------------------------------------------
//
// getParameterReferenceElement()
//
//     <!ELEMENT PARAMETER.REFERENCE (QUALIFIER*)>
//     <!ATTLIST PARAMETER.REFERENCE
//         %CIMName;
//         %ReferenceClass;>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getParameterReferenceElement(
    XmlParser& parser, 
    CIMParameter& parameter)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "PARAMETER.REFERENCE"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    // Get PARAMETER.NAME attribute:

    CIMName name = getCimNameAttribute(
	parser.getLine(), entry, "PARAMETER.REFERENCE");

    // Get PARAMETER.REFERENCECLASS attribute:

    CIMName referenceClass = getReferenceClassAttribute(
	parser.getLine(), entry, "PARAMETER.REFERENCE");

    // Create parameter:

    parameter = CIMParameter(name, CIMTYPE_REFERENCE, false, 0, referenceClass);

    if (!empty)
    {
	getQualifierElements(parser, parameter);
	expectEndTag(parser, "PARAMETER.REFERENCE");
    }

    return true;
}

//------------------------------------------------------------------------------
//
// getParameterReferenceArrayElement()
//
//     <!ELEMENT PARAMETER.REFARRAY (QUALIFIER*)>
//     <!ATTLIST PARAMETER.REFARRAY
//         %CIMName;
//         %ReferenceClass;
//         %ArraySize;>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getParameterReferenceArrayElement(
    XmlParser& parser, 
    CIMParameter& parameter)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "PARAMETER.REFARRAY"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    // Get PARAMETER.NAME attribute:

    CIMName name = getCimNameAttribute(
	parser.getLine(), entry, "PARAMETER.REFARRAY");

    // Get PARAMETER.REFERENCECLASS attribute:

    CIMName referenceClass = getReferenceClassAttribute(
	parser.getLine(), entry, "PARAMETER.REFARRAY");

    // Get PARAMETER.ARRAYSIZE attribute:

    Uint32 arraySize = 0;
    getArraySizeAttribute(parser.getLine(), entry, "PARAMETER.REFARRAY",
			  arraySize);

    // Create parameter:

    parameter = CIMParameter(name, CIMTYPE_REFERENCE, true, arraySize,
			     referenceClass);

    if (!empty)
    {
	getQualifierElements(parser, parameter);
	expectEndTag(parser, "PARAMETER.REFARRAY");
    }

    return true;
}

//------------------------------------------------------------------------------
//
// GetParameterElements()
//
//------------------------------------------------------------------------------

template<class CONTAINER>
void GetParameterElements(XmlParser& parser, CONTAINER& container)
{
    CIMParameter parameter;

    while (XmlReader::getParameterElement(parser, parameter) ||
	XmlReader::getParameterArrayElement(parser, parameter) ||
	XmlReader::getParameterReferenceElement(parser, parameter) ||
	XmlReader::getParameterReferenceArrayElement(parser, parameter))
    {
	try
	{
	    container.addParameter(parameter);
	}
	catch (AlreadyExistsException&)
	{

	  // l10n

	  // throw XmlSemanticError(parser.getLine(), "duplicate parameter");

	  MessageLoaderParms mlParms("Common.XmlReader.DUPLICATE_PARAMETER",
				     "duplicate parameter");
	  
	  throw XmlSemanticError(parser.getLine(), mlParms);
	}
    }
}

//------------------------------------------------------------------------------
//
// getQualifierDeclElement()
//
//     <!ELEMENT QUALIFIER.DECLARATION (SCOPE?,(VALUE|VALUE.ARRAY)?)>
//     <!ATTLIST QUALIFIER.DECLARATION 
//         %CIMName;               
//         %CIMType; #REQUIRED
//         ISARRAY (true|false) #IMPLIED
//         %ArraySize;
//         %QualifierFlavor;>
//         
//------------------------------------------------------------------------------

Boolean XmlReader::getQualifierDeclElement(
    XmlParser& parser, 
    CIMQualifierDecl& qualifierDecl)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "QUALIFIER.DECLARATION"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    // Get NAME attribute:

    CIMName name = getCimNameAttribute(
	parser.getLine(), entry, "QUALIFIER.DECLARATION");

    // Get TYPE attribute:

    CIMType type;
    getCimTypeAttribute(parser.getLine(), entry, type, "QUALIFIER.DECLARATION");

    // Get ISARRAY attribute:

    Boolean isArray = getCimBooleanAttribute(
        parser.getLine(), entry, "QUALIFIER.DECLARATION", "ISARRAY",
        false, false); 

    // Get ARRAYSIZE attribute:

    Uint32 arraySize = 0;
    Boolean gotArraySize = getArraySizeAttribute(parser.getLine(),
	entry, "QUALIFIER.DECLARATION", arraySize);

    // Get flavor oriented attributes:

    CIMFlavor flavor = getFlavor (entry, parser.getLine (), 
        "QUALIFIER.DECLARATION");

    // No need to look for interior elements if empty tag:

    CIMScope scope = CIMScope ();
    CIMValue value;
    Boolean gotValue = false;

    if (!empty)
    {
	// Get the option SCOPE element:

	scope = getOptionalScope(parser);

	// Get VALUE or VALUE.ARRAY element:

	if (getValueArrayElement(parser, type, value))
	{
	    if (!isArray)
	    {

	      // l10n

	      // throw XmlSemanticError(parser.getLine(),
	      //    "VALUE.ARRAY element encountered without "
	      //    "ISARRAY attribute");

	      MessageLoaderParms mlParms("Common.XmlReader.ARRAY_WITHOUT_ISARRAY",
					 "VALUE.ARRAY element encountered without ISARRAY attribute");
	      
	      throw XmlSemanticError(parser.getLine(), mlParms);
	    }

	    if (arraySize && arraySize != value.getArraySize())
	    {

	      // l10n

	      // throw XmlSemanticError(parser.getLine(),
	      //   "VALUE.ARRAY size is not the same as "
	      //    "ARRAYSIZE attribute");

	      MessageLoaderParms mlParms("Common.XmlReader.ARRAY_SIZE_NOT_SAME",
					 "VALUE.ARRAY size is not the same as ARRAYSIZE attribute");
	      
	      throw XmlSemanticError(parser.getLine(), mlParms);
	    }

            gotValue = true;
	}
	else if (getValueElement(parser, type, value))
	{
	    if (isArray)
	    {

	      // l10n

	      // throw XmlSemanticError(parser.getLine(),
	      //    "ISARRAY attribute used but VALUE element encountered");

	      MessageLoaderParms mlParms("Common.XmlReader.ARRAY_ATTRIBUTE_DIFFERENT",
					 "ISARRAY attribute used but VALUE element encountered");
	      
	      throw XmlSemanticError(parser.getLine(), mlParms);
	    }

            gotValue = true;
	}

	// Now get the closing tag:

	expectEndTag(parser, "QUALIFIER.DECLARATION");
    }

    if (!gotValue)
    {
	if (isArray)
	    value.setNullValue(type, true, arraySize);
	else
	    value.setNullValue(type, false);
    }

    CIMQualifierDecl tmp(name, value, scope, flavor, arraySize);
    qualifierDecl = CIMQualifierDecl(name, value, scope, flavor, arraySize);
    return true;
}

//------------------------------------------------------------------------------
// getMethodElement()
//
//     <!ELEMENT METHOD (QUALIFIER*,(PARAMETER|PARAMETER.REFERENCE|
//         PARAMETER.ARRAY|PARAMETER.REFARRAY)*)>
//     <!ATTLIST METHOD
//         %CIMName;
//         %CIMType; #IMPLIED
//         %ClassOrigin;
//         %Propagated;>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getMethodElement(XmlParser& parser, CIMMethod& method)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "METHOD"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    CIMName name = getCimNameAttribute(parser.getLine(), entry, "PROPERTY");

    CIMType type;
    getCimTypeAttribute(parser.getLine(), entry, type, "PROPERTY");

    CIMName classOrigin = 
	getClassOriginAttribute(parser.getLine(), entry, "PROPERTY");

    Boolean propagated = getCimBooleanAttribute(
	parser.getLine(), entry, "PROPERTY", "PROPAGATED", false, false);

    method = CIMMethod(name, type, classOrigin, propagated);

    if (!empty)
    {
        // ATTN-RK-P2-20020219: Decoding algorithm must not depend on the
        // ordering of qualifiers and parameters.
	getQualifierElements(parser, method);

	GetParameterElements(parser, method);

	expectEndTag(parser, "METHOD");
    }

    return true;
}

//------------------------------------------------------------------------------
// getClassElement()
//
//     <!ELEMENT CLASS (QUALIFIER*,
//         (PROPERTY|PROPERTY.ARRAY|PROPERTY.REFERENCE)*,METHOD*)>
//     <!ATTLIST CLASS %CIMName; %SuperClass;>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getClassElement(XmlParser& parser, CIMClass& cimClass)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "CLASS"))
	return false;

    CIMName name = getCimNameAttribute(parser.getLine(), entry, "CLASS");

    CIMName superClass = getSuperClassAttribute(parser.getLine(), entry,"CLASS");

    cimClass = CIMClass(name, superClass);

	if(entry.type != XmlEntry::EMPTY_TAG) 
	{

    // Get QUALIFIER elements:

    getQualifierElements(parser, cimClass);

    // Get PROPERTY elements:

    GetPropertyElements(parser, cimClass);

    // Get METHOD elements:

    CIMMethod method;

    while (getMethodElement(parser, method))
	cimClass.addMethod(method);	

    // Get CLASS end tag:
	
	expectEndTag(parser, "CLASS");
	}

    return true;
}

//------------------------------------------------------------------------------
// getInstanceElement()
//
//     <!ELEMENT INSTANCE (QUALIFIER*,
//         (PROPERTY|PROPERTY.ARRAY|PROPERTY.REFERENCE)*) >
//     <!ATTLIST INSTANCE
//         %ClassName;>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getInstanceElement(
    XmlParser& parser, 
    CIMInstance& cimInstance)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "INSTANCE"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    String className = getClassNameAttribute(
	parser.getLine(), entry, "INSTANCE");

    cimInstance = CIMInstance(className);

    if (!empty)
    {
        // Get QUALIFIER elements:
        getQualifierElements(parser, cimInstance);

        // Get PROPERTY elements:
        GetPropertyElements(parser, cimInstance);

        // Get INSTANCE end tag:
        expectEndTag(parser, "INSTANCE");
    }

    return true;
}

//------------------------------------------------------------------------------
// getNamedInstanceElement()
//
//     <!ELEMENT VALUE.NAMEDINSTANCE (INSTANCENAME,INSTANCE)>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getNamedInstanceElement(
    XmlParser& parser, 
    CIMInstance& namedInstance)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "VALUE.NAMEDINSTANCE"))
	return false;

    CIMObjectPath instanceName;

    // Get INSTANCENAME elements:

    if (!getInstanceNameElement(parser, instanceName))
    {

      // l10n

      // throw XmlValidationError(parser.getLine(), 
      //    "expected INSTANCENAME element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_INSTANCENAME_ELEMENT",
				 "expected INSTANCENAME element");
      
      throw XmlValidationError(parser.getLine(), mlParms);
    }

    // Get INSTANCE elements:

    if (!getInstanceElement(parser, namedInstance))
    {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "expected INSTANCE element");


      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_INSTANCE_ELEMENT",
				 "expected INSTANCE element");
      
      throw XmlValidationError(parser.getLine(), mlParms);
    }

    // Get VALUE.NAMEDINSTANCE end tag:

    expectEndTag(parser, "VALUE.NAMEDINSTANCE");

    namedInstance.setPath (instanceName);

    return true;
}

//------------------------------------------------------------------------------
//
// getObject()
//
//------------------------------------------------------------------------------

void XmlReader::getObject(XmlParser& parser, CIMClass& x)
{
    if (!getClassElement(parser, x))
    {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "expected CLASS element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_CLASS_ELEMENT",
				 "expected CLASS element");
      
      throw XmlValidationError(parser.getLine(), mlParms);
    }
}

//------------------------------------------------------------------------------
//
// getObject()
//
//------------------------------------------------------------------------------

void XmlReader::getObject(XmlParser& parser, CIMInstance& x)
{
    if (!getInstanceElement(parser, x))
    {

      // l10n
      
      // throw XmlValidationError(parser.getLine(),
      //   "expected INSTANCE element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_INSTANCE_ELEMENT",
				 "expected INSTANCE element");
      
      throw XmlValidationError(parser.getLine(), mlParms);
    }
}

//------------------------------------------------------------------------------
//
// getObject()
//
//------------------------------------------------------------------------------

void XmlReader::getObject(XmlParser& parser, CIMQualifierDecl& x)
{
    if (!getQualifierDeclElement(parser, x))
    {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "expected QUALIFIER.DECLARATION element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_QUALIFIER_DECLARATION_ELEMENT",
				 "expected QUALIFIER.DECLARATION element");
      
      throw XmlValidationError(parser.getLine(), mlParms);
    }
}

//------------------------------------------------------------------------------
//
// getMessageStartTag()
//
//------------------------------------------------------------------------------

Boolean XmlReader::getMessageStartTag(
    XmlParser& parser, 
    String& id,
    String& protocolVersion)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "MESSAGE"))
	return false;

    // Get MESSAGE.ID:

    if (!entry.getAttributeValue("ID", id)) {

      // l10n

      // throw XmlValidationError(parser.getLine(), 
      //   "Invalid or missing MESSAGE.ID attribute");

      MessageLoaderParms mlParms("Common.XmlReader.INVALID_MISSING_MESSAGE_ID_ATTRIBUTE",
				 "Invalid or missing MESSAGE.ID attribute");
      
      throw XmlValidationError(parser.getLine(), mlParms);
    }      


    // Get MESSAGE.PROTOCOLVERSION:

    if (!entry.getAttributeValue("PROTOCOLVERSION", protocolVersion)) {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "Invalid or missing MESSAGE.PROTOCOLVERSION attribute");

      MessageLoaderParms mlParms("Common.XmlReader.INVALID_MISSING_PROTOCOLVERSION_ATTRIBUTE",
				 "Invalid or missing MESSAGE.PROTOCOLVERSION attribute");
      
      throw XmlValidationError(parser.getLine(), mlParms);
    }
    
    return true;
}

//------------------------------------------------------------------------------
//
// getIMethodCallStartTag()
//
//------------------------------------------------------------------------------

Boolean XmlReader::getIMethodCallStartTag(
    XmlParser& parser, 
    const char*& name)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "IMETHODCALL"))
	return false;

    // Get IMETHODCALL.NAME attribute:


    if (!entry.getAttributeValue("NAME", name)) {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "Missing IMETHODCALL.NAME attribute");

      MessageLoaderParms mlParms("Common.XmlReader.MISSING_IMETHODCALL_ATTRIBUTE",
				 "Missing IMETHODCALL.NAME attribute");

      throw XmlValidationError(parser.getLine(), mlParms);
    }


    return true;
}

//------------------------------------------------------------------------------
//
// getIMethodResponseStartTag()
//
//------------------------------------------------------------------------------

Boolean XmlReader::getIMethodResponseStartTag(
    XmlParser& parser, 
    const char*& name)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "IMETHODRESPONSE"))
	return false;

    // Get IMETHODRESPONSE.NAME attribute:

    if (!entry.getAttributeValue("NAME", name)) {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "Missing IMETHODRESPONSE.NAME attribute");

      MessageLoaderParms mlParms("Common.XmlReader.MISSING_IMETHODRESPONSE_ATTRIBUTE",
				 "Missing IMETHODRESPONSE.NAME attribute");

      throw XmlValidationError(parser.getLine(), mlParms);
    }


    return true;
}

//------------------------------------------------------------------------------
//
// getIParamValueTag()
//
//------------------------------------------------------------------------------

Boolean XmlReader::getIParamValueTag(
    XmlParser& parser, 
    const char*& name)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "IPARAMVALUE"))
	return false;

    // Get IPARAMVALUE.NAME attribute:

    if (!entry.getAttributeValue("NAME", name)) {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "Missing IPARAMVALUE.NAME attribute");

      MessageLoaderParms mlParms("Common.XmlReader.MISSING_IPARAMVALUE_ATTRIBUTE",
				 "Missing IPARAMVALUE.NAME attribute");

      throw XmlValidationError(parser.getLine(), mlParms);
    }

    return true;
}

//------------------------------------------------------------------------------
//
// getBooleanValueElement()
//
//     Get an elements like: "<VALUE>FALSE</VALUE>"
//
//------------------------------------------------------------------------------

Boolean XmlReader::getBooleanValueElement(
    XmlParser& parser, 
    Boolean& result,
    Boolean required)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "VALUE"))
    {
	if (required)
	{

	  // l10n

	  // throw XmlValidationError(parser.getLine(),
	  // "Expected VALUE element");

	  MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_VALUE_ELEMENT",
				     "Expected VALUE element");
	  
	  throw XmlValidationError(parser.getLine(), mlParms);
	}
	return false;
    }

    expectContentOrCData(parser, entry);

    if (System::strcasecmp(entry.text, "TRUE") == 0)
	result = true;
    else if (System::strcasecmp(entry.text, "FALSE") == 0)
	result = false;
    else {

      // l10n

      // throw XmlSemanticError(parser.getLine(), 
      //   "Invalid value for VALUE element: must be \"TRUE\" or \"FALSE\"");

      MessageLoaderParms mlParms("Common.XmlReader.INVALID_VALUE_FOR_VALUE_ELEMENT",
				 "Invalid value for VALUE element: must be \"TRUE\" or \"FALSE\"");
      
      throw XmlSemanticError(parser.getLine(), mlParms);
    }

    expectEndTag(parser, "VALUE");

    return true;
}

//------------------------------------------------------------------------------
//     Pending DMTF CR
//
//     <!ELEMENT ERROR (INSTANCE*)> 
//     <!ATTLIST ERROR 
//         CODE CDATA #REQUIRED
//         DESCRIPTION CDATA #IMPLIED>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getErrorElement(
    XmlParser& parser, 
    CIMException& cimException,
    Boolean required)
{
    XmlEntry entry;

    if (!testStartTagOrEmptyTag(parser, entry, "ERROR"))
    {
      if (required) {

	// l10n

	// throw XmlValidationError(parser.getLine(),"Expected ERROR element");
	
	MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_ERROR_ELEMENT",
				   "Expected ERROR element");
	
	throw XmlValidationError(parser.getLine(), mlParms);
	
      }
      return false;
    }

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    // Get ERROR.CODE

    Uint32 tmpCode;

    if (!entry.getAttributeValue("CODE", tmpCode)) {


      // l10n

      // throw XmlValidationError(
      //       parser.getLine(), "missing ERROR.CODE attribute");

      MessageLoaderParms mlParms("Common.XmlReader.MISSING_ERROR_CODE_ATTRIBUTE",
				 "missing ERROR.CODE attribute");
      
      throw XmlValidationError(parser.getLine(), mlParms);

    }

    // Get ERROR.DESCRIPTION:

    String tmpDescription;

    entry.getAttributeValue("DESCRIPTION", tmpDescription);

    if (!empty)
    {
	while (testStartTagOrEmptyTag(parser, entry))
	{
	    skipElement(parser, entry);
	}

	expectEndTag(parser, "ERROR");
    }

    cimException = PEGASUS_CIM_EXCEPTION(CIMStatusCode(tmpCode), tmpDescription);
    return true;
}


//------------------------------------------------------------------------------
// getValueObjectElement()
//
// <!ELEMENT VALUE.OBJECT (CLASS|INSTANCE)>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getValueObjectElement(
    XmlParser& parser, 
    CIMObject& object)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "VALUE.OBJECT"))
	return false;

    CIMInstance cimInstance;
    CIMClass cimClass;

    if (XmlReader::getInstanceElement(parser, cimInstance))
    {
	object = CIMObject(cimInstance);
    }
    else if (!XmlReader::getClassElement(parser, cimClass))
    {
	object = CIMObject(cimClass);
    }
    else
    {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "Expected INSTANCE or CLASS element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_INSTANCE_OR_CLASS_ELEMENT",
				 "Expected INSTANCE or CLASS element");
      
      throw XmlValidationError(parser.getLine(), mlParms);

    }

    expectEndTag(parser, "VALUE.OBJECT");

    return true;
}

//------------------------------------------------------------------------------
// getValueObjectWithPathElement()
//
// <!ELEMENT VALUE.OBJECTWITHPATH ((CLASSPATH,CLASS)|(INSTANCEPATH,INSTANCE))>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getValueObjectWithPathElement(
    XmlParser& parser, 
    CIMObject& objectWithPath)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "VALUE.OBJECTWITHPATH"))
	return false;

    CIMObjectPath reference;
    Boolean isInstance = false;

    if (XmlReader::getInstancePathElement(parser, reference))
	isInstance = true;
    else if (!XmlReader::getClassPathElement(parser, reference))
    {

      // l10n 485
      
      // throw XmlValidationError(parser.getLine(),
      //    "Expected INSTANCEPATH or CLASSPATH element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_INSTANCEPATH_OR_CLASSPATH_ELEMENT",
				 "Expected INSTANCEPATH or CLASSPATH element");
      
      throw XmlValidationError(parser.getLine(), mlParms);
    }

    if (isInstance)
    {
	CIMInstance cimInstance;

	if (!XmlReader::getInstanceElement(parser, cimInstance))
	{

	  // l10n

	  // throw XmlValidationError(parser.getLine(),
	  //		   "Expected INSTANCE element");

	  MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_INSTANCE_ELEMENT",
				     "Expected INSTANCE element");
	  
	  throw XmlValidationError(parser.getLine(), mlParms);
	}
	objectWithPath = CIMObject (cimInstance);
        objectWithPath.setPath (reference);
    }
    else
    {
	CIMClass cimClass;

	if (!XmlReader::getClassElement(parser, cimClass))
	{

	  // l10n

	  // throw XmlValidationError(parser.getLine(),
	  // "Expected CLASS element");

	  MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_CLASS_ELEMENT",
				     "Expected CLASS element");
	  
	  throw XmlValidationError(parser.getLine(), mlParms);
	}
	objectWithPath = CIMObject (cimClass);
        objectWithPath.setPath (reference);
    }

    expectEndTag(parser, "VALUE.OBJECTWITHPATH");

    return true;
}

//------------------------------------------------------------------------------
// getValueObjectWithLocalPathElement()
//
// <!ELEMENT VALUE.OBJECTWITHLOCALPATH
//     ((LOCALCLASSPATH,CLASS)|(LOCALINSTANCEPATH,INSTANCE))>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getValueObjectWithLocalPathElement(
    XmlParser& parser, 
    CIMObject& objectWithPath)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "VALUE.OBJECTWITHLOCALPATH"))
	return false;

    CIMObjectPath reference;
    Boolean isInstance = false;

    if (XmlReader::getLocalInstancePathElement(parser, reference))
	isInstance = true;
    else if (!XmlReader::getLocalClassPathElement(parser, reference))
    {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "Expected LOCALINSTANCEPATH or LOCALCLASSPATH element");

      //l10n updated
      MessageLoaderParms mlParms("Common.XmlConstants.MISSING_ELEMENT_LOCALPATH",
      														MISSING_ELEMENT_LOCALPATH);
      
      throw XmlValidationError(parser.getLine(), mlParms);

    }

    if (isInstance)
    {
	CIMInstance cimInstance;

	if (!XmlReader::getInstanceElement(parser, cimInstance))
	{

	  // l10n

	  // throw XmlValidationError(parser.getLine(),
	  //		   "Expected INSTANCE element");

	  MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_INSTANCE_ELEMENT",
				     "Expected INSTANCE element");
	  
	  throw XmlValidationError(parser.getLine(), mlParms);

	}
	objectWithPath = CIMObject (cimInstance);
	objectWithPath.setPath (reference);
    }
    else
    {
	CIMClass cimClass;

	if (!XmlReader::getClassElement(parser, cimClass))
	{

	  // l10n

	  // throw XmlValidationError(parser.getLine(),
	  // "Expected CLASS element");

	  MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_CLASS_ELEMENT",
				     "Expected CLASS element");
	  
	  throw XmlValidationError(parser.getLine(), mlParms);


	}
	objectWithPath = CIMObject (cimClass);
	objectWithPath.setPath (reference);
    }

    expectEndTag(parser, "VALUE.OBJECTWITHLOCALPATH");

    return true;
}

//------------------------------------------------------------------------------
// getObjectArray()
//
// <object>
//     (VALUE.OBJECT|VALUE.OBJECTWITHLOCALPATH|VALUE.OBJECTWITHPATH)
//
//------------------------------------------------------------------------------

void XmlReader::getObjectArray(
    XmlParser& parser, 
    Array<CIMObject>& objectArray)
{
    CIMObject object;
    CIMObject objectWithPath;

    objectArray.clear();

    if (getValueObjectElement(parser, object))
    {
        objectArray.append(object);
        while (getValueObjectElement(parser, object))
            objectArray.append(object);
    }
    else if (getValueObjectWithPathElement(parser, objectWithPath))
    {
        objectArray.append(objectWithPath);
        while (getValueObjectWithPathElement(parser, objectWithPath))
            objectArray.append(objectWithPath);
    }
    else if (getValueObjectWithLocalPathElement(parser, objectWithPath))
    {
        objectArray.append(objectWithPath);
        while (getValueObjectWithLocalPathElement(parser, objectWithPath))
            objectArray.append(objectWithPath);
    }
}

//------------------------------------------------------------------------------
//
// <objectName>: (CLASSNAME|INSTANCENAME)
//
//------------------------------------------------------------------------------

Boolean XmlReader::getObjectNameElement(
    XmlParser& parser, 
    CIMObjectPath& objectName)
{
    CIMName className;

    if (getClassNameElement(parser, className, false))
    {
	objectName.set(String(), CIMNamespaceName(), className);
	return true;
    }
    else if (getInstanceNameElement(parser, objectName))
	return true;
    else
    {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "expected CLASSNAME or INSTANCENAME element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_CLASSNAME_OR_INSTANCENAME_ELEMENT",
				 "Expected CLASSNAME or INSTANCENAME element");
      
      throw XmlValidationError(parser.getLine(), mlParms);
      
    }

    return false;
}

//------------------------------------------------------------------------------
//
// <!ELEMENT OBJECTPATH (INSTANCEPATH|CLASSPATH)>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getObjectPathElement(
    XmlParser& parser, 
    CIMObjectPath& objectPath)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "OBJECTPATH"))
	return false;

    if (getClassPathElement(parser, objectPath))
    {
	expectEndTag(parser, "OBJECTPATH");
	return true;
    }
    else if (getInstancePathElement(parser, objectPath))
    {
	expectEndTag(parser, "OBJECTPATH");
	return true;
    }
    else
    {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "expected INSTANCEPATH or CLASSPATH element");

      MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_INSTANCEPATH_OR_CLASSPATH_ELEMENT",
				 "expected INSTANCEPATH or CLASSPATH element");
      
      throw XmlValidationError(parser.getLine(), mlParms);
    }

    PEGASUS_UNREACHABLE ( return false; )
}

//------------------------------------------------------------------------------
//
// getEMethodCallStartTag()
//
//------------------------------------------------------------------------------

Boolean XmlReader::getEMethodCallStartTag(
    XmlParser& parser, 
    const char*& name)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "EXPMETHODCALL"))
	return false;

    // Get EXPMETHODCALL.NAME attribute:


      if (!entry.getAttributeValue("NAME", name)) {

	// l10n

	// throw XmlValidationError(parser.getLine(),
	// "Missing EXPMETHODCALL.NAME attribute");

	MessageLoaderParms mlParms("Common.XmlReader.MISSING_EXPMETHODCALL_ATTRIBUTE",
				   "Missing EXPMETHODCALL.NAME attribute");
	
	throw XmlValidationError(parser.getLine(), mlParms);
      }

    return true;
}

//------------------------------------------------------------------------------
//
// getEMethodResponseStartTag()
//
//------------------------------------------------------------------------------

Boolean XmlReader::getEMethodResponseStartTag(
    XmlParser& parser, 
    const char*& name)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "EXPMETHODRESPONSE"))
	return false;

    // Get EXPMETHODRESPONSE.NAME attribute:


      if (!entry.getAttributeValue("NAME", name)) {
	// l10n
	
	// throw XmlValidationError(
	//   parser.getLine(), "Missing EXPMETHODRESPONSE.NAME attribute");
	
	MessageLoaderParms mlParms("Common.XmlReader.MISSING_EXPMETHODRESPONSE_ATTRIBUTE",
				   "Missing EXPMETHODRESPONSE.NAME attribute");
	
	throw XmlValidationError(parser.getLine(), mlParms);
      }

    return true;
}

//------------------------------------------------------------------------------
//
// getEParamValueTag()
//
//------------------------------------------------------------------------------

Boolean XmlReader::getEParamValueTag(
    XmlParser& parser, 
    const char*& name)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "EXPPARAMVALUE"))
	return false;

    // Get EXPPARAMVALUE.NAME attribute:


    if (!entry.getAttributeValue("NAME", name)) {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "Missing EXPPARAMVALUE.NAME attribute");

      MessageLoaderParms mlParms("Common.XmlReader.MISSING_EXPPARAMVALUE_ATTRIBUTE",
				 "Missing EXPPARAMVALUE.NAME attribute");

      throw XmlValidationError(parser.getLine(), mlParms);
    }



    return true;
}

//------------------------------------------------------------------------------
//
// getMethodCallStartTag()
//
//------------------------------------------------------------------------------

Boolean XmlReader::getMethodCallStartTag(
    XmlParser& parser, 
    const char*& name)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "METHODCALL"))
	return false;

    // Get METHODCALL.NAME attribute:


    if (!entry.getAttributeValue("NAME", name)) {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //	       "Missing METHODCALL.NAME attribute");

      MessageLoaderParms mlParms("Common.XmlReader.MISSING_METHODCALL_ATTRIBUTE",
				 "Missing METHODCALL.NAME attribute");

      throw XmlValidationError(parser.getLine(), mlParms);
    }


    return true;
}

//------------------------------------------------------------------------------
//
// getMethodResponseStartTag()
//
//------------------------------------------------------------------------------

Boolean XmlReader::getMethodResponseStartTag(
    XmlParser& parser, 
    const char*& name)
{
    XmlEntry entry;

    if (!testStartTag(parser, entry, "METHODRESPONSE"))
	return false;

    // Get METHODRESPONSE.NAME attribute:


    if (!entry.getAttributeValue("NAME", name)) {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "Missing METHODRESPONSE.NAME attribute");

      MessageLoaderParms mlParms("Common.XmlReader.MISSING_METHODRESPONSE_ATTRIBUTE",
				 "Missing METHODRESPONSE.NAME attribute");

      throw XmlValidationError(parser.getLine(), mlParms);
    }

    return true;
}

//------------------------------------------------------------------------------
//
// getParamValueElement()
//
// <!ELEMENT PARAMVALUE (VALUE|VALUE.REFERENCE|VALUE.ARRAY|VALUE.REFARRAY)?>
// <!ATTLIST PARAMVALUE
//      %CIMName;
//      %ParamType;>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getParamValueElement(
    XmlParser& parser, 
    CIMParamValue& paramValue)
{
    XmlEntry entry;
    const char* name;
    CIMType type;
    CIMValue value;

    if (!testStartTagOrEmptyTag(parser, entry, "PARAMVALUE"))
	return false;

    Boolean empty = entry.type == XmlEntry::EMPTY_TAG;

    // Get PARAMVALUE.NAME attribute:

    if (!entry.getAttributeValue("NAME", name)) {

      // l10n

      // throw XmlValidationError(parser.getLine(),
      //   "Missing PARAMVALUE.NAME attribute");

      MessageLoaderParms mlParms("Common.XmlReader.MISSING_PARAMVALUE_ATTRIBUTE",
				 "Missing PARAMVALUE.NAME attribute");

      throw XmlValidationError(parser.getLine(), mlParms);
    }


    // Get PARAMVALUE.PARAMTYPE attribute:

    Boolean gotType = getCimTypeAttribute(parser.getLine(), entry, type,
                                          "PARAMVALUE", "PARAMTYPE", false);

    if (!empty)
    {
        // Parse VALUE.REFERENCE and VALUE.REFARRAY type
        if ( (type == CIMTYPE_REFERENCE) || !gotType )
        {
	    CIMObjectPath reference;
	    if (XmlReader::getValueReferenceElement(parser, reference))
	    {
	        value.set(reference);
	        type = CIMTYPE_REFERENCE;
                gotType = true;
	    }
            else if (XmlReader::getValueReferenceArrayElement(parser, value))
	    {
	        type = CIMTYPE_REFERENCE;
                gotType = true;
	    }
            // If type==reference but no VALUE.REFERENCE found, use null value
        }

        // Parse non-reference value
        if ( type != CIMTYPE_REFERENCE )
        {
            CIMType effectiveType;
            if (!gotType)
	    {
	        // If we don't know what type the value is, read it as a String
		effectiveType = CIMTYPE_STRING;
	    }
            else
	    {
		effectiveType = type;
	    }

            if ( !XmlReader::getValueArrayElement(parser, effectiveType, value) &&
	         !XmlReader::getValueElement(parser, effectiveType, value) )
	    {
	        value.clear();    // Isn't necessary; should already be cleared
	    }
        }

        expectEndTag(parser, "PARAMVALUE");
    }

    paramValue = CIMParamValue(name, value, gotType);

    return true;
}

//------------------------------------------------------------------------------
//
// getReturnValueElement()
//
// <!ELEMENT RETURNVALUE (VALUE|VALUE.REFERENCE)>
// <!ATTLIST RETURNVALUE
//      %ParamType;>
//
//------------------------------------------------------------------------------

Boolean XmlReader::getReturnValueElement(
    XmlParser& parser, 
    CIMValue& returnValue)
{
    XmlEntry entry;
    CIMType type;
    CIMValue value;

    if (!testStartTag(parser, entry, "RETURNVALUE"))
	return false;

    // Get RETURNVALUE.PARAMTYPE attribute:
    // NOTE: Array type return values are not allowed (2/20/02)

    Boolean gotType = getCimTypeAttribute(parser.getLine(), entry, type,
                                          "RETURNVALUE", "PARAMTYPE", false);

    // Parse VALUE.REFERENCE type
    if ( (type == CIMTYPE_REFERENCE) || !gotType )
    {
        CIMObjectPath reference;
        if (XmlReader::getValueReferenceElement(parser, reference))
        {
            returnValue.set(reference);
            type = CIMTYPE_REFERENCE;
            gotType = true;
        }
        else if (type == CIMTYPE_REFERENCE)
        {

	  // l10n

	  // throw XmlValidationError(parser.getLine(),
	  //   "expected VALUE.REFERENCE element");

	  MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_VALUE_REFERENCE_ELEMENT",
				     "expected VALUE.REFERENCE element");
	  
	  throw XmlValidationError(parser.getLine(), mlParms);
        }
    }

    // Parse non-reference return value
    if ( type != CIMTYPE_REFERENCE )
    {
        if (!gotType)
        {
            // If we don't know what type the value is, read it as a String
            type = CIMTYPE_STRING;
        }

        if ( !XmlReader::getValueElement(parser, type, returnValue) )
        {

	  // l10n

	  // throw XmlValidationError(parser.getLine(),
	  //   "expected VALUE element");

	  MessageLoaderParms mlParms("Common.XmlReader.EXPECTED_VALUE_ELEMENT",
				     "expected VALUE element");
	  
	  throw XmlValidationError(parser.getLine(), mlParms);
        }
    }

    expectEndTag(parser, "RETURNVALUE");

    return true;
}

PEGASUS_NAMESPACE_END

