1 karl 1.1.2.2 //%LICENSE////////////////////////////////////////////////////////////////
2 //
3 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 karl 1.1.2.2 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //////////////////////////////////////////////////////////////////////////
29 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include <Pegasus/Common/Exception.h>
33 #include <Pegasus/Common/Tracer.h>
34 #include <Pegasus/Common/CommonUTF.h>
35 #include <Pegasus/Common/Constants.h>
36 #include <Pegasus/Common/StringConversion.h>
37 #include <Pegasus/Common/ArrayInternal.h>
38
39 #if defined(PEGASUS_HAS_ICU) && defined(PEGASUS_INDFORMATTER_USE_ICU)
40 # include <unicode/locid.h>
41 # include <unicode/datefmt.h>
42 # include <unicode/unistr.h>
43 karl 1.1.2.2 #endif
44
45 #include "IndicationFormatter.h"
46
47 PEGASUS_NAMESPACE_BEGIN
48
49 ///////////////////////////////////////////////////////////////////////////////
50 //
51 // CIMValueLocalizer
52 //
53 ///////////////////////////////////////////////////////////////////////////////
54
55 class CIMValueLocalizer
56 {
57 public:
58
59 /**
60 Constructs a CIMValueLocalizer object. The CIMValueLocalizer can be
61 used to localize a CIMValue string based on a specified
62 ContentLanguageList. Localization is possible only if the
63 ContentLanguageList includes no more than one language tag.
64 karl 1.1.2.2
65 @param contentLangs A ContentLanguageList containing a LanguageTag
66 with which to perform localization.
67 */
68 CIMValueLocalizer(const ContentLanguageList& contentLangs);
69 ~CIMValueLocalizer();
70
71 String getLocalizedValue(Boolean value) const
72 {
73 return _localizeBoolean(value);
74 }
75
76 String getLocalizedValue(Uint8 value) const
77 {
78 return getLocalizedValue(Uint32(value));
79 }
80
81 String getLocalizedValue(Sint8 value) const
82 {
83 return getLocalizedValue(Sint32(value));
84 }
85 karl 1.1.2.2
86 String getLocalizedValue(Uint16 value) const
87 {
88 return getLocalizedValue(Uint32(value));
89 }
90
91 String getLocalizedValue(Sint16 value) const
92 {
93 return getLocalizedValue(Sint32(value));
94 }
95
96 String getLocalizedValue(Uint32 value) const
97 {
98 Uint32 outputLength = 0;
99 char buffer[22];
100 const char* output = Uint32ToString(buffer, value, outputLength);
101 return String(output, outputLength);
102 }
103
104 String getLocalizedValue(Sint32 value) const
105 {
106 karl 1.1.2.2 Uint32 outputLength = 0;
107 char buffer[22];
108 const char* output = Sint32ToString(buffer, value, outputLength);
109 return String(output, outputLength);
110 }
111
112 String getLocalizedValue(Uint64 value) const
113 {
114 Uint32 outputLength = 0;
115 char buffer[22];
116 const char* output = Uint64ToString(buffer, value, outputLength);
117 return String(output, outputLength);
118 }
119
120 String getLocalizedValue(Sint64 value) const
121 {
122 Uint32 outputLength = 0;
123 char buffer[22];
124 const char* output = Sint64ToString(buffer, value, outputLength);
125 return String(output, outputLength);
126 }
127 karl 1.1.2.2
128 String getLocalizedValue(Real32 value) const
129 {
130 char buffer[32];
131 sprintf(buffer, "%.7e", value);
132 return String(buffer);
133 }
134
135 String getLocalizedValue(Real64 value) const
136 {
137 char buffer[32];
138 sprintf(buffer, "%.16e", value);
139 return String(buffer);
140 }
141
142 String getLocalizedValue(Char16 value) const
143 {
144 return String(&value, 1);
145 }
146
147 String getLocalizedValue(const String& value) const
148 karl 1.1.2.2 {
149 return value;
150 }
151
152 String getLocalizedValue(const CIMDateTime& value) const
153 {
154 return _localizeDateTime(value);
155 }
156
157 String getLocalizedValue(const CIMObjectPath& value) const
158 {
159 return value.toString();
160 }
161
162 String getLocalizedValue(const CIMObject& value) const
163 {
164 return value.toString();
165 }
166
167 String getLocalizedValue(const CIMInstance& value) const
168 {
169 karl 1.1.2.2 return CIMObject(value).toString();
170 }
171
172 private:
173
174 CIMValueLocalizer(const CIMValueLocalizer&);
175 CIMValueLocalizer& operator=(const CIMValueLocalizer&);
176
177 String _localizeDateTime(const CIMDateTime& dateTimeValue) const;
178 String _localizeBoolean(Boolean booleanValue) const;
179
180 Boolean canLocalize;
181 #if defined(PEGASUS_HAS_ICU) && defined(PEGASUS_INDFORMATTER_USE_ICU)
182 Locale locale;
183 #endif
184 };
185
186 CIMValueLocalizer::CIMValueLocalizer(const ContentLanguageList& contentLangs)
187 {
188 canLocalize = false;
189
190 karl 1.1.2.2 #if defined(PEGASUS_HAS_ICU) && defined(PEGASUS_INDFORMATTER_USE_ICU)
191 if (InitializeICU::initICUSuccessful())
192 {
193 if (contentLangs.size() == 0)
194 {
195 // No language specified; use the default.
196 locale = Locale::getDefault();
197 canLocalize = true;
198 }
199 else if (contentLangs.size() == 1)
200 {
201 LanguageTag languageTag = contentLangs.getLanguageTag(0);
202 locale = Locale(
203 (const char*) languageTag.getLanguage.getCString(),
204 (const char*) languageTag.getCountry.getCString(),
205 (const char*) languageTag.getVariant.getCString());
206 canLocalize = !locale.isBogus();
207 }
208 else
209 {
210 // ContentLanguageList has multiple language tags; do not localize.
211 karl 1.1.2.2 }
212 }
213 #endif
214 }
215
216 CIMValueLocalizer::~CIMValueLocalizer()
217 {
218 }
219
220 String CIMValueLocalizer::_localizeDateTime(
221 const CIMDateTime& dateTimeValue) const
222 {
223 #if defined(PEGASUS_HAS_ICU) && defined(PEGASUS_INDFORMATTER_USE_ICU)
224 PEG_METHOD_ENTER(TRC_IND_FORMATTER, "CIMValueLocalizer::_localizeDateTime");
225
226 if (canLocalize)
227 {
228 // The CIMDateTime epoch begins 1/1/0000 (12 am Jan 1, 1BCE).
229 // The ICU epoch begins 1/1/1970 (1 January 1970 0:00 UTC).
230
231 const CIMDateTime EPOCH1970 = CIMDateTime("19700101000000.000000+000");
232 karl 1.1.2.2 UDate icuDateTimeMillisecs = (Sint64)
233 (dateTimeValue.toMicroSeconds() - EPOCH1970.toMicroSeconds())/1000;
234
235 // Use a medium length DATE/TIME format (e.g., Jan 12, 1982 3:30:32pm)
236 AutoPtr<DateFormat> fmt;
237
238 try
239 {
240 if (locale == 0)
241 {
242 fmt.reset(DateFormat::createDateTimeInstance(
243 DateFormat::MEDIUM, DateFormat::MEDIUM));
244 }
245 else
246 {
247 fmt.reset(DateFormat::createDateTimeInstance(
248 DateFormat::MEDIUM, DateFormat::MEDIUM, locale));
249 }
250 }
251 catch (...)
252 {
253 karl 1.1.2.2 PEG_TRACE_CSTRING(TRC_IND_FORMATTER, Tracer::LEVEL2,
254 "Caught exception from DateFormat::createDateTimeInstance");
255
256 PEG_METHOD_EXIT();
257 return dateTimeValue.toString();
258 }
259
260 if (fmt.get() == 0)
261 {
262 PEG_TRACE_CSTRING(TRC_IND_FORMATTER, Tracer::LEVEL2,
263 "Memory allocation error creating DateTime instance.");
264 PEG_METHOD_EXIT();
265 return dateTimeValue.toString();
266 }
267
268 // Format the Date and Time
269 UErrorCode status = U_ZERO_ERROR;
270 UnicodeString dateTimeUniStr;
271 fmt->format(icuDateTimeMillisecs, dateTimeUniStr, status);
272
273 if (U_FAILURE(status))
274 karl 1.1.2.2 {
275 PEG_METHOD_EXIT();
276 return dateTimeValue.toString();
277 }
278
279 // convert UnicodeString to char *
280 char dateTimeBuffer[256];
281 String datetimeStr;
282
283 // Copy the contents of the string into dateTimeBuffer
284 Uint32 strLen = dateTimeUniStr.extract(
285 0, sizeof(dateTimeBuffer), dateTimeBuffer);
286
287 if (strLen >= sizeof(dateTimeBuffer))
288 {
289 // There is not enough space in dateTimeBuffer
290 char* extractedStr = new char[strLen + 1];
291 strLen = dateTimeUniStr.extract(0, strLen + 1, extractedStr);
292 datetimeStr = extractedStr;
293 delete [] extractedStr;
294 }
295 karl 1.1.2.2 else
296 {
297 datetimeStr = dateTimeBuffer;
298 }
299
300 PEG_METHOD_EXIT();
301 return datetimeStr;
302 }
303
304 PEG_METHOD_EXIT();
305 #endif
306
307 return dateTimeValue.toString();
308 }
309
310 String CIMValueLocalizer::_localizeBoolean(Boolean booleanValue) const
311 {
312 PEG_METHOD_ENTER(TRC_IND_FORMATTER, "CIMValueLocalizer::_localizeBoolean");
313
314 if (canLocalize)
315 {
316 karl 1.1.2.2 if (booleanValue)
317 {
318 MessageLoaderParms parms(
319 "Common.IndicationFormatter._MSG_BOOLEAN_TRUE",
320 "true");
321
322 PEG_METHOD_EXIT();
323 return MessageLoader::getMessage(parms);
324 }
325 else
326 {
327 MessageLoaderParms parms(
328 "Common.IndicationFormatter._MSG_BOOLEAN_FALSE",
329 "false");
330
331 PEG_METHOD_EXIT();
332 return MessageLoader::getMessage(parms);
333 }
334 }
335
336 PEG_METHOD_EXIT();
337 karl 1.1.2.2 return booleanValue ? "true" : "false";
338 }
339
340
341 ///////////////////////////////////////////////////////////////////////////////
342 //
343 // IndicationFormatter
344 //
345 ///////////////////////////////////////////////////////////////////////////////
346
347 template<class T>
348 void appendArrayValue(
349 String& buffer,
350 const CIMValue& value,
351 Uint32 arrayIndex,
352 const CIMValueLocalizer& cimValueLocalizer)
353 {
354 PEGASUS_ASSERT(value.isArray());
355
356 Array<T> arrayValue;
357 value.get(arrayValue);
358 karl 1.1.2.2
359 // Empty brackets (e.g. []), gets all values of the array
360 if (arrayIndex == PEG_NOT_FOUND)
361 {
362 buffer.append("[");
363
364 for (Uint32 i = 0, arraySize = arrayValue.size(); i < arraySize; i++)
365 {
366 buffer.append(cimValueLocalizer.getLocalizedValue(arrayValue[i]));
367 if (i < arraySize - 1)
368 {
369 buffer.append(",");
370 }
371 }
372
373 buffer.append("]");
374 }
375 else
376 {
377 buffer.append(
378 cimValueLocalizer.getLocalizedValue(arrayValue[arrayIndex]));
379 karl 1.1.2.2 }
380 }
381
382 void IndicationFormatter::validateTextFormat(
383 const String& textStr,
384 const CIMClass& indicationClass,
385 const Array<String>& textFormatParams)
386 {
387 PEG_METHOD_ENTER(TRC_IND_FORMATTER,
388 "IndicationFormatter::validateTextFormat");
389
390 String textFormatStr = textStr;
391 Uint32 leftBrace = textFormatStr.find("{");
392 Uint32 rightBrace;
393
394 do
395 {
396 String textFormatSubStr;
397
398 if (leftBrace != PEG_NOT_FOUND)
399 {
400 karl 1.1.2.2 // Do not expect a right brace before the left
401 // brace. e.g An invalid text format string could be:
402 // "Indication occurred at 2, datetime} with
403 // identify ID {3, string}"
404
405 textFormatSubStr = textFormatStr.subString(0, leftBrace);
406
407 Uint32 rightBrace2 = textFormatSubStr.find("}");
408 if (rightBrace2 != PEG_NOT_FOUND)
409 {
410 textFormatSubStr = textFormatStr.subString(
411 0, (rightBrace2 + 1));
412 MessageLoaderParms parms(
413 "Common.IndicationFormatter."
414 "_MSG_INVALID_SYNTAX_OF_FOR_PROPERTY",
415 "Invalid syntax at $0 in property $1",
416 textFormatSubStr,
417 _PROPERTY_TEXTFORMAT.getString());
418
419 PEG_METHOD_EXIT();
420 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_INVALID_PARAMETER, parms);
421 karl 1.1.2.2 }
422
423 // expect right brace
424 textFormatStr = textFormatStr.subString(leftBrace+1);
425 rightBrace = textFormatStr.find("}");
426
427 // Do not expect a left brace between left and right
428 // braces. e.g A text string: "Indication occurred
429 // at {2, datetime with identify ID {3, string}" is
430 // an invalid format.
431
432 if (rightBrace != PEG_NOT_FOUND)
433 {
434 textFormatSubStr.clear();
435 textFormatSubStr = textFormatStr.subString(0, rightBrace);
436
437 Uint32 leftBrace2 = textFormatSubStr.find("{");
438 if (leftBrace2 != PEG_NOT_FOUND)
439 {
440 textFormatSubStr = textFormatStr.subString(
441 0, (leftBrace2 + 1));
442 karl 1.1.2.2 MessageLoaderParms parms(
443 "Common.IndicationFormatter."
444 "_MSG_INVALID_SYNTAX_OF_FOR_PROPERTY",
445 "Invalid syntax at $0 in property $1",
446 textFormatSubStr,
447 _PROPERTY_TEXTFORMAT.getString());
448
449 PEG_METHOD_EXIT();
450 throw PEGASUS_CIM_EXCEPTION_L(
451 CIM_ERR_INVALID_PARAMETER, parms);
452 }
453
454 String propertyParam;
455 String propertyTypeStr;
456 String propertyIndexStr;
457 Uint32 comma = textFormatSubStr.find(",");
458
459 if (comma == PEG_NOT_FOUND)
460 {
461 // A dynamic content can have format either
462 // {index} or {index[x]}
463 karl 1.1.2.2 propertyParam = textFormatSubStr;
464 propertyTypeStr = String::EMPTY;
465 }
466 else
467 {
468 // A dynamic content can have format either
469 // {index, type} or {index[x], type}
470 propertyParam = textFormatSubStr.subString(0, comma);
471 propertyTypeStr = textFormatSubStr.subString(comma +1);
472 }
473
474 Uint32 leftBracket = propertyParam.find("[");
475 Uint32 rightBracket = propertyParam.find("]");
476 Boolean isArray = false;
477
478 // A dynamic content has syntax either {index} or {index, type}
479 if (leftBracket == PEG_NOT_FOUND)
480 {
481 // there is no left bracket, do not expect a right bracket
482 if (rightBracket != PEG_NOT_FOUND)
483 {
484 karl 1.1.2.2 textFormatSubStr = textFormatStr.subString(
485 0, (rightBracket + 1));
486 MessageLoaderParms parms(
487 "Common.IndicationFormatter."
488 "_MSG_INVALID_SYNTAX_OF_FOR_PROPERTY",
489 "Invalid syntax at $0 in property $1",
490 textFormatSubStr,
491 _PROPERTY_TEXTFORMAT.getString());
492
493 PEG_METHOD_EXIT();
494 throw PEGASUS_CIM_EXCEPTION_L(
495 CIM_ERR_INVALID_PARAMETER, parms);
496 }
497
498 propertyIndexStr = propertyParam;
499 isArray = false;
500 }
501 // A dynamic content has syntax either
502 // {index[]} or {index[], type}
503 else
504 {
505 karl 1.1.2.2 // there is a left bracket, expect a right bracket
506 if (rightBracket == PEG_NOT_FOUND)
507 {
508 MessageLoaderParms parms(
509 "Common.IndicationFormatter."
510 "_MSG_INVALID_SYNTAX_OF_FOR_PROPERTY",
511 "Invalid syntax at $0 in property $1",
512 textFormatSubStr,
513 _PROPERTY_TEXTFORMAT.getString());
514
515 PEG_METHOD_EXIT();
516 throw PEGASUS_CIM_EXCEPTION_L(
517 CIM_ERR_INVALID_PARAMETER, parms);
518 }
519
520 propertyIndexStr = propertyParam.subString(0, leftBracket);
521 isArray = true;
522 }
523
524 Uint32 propertyIndex = _parseIndex(propertyIndexStr);
525
526 karl 1.1.2.2 // check the property index
527 if (propertyIndex >= textFormatParams.size())
528 {
529 // property index is out of bounds
530 MessageLoaderParms parms(
531 "Common.IndicationFormatter."
532 "_MSG_INDEX_IS_OUT_OF_BOUNDS",
533 "The value of index $0 in property $1 is out of bounds",
534 propertyIndex,
535 _PROPERTY_TEXTFORMATPARAMETERS.getString());
536
537 PEG_METHOD_EXIT();
538 throw PEGASUS_CIM_EXCEPTION_L(
539 CIM_ERR_INVALID_PARAMETER, parms);
540 }
541
542 if (propertyTypeStr != String::EMPTY)
543 {
544 _validatePropertyType(indicationClass,
545 textFormatParams[propertyIndex],
546 propertyTypeStr, isArray);
547 karl 1.1.2.2 }
548
549 textFormatStr = textFormatStr.subString(rightBrace+1);
550 }
551 else // no right brace
552 {
553 MessageLoaderParms parms(
554 "Common.IndicationFormatter."
555 "_MSG_INVALID_SYNTAX_OF_FOR_PROPERTY",
556 "Invalid syntax at $0 in property $1",
557 textFormatSubStr,
558 _PROPERTY_TEXTFORMAT.getString());
559
560 PEG_METHOD_EXIT();
561 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_INVALID_PARAMETER, parms);
562 }
563 }
564 else // no left brace
565 {
566 // does not expect right brace
567 rightBrace = textFormatStr.find("}");
568 karl 1.1.2.2
569 if (rightBrace != PEG_NOT_FOUND)
570 {
571 textFormatSubStr = textFormatStr.subString(0, rightBrace + 1);
572 MessageLoaderParms parms(
573 "Common.IndicationFormatter."
574 "_MSG_INVALID_SYNTAX_OF_FOR_PROPERTY",
575 "Invalid syntax at $0 in property $1",
576 textFormatSubStr,
577 _PROPERTY_TEXTFORMAT.getString());
578
579 PEG_METHOD_EXIT();
580 throw PEGASUS_CIM_EXCEPTION_L(
581 CIM_ERR_INVALID_PARAMETER, parms);
582 }
583
584 break;
585 }
586
587 leftBrace = textFormatStr.find("{");
588 } while (textFormatStr.size() > 0);
589 karl 1.1.2.2
590 PEG_METHOD_EXIT();
591 }
592
593 inline Boolean _isSpace(Char16 c)
594 {
595 return (c == ' ') || (c == '\t') || (c == '\r') || (c == '\n');
596 }
597
598 void IndicationFormatter::_trim(String& s)
599 {
600 while (s.size() && _isSpace(s[s.size()-1]))
601 {
602 s.remove(s.size() - 1);
603 }
604
605 while (s.size() && _isSpace(s[0]))
606 {
607 s.remove(0, 1);
608 }
609 }
610 karl 1.1.2.2
611 void IndicationFormatter::_validatePropertyType(
612 const CIMClass& indicationClass,
613 const String& propertyParam,
614 const String& typeStr,
615 const Boolean& isArray)
616 {
617 PEG_METHOD_ENTER(TRC_IND_FORMATTER,
618 "IndicationFormatter::_validatePropertyType");
619
620 String propertyTypeStr = typeStr;
621
622 Array<String> validPropertyTypes;
623 validPropertyTypes.append("boolean");
624 validPropertyTypes.append("uint8");
625 validPropertyTypes.append("sint8");
626 validPropertyTypes.append("uint16");
627 validPropertyTypes.append("sint16");
628 validPropertyTypes.append("uint32");
629 validPropertyTypes.append("sint32");
630 validPropertyTypes.append("uint64");
631 karl 1.1.2.2 validPropertyTypes.append("sint64");
632 validPropertyTypes.append("real32");
633 validPropertyTypes.append("real64");
634 validPropertyTypes.append("char16");
635 validPropertyTypes.append("string");
636 validPropertyTypes.append("datetime");
637 validPropertyTypes.append("reference");
638
639 propertyTypeStr.toLower();
640 _trim(propertyTypeStr);
641
642 //
643 // Checks if the provided property type is a valid type
644 //
645 if (!(Contains(validPropertyTypes, propertyTypeStr)))
646 {
647 // the provided property type is not valid type
648 MessageLoaderParms parms(
649 "Common.IndicationFormatter."
650 "_MSG_INVALID_TYPE_OF_FOR_PROPERTY",
651 "Invalid property type of $0 in property $1",
652 karl 1.1.2.2 propertyTypeStr,
653 _PROPERTY_TEXTFORMAT.getString());
654
655 PEG_METHOD_EXIT();
656 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_INVALID_PARAMETER, parms);
657 }
658
659 for (Uint32 i = 0; i < indicationClass.getPropertyCount(); i++)
660 {
661 CIMName propertyName = indicationClass.getProperty(i).getName();
662
663 if (String::equalNoCase(propertyParam, propertyName.getString()))
664 {
665 // get the property type;
666 CIMType propertyType = indicationClass.getProperty(i).getType();
667
668 // Check if the property is an array type
669 if ((isArray && !(indicationClass.getProperty(i).isArray())) ||
670 (!isArray && indicationClass.getProperty(i).isArray()))
671 {
672 MessageLoaderParms parms(
673 karl 1.1.2.2 "Common.IndicationFormatter."
674 "_MSG_PROPERTY_IS_NOT_AN_ARRAY_TYPE",
675 "The property $0 is not an array type",
676 propertyName.getString());
677
678 PEG_METHOD_EXIT();
679 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_INVALID_PARAMETER, parms);
680 }
681
682 // property type matches
683 if (String::equalNoCase(
684 propertyTypeStr, cimTypeToString(propertyType)))
685 {
686 break;
687 }
688
689 MessageLoaderParms parms(
690 "Common.IndicationFormatter."
691 "_MSG_MISS_MATCHED_TYPE_OF_FOR_PROPERTY",
692 "The provided property type of $0 in $1 does not match "
693 "the property type $2",
694 karl 1.1.2.2 propertyTypeStr,
695 cimTypeToString(propertyType),
696 _PROPERTY_TEXTFORMAT.getString());
697
698 PEG_METHOD_EXIT();
699 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_INVALID_PARAMETER, parms);
700 }
701 }
702
703 PEG_METHOD_EXIT();
704 }
705
706 void IndicationFormatter::validateTextFormatParameters(
707 const CIMPropertyList& propertyList,
708 const CIMClass& indicationClass,
709 const Array<String>& textFormatParams)
710 {
711 PEG_METHOD_ENTER(TRC_IND_FORMATTER,
712 "IndicationFormatter::validateTextFormatParameters");
713
714 Array<String> indicationClassProperties;
715 karl 1.1.2.2
716 if (propertyList.isNull())
717 {
718 // All the properties are selected
719 for (Uint32 i = 0; i < indicationClass.getPropertyCount(); i++)
720 {
721 indicationClassProperties.append(
722 indicationClass.getProperty(i).getName().getString());
723 }
724 }
725 else
726 {
727 // Partial properties are selected
728 Array<CIMName> propertyNames = propertyList.getPropertyNameArray();
729
730 for (Uint32 j = 0; j < propertyNames.size(); j++)
731 {
732 indicationClassProperties.append(propertyNames[j].getString());
733 }
734 }
735
736 karl 1.1.2.2 // check if the textFormatParams is contained in the
737 // indicationClassProperties
738 for (Uint32 k = 0; k < textFormatParams.size(); k++)
739 {
740 if (!Contains(indicationClassProperties, textFormatParams[k]))
741 {
742 // The property name in TextFormatParameters is not
743 // included in the select clause of the associated filter query
744 MessageLoaderParms parms(
745 "Common.IndicationFormatter."
746 "_MSG_MISS_MATCHED_PROPERTY_NAME",
747 "The property name $0 in $1 does not match the properties "
748 "in the select clause",
749 textFormatParams[k],
750 _PROPERTY_TEXTFORMATPARAMETERS.getString());
751
752 PEG_METHOD_EXIT();
753 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_INVALID_PARAMETER, parms);
754 }
755 }
756
757 karl 1.1.2.2 PEG_METHOD_EXIT();
758 }
759
760 Uint32 IndicationFormatter::_parseIndex(const String& indexStr)
761 {
762 Uint32 index = PEG_NOT_FOUND;
763 char dummy[2];
764 int numConversions =
765 sscanf(indexStr.getCString(), "%u%1s", &index, dummy);
766
767 if ((numConversions != 1) || (index == PEG_NOT_FOUND))
768 {
769 MessageLoaderParms parms(
770 "IndicationFormatter.IndicationFormatter._MSG_INVALID_INDEX",
771 "Invalid index string '$0'",
772 indexStr);
773
774 throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_INVALID_PARAMETER, parms);
775 }
776
777 return index;
778 karl 1.1.2.2 }
779
780 String IndicationFormatter::getFormattedIndText(
781 const CIMInstance& subscription,
782 const CIMInstance& indication,
783 const ContentLanguageList& contentLangs)
784 {
785 PEG_METHOD_ENTER (TRC_IND_FORMATTER,
786 "IndicationFormatter::getFormattedIndText");
787
788 String indicationText;
789 String textFormat;
790 CIMValue textFormatValue;
791 CIMValue textFormatParamsValue;
792
793 Array<String> textFormatParams;
794
795 // get TextFormat from subscription
796 Uint32 textFormatPos = subscription.findProperty(_PROPERTY_TEXTFORMAT);
797
798 // if the property TextFormat is not found,
799 karl 1.1.2.2 // indication is constructed with default format
800 if (textFormatPos == PEG_NOT_FOUND)
801 {
802 indicationText = _formatDefaultIndicationText(indication, contentLangs);
803 }
804 else
805 {
806 textFormatValue = subscription.getProperty(textFormatPos).getValue();
807
808 // if the value of textFormat is NULL,
809 // indication is constructed with default format
810 if (textFormatValue.isNull())
811 {
812 indicationText =
813 _formatDefaultIndicationText(indication, contentLangs);
814 }
815 else
816 {
817 // get TextFormatParameters from subscription
818 Uint32 textFormatParamsPos = subscription.findProperty(
819 _PROPERTY_TEXTFORMATPARAMETERS);
820 karl 1.1.2.2
821 if (textFormatParamsPos != PEG_NOT_FOUND)
822 {
823 textFormatParamsValue = subscription.getProperty(
824 textFormatParamsPos).getValue();
825 }
826
827 // constructs indication with specified format
828 if ((textFormatValue.getType() == CIMTYPE_STRING) &&
829 !(textFormatValue.isArray()))
830 {
831 textFormatValue.get(textFormat);
832 if (!textFormatParamsValue.isNull())
833 {
834 if ((textFormatParamsValue.getType() == CIMTYPE_STRING) &&
835 (textFormatParamsValue.isArray()))
836 {
837 textFormatParamsValue.get(textFormatParams);
838 }
839 }
840
841 karl 1.1.2.2 indicationText = _formatIndicationText(
842 textFormat,
843 textFormatParams,
844 indication,
845 contentLangs);
846 }
847 else
848 {
849 indicationText =
850 _formatDefaultIndicationText(indication, contentLangs);
851 }
852 }
853 }
854
855 PEG_METHOD_EXIT();
856 return indicationText;
857 }
858
859 String IndicationFormatter::_formatDefaultIndicationText(
860 const CIMInstance& indication,
861 const ContentLanguageList& contentLangs)
862 karl 1.1.2.2 {
863 PEG_METHOD_ENTER (TRC_IND_FORMATTER,
864 "IndicationFormatter::_formatDefaultIndicationText");
865
866 String indicationStr = "Indication (default format):";
867
868 CIMValueLocalizer cimValueLocalizer(contentLangs);
869
870 for (Uint32 i = 0, n = indication.getPropertyCount(); i < n; i++)
871 {
872 if (i > 0)
873 {
874 indicationStr.append(", ");
875 }
876
877 CIMConstProperty property = indication.getProperty(i);
878 CIMValue propertyValue = property.getValue();
879
880 indicationStr.append(property.getName().getString());
881 indicationStr.append(" = ");
882
883 karl 1.1.2.2 if (!propertyValue.isNull())
884 {
885 if (propertyValue.isArray())
886 {
887 indicationStr.append(_getArrayValues(
888 propertyValue, PEG_NOT_FOUND, contentLangs));
889 }
890 else // value is not an array
891 {
892 CIMType type = propertyValue.getType();
893
894 if (type == CIMTYPE_DATETIME)
895 {
896 CIMDateTime dateTimeValue;
897 propertyValue.get(dateTimeValue);
898 indicationStr.append(
899 cimValueLocalizer.getLocalizedValue(dateTimeValue));
900 }
901 else if (type == CIMTYPE_BOOLEAN)
902 {
903 Boolean booleanValue;
904 karl 1.1.2.2 propertyValue.get(booleanValue);
905 indicationStr.append(
906 cimValueLocalizer.getLocalizedValue(booleanValue));
907 }
908 else
909 {
910 indicationStr.append(propertyValue.toString());
911 }
912 }
913 }
914 else
915 {
916 indicationStr.append("NULL");
917 }
918 }
919
920 PEG_METHOD_EXIT();
921 return indicationStr;
922 }
923
924 String IndicationFormatter::_formatIndicationText(
925 karl 1.1.2.2 const String& textFormat,
926 const Array<String>& textFormatParams,
927 const CIMInstance& indication,
928 const ContentLanguageList& contentLangs)
929 {
930 PEG_METHOD_ENTER(TRC_IND_FORMATTER,
931 "IndicationFormatter::_formatIndicationText");
932
933 String indicationText;
934 String indicationFormat = textFormat;
935
936 // Parsing the specified indication text format.
937 // As an example, a format string for a UPS AlertIndication
938 // could be defined as follows: A {4, string} UPS Alert was
939 // detected on the device {6[1]}.
940 Uint32 leftBrace;
941 while ((leftBrace = indicationFormat.find("{")) != PEG_NOT_FOUND)
942 {
943 // Append the text up to the left brace
944 indicationText.append(indicationFormat.subString(0, leftBrace));
945 indicationFormat = indicationFormat.subString(leftBrace+1);
946 karl 1.1.2.2 Uint32 rightBrace = indicationFormat.find("}");
947
948 // expecting a right brace
949 if (rightBrace != PEG_NOT_FOUND)
950 {
951 // gets property index which is inside braces.
952 // The supported formats are: {index} or {index, type}
953 // or {index[x]} or {index[x], type}
954 String propertyParam = indicationFormat.subString(0, rightBrace);
955 Uint32 comma = propertyParam.find(",");
956
957 // A dynamic content has syntax {index, type} or {index[x], type}
958 if (comma != PEG_NOT_FOUND)
959 {
960 propertyParam = propertyParam.subString(0, comma);
961 }
962
963 String propertyIndexStr;
964 String arrayIndexStr;
965 Uint32 leftBracket = propertyParam.find("[");
966
967 karl 1.1.2.2 if (leftBracket == PEG_NOT_FOUND)
968 {
969 // A dynamic content has syntax {index} or {index, type}
970 propertyIndexStr = propertyParam;
971 }
972 else
973 {
974 // A dynamic content has syntax {index[x]} or {index[x], type}
975 propertyIndexStr = propertyParam.subString(0, leftBracket);
976 propertyParam = propertyParam.subString(leftBracket);
977
978 Uint32 rightBracket = propertyParam.find("]");
979 arrayIndexStr = propertyParam.subString(1, rightBracket-1);
980 }
981
982 String propertyValue;
983
984 try
985 {
986 Uint32 propertyIndex = _parseIndex(propertyIndexStr);
987 Uint32 arrayIndex = PEG_NOT_FOUND;
988 karl 1.1.2.2
989 if (arrayIndexStr.size())
990 {
991 arrayIndex = _parseIndex(arrayIndexStr);
992 }
993
994 if (propertyIndex >= textFormatParams.size())
995 {
996 // Property index is out of range
997 propertyValue = "UNKNOWN";
998 }
999 else
1000 {
1001 // get indication property value
1002 propertyValue = _getIndPropertyValue(
1003 textFormatParams[propertyIndex],
1004 arrayIndex,
1005 indication,
1006 contentLangs);
1007 }
1008 }
1009 karl 1.1.2.2 catch (CIMException& c)
1010 {
1011 PEG_TRACE((TRC_IND_FORMATTER, Tracer::LEVEL2,
1012 "Exception at parsing indication property: %s",
1013 (const char*)c.getMessage().getCString()));
1014 propertyValue = "UNKNOWN";
1015 }
1016
1017 indicationText.append(propertyValue);
1018 }
1019
1020 indicationFormat = indicationFormat.subString(rightBrace+1);
1021 }
1022
1023 indicationText.append(indicationFormat);
1024
1025 PEG_METHOD_EXIT();
1026 return indicationText;
1027 }
1028
1029 String IndicationFormatter::_getIndPropertyValue(
1030 karl 1.1.2.2 const String& propertyName,
1031 Uint32 arrayIndex,
1032 const CIMInstance& indication,
1033 const ContentLanguageList& contentLangs)
1034 {
1035 PEG_METHOD_ENTER(TRC_IND_FORMATTER,
1036 "IndicationFormatter::_getIndPropertyValue");
1037
1038 Uint32 pos = indication.findProperty(propertyName);
1039
1040 if (pos == PEG_NOT_FOUND)
1041 {
1042 PEG_METHOD_EXIT();
1043 return "UNKNOWN";
1044 }
1045
1046 CIMConstProperty property = indication.getProperty(pos);
1047 CIMValue propertyValue = property.getValue();
1048
1049 if (propertyValue.isNull())
1050 {
1051 karl 1.1.2.2 PEG_METHOD_EXIT();
1052 return "NULL";
1053 }
1054
1055 if (propertyValue.isArray())
1056 {
1057 PEG_METHOD_EXIT();
1058 return _getArrayValues(propertyValue, arrayIndex, contentLangs);
1059 }
1060
1061 // Value is not an array
1062
1063 CIMValueLocalizer cimValueLocalizer(contentLangs);
1064
1065 if (propertyValue.getType() == CIMTYPE_DATETIME)
1066 {
1067 CIMDateTime dateTimeValue;
1068 propertyValue.get(dateTimeValue);
1069 PEG_METHOD_EXIT();
1070 return cimValueLocalizer.getLocalizedValue(dateTimeValue);
1071 }
1072 karl 1.1.2.2
1073 if (propertyValue.getType() == CIMTYPE_BOOLEAN)
1074 {
1075 Boolean booleanValue;
1076 propertyValue.get(booleanValue);
1077 PEG_METHOD_EXIT();
1078 return cimValueLocalizer.getLocalizedValue(booleanValue);
1079 }
1080
1081 PEG_METHOD_EXIT();
1082 return propertyValue.toString();
1083 }
1084
1085 String IndicationFormatter::_getArrayValues(
1086 const CIMValue& value,
1087 Uint32 arrayIndex,
1088 const ContentLanguageList& contentLangs)
1089 {
1090 PEG_METHOD_ENTER(TRC_IND_FORMATTER, "IndicationFormatter::_getArrayValues");
1091
1092 if ((arrayIndex != PEG_NOT_FOUND) &&
1093 karl 1.1.2.2 (arrayIndex >= value.getArraySize()))
1094 {
1095 // Array index is out of range
1096 PEG_METHOD_EXIT();
1097 return "UNKNOWN";
1098 }
1099
1100 String arrayValues;
1101 CIMValueLocalizer cimValueLocalizer(contentLangs);
1102
1103 switch (value.getType())
1104 {
1105 case CIMTYPE_UINT8:
1106 {
1107 appendArrayValue<Uint8>(
1108 arrayValues, value, arrayIndex, cimValueLocalizer);
1109 break;
1110 }
1111
1112 case CIMTYPE_SINT8:
1113 {
1114 karl 1.1.2.2 appendArrayValue<Sint8>(
1115 arrayValues, value, arrayIndex, cimValueLocalizer);
1116 break;
1117 }
1118
1119 case CIMTYPE_UINT16:
1120 {
1121 appendArrayValue<Uint16>(
1122 arrayValues, value, arrayIndex, cimValueLocalizer);
1123 break;
1124 }
1125
1126 case CIMTYPE_SINT16:
1127 {
1128 appendArrayValue<Sint16>(
1129 arrayValues, value, arrayIndex, cimValueLocalizer);
1130 break;
1131 }
1132
1133 case CIMTYPE_UINT32:
1134 {
1135 karl 1.1.2.2 appendArrayValue<Uint32>(
1136 arrayValues, value, arrayIndex, cimValueLocalizer);
1137 break;
1138 }
1139
1140 case CIMTYPE_SINT32:
1141 {
1142 appendArrayValue<Sint32>(
1143 arrayValues, value, arrayIndex, cimValueLocalizer);
1144 break;
1145 }
1146
1147 case CIMTYPE_UINT64:
1148 {
1149 appendArrayValue<Uint64>(
1150 arrayValues, value, arrayIndex, cimValueLocalizer);
1151 break;
1152 }
1153
1154 case CIMTYPE_SINT64:
1155 {
1156 karl 1.1.2.2 appendArrayValue<Sint64>(
1157 arrayValues, value, arrayIndex, cimValueLocalizer);
1158 break;
1159 }
1160
1161 case CIMTYPE_REAL32:
1162 {
1163 appendArrayValue<Real32>(
1164 arrayValues, value, arrayIndex, cimValueLocalizer);
1165 break;
1166 }
1167
1168 case CIMTYPE_REAL64:
1169 {
1170 appendArrayValue<Real64>(
1171 arrayValues, value, arrayIndex, cimValueLocalizer);
1172 break;
1173 }
1174
1175 case CIMTYPE_BOOLEAN:
1176 {
1177 karl 1.1.2.2 appendArrayValue<Boolean>(
1178 arrayValues, value, arrayIndex, cimValueLocalizer);
1179 break;
1180 }
1181
1182 case CIMTYPE_CHAR16:
1183 {
1184 appendArrayValue<Char16>(
1185 arrayValues, value, arrayIndex, cimValueLocalizer);
1186 break;
1187 }
1188
1189 case CIMTYPE_STRING:
1190 {
1191 appendArrayValue<String>(
1192 arrayValues, value, arrayIndex, cimValueLocalizer);
1193 break;
1194 }
1195
1196 case CIMTYPE_DATETIME:
1197 {
1198 karl 1.1.2.2 appendArrayValue<CIMDateTime>(
1199 arrayValues, value, arrayIndex, cimValueLocalizer);
1200 break;
1201 }
1202
1203 case CIMTYPE_REFERENCE:
1204 {
1205 appendArrayValue<CIMObjectPath>(
1206 arrayValues, value, arrayIndex, cimValueLocalizer);
1207 break;
1208 }
1209
1210 case CIMTYPE_OBJECT:
1211 {
1212 appendArrayValue<CIMObject>(
1213 arrayValues, value, arrayIndex, cimValueLocalizer);
1214 break;
1215 }
1216
1217 case CIMTYPE_INSTANCE:
1218 {
1219 karl 1.1.2.2 appendArrayValue<CIMInstance>(
1220 arrayValues, value, arrayIndex, cimValueLocalizer);
1221 break;
1222 }
1223
1224 default:
1225 {
1226 PEG_TRACE((TRC_IND_FORMATTER, Tracer::LEVEL2,
1227 "Unknown CIMType: %u",
1228 value.getType()));
1229
1230 arrayValues.append("UNKNOWN");
1231 break;
1232 }
1233 }
1234
1235 PEG_METHOD_EXIT();
1236 return arrayValues;
1237 }
1238
1239 PEGASUS_NAMESPACE_END
|