OW_XMLCIMFactory.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Vintela, Inc. nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
00029 *******************************************************************************/
00030 
00036 #include "OW_config.h"
00037 #include "OW_XMLCIMFactory.hpp"
00038 #include "OW_String.hpp"
00039 #include "OW_CIMObjectPath.hpp"
00040 #include "OW_XMLClass.hpp"
00041 #include "OW_Format.hpp"
00042 #include "OW_CIMClass.hpp"
00043 #include "OW_CIMInstance.hpp"
00044 #include "OW_CIMValue.hpp"
00045 #include "OW_Assertion.hpp"
00046 #include "OW_CIMQualifier.hpp"
00047 #include "OW_CIMQualifierType.hpp"
00048 #include "OW_CIMProperty.hpp"
00049 #include "OW_CIMMethod.hpp"
00050 #include "OW_CIMDateTime.hpp"
00051 #include "OW_CIMFlavor.hpp"
00052 #include "OW_CIMParameter.hpp"
00053 #include "OW_CIMValueCast.hpp"
00054 #include "OW_TempFileStream.hpp"
00055 #include "OW_CIMXMLParser.hpp"
00056 #include "OW_Bool.hpp"
00057 #include "OW_XMLParseException.hpp"
00058 #include <algorithm> // for find_if
00059 
00060 namespace OW_NAMESPACE
00061 {
00062 
00063 namespace XMLCIMFactory
00064 {
00065 
00066 static void
00067 getLocalNameSpacePathAndSet(CIMObjectPath& cop, CIMXMLParser& parser)
00068 {
00069    // <!ELEMENT LOCALNAMESPACEPATH (NAMESPACE+)>
00070    if (!parser.tokenIsId(CIMXMLParser::E_LOCALNAMESPACEPATH))
00071    {
00072       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, "Expected <LOCALNAMESPACEPATH>");
00073    }
00074    parser.mustGetChildId(CIMXMLParser::E_NAMESPACE);
00075    // <!ELEMENT NAMESPACE EMPTY>
00076    // <!ATTLIST NAMESPACE %CIMName;>
00077    String ns;
00078    while (parser.tokenIsId(CIMXMLParser::E_NAMESPACE))   
00079    {
00080       String nscomp = parser.mustGetAttribute(CIMXMLParser::A_NAME);
00081       if (!nscomp.empty())
00082       {
00083          if (!ns.empty() )
00084          {
00085             ns += "/";
00086          }
00087          ns += nscomp;
00088       }
00089       parser.mustGetNextTag();
00090       parser.mustGetEndTag(); // pass </NAMESPACE>
00091    }
00092    if (ns.empty())
00093    {
00094       ns = "root";
00095    }
00096    cop.setNameSpace(ns);
00097    parser.mustGetEndTag(); // pass </LOCALNAMESPACEPATH>
00098 }
00100 static void
00101 getNameSpacePathAndSet(CIMObjectPath& cop, CIMXMLParser& parser)
00102 {
00103    // <!ELEMENT NAMESPACEPATH (HOST,LOCALNAMESPACEPATH)>
00104    // <!ELEMENT HOST (#PCDATA)>
00105    parser.mustGetChildId(CIMXMLParser::E_HOST);
00106    parser.mustGetNext();
00107    if (!parser.isData())
00108    {
00109       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, "invalid <HOST> in <NAMESPACEPATH>");
00110    }
00111    cop.setHost(parser.getData());
00112    parser.mustGetNextTag();
00113    parser.mustGetEndTag(); // pass </HOST>
00114    getLocalNameSpacePathAndSet(cop, parser);
00115    parser.mustGetEndTag(); // pass </NAMESPACEPATH>
00116 }
00117 static void getKeyValue(CIMXMLParser& parser, CIMValue& value)
00118 {
00119    String valuetype = parser.mustGetAttribute(CIMXMLParser::A_VALUETYPE);
00120    parser.mustGetNext();
00121    if (!parser.isData())
00122    {
00123       value = CIMValue("");
00124    }
00125    else
00126    {
00127       value = CIMValue(parser.getData());
00128       parser.mustGetNextTag();
00129    }
00130    parser.mustGetEndTag();
00131    // cast the value to the correct type, if not a string
00132    if (valuetype == "boolean")
00133    {
00134       value = CIMValueCast::castValueToDataType(value,CIMDataType::BOOLEAN);
00135    }
00136    else if (valuetype == "numeric")
00137    {
00138       try
00139       {
00140          value = CIMValueCast::castValueToDataType(value,CIMDataType::SINT64);
00141       }
00142       catch (const CIMException& e)
00143       {
00144          value = CIMValueCast::castValueToDataType(value,CIMDataType::REAL64);
00145       }
00146    }
00147 }
00149 static void getInstanceName(CIMXMLParser& parser, CIMObjectPath& cimPath)
00150 {
00151    // <!ELEMENT INSTANCENAME (KEYBINDING*|KEYVALUE?|VALUE.REFERENCE?)>
00152    // <!ATTLIST INSTANCENAME %ClassName;>
00153    CIMPropertyArray propertyArray;
00154    CIMProperty cp(CIMNULL);
00155    OW_ASSERT(parser.tokenIsId(CIMXMLParser::E_INSTANCENAME));
00156    String thisClassName = parser.getAttribute(CIMXMLParser::A_CLASSNAME);
00157    cimPath.setClassName(thisClassName);
00158    //parser.getChild();
00159    parser.getNextTag();
00160    if (parser.tokenIsId(CIMXMLParser::E_KEYBINDING))
00161    {
00162       do
00163       {
00164          // <!ELEMENT KEYBINDING (KEYVALUE|VALUE.REFERENCE)>
00165          // <!ATTLIST KEYBINDING %CIMName;>
00166          //
00167          // <!ELEMENT KEYVALUE (#PCDATA)>
00168          // <!ATTLIST KEYVALUE
00169          //          VALUETYPE    (string|boolean|numeric)  'string'>
00170          CIMValue value(CIMNULL);
00171          String name;
00172          CIMXMLParser keyval;
00173          name = parser.mustGetAttribute(CIMXMLParser::A_NAME);
00174          parser.mustGetChild();
00175          switch (parser.getToken())
00176          {
00177             case CIMXMLParser::E_KEYVALUE:
00178                getKeyValue(parser,value);
00179                break;
00180             case CIMXMLParser::E_VALUE_REFERENCE:
00181                value = XMLCIMFactory::createValue(parser, "REF", E_VALUE_NOT_EMBEDDED_OBJECT);
00182                break;
00183             default:
00184                OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00185                   "Not a valid instance declaration");
00186          }
00187          cp = CIMProperty(name, value);
00188          propertyArray.push_back(cp);
00189          parser.mustGetEndTag(); // pass </KEYBINDING>
00190       } while (parser.tokenIsId(CIMXMLParser::E_KEYBINDING));
00191    }
00192    else if (parser.tokenIsId(CIMXMLParser::E_KEYVALUE))
00193    {
00194       CIMValue value(CIMNULL);
00195       cp = CIMProperty();
00196       getKeyValue(parser,value);
00197       cp.setDataType(value.getCIMDataType());
00198       cp.setValue(value);
00199       propertyArray.push_back(cp);
00200    }
00201    else if (parser.tokenIsId(CIMXMLParser::E_VALUE_REFERENCE))
00202    {
00203       CIMValue value = XMLCIMFactory::createValue(parser, "REF", E_VALUE_NOT_EMBEDDED_OBJECT);
00204       cp = CIMProperty();
00205       cp.setDataType(CIMDataType::REFERENCE);
00206       cp.setValue(value);
00207       propertyArray.push_back(cp);
00208    }
00209    // No. Any of the sub-elements are optional.  If none are found, then the
00210    // path is to a singleton.
00211    //else
00212    //{
00213    // OW_THROWCIMMSG(CIMException::FAILED,
00214    //    "not a valid instance declaration");
00215    //}
00216    parser.mustGetEndTag();
00217    cimPath.setKeys(propertyArray);
00218 }
00220 CIMObjectPath
00221 createObjectPath(CIMXMLParser& parser)
00222 {
00223    CIMObjectPath rval;
00224    int token = parser.getToken();
00225    switch (token)
00226    {
00227       case CIMXMLParser::E_OBJECTPATH:
00228          parser.mustGetChild();
00229          rval = createObjectPath(parser);
00230          parser.mustGetEndTag(); // pass </OBJECTPATH>
00231          return rval;
00232       case CIMXMLParser::E_LOCALCLASSPATH:
00233          parser.mustGetChildId(CIMXMLParser::E_LOCALNAMESPACEPATH);
00234          getLocalNameSpacePathAndSet(rval, parser);
00235          parser.mustGetNextId(CIMXMLParser::E_CLASSNAME);
00236          rval.setClassName(parser.mustGetAttribute(CIMXMLParser::A_NAME));
00237          parser.mustGetNextTag();
00238          parser.mustGetEndTag(); // pass </CLASSNAME>
00239          parser.mustGetEndTag(); // pass </LOCALCLASSPATH>
00240          return rval;
00241       case CIMXMLParser::E_CLASSPATH:
00242          parser.mustGetChildId(CIMXMLParser::E_NAMESPACEPATH);
00243          getNameSpacePathAndSet(rval, parser);
00244          parser.mustGetNextId(CIMXMLParser::E_CLASSNAME);
00245          rval.setClassName(parser.mustGetAttribute(CIMXMLParser::A_NAME));
00246          parser.mustGetNextTag();
00247          parser.mustGetEndTag(); // pass </CLASSNAME>
00248          parser.mustGetEndTag(); // pass </LOCALCLASSPATH>
00249          return rval;
00250       case CIMXMLParser::E_CLASSNAME:
00251          rval.setClassName(parser.mustGetAttribute(CIMXMLParser::A_NAME));
00252          parser.mustGetNextTag();
00253          parser.mustGetEndTag(); // pass </CLASSNAME>
00254          return rval;
00255       case CIMXMLParser::E_INSTANCENAME:
00256          getInstanceName(parser, rval);
00257          return rval;
00258       case CIMXMLParser::E_LOCALINSTANCEPATH:
00259          parser.mustGetChildId(CIMXMLParser::E_LOCALNAMESPACEPATH);
00260          getLocalNameSpacePathAndSet(rval, parser);
00261          break;
00262       case CIMXMLParser::E_INSTANCEPATH:
00263          parser.mustGetChildId(CIMXMLParser::E_NAMESPACEPATH);
00264          getNameSpacePathAndSet(rval, parser);
00265          break;
00266       default:
00267             OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00268                Format("Invalid XML for Object path construction.  Node "
00269                   "name = %1", parser.getName()).c_str());
00270             break;
00271    }
00272    // read <INSTANCENAME>
00273    getInstanceName(parser, rval);
00274    parser.mustGetEndTag(); // pass </LOCALINSTANCEPATH> or </INSTANCEPATH>
00275    return rval;
00276 }
00278 CIMClass
00279 createClass(CIMXMLParser& parser)
00280 {
00281    CIMClass rval;
00282    CIMName superClassName;
00283    
00284    if (!parser.tokenIsId(CIMXMLParser::E_CLASS))
00285    {
00286       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, "Not class XML");
00287    }
00288    
00289    String inClassName = parser.mustGetAttribute(CIMXMLParser::A_NAME);
00290    rval.setName(inClassName);
00291    superClassName = parser.getAttribute(CIMXMLParser::A_SUPERCLASS);
00292    if (superClassName != "")
00293    {
00294       rval.setSuperClass(superClassName);
00295    }
00296 
00297    //
00298    // Find qualifier information
00299    //
00300    parser.mustGetNextTag();
00301    while (parser.tokenIsId(CIMXMLParser::E_QUALIFIER))
00302    {
00303       CIMQualifier cq = createQualifier(parser);
00304 //         if (cq.getName().equalsIgnoreCase(CIMQualifier::CIM_QUAL_ASSOCIATION))
00305 //         {
00306 //             if (!cq.getValue()
00307 //                 || cq.getValue() != CIMValue(false))
00308 //             {
00309 //                 rval.setIsAssociation(true);
00310 //             }
00311 //         }
00312       rval.addQualifier(cq);
00313    }
00314    //
00315    // Load properties
00316    //
00317    while (parser.tokenIsId(CIMXMLParser::E_PROPERTY)
00318          || parser.tokenIsId(CIMXMLParser::E_PROPERTY_ARRAY)
00319          || parser.tokenIsId(CIMXMLParser::E_PROPERTY_REFERENCE))
00320    {
00321       rval.addProperty(createProperty(parser));
00322    }
00323    //
00324    // Load methods
00325    //
00326    while (parser.tokenIsId(CIMXMLParser::E_METHOD))
00327    {
00328       rval.addMethod(createMethod(parser));
00329    }
00330    parser.mustGetEndTag();
00331    return rval;
00332 }
00334 CIMInstance
00335 createInstance(CIMXMLParser& parser)
00336 {
00337    CIMInstance rval;
00338    if (!parser.tokenIsId(CIMXMLParser::E_INSTANCE))
00339    {
00340       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, "Not instance XML");
00341    }
00342       
00343    rval.setClassName(parser.mustGetAttribute(CIMXMLParser::A_CLASSNAME));
00344 
00345    String language = parser.getAttribute(CIMXMLParser::A_XML_LANG, false);
00346    if (!language.empty())
00347    {
00348       rval.setLanguage(language);
00349    }
00350 
00351    //
00352    // Find qualifier information
00353    //
00354    CIMQualifierArray quals;
00355    parser.getChild();
00356    while (parser.tokenIsId(CIMXMLParser::E_QUALIFIER))
00357    {
00358       quals.append(createQualifier(parser));
00359    }
00360    rval.setQualifiers(quals);
00361    //
00362    // Load properties
00363    //
00364    CIMPropertyArray props;
00365    while (parser.tokenIsId(CIMXMLParser::E_PROPERTY)
00366          || parser.tokenIsId(CIMXMLParser::E_PROPERTY_ARRAY)
00367          || parser.tokenIsId(CIMXMLParser::E_PROPERTY_REFERENCE))
00368    {
00369       props.append(createProperty(parser));
00370    }
00371    rval.setProperties(props);
00372    parser.mustGetEndTag();
00373    return rval;
00374 }
00375 namespace /* anonymous */
00376 {
00377 inline void StringToType(const String& s, UInt8& b)
00378 {
00379    b = s.toUInt8();
00380 }
00381 inline void StringToType(const String& s, Int8& b)
00382 {
00383    b = s.toInt8();
00384 }
00385 inline void StringToType(const String& s, UInt16& b)
00386 {
00387    b = s.toUInt16();
00388 }
00389 inline void StringToType(const String& s, Int16& b)
00390 {
00391    b = s.toInt16();
00392 }
00393 inline void StringToType(const String& s, UInt32& b)
00394 {
00395    b = s.toUInt32();
00396 }
00397 inline void StringToType(const String& s, Int32& b)
00398 {
00399    b = s.toInt32();
00400 }
00401 inline void StringToType(const String& s, UInt64& b)
00402 {
00403    b = s.toUInt64();
00404 }
00405 inline void StringToType(const String& s, Int64& b)
00406 {
00407    b = s.toInt64();
00408 }
00409 inline void StringToType(const String& s, String& b)
00410 {
00411    b = s;
00412 }
00413 inline void StringToType(const String& s, Real32& b)
00414 {
00415    b = s.toReal32();
00416 }
00417 inline void StringToType(const String& s, Real64& b)
00418 {
00419    b = s.toReal64();
00420 }
00421 inline void StringToType(const String& s, Char16& b)
00422 {
00423    b = Char16(s);
00424 }
00425 inline void StringToType(const String& s, CIMDateTime& b)
00426 {
00427    b = CIMDateTime(s);
00428 }
00429 } /* end anonymous namespace */
00430 
00432 template <class T>
00433 static inline void
00434 convertCimType(Array<T>& ra, CIMXMLParser& parser)
00435 {
00436    // start out possibly pointing at <VALUE>
00437    while (parser.tokenIsId(CIMXMLParser::E_VALUE))
00438    {
00439       parser.mustGetNext();
00440       if (parser.isData())
00441       {
00442          String vstr = parser.getData();
00443          T val;
00444          StringToType(vstr, val);
00445          ra.append(val);
00446          parser.mustGetNextTag();
00447       }
00448       else
00449       {
00450          T val;
00451          StringToType("", val);
00452          ra.append(val);
00453       }
00454       parser.mustGetEndTag();
00455    }
00456 }
00457 
00459 CIMValue
00460 createValue(CIMXMLParser& parser, String const& valueType)
00461 {
00462    return createValue(parser, valueType, E_VALUE_NOT_EMBEDDED_OBJECT);
00463 }
00464 
00465 namespace
00466 {
00467 
00468 CIMValue
00469 convertXMLtoEmbeddedObject(const String& str)
00470 {
00471    CIMValue rval(CIMNULL);
00472    // try to convert the string to an class or instance
00473    TempFileStream ostr;
00474    ostr << str;
00475    try
00476    {
00477       try
00478       {
00479          ostr.rewind();
00480          CIMXMLParser parser(ostr);
00481          CIMInstance ci = XMLCIMFactory::createInstance(parser);
00482          rval = CIMValue(ci);
00483       }
00484       catch (const CIMException&)
00485       {
00486          // XML wasn't an instance, so try an class
00487          try
00488          {
00489             ostr.rewind();
00490             CIMXMLParser parser(ostr);
00491             CIMClass cc = XMLCIMFactory::createClass(parser);
00492             rval = CIMValue(cc);
00493          }
00494          catch (const CIMException&)
00495          {
00496             // XML isn't a class or an instance, so just leave it alone
00497          }
00498       }
00499    }
00500    catch (XMLParseException& xmlE)
00501    {
00502    }
00503    return rval;
00504 }
00505 
00506 struct valueIsEmbeddedInstance
00507 {
00508    bool operator()(const CIMValue& v)
00509    {
00510       return v.getType() == CIMDataType::EMBEDDEDINSTANCE;
00511    }
00512 };
00513 
00514 struct valueIsEmbeddedClass
00515 {
00516    bool operator()(const CIMValue& v)
00517    {
00518       return v.getType() == CIMDataType::EMBEDDEDCLASS;
00519    }
00520 };
00521 
00522 bool isKnownEmbeddedObjectName(const String& name)
00523 {
00524    // This is a bad hack, hopefully EmbeddedObject will become a real
00525    // data type someday.
00526    // This is all property names in the CIM Schema (as of 2.7.1) that have
00527    // an EmbeddedObject(true) qualifier.
00528    // If this list gets much bigger, use a HashMap
00529    String lname(name);
00530    lname.toLowerCase();
00531    return
00532       lname.equals("sourceinstance") ||
00533       lname.equals("previousinstance") ||
00534       lname.equals("methodparameters") ||
00535       lname.equals("classdefinition") ||
00536       lname.equals("previousclassdefinition") ||
00537       lname.equals("indobject");
00538 }
00539 
00540 } // anonymous namespace
00541 
00542 
00544 CIMValue
00545 createValue(CIMXMLParser& parser, String const& valueType, EEmbeddedObjectFlag embeddedObjectFlag)
00546 {
00547    CIMValue rval(CIMNULL);
00548    try
00549    {
00550    
00551       int token = parser.getToken();
00552    
00553       switch (token)
00554       {
00555          // <VALUE> elements
00556          case CIMXMLParser::E_VALUE:
00557             {
00558                parser.mustGetNext();
00559                if (parser.isData())
00560                {
00561                   String vstr = parser.getData();
00562                   rval = CIMValue::createSimpleValue(valueType, vstr);
00563                   parser.mustGetNextTag(); // pass text
00564                }
00565                else
00566                {
00567                   rval = CIMValue::createSimpleValue(valueType, "");
00568                }
00569                parser.mustGetEndTag(); // get </VALUE>
00570                break;
00571             }
00572    
00573          // <VALUE.ARRAY> elements
00574          case CIMXMLParser::E_VALUE_ARRAY:
00575             {
00576                int type = CIMDataType::strToSimpleType(valueType);
00577                if (type == CIMDataType::INVALID)
00578                {
00579                   OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00580                      "Invalid data type on node");
00581                }
00582                parser.mustGetNextTag();
00583    
00584                switch (type)
00585                {
00586                   case CIMDataType::UINT8:
00587                   {
00588                      UInt8Array ra;
00589                      convertCimType(ra, parser);
00590                      rval = CIMValue(ra);
00591                      break;
00592                   }
00593    
00594                   case CIMDataType::SINT8:
00595                      {
00596                         Int8Array ra;
00597                         convertCimType(ra, parser);
00598                         rval = CIMValue(ra);
00599                         break;
00600                      }
00601    
00602                   case CIMDataType::UINT16:
00603                      {
00604                         UInt16Array ra;
00605                         convertCimType(ra, parser);
00606                         rval = CIMValue(ra);
00607                         break;
00608                      }
00609    
00610                   case CIMDataType::SINT16:
00611                      {
00612                         Int16Array ra;
00613                         convertCimType(ra, parser);
00614                         rval = CIMValue(ra);
00615                         break;
00616                      }
00617    
00618                   case CIMDataType::UINT32:
00619                      {
00620                         UInt32Array ra;
00621                         convertCimType(ra, parser);
00622                         rval = CIMValue(ra);
00623                         break;
00624                      }
00625    
00626                   case CIMDataType::SINT32:
00627                      {
00628                         Int32Array ra;
00629                         convertCimType(ra, parser);
00630                         rval = CIMValue(ra);
00631                         break;
00632                      }
00633    
00634                   case CIMDataType::UINT64:
00635                      {
00636                         UInt64Array ra;
00637                         convertCimType(ra, parser);
00638                         rval = CIMValue(ra);
00639                         break;
00640                      }
00641    
00642                   case CIMDataType::SINT64:
00643                      {
00644                         Int64Array ra;
00645                         convertCimType(ra, parser);
00646                         rval = CIMValue(ra);
00647                         break;
00648                      }
00649    
00650                   case CIMDataType::BOOLEAN:
00651                      {
00652                         BoolArray ra;
00653                         StringArray sra;
00654                         convertCimType(sra, parser);
00655                         for (size_t i = 0; i < sra.size(); i++)
00656                         {
00657                            Bool bv = sra[i].equalsIgnoreCase("TRUE");
00658                            ra.append(bv);
00659                         }
00660    
00661                         rval = CIMValue(ra);
00662                         break;
00663                      }
00664    
00665                   case CIMDataType::REAL32:
00666                      {
00667                         Real32Array ra;
00668                         convertCimType(ra, parser);
00669                         rval = CIMValue(ra);
00670                         break;
00671                      }
00672    
00673                   case CIMDataType::REAL64:
00674                      {
00675                         Real64Array ra;
00676                         convertCimType(ra, parser);
00677                         rval = CIMValue(ra);
00678                         break;
00679                      }
00680    
00681                   case CIMDataType::CHAR16:
00682                      {
00683                         Char16Array ra;
00684                         convertCimType(ra, parser);
00685                         rval = CIMValue(ra);
00686                         break;
00687                      }
00688    
00689                   case CIMDataType::DATETIME:
00690                      {
00691                         CIMDateTimeArray ra;
00692                         convertCimType(ra, parser);
00693                         rval = CIMValue(ra);
00694                         break;
00695                      }
00696    
00697                   case CIMDataType::STRING:
00698                      {
00699                         StringArray ra;
00700                         convertCimType(ra, parser);
00701                         rval = CIMValue(ra);
00702                         break;
00703                      }
00704    
00705                   default:
00706                      OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00707                         "Invalid data type on node");
00708                }
00709    
00710                parser.mustGetEndTag(); // pass </VALUE.ARRAY>
00711                break;
00712             }
00713    
00714          case CIMXMLParser::E_VALUE_REFARRAY:
00715             {
00716                CIMObjectPathArray opArray;
00717                parser.getNextTag();
00718    
00719                while (parser.tokenIsId(CIMXMLParser::E_VALUE_REFERENCE))
00720                {
00721                   CIMObjectPath cop(CIMNULL);
00722                   CIMValue v = createValue(parser, valueType, E_VALUE_NOT_EMBEDDED_OBJECT);
00723                   v.get(cop);
00724    
00725                   opArray.append(cop);
00726                }
00727    
00728                rval = CIMValue(opArray);
00729                parser.mustGetEndTag(); // pass <VALUE.REFARRAY>
00730                break;
00731             }
00732    
00733          case CIMXMLParser::E_VALUE_REFERENCE:
00734             {
00735                parser.mustGetChild();
00736                CIMObjectPath cop = createObjectPath(parser);
00737                parser.mustGetEndTag(); // pass </VALUE.REFERENCE>
00738                rval = CIMValue(cop);
00739                break;
00740             }
00741    
00742          default:
00743             OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00744                "Not value XML");
00745       }
00746 
00747 
00748       // handle embedded class or instance
00749       if (embeddedObjectFlag == E_VALUE_IS_EMBEDDED_INSTANCE || embeddedObjectFlag == E_VALUE_IS_EMBEDDED_OBJECT)
00750       {
00751          if (rval.getCIMDataType().isArrayType())
00752          {
00753             StringArray xmlstrings;
00754             rval.get(xmlstrings);
00755             CIMValueArray values;
00756             for (size_t i = 0; i < xmlstrings.size(); ++i)
00757             {
00758                CIMValue v = convertXMLtoEmbeddedObject(xmlstrings[i]);
00759                if (!v)
00760                {
00761                   break;
00762                }
00763                values.push_back(v);
00764             }
00765             if (values.size() == xmlstrings.size() && values.size() > 0)
00766             {
00767                if (std::find_if (values.begin(), values.end(), valueIsEmbeddedInstance()) == values.end())
00768                {
00769                   // no instances, so they all must be classes
00770                   CIMClassArray classes;
00771                   for (size_t i = 0; i < values.size(); ++i)
00772                   {
00773                      CIMClass c(CIMNULL);
00774                      values[i].get(c);
00775                      classes.push_back(c);
00776                   }
00777                   rval = CIMValue(classes);
00778                }
00779                else if (std::find_if (values.begin(), values.end(), valueIsEmbeddedClass()) == values.end())
00780                {
00781                   // no classes, the all must be instances
00782                   CIMInstanceArray instances;
00783                   for (size_t i = 0; i < values.size(); ++i)
00784                   {
00785                      CIMInstance c(CIMNULL);
00786                      values[i].get(c);
00787                      instances.push_back(c);
00788                   }
00789                   rval = CIMValue(instances);
00790                }
00791                else
00792                {
00793                   // there are both classes and instances - we cannot handle this!
00794                   // we'll just leave the property alone (as a string)
00795                }
00796             }
00797             else if (values.size() == 0)
00798             {
00799                // it was an empty array.  Assume it was instances, not classes.
00800                rval = CIMValue(CIMInstanceArray());
00801             }
00802          }
00803          else
00804          {
00805             CIMValue v = convertXMLtoEmbeddedObject(rval.toString());
00806             if (v)
00807             {
00808                rval = v;
00809             }
00810          }
00811       }
00812 
00813    
00814    }
00815    catch (const StringConversionException& e)
00816    {
00817       // Workaround for SNIA client which sends <VALUE>NULL</VALUE> for NULL values
00818       if (parser.isData())
00819       {
00820          if (parser.getData().equalsIgnoreCase("NULL"))
00821          {
00822             rval = CIMValue(CIMNULL);
00823             parser.getNextTag();
00824             parser.mustGetEndTag();
00825          }
00826          else
00827          {
00828             OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, e.getMessage());
00829          }
00830       }
00831       else
00832       {
00833          rval = CIMValue(CIMNULL);
00834          parser.mustGetEndTag();
00835       }
00836    }
00837    return rval;
00838 }
00840 CIMQualifier
00841 createQualifier(CIMXMLParser& parser)
00842 {
00843    if (!parser.tokenIsId(CIMXMLParser::E_QUALIFIER))
00844    {
00845       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, "Not qualifier XML");
00846    }
00847    CIMDataType dt(CIMNULL);
00848    String name = parser.mustGetAttribute(CIMXMLParser::A_NAME);
00849    String cimType = parser.getAttribute(CIMXMLParser::A_TYPE);
00850    String propagate = parser.getAttribute(CIMXMLParser::A_PROPAGATED);
00851    String tosubclass = parser.getAttribute(CIMXMLParser::A_TOSUBCLASS);
00852    String overridable = parser.getAttribute(
00853       CIMXMLParser::A_OVERRIDABLE);
00854    //String toinstance = parser.getAttribute(
00855    // XMLParameters::paramToInstance);
00856    String translatable = parser.getAttribute(
00857       CIMXMLParser::A_TRANSLATABLE);
00858 
00859    String language = parser.getAttribute(CIMXMLParser::A_XML_LANG, false);
00860 
00861    //
00862    // Build qualifier
00863    //
00864    if (!cimType.empty())
00865    {
00866       dt = CIMDataType::getDataType(cimType);
00867    }
00868    if (!dt)
00869    {
00870       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00871          Format("Qualifier not assigned a data type: %1", name).c_str());
00872    }
00873    CIMQualifierType cqt;
00874    cqt.setDataType(dt);
00875    cqt.setName(name);
00876    
00877    CIMQualifier rval(cqt);
00878    if (overridable.equalsIgnoreCase("false"))
00879    {
00880       rval.addFlavor(CIMFlavor(CIMFlavor::DISABLEOVERRIDE));
00881    }
00882    else
00883    {
00884       rval.addFlavor(CIMFlavor(CIMFlavor::ENABLEOVERRIDE));
00885    }
00886    if (tosubclass.equalsIgnoreCase("false"))
00887    {
00888       rval.addFlavor(CIMFlavor(CIMFlavor::RESTRICTED));
00889    }
00890    else
00891    {
00892       rval.addFlavor(CIMFlavor(CIMFlavor::TOSUBCLASS));
00893    }
00894    //if (toinstance.equalsIgnoreCase("true"))
00895    //{
00896    // rval.addFlavor(CIMFlavor(CIMFlavor::TOINSTANCE));
00897    //}
00898    if (translatable.equalsIgnoreCase("true"))
00899    {
00900       rval.addFlavor(CIMFlavor(CIMFlavor::TRANSLATE));
00901    }
00902    rval.setPropagated(propagate.equalsIgnoreCase("true"));
00903    
00904    if (!language.empty())
00905    {
00906       rval.setLanguage(language);
00907    }
00908 
00909    parser.mustGetNextTag();
00910    if (parser.tokenIsId(CIMXMLParser::E_VALUE_ARRAY)
00911       || parser.tokenIsId(CIMXMLParser::E_VALUE))
00912    {
00913       rval.setValue(createValue(parser, cimType, E_VALUE_NOT_EMBEDDED_OBJECT));
00914    }
00915    parser.mustGetEndTag();
00916    return rval;
00917 }
00919 CIMMethod
00920 createMethod(CIMXMLParser& parser)
00921 {
00922    if (!parser.tokenIsId(CIMXMLParser::E_METHOD))
00923    {
00924       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, "Not method XML");
00925    }
00926    String methodName = parser.mustGetAttribute(CIMXMLParser::A_NAME);
00927    String cimType = parser.getAttribute(CIMXMLParser::A_TYPE);
00928    String classOrigin = parser.getAttribute(
00929       CIMXMLParser::A_CLASSORIGIN);
00930    String propagate = parser.getAttribute(CIMXMLParser::A_PROPAGATED);
00931    //
00932    // A method name must be given
00933    //
00934    if (methodName.empty())
00935    {
00936       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
00937          "No method name in XML");
00938    }
00939    CIMMethod rval;
00940    //
00941    // If no return data type, then method returns nothing (void)
00942    //
00943    if (!cimType.empty())
00944    {
00945       rval.setReturnType(CIMDataType::getDataType(cimType));
00946    }
00947    rval.setName(methodName);
00948    if (!classOrigin.empty())
00949    {
00950       rval.setOriginClass(classOrigin);
00951    }
00952    rval.setPropagated(propagate.equalsIgnoreCase("true"));
00953    parser.mustGetNextTag();
00954    //
00955    // See if there are qualifiers
00956    //
00957    while (parser.tokenIsId(CIMXMLParser::E_QUALIFIER))
00958    {
00959       rval.addQualifier(createQualifier(parser));
00960    }
00961    //
00962    // Handle parameters
00963    while (parser.tokenIsId(CIMXMLParser::E_PARAMETER)
00964       || parser.tokenIsId(CIMXMLParser::E_PARAMETER_REFERENCE)
00965       || parser.tokenIsId(CIMXMLParser::E_PARAMETER_ARRAY)
00966       || parser.tokenIsId(CIMXMLParser::E_PARAMETER_REFARRAY))
00967    {
00968       rval.addParameter(createParameter(parser));
00969    }
00970    parser.mustGetEndTag();
00971    return rval;
00972 }
00973 
00974 EEmbeddedObjectFlag getEmbeddedObjectType(const CIMXMLParser& parser)
00975 {
00976    EEmbeddedObjectFlag embeddedObjectType = E_VALUE_NOT_EMBEDDED_OBJECT;
00977    String embeddedObjectValue = parser.getAttribute(CIMXMLParser::A_EMBEDDEDOBJECT);
00978    if (embeddedObjectValue == CIMXMLParser::AV_EMBEDDEDOBJECT_OBJECT_VALUE)
00979    {
00980       embeddedObjectType = E_VALUE_IS_EMBEDDED_OBJECT;
00981    }
00982    else if (embeddedObjectValue == CIMXMLParser::AV_EMBEDDEDOBJECT_INSTANCE_VALUE)
00983    {
00984       embeddedObjectType = E_VALUE_IS_EMBEDDED_INSTANCE;
00985    }
00986    return embeddedObjectType;
00987 }
00988 
00990 CIMProperty
00991 createProperty(CIMXMLParser& parser)
00992 {
00993    int token = parser.getToken();
00994    if (token != CIMXMLParser::E_PROPERTY
00995       && token != CIMXMLParser::E_PROPERTY_ARRAY
00996       && token != CIMXMLParser::E_PROPERTY_REFERENCE)
00997    {
00998       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, "not property XML");
00999    }
01000    String superClassName;
01001    String inClassName;
01002    String propName = parser.mustGetAttribute(CIMXMLParser::A_NAME);
01003    String cimType = parser.getAttribute(CIMXMLParser::A_TYPE);
01004    String classOrigin = parser.getAttribute(
01005       CIMXMLParser::A_CLASSORIGIN);
01006    String propagate = parser.getAttribute(CIMXMLParser::A_PROPAGATED);
01007    
01008    EEmbeddedObjectFlag embeddedObjectType = getEmbeddedObjectType(parser);
01009 
01010    CIMProperty rval(propName);
01011    //
01012    // If no return data type, then property isn't properly defined
01013    //
01014    if (token == CIMXMLParser::E_PROPERTY_REFERENCE)
01015    {
01016       rval.setDataType(CIMDataType(parser.getAttribute(
01017          CIMXMLParser::A_REFERENCECLASS)));
01018    }
01019    else if (!cimType.empty())
01020    {
01021       rval.setDataType(CIMDataType::getDataType(cimType));
01022    }
01023    else
01024    {
01025       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
01026          "property has null data type");
01027    }
01028    //
01029    // Array type property
01030    //
01031    if (token == CIMXMLParser::E_PROPERTY_ARRAY)
01032    {
01033       String arraySize = parser.getAttribute(
01034          CIMXMLParser::A_ARRAYSIZE);
01035       CIMDataType dt = rval.getDataType();
01036       if (!arraySize.empty())
01037       {
01038          Int32 aSize = 0;
01039          try
01040          {
01041             aSize = arraySize.toInt32();
01042          }
01043          catch (const StringConversionException&)
01044          {
01045             OW_THROWCIMMSG(CIMException::FAILED, Format("Array size: \"%1\" is invalid", arraySize).c_str());
01046          }
01047          dt.setToArrayType(aSize);
01048       }
01049       else
01050       {
01051          // no limit
01052          dt.setToArrayType(0);
01053       }
01054       rval.setDataType(dt);
01055    }
01056    rval.setOriginClass(classOrigin);
01057    rval.setPropagated(!propagate.empty() && propagate.equalsIgnoreCase("true"));
01058    //
01059    // See if there are qualifiers
01060    //
01061    parser.mustGetNextTag();
01062    while (parser.tokenIsId(CIMXMLParser::E_QUALIFIER))
01063    {
01064       rval.addQualifier(createQualifier(parser));
01065    }
01066 
01067    if (parser.tokenIsId(CIMXMLParser::E_VALUE)
01068       || parser.tokenIsId(CIMXMLParser::E_VALUE_ARRAY)
01069       || parser.tokenIsId(CIMXMLParser::E_VALUE_REFERENCE))
01070    {
01071       // embeddedObjectType would only be set to E_VALUE_IS_EMBEDDED_OBJECT or E_VALUE_IS_EMBEDDED_INSTANCE if the xml contains the EmbeddedObject attribute.
01072       if (embeddedObjectType == E_VALUE_NOT_EMBEDDED_OBJECT)
01073       {
01074          // check for old ways to enable the embedded decoding
01075          if ((rval.hasTrueQualifier(CIMQualifier::CIM_QUAL_EMBEDDEDOBJECT) &&
01076              rval.getDataType().getType() == CIMDataType::STRING) ||
01077             isKnownEmbeddedObjectName(rval.getName())
01078             )
01079          {
01080             embeddedObjectType = E_VALUE_IS_EMBEDDED_OBJECT;
01081          }
01082       }
01083 
01084       CIMDataType dt = rval.getDataType();
01085       CIMValue val = createValue(parser, cimType, embeddedObjectType);
01086       if (val)
01087       {
01088          dt.syncWithValue(val);
01089       }
01090       else if (embeddedObjectType == E_VALUE_IS_EMBEDDED_OBJECT || embeddedObjectType == E_VALUE_IS_EMBEDDED_INSTANCE)
01091       {
01092          if (dt.isArrayType())
01093          {
01094             dt = CIMDataType(CIMDataType::EMBEDDEDINSTANCE, dt.getSize());
01095          }
01096          else
01097          {
01098             dt = CIMDataType(CIMDataType::EMBEDDEDINSTANCE);
01099          }
01100       }
01101       rval.setDataType(dt);
01102 
01103       rval.setValue(val);
01104    }
01105    parser.mustGetEndTag();
01106    return rval;
01107 }
01108 
01110 CIMParameter
01111 createParameter(CIMXMLParser& parser)
01112 {
01113    int paramToken = parser.getToken();
01114    
01115    if (paramToken != CIMXMLParser::E_PARAMETER
01116       && paramToken != CIMXMLParser::E_PARAMETER_REFERENCE
01117       && paramToken != CIMXMLParser::E_PARAMETER_ARRAY
01118       && paramToken != CIMXMLParser::E_PARAMETER_REFARRAY)
01119    {
01120       OW_THROWCIMMSG(CIMException::INVALID_PARAMETER, "Not parameter XML");
01121    }
01122    
01123    //
01124    // Fetch name
01125    //
01126    CIMParameter rval(parser.mustGetAttribute(CIMXMLParser::A_NAME));
01127    
01128    //
01129    // Get parameter type
01130    //
01131    switch (paramToken)
01132    {
01133       case CIMXMLParser::E_PARAMETER:
01134       {
01135          rval.setDataType(CIMDataType::getDataType(
01136             parser.mustGetAttribute(CIMXMLParser::A_TYPE)));
01137          break;
01138       }
01139    
01140       case CIMXMLParser::E_PARAMETER_REFERENCE:
01141       {
01142          rval.setDataType(CIMDataType(
01143             parser.getAttribute(CIMXMLParser::A_REFERENCECLASS)));
01144          break;
01145       }
01146    
01147       case CIMXMLParser::E_PARAMETER_ARRAY:
01148       {
01149          CIMDataType dt = CIMDataType::getDataType(
01150             parser.mustGetAttribute(CIMXMLParser::A_TYPE));
01151    
01152          if (!dt)
01153          {
01154             OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
01155                "invalid parameter data type");
01156          }
01157    
01158          try
01159          {
01160             dt.setToArrayType(
01161                parser.getAttribute(CIMXMLParser::A_ARRAYSIZE).toInt32());
01162          }
01163          catch (const StringConversionException&)
01164          {
01165             dt.setToArrayType(0);
01166          }
01167          rval.setDataType(dt);
01168          break;
01169       }
01170    
01171       case CIMXMLParser::E_PARAMETER_REFARRAY:
01172       {
01173          CIMDataType dt = CIMDataType(
01174             parser.getAttribute(CIMXMLParser::A_REFERENCECLASS));
01175    
01176          try
01177          {
01178             dt.setToArrayType(
01179                parser.getAttribute(CIMXMLParser::A_ARRAYSIZE).toInt32());
01180          }
01181          catch (const StringConversionException&)
01182          {
01183             dt.setToArrayType(0);
01184          }
01185          rval.setDataType(dt);
01186          break;
01187       }
01188    
01189       default:
01190          OW_THROWCIMMSG(CIMException::INVALID_PARAMETER,
01191             "could not decode parameter XML");
01192    }
01193    
01194    //
01195    // See if there are qualifiers
01196    //
01197    CIMQualifierArray qualArray;
01198    parser.mustGetNextTag();
01199    while (parser.tokenIsId(CIMXMLParser::E_QUALIFIER))
01200    {
01201       qualArray.append(createQualifier(parser));
01202    }
01203    rval.setQualifiers(qualArray);
01204    parser.mustGetEndTag();
01205    return rval;
01206 }
01207 
01208 } // end namespace XMLCIMFactory
01209 } // end namespace OW_NAMESPACE
01210 

Generated on Thu Feb 9 08:48:18 2006 for openwbem by  doxygen 1.4.6