BUG#: 8671
[tpot/pegasus.git.bak/pegasus.git] / src / Clients / cimcli / ObjectBuilder.cpp
1 //%2006////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
11 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
20 // 
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 //%/////////////////////////////////////////////////////////////////////////////
33 #include <Pegasus/Common/Config.h>
34 #include <Pegasus/Common/Constants.h>
35 #include <Pegasus/Common/PegasusAssert.h>
36 #include <Pegasus/Common/StringConversion.h>
37 #include <Pegasus/Common/Tracer.h>
38 #include <Pegasus/Common/XmlWriter.h>
39
40 #include "CIMCLIClient.h"
41 #include "ObjectBuilder.h"
42 #include "CIMCLICommon.h"
43
44 PEGASUS_USING_STD;
45 PEGASUS_NAMESPACE_BEGIN
46
47 class csvStringParse;
48
49 // Cleans an input array by removing the { } tokens that surround
50 // the array.  Does nothing if they do not exist.  If there is 
51 // an unmatched set, an error is generated.
52 // Allows the user to input array definitions surrounded by { }
53 // as an option.
54 void _cleanArray(String& x)
55 {
56     if (x[0] == '{' && x[x.size()] == '}')
57     {
58         x.remove(0,1);
59         x.remove(x.size(),1);
60     }
61     else if(x[0] == '{' || x[x.size()] == '}')
62     {
63         cerr << "Error: Parse Error: Array " << x << endl;
64         exit(CIMCLI_INPUT_ERR);
65     }
66 }
67
68 // FUTURE - Expand this for other date time literals suchs as TODAY
69 //
70 CIMDateTime _getDateTime(const String& str)
71 {
72     if (String::equalNoCase(str,"NOW"))
73     {
74         return CIMDateTime::getCurrentDateTime();
75     }
76     return CIMDateTime(str);
77 }
78
79 Boolean _StringToBoolean(const String& x)
80 {
81     if (String::equalNoCase(x,"true"))
82     {
83         return true;
84     }
85     else if (String::equalNoCase(x,"false"))
86     {
87         return false;
88     }
89     cerr << "Parse Error: Boolean Parmeter " << x << endl;
90     exit(CIMCLI_INPUT_ERR);
91     return false;
92 }
93
94 Uint32 _includesType(const String& name)
95 {
96     // FUTURE  KS add code. For now this is null because we do not
97     // support the data type option on input.
98     return 0;
99 }
100
101 /* Parser for comma-separated-strings (csv). This parser takes into
102    account quoted strings the " character and returns everything
103    within a quoted block in the string in one batch.  It also
104    considers the backslash "\" escape character to escape single
105    double quotes.
106    Example:
107      csvStringParse x (inputstring, ",");
108      while (x.more())
109         rtnString = x.next();
110 */ 
111 class csvStringParse
112 {
113 public:
114     /* Define a string to parse for comma separated values and the
115        separation character
116     */
117     csvStringParse(const String& csvString, const int separator)
118     {
119         _inputString = csvString;
120         _separator = separator;
121         _idx = 0;
122         _end = csvString.size();
123     }
124
125     /* determine if there is more to parse
126        @return true if there is more to parse
127     */
128     Boolean more()
129     {
130         return (_idx < _end)? true : false;
131     }
132
133     /* get next string from input. Note that this will continue to
134        return empty strings if you parse past the point where more()
135        returns false.
136        @return String
137     */ 
138     String next()
139     {
140         String rtnValue;
141         parsestate state = NOTINQUOTE;
142
143         while ((_idx <= _end) && (_inputString[_idx]))
144         {
145             char idxchar = _inputString[_idx];
146             switch (state)
147             {
148                 case NOTINQUOTE:
149                     switch (idxchar)
150                     {
151                         case '\\':
152                             state = INSQUOTE;
153                             break;
154
155                         case '"':
156                             state = INDQUOTE;
157                             break;
158
159                         default:
160                             if (idxchar == _separator)
161                             {
162                                 _idx++;
163                                 return rtnValue;
164                             }
165                             else
166                                 rtnValue.append(idxchar);
167                             break;
168                     }
169                     break;
170
171                 // add next character and set NOTINQUOTE State
172                 case INSQUOTE:
173                     rtnValue.append(idxchar);
174                     state = NOTINQUOTE;
175                     break;
176
177                 // append all but quote character
178                 case INDQUOTE:
179                     switch (idxchar)
180                     {
181                         case '"':
182                             state = NOTINQUOTE;
183                             break;
184                         default:
185                             rtnValue.append(idxchar);
186                             break;
187                     }
188             }
189             _idx++;
190         }   // end while
191         return (rtnValue);
192     }
193
194 private:
195     enum parsestate {INDQUOTE, INSQUOTE, NOTINQUOTE};
196     Uint32 _idx;
197     int _separator;
198     Uint32 _end;
199     String _inputString;
200 };
201
202 Sint64 _strToSint(const char* str, CIMType type)
203 {
204     Sint64 s64;
205     Boolean success =
206         (StringConversion::stringToSint64(
207              str, StringConversion::decimalStringToUint64, s64) ||
208          StringConversion::stringToSint64(
209              str, StringConversion::hexStringToUint64, s64) ||
210          StringConversion::stringToSint64(
211              str, StringConversion::octalStringToUint64, s64) ||
212          StringConversion::stringToSint64(
213              str, StringConversion::binaryStringToUint64, s64)) &&
214         StringConversion::checkSintBounds(s64, type);
215     if (!success)
216     {
217         printf("Parse Error: Value conversion error. %s. type %s\n",
218                str, cimTypeToString(type));
219     }
220
221     return s64;
222 }
223
224 Uint64 _strToUint(const char* str, CIMType type)
225 {
226     Uint64 u64;
227     Boolean success =
228         (StringConversion::decimalStringToUint64(str, u64) ||
229          StringConversion::hexStringToUint64(str, u64) ||
230          StringConversion::octalStringToUint64(str, u64) ||
231          StringConversion::binaryStringToUint64(str, u64)) &&
232          StringConversion::checkUintBounds(u64, type);
233
234     if (!success)
235     {
236         fprintf(stderr,"Parse Error: Value conversion error. %s. type %s\n",
237                str, cimTypeToString(type));
238         exit(CIMCLI_INPUT_ERR);
239     }
240
241     return u64;
242 }
243
244 /* Convert a single string provided as input into a CIM variable
245    and place it in a CIMValue.
246    @param str char* representing string to be parsed.
247    @param type CIMType expected.
248    @return CIMValue with the new value.
249 */
250 Real64 _strToReal(const char * str, CIMType type)
251 {
252     Real64 r64;
253
254     if (!StringConversion::stringToReal64(str, r64))
255     {
256         fprintf(stderr, "Parse Error: Value conversion error. %s. type %s\n",
257                str, cimTypeToString(type));
258         exit(CIMCLI_INPUT_ERR);
259     }
260     return r64;
261 }
262
263 /* Convert a single string provided as input into a CIM variable
264    and place it in a CIMValue.
265    @param str char* representing string to be parsed.
266    @param type CIMType expected.
267    @return CIMValue with the new value. If the parse fails, this function
268    terminates with an exit CIMCLI_INPUT_ERR.
269 */
270 static CIMValue _stringToScalarValue(const char* str, CIMType type)
271 {
272     Uint64 u64;
273
274     switch (type)
275     {
276         case CIMTYPE_BOOLEAN:
277             return CIMValue(_StringToBoolean(str));
278
279         case CIMTYPE_UINT8:
280             return CIMValue(Uint8(_strToUint(str, type)));
281     
282         case CIMTYPE_SINT8:
283             return CIMValue(Sint8(_strToSint(str, type)));
284
285         case CIMTYPE_UINT16:
286             return CIMValue(Uint16(_strToUint(str, type)));
287
288         case CIMTYPE_SINT16:
289             return CIMValue(Sint16(_strToSint(str, type)));
290
291         case CIMTYPE_UINT32:
292             return CIMValue(Uint32(_strToUint(str, type)));
293
294         case CIMTYPE_SINT32:
295             return CIMValue(Sint32(_strToSint(str, type)));
296
297         case CIMTYPE_UINT64:
298             return CIMValue(Uint64(_strToUint(str, type)));
299
300         case CIMTYPE_SINT64:
301             return CIMValue(Sint64(_strToSint(str, type)));
302
303         case CIMTYPE_REAL32:
304             return CIMValue(Real32(_strToReal(str, type)));
305
306         case CIMTYPE_REAL64:
307             return CIMValue(Real64(_strToReal(str, type)));
308
309         case CIMTYPE_STRING:
310             return CIMValue(String(str));
311
312         case CIMTYPE_DATETIME:
313             return CIMValue(_getDateTime(str));
314
315         default:
316             cerr << "Error: Parser Error. Data type " << cimTypeToString(type) 
317                  << " not allowed" << endl;
318             exit(CIMCLI_INPUT_ERR);
319     }
320     return CIMValue();
321 }
322 /*
323     Parse out comma-separated values from input string and build the
324     CIMValue array representing the input for array type input entities.
325     @param str const char * containing the comma-separated values
326     to be parsed.  All value elements in the CSV string must be
327     parsable to the same type.
328     @param v CIMValue into which the resulting values are added to
329     any existing values
330     @return Returns complete CIMValue.
331 */
332 Boolean _buildArrayValue(
333     const char * str,
334     CIMValue& val)
335 {
336     CIMType type = val.getType();
337     Uint32 arrayDimension = val.getArraySize();
338
339     csvStringParse strl((String)String(str), ',');
340
341     switch (type)
342     {
343         case CIMTYPE_BOOLEAN:
344         {
345             Array<Boolean> a;
346             val.get(a);
347             while(strl.more())
348             {
349                  a.append(_StringToBoolean(strl.next()));
350             }
351             val.set(a);
352             break;
353         }
354         case CIMTYPE_UINT8:
355         {   
356             Array<Uint8> a;
357             val.get(a);
358             while(strl.more())
359                 a.append(_strToUint(strl.next().getCString(), type));
360             val.set(a);
361             break;
362         }
363         case CIMTYPE_SINT8:
364         {   
365             Array<Sint8> a;
366             val.get(a);
367             while(strl.more())
368                 a.append(_strToSint(strl.next().getCString(), type));
369             val.set(a);
370             break;
371         }
372         case CIMTYPE_UINT16:
373         {   
374             Array<Uint16> a;
375             val.get(a);
376             while(strl.more())
377                 a.append(_strToUint(strl.next().getCString(), type));
378             val.set(a);
379             break;
380         }
381         case CIMTYPE_SINT16:
382         {   
383             Array<Sint16> a;
384             val.get(a);
385             while(strl.more())
386                 a.append(_strToSint(strl.next().getCString(), type));
387             val.set(a);
388             break;
389         }
390         case CIMTYPE_UINT32:
391         {   
392             Array<Uint32> a;
393             val.get(a);
394             while(strl.more())
395                 a.append(_strToUint(strl.next().getCString(), type));
396             val.set(a);
397             break;
398         }
399         case CIMTYPE_SINT32:
400         {   
401             Array<Sint32> a;
402             val.get(a);
403             while(strl.more())
404                 a.append(_strToSint(strl.next().getCString(), type));
405             val.set(a);
406             break;
407         }
408         case CIMTYPE_UINT64:
409         {   
410             Array<Uint64> a;
411             val.get(a);
412             while(strl.more())
413                 a.append(_strToUint(strl.next().getCString(), type));
414             val.set(a);
415             break;
416         }
417         case CIMTYPE_SINT64:
418         {   
419             Array<Sint64> a;
420             val.get(a);
421             while(strl.more())
422                 a.append(_strToSint(strl.next().getCString(), type));
423             val.set(a);
424             break;
425         }
426         case CIMTYPE_REAL32:
427         {   
428             Array<Real32> a;
429             val.get(a);
430             while(strl.more())
431                 a.append(_strToUint(strl.next().getCString(), type));
432             val.set(a);
433             break;
434         }
435         case CIMTYPE_REAL64:
436         {   
437             Array<Real64> a;
438             val.get(a);
439             while(strl.more())
440                 a.append(_strToSint(strl.next().getCString(), type));
441             val.set(a);
442             break;
443         }
444         case CIMTYPE_STRING:
445         {   
446             Array<String> a;
447             val.get(a);
448             while(strl.more())
449                 a.append(strl.next());
450             val.set(a);
451             break;
452         }
453         case CIMTYPE_DATETIME:
454         {   
455             Array<CIMDateTime> a;
456             val.get(a);
457             while(strl.more())
458                 a.append(_getDateTime(strl.next()));
459             val.set(a);
460             break;
461         }
462     default:
463         cout << "Error: Parse Error. Data type " << cimTypeToString(type) 
464         << " not allowed" << endl;
465         exit(CIMCLI_INPUT_ERR);
466     }
467     return true;
468 }
469
470 /*
471      Create a method parameter from the tokenized information for the
472      method name, value, type, etc.
473 */
474 CIMParamValue _createMethodParamValue(  const CIMName& name,
475     const String& value,
476     const CIMParameter& thisParam,
477     Boolean verbose,
478     const CIMNamespaceName& nameSpace)
479 {
480     CIMType type = thisParam.getType();
481     String paramName = thisParam.getName().getString();
482
483     CIMValue vp(type,thisParam.isArray());
484
485         if (vp.isArray())
486         {
487             _buildArrayValue(value.getCString(), vp );
488             // set the value array into the property value
489             return CIMParamValue(paramName,vp,true);
490         }
491         else
492         {   // scalar
493             CIMValue v;
494             v = _stringToScalarValue(value.getCString(), vp.getType());
495             return CIMParamValue(paramName,v,true);
496         }
497
498     // should never get here
499     return CIMParamValue();
500 }
501
502 /******************************************************************
503 *
504 *   ObjectBuilder Class. Creates instances and parameters from
505 *     name/value pairs received and the corresponding class
506 *     definitions.
507 **
508 *******************************************************************/
509 /*
510     Constructor, sets up a single object with the input pairs
511     and the definition to get the class required for the
512     parsing and entity building.
513 */
514 ObjectBuilder::ObjectBuilder(
515     const Array<String>& inputPairs,
516     CIMClient& client,
517     const CIMNamespaceName& nameSpace,
518     const CIMName& className,
519     const CIMPropertyList& cimPropertyList,
520     Boolean verbose)
521 {
522     // get the class. Exceptions including class_not_found are automatic
523     // not localOnly (Need all properties), get qualifiers and classOrigin
524     // since we can filter them out later
525
526     _verbose = verbose;
527     _className = className;
528     
529     _thisClass = client.getClass(nameSpace, className,
530                         false,true,true,cimPropertyList);
531
532     _nameSpace = nameSpace;
533     if (inputPairs.size() != 0)
534     {
535         /* Here loop starts from 1, since the Class Name is  first parameter
536            and we want only the property name and value here
537         */
538         for (Uint32 i = 1 ; i < inputPairs.size() ; i++)
539         {
540             String name;
541             String value;
542             Uint32 sep;
543
544             // parse each pair and eliminate any illegal returns
545             if ((sep = _parseValuePair(inputPairs[i], name, value)) != ILLEGAL)
546             {
547                 _featureNameList.append(CIMName(name));
548                 _valueStringList.append(value);
549                 _parseType.append(sep);
550             }
551             else
552             {
553                 cerr << "Parse Failed " << inputPairs[i] << endl;
554             }
555         }
556
557         if (_verbose)
558         {
559             // This loop displays all the names and 
560             // property values of the instance
561             for (Uint32 i=0; i < _featureNameList.size(); i++)
562             {
563                 cout << "Name= " << _featureNameList[i].getString()
564                      << ", valueString= " << _valueStringList[i] << endl;
565             }
566         }
567     }
568 }
569
570 ObjectBuilder::~ObjectBuilder()
571 {
572 }
573
574 Array<CIMName> ObjectBuilder::getPropertyList()
575 {
576     return  _featureNameList;
577 }
578
579 const CIMClass ObjectBuilder::getTargetClass()
580 {
581     return _thisClass;
582 }
583
584 CIMObjectPath ObjectBuilder::buildCIMObjectPath()
585 {
586     CIMInstance testInstance = buildInstance(
587         true, true,
588         CIMPropertyList());
589
590     CIMObjectPath thisPath = testInstance.buildPath(_thisClass);
591
592     return thisPath;
593 }
594 /*
595     Parse the input string to separate out the strings for name and
596     value components. The name component must be a CIM_Name and contain
597     only alphanumerics and _ characters. The value is optional.
598     The possible separators are today
599     "=" and "!". and no value component is allowed after the ! separator
600 */
601 Uint32 ObjectBuilder::_parseValuePair(const String& input,
602                                          String& name,
603                                          String& value)
604 {
605     _termType terminator;
606     value = String::EMPTY;
607
608     Boolean separatorFound = false;
609     for (Uint32 i = 0 ; i < input.size() ; i++)
610     {
611         if ((input[i] != '=') && (input[i] !=  '!'))
612         {
613             name.append(input[i]);
614         }
615         else  //separator character found
616         {
617             if (input[i] == '=')
618             {
619                 terminator = VALUE;
620             }
621             if (input[i] == '!')
622             {
623                 terminator = EXCLAM;
624             }
625             separatorFound = true;
626             break;
627         }
628     }
629
630     // separator must be found
631     if (!separatorFound)
632     {
633         cerr << "Parse error: No separator " << input << endl;
634         return ILLEGAL;
635     }
636     // There must be a name entity
637     if (name.size() == 0)
638     {
639         cerr << "Parse error: No name component " << input << endl;
640         return ILLEGAL;
641     }
642     // value component is optional but sets different _termType values
643     if (input.size() == name.size() + 1)
644     {
645         if (terminator == EXCLAM)
646         {
647             return EXCLAM;
648         }
649         else
650         {
651             return NO_VALUE;
652         }
653     }
654     value = input.subString(name.size() + 1, PEG_NOT_FOUND);
655     return VALUE;
656 }
657 /*
658     Build an instance from the information in the ObjectBuilder
659     object.
660 */
661 CIMInstance ObjectBuilder::buildInstance(
662     Boolean includeQualifiers,
663     Boolean includeClassOrigin,
664     const CIMPropertyList& propertyList)
665 {
666     // create the instance skeleton with the defined properties
667     CIMInstance newInstance = _thisClass.buildInstance(
668         includeQualifiers,
669         includeClassOrigin,
670         CIMPropertyList());
671
672     Array<CIMName> myPropertyList;
673     Uint32 propertyPos;
674
675     // Set all the input property values into the instance
676     for (Uint32 index = 0; index < _featureNameList.size(); index++)
677     {
678         if ((propertyPos = _thisClass.findProperty(
679             _featureNameList[index])) == PEG_NOT_FOUND)
680         {
681             cerr << "Warning property Name " 
682                  << _featureNameList[index].getString() 
683                  << " Input value " <<  _valueStringList[index]
684                  << " not in class: " << _thisClass.getClassName().getString()
685                  << " Skipping."
686                  << endl;
687             continue;
688         }
689         
690         // get value for this property from built instance
691
692         CIMProperty ip = newInstance.getProperty(propertyPos);
693         CIMValue iv = ip.getValue();
694
695         // If input not NULL type (ends with =) set the value component
696         // into property.  NULL input sets whatever is in the class into
697         // the instance (done by buildInstance);
698         if (_parseType[index] == EXCLAM)
699         {
700             if (iv.getType() == CIMTYPE_STRING)
701             {
702                 iv.set(String::EMPTY);
703                 ip.setValue(iv);
704             }
705             else
706             {
707                 cerr << "Error: " << ip.getName().getString() 
708                     << "! parameter terminator allowed only on String types "
709                     << endl;
710                 exit(CIMCLI_INPUT_ERR);
711             }
712         }
713         else if (_parseType[index] == VALUE)
714         {
715             if (iv.isArray())
716             {
717                 _cleanArray(_valueStringList[index]);
718                 if (!_buildArrayValue(
719                     _valueStringList[index].getCString(), iv))
720                 {
721                     cerr << "Parse Error: parameter "
722                        << _featureNameList[index].getString() 
723                        << " "
724                        << _valueStringList[index] << endl;
725                     exit(CIMCLI_INPUT_ERR);
726                 }
727             }
728             else  // scalar
729             {  
730                 // Replace property value in new instance
731                 iv = _stringToScalarValue(
732                     _valueStringList[index].getCString(), ip.getType());
733             }
734             ip.setValue(iv);
735         }
736
737         else if(_parseType[index] == NO_VALUE)
738         {
739             // do nothing
740         }
741         else if(_parseType[index] == ILLEGAL)
742         {
743             // do nothing
744         }
745
746         myPropertyList.append(CIMName(_featureNameList[index]));
747     }
748
749     // Delete any properties not on the property list
750     newInstance.filter(
751         includeQualifiers,
752         includeClassOrigin,
753         CIMPropertyList(myPropertyList));
754
755     // Display the Instance if verbose
756     if (_verbose)
757     {
758         cout << "Instance Built" << endl;
759         XmlWriter::printInstanceElement(newInstance, cout);
760     }
761
762     return newInstance;
763 }
764
765 Array<CIMParamValue> ObjectBuilder::buildMethodParameters()
766 {
767     Array<CIMParamValue> params;
768
769     // Find Method
770     Uint32 methodPos;
771     CIMMethod thisClassMethod;
772
773     if ((methodPos = _thisClass.findMethod(_methodName)) == PEG_NOT_FOUND)
774     {
775         cerr << "Error: method " << _methodName.getString()
776             << " Not method in the class " << _className.getString()
777             <<  endl;
778         exit(CIMCLI_INPUT_ERR);
779     }
780     else
781     {
782         thisClassMethod = _thisClass.getMethod(methodPos);
783     }
784
785     // find parameter for each input.
786     for (Uint32 index = 0; index < _featureNameList.size(); index++)
787     {
788         Uint32 parameterPos;
789         if ((parameterPos = thisClassMethod.findParameter(
790             CIMName(_featureNameList[index]))) == PEG_NOT_FOUND)
791         {
792             cerr << "Error: parameter " << _featureNameList[index].getString() 
793                 << " not valid method parameter in class "
794                 << _className.getString()
795                 << endl;
796             exit(CIMCLI_INPUT_ERR);
797         }
798
799         CIMParameter thisParameter = thisClassMethod.getParameter(parameterPos);
800
801         CIMParamValue localParamValue = _createMethodParamValue(
802             _featureNameList[index],
803             _valueStringList[index],
804              thisParameter,
805             _verbose,
806             CIMNamespaceName());
807
808         if (true)
809         {
810             // successful addition of parameter value
811             params.append(localParamValue);
812         }
813         else
814         {
815             // error adding parameter value
816             cerr << "Error: Parsing Error adding parameter"
817                 << _featureNameList[index].getString() << " "
818                 << _valueStringList[index] << endl;
819                 exit(CIMCLI_INPUT_ERR);
820         }
821     }
822     return params;
823 }
824
825 void ObjectBuilder::setMethod(CIMName& name)
826 {
827     _methodName = name;
828 }
829
830 PEGASUS_NAMESPACE_END
831
832 // END_OF_FILE