View Javadoc
1   /*
2     (C) Copyright IBM Corp. 2006, 2012
3   
4     THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE
5     ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE
6     CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT.
7   
8     You can obtain a current copy of the Eclipse Public License from
9     http://www.opensource.org/licenses/eclipse-1.0.php
10  
11    @author : Endre Bak, ebak@de.ibm.com
12   * 
13   * Flag       Date        Prog         Description
14   * -------------------------------------------------------------------------------
15   * 1565892    2006-11-06  ebak         Make SBLIM client JSR48 compliant
16   * 1660756    2007-02-22  ebak         Embedded object support
17   * 1669961    2006-04-16  lupusalex    CIMTypedElement.getType() =>getDataType()
18   * 1736318    2007-06-13  lupusalex    Wrong object path in HTTP header
19   * 2003590    2008-06-30  blaschke-oss Change licensing from CPL to EPL
20   * 2204488 	  2008-10-28  raman_arora  Fix code to remove compiler warnings
21   * 2524131    2009-01-21  raman_arora  Upgrade client to JDK 1.5 (Phase 1)
22   * 2531371    2009-02-10  raman_arora  Upgrade client to JDK 1.5 (Phase 2)
23   * 2763216    2009-04-14  blaschke-oss Code cleanup: visible spelling/grammar errors
24   * 2791860    2009-05-14  blaschke-oss Export instance to mof, wrong syntax
25   * 2797550    2009-06-01  raman_arora  JSR48 compliance - add Java Generics
26   * 3185824    2011-02-18  blaschke-oss Char16 definition includes whitespace
27   * 3510090    2012-03-23  blaschke-oss Fix CIMObjectPath.toString() inconsistencies
28   * 3529151    2012-08-22  blaschke-oss TCK: CIMInstance property APIs include keys from COP
29   */
30  
31  package org.metricshub.wbem.sblim.cimclient.internal.util;
32  
33  /*-
34   * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
35   * WBEM Java Client
36   * ჻჻჻჻჻჻
37   * Copyright 2023 - 2025 MetricsHub
38   * ჻჻჻჻჻჻
39   * Licensed under the Apache License, Version 2.0 (the "License");
40   * you may not use this file except in compliance with the License.
41   * You may obtain a copy of the License at
42   *
43   *      http://www.apache.org/licenses/LICENSE-2.0
44   *
45   * Unless required by applicable law or agreed to in writing, software
46   * distributed under the License is distributed on an "AS IS" BASIS,
47   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
48   * See the License for the specific language governing permissions and
49   * limitations under the License.
50   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
51   */
52  
53  import java.util.Comparator;
54  import java.util.TreeMap;
55  import org.metricshub.wbem.javax.cim.CIMClass;
56  import org.metricshub.wbem.javax.cim.CIMDataType;
57  import org.metricshub.wbem.javax.cim.CIMDateTime;
58  import org.metricshub.wbem.javax.cim.CIMElement;
59  import org.metricshub.wbem.javax.cim.CIMFlavor;
60  import org.metricshub.wbem.javax.cim.CIMInstance;
61  import org.metricshub.wbem.javax.cim.CIMMethod;
62  import org.metricshub.wbem.javax.cim.CIMObjectPath;
63  import org.metricshub.wbem.javax.cim.CIMParameter;
64  import org.metricshub.wbem.javax.cim.CIMProperty;
65  import org.metricshub.wbem.javax.cim.CIMQualifiedElementInterface;
66  import org.metricshub.wbem.javax.cim.CIMQualifier;
67  import org.metricshub.wbem.javax.cim.CIMQualifierType;
68  import org.metricshub.wbem.javax.cim.CIMScope;
69  import org.metricshub.wbem.javax.cim.CIMTypedElement;
70  import org.metricshub.wbem.javax.cim.CIMValuedElement;
71  
72  /**
73   * Class MOF is responsible for helping MOF String generation.
74   */
75  public class MOF {
76  	/**
77  	 * CLASS
78  	 */
79  	public static final String CLASS = "class";
80  
81  	/**
82  	 * TRUE
83  	 */
84  	public static final String TRUE = "true";
85  
86  	/**
87  	 * FALSE
88  	 */
89  	public static final String FALSE = "false";
90  
91  	/**
92  	 * NULL
93  	 */
94  	public static final String NULL = "null";
95  
96  	/**
97  	 * ENABLEOVERRIDE
98  	 */
99  	public static final String ENABLEOVERRIDE = "enableoverride";
100 
101 	/**
102 	 * DISABLEOVERRIDE
103 	 */
104 	public static final String DISABLEOVERRIDE = "disableOverride";
105 
106 	/**
107 	 * RESTRICTED
108 	 */
109 	public static final String RESTRICTED = "restricted";
110 
111 	/**
112 	 * TOSUBCLASS
113 	 */
114 	public static final String TOSUBCLASS = "tosubclass";
115 
116 	/**
117 	 * TRANSLATABLE
118 	 */
119 	public static final String TRANSLATABLE = "translatable";
120 
121 	/**
122 	 * DT_BOOL
123 	 */
124 	public static final String DT_BOOL = "boolean";
125 
126 	/**
127 	 * DT_CHAR16
128 	 */
129 	public static final String DT_CHAR16 = "char16";
130 
131 	/**
132 	 * DT_DATETIME
133 	 */
134 	public static final String DT_DATETIME = "datetime";
135 
136 	/**
137 	 * DT_REAL32
138 	 */
139 	public static final String DT_REAL32 = "real32";
140 
141 	/**
142 	 * DT_REAL64
143 	 */
144 	public static final String DT_REAL64 = "real64";
145 
146 	/**
147 	 * DT_SINT16
148 	 */
149 	public static final String DT_SINT16 = "sint16";
150 
151 	/**
152 	 * DT_SINT32
153 	 */
154 	public static final String DT_SINT32 = "sint32";
155 
156 	/**
157 	 * DT_SINT64
158 	 */
159 	public static final String DT_SINT64 = "sint64";
160 
161 	/**
162 	 * DT_SINT8
163 	 */
164 	public static final String DT_SINT8 = "sint8";
165 
166 	/**
167 	 * DT_STR
168 	 */
169 	public static final String DT_STR = "string";
170 
171 	/**
172 	 * DT_UINT16
173 	 */
174 	public static final String DT_UINT16 = "uint16";
175 
176 	/**
177 	 * DT_UINT32
178 	 */
179 	public static final String DT_UINT32 = "uint32";
180 
181 	/**
182 	 * DT_UINT64
183 	 */
184 	public static final String DT_UINT64 = "uint64";
185 
186 	/**
187 	 * DT_UINT8
188 	 */
189 	public static final String DT_UINT8 = "uint8";
190 
191 	/**
192 	 * INVALID
193 	 */
194 	public static final String INVALID = "invalid";
195 
196 	/**
197 	 * REF
198 	 */
199 	public static final String REF = "ref";
200 
201 	/**
202 	 * INSTOF
203 	 */
204 	public static final String INSTOF = "instance of ";
205 
206 	/**
207 	 * QUALIFIER
208 	 */
209 	public static final String QUALIFIER = "qualifier";
210 
211 	/**
212 	 * SCOPE
213 	 */
214 	public static final String SCOPE = "scope";
215 
216 	/**
217 	 * ANY
218 	 */
219 	public static final String ANY = "any";
220 
221 	/**
222 	 * ASSOCIATION
223 	 */
224 	public static final String ASSOCIATION = "association";
225 
226 	/**
227 	 * INDICATION
228 	 */
229 	public static final String INDICATION = "indication";
230 
231 	/**
232 	 * METHOD
233 	 */
234 	public static final String METHOD = "method";
235 
236 	/**
237 	 * PARAMETER
238 	 */
239 	public static final String PARAMETER = "parameter";
240 
241 	/**
242 	 * PROPERTY
243 	 */
244 	public static final String PROPERTY = "property";
245 
246 	/**
247 	 * REFERENCE
248 	 */
249 	public static final String REFERENCE = "reference";
250 
251 	/**
252 	 * INSTANCE
253 	 */
254 	public static final String INSTANCE = "instance";
255 
256 	/**
257 	 * NAMESPACE
258 	 */
259 	public static final String NAMESPACE = "namespace";
260 
261 	/**
262 	 * INDENT
263 	 */
264 	public static final String INDENT = "  ";
265 
266 	/**
267 	 * EMPTY
268 	 */
269 	public static final String EMPTY = "";
270 
271 	// TODO: formatter problem: " -> &quot; Is it necessary in <pre> section?
272 
273 	/**
274 	 * <pre>
275 	 *        classDeclaration		=	[ qualifierList ] CLASS className [ superClass ]
276 	 *       					&quot;{&quot; *classFeature &quot;}&quot; &quot;;&quot;
277 	 *        classFeature			=	propertyDeclaration | methodDeclaration
278 	 *
279 	 *        superClass				=	&quot;:&quot; className
280 	 * </pre>
281 	 *
282 	 * @param pCl
283 	 * @param pInd
284 	 * @return the MOF string
285 	 */
286 	public static String classDeclaration(CIMClass pCl, String pInd) {
287 		// for associator classes an other function should be called ?
288 		StringBuffer buf = new StringBuffer();
289 		buf.append(qualifierList(pCl, pInd));
290 		buf.append(CLASS + ' ' + pCl.getName() + ' ');
291 		String supCl = pCl.getSuperClassName();
292 		if (supCl != null) buf.append(':' + supCl + ' ');
293 		buf.append("{\n");
294 		// *classFeature
295 		for (int i = 0; i < pCl.getPropertyCount(); i++) buf.append(propertyDeclaration(pCl.getProperty(i), pInd + INDENT));
296 		for (int i = 0; i < pCl.getMethodCount(); i++) buf.append(methodDeclaration(pCl.getMethod(i), pInd + INDENT));
297 		buf.append("};");
298 		return buf.toString();
299 	}
300 
301 	/**
302 	 * instanceDeclaration = [ qualifierList ] INSTANCE OF className [ alias ]
303 	 * "{" 1*valueInitializer "}" ";"
304 	 *
305 	 * @param pInst
306 	 * @param pInd
307 	 * @return the MOF string
308 	 */
309 	public static String instanceDeclaration(CIMInstance pInst, String pInd) {
310 		// TODO: Why is there qualifierList in the BNF? CIMInstance doesn't have
311 		// qualifiers
312 		// TODO: What is the alias? How to use?
313 		StringBuffer buf = new StringBuffer();
314 		buf.append(pInd + INSTOF + pInst.getClassName() + " {\n");
315 		// Add all properties in prop array
316 		for (int i = 0; i < pInst.getPropertyCount(); i++) buf.append(
317 			valueInitializer(pInst.getProperty(i), pInd + INDENT)
318 		);
319 		// Add keys that are NOT also in prop array
320 		CIMProperty<?>[] keys = pInst.getKeys();
321 		for (int i = 0; i < keys.length; i++) {
322 			if (pInst.getProperty(keys[i].getName()) == null) {
323 				buf.append(valueInitializer(keys[i], pInd + INDENT));
324 			}
325 		}
326 		buf.append(pInd + "};");
327 		return buf.toString();
328 	}
329 
330 	/**
331 	 * <pre>
332 	 *        methodDeclaration		=	[ qualifierList ] dataType methodName
333 	 *       							&quot;(&quot; [ parameterList ] &quot;)&quot; &quot;;&quot;
334 	 * </pre>
335 	 *
336 	 * @param pMethod
337 	 * @param pInd
338 	 * @return the MOF string
339 	 */
340 	public static String methodDeclaration(CIMMethod<?> pMethod, String pInd) {
341 		StringBuffer buf = new StringBuffer();
342 		buf.append(qualifierList(pMethod, pInd));
343 		buf.append(pInd + dataType(pMethod) + ' ' + pMethod.getName() + '(');
344 		if (pMethod.getParameters().length > 0) {
345 			buf.append('\n');
346 			buf.append(parameterList(pMethod, pInd + INDENT) + '\n' + pInd);
347 		}
348 		buf.append(");\n");
349 		return buf.toString();
350 	}
351 
352 	/**
353 	 * parameter
354 	 *
355 	 * @param pParam
356 	 *            - CIMParameter
357 	 * @param pInd
358 	 * @return the MOF string
359 	 */
360 	public static String parameter(CIMParameter<?> pParam, String pInd) {
361 		return typedElement(pParam, pInd);
362 	}
363 
364 	/**
365 	 *
366 	 * typedElement = [ qualifierList ] (dataType|objectRef) parameterName [
367 	 * array ]
368 	 *
369 	 * @param pTypedElement
370 	 * @param pInd
371 	 * @return the MOF string
372 	 */
373 	public static String typedElement(CIMTypedElement pTypedElement, String pInd) {
374 		return (
375 			qualifierList(pTypedElement, pInd) +
376 			pInd +
377 			dataType(pTypedElement) +
378 			' ' +
379 			pTypedElement.getName() +
380 			array(pTypedElement)
381 		);
382 	}
383 
384 	/**
385 	 * <pre>
386 	 *        valuedElement 		=	typedElement [ defaultValue ] &quot;;&quot;
387 	 *        defaultValue			=	&quot;=&quot; initializer
388 	 * </pre>
389 	 *
390 	 * @param pValuedElement
391 	 * @param pInd
392 	 * @return the MOF string
393 	 */
394 	public static String valuedElement(CIMValuedElement<?> pValuedElement, String pInd) {
395 		StringBuffer buf = new StringBuffer(typedElement(pValuedElement, pInd));
396 		if (pValuedElement.getValue() != null) buf.append(defaultValue(pValuedElement, pInd));
397 		buf.append(';');
398 		return buf.toString();
399 	}
400 
401 	/**
402 	 * <pre>
403 	 *        qualifierList			=	&quot;[&quot; qualifier *( &quot;,&quot; qualifier ) &quot;]&quot;
404 	 * </pre>
405 	 *
406 	 * @param pElement
407 	 * @param pInd
408 	 * @return the MOF string +newLine if qualifiers present or empty string
409 	 */
410 	public static String qualifierList(CIMElement pElement, String pInd) {
411 		if (!(pElement instanceof CIMQualifiedElementInterface)) return "";
412 		CIMQualifiedElementInterface qualified = (CIMQualifiedElementInterface) pElement;
413 		if (qualified.getQualifierCount() == 0) return "";
414 		StringBuffer buf = new StringBuffer(pInd + '[');
415 		for (int i = 0; i < qualified.getQualifierCount(); i++) {
416 			if (i > 0) buf.append(",\n" + pInd);
417 			buf.append(qualifier(qualified.getQualifier(i)));
418 		}
419 		buf.append("]\n");
420 		return buf.toString();
421 	}
422 
423 	/**
424 	 * <pre>
425 	 *        qualifierDeclaration	=	QUALIFIER qualifierName qualifierType scope
426 	 *        							[ defaultFlavor ] &quot;;&quot;
427 	 * </pre>
428 	 *
429 	 * @param pQType
430 	 * @return the MOF string
431 	 */
432 	public static String qualifierDeclaration(CIMQualifierType<?> pQType) {
433 		return (
434 			QUALIFIER +
435 			' ' +
436 			pQType.getName() +
437 			' ' +
438 			dataType(pQType) +
439 			' ' +
440 			scope(pQType.getScope()) +
441 			' ' +
442 			flavor(pQType.getFlavor()) +
443 			';'
444 		);
445 	}
446 
447 	/**
448 	 * <pre>
449 	 *        scope		=	&quot;,&quot; SCOPE &quot;(&quot; metaElement *( &quot;,&quot; metaElement ) &quot;)&quot;
450 	 *        metaElement	=	CLASS | ASSOCIATION | INDICATION | QUALIFIER
451 	 *       					PROPERTY | REFERENCE | METHOD | PARAMETER | ANY
452 	 * </pre>
453 	 *
454 	 * @param pScopes
455 	 * @return the MOF string
456 	 */
457 	public static String scope(int pScopes) {
458 		ScopeBuffer buf = new ScopeBuffer(pScopes);
459 		buf.append(SCOPE + "(");
460 		if (pScopes == CIMScope.ANY) {
461 			buf.append(ANY);
462 		} else {
463 			buf.append(CIMScope.ASSOCIATION, ASSOCIATION);
464 			buf.append(CIMScope.CLASS, CLASS);
465 			buf.append(CIMScope.INDICATION, INDICATION);
466 			buf.append(CIMScope.METHOD, METHOD);
467 			buf.append(CIMScope.PARAMETER, PARAMETER);
468 			buf.append(CIMScope.PROPERTY, PROPERTY);
469 			buf.append(CIMScope.REFERENCE, REFERENCE);
470 		}
471 		buf.append(')');
472 		return buf.toString();
473 	}
474 
475 	/**
476 	 * OVERRIDABLE (true|false) 'true' -> DISABLEOVERRIDE=false TOSUBCLASS
477 	 * (true|false) 'true' -> RESTRICTED=false TOINSTANCE (true|false) 'false'
478 	 * TRANSLATABLE (true|false) 'false' -> TRANSLTE=false
479 	 */
480 	public static final int DEF_FLAVOR = 0;
481 
482 	/**
483 	 * <pre>
484 	 * flavor = ENABLEOVERRIDE | DISABLEOVERRIDE | RESTRICTED | TOSUBCLASS | TRANSLATABLE
485 	 * </pre>
486 	 *
487 	 * @param flavor
488 	 * @return the MOF string
489 	 */
490 	public static String flavor(int flavor) {
491 		// flavors = { DISABLEOVERRIDE, RESTRICTED, TRANSLATE }
492 		// !DISABLEOVERRIDE = ENABLEOVERRIDE
493 		// !RESTRICTED = TOSUBCLASS
494 		// !TRANSLATE = ?
495 		StringBuffer buf = new StringBuffer();
496 		buf.append(((flavor & CIMFlavor.DISABLEOVERRIDE) > 0 ? DISABLEOVERRIDE : ENABLEOVERRIDE));
497 		buf.append(' ' + ((flavor & CIMFlavor.RESTRICTED) > 0 ? RESTRICTED : TOSUBCLASS));
498 		if ((flavor & CIMFlavor.TRANSLATE) > 0) buf.append(' ' + TRANSLATABLE);
499 		return buf.toString();
500 	}
501 
502 	/**
503 	 * <pre>
504 	 *        qualifier				=	qualifierName [ qualifierParameter ] [ &quot;:&quot; 1*flavor ]
505 	 * </pre>
506 	 *
507 	 * @param pQuali
508 	 * @return the MOF string
509 	 */
510 	public static String qualifier(CIMQualifier<?> pQuali) {
511 		StringBuffer buf = new StringBuffer();
512 		buf.append(pQuali.getName());
513 		// TODO: review. Why qualifierParameter is optional?
514 		if (pQuali.getDataType() != null && pQuali.getValue() != null) buf.append(qualifierParameter(pQuali));
515 		// FIXME: why flavors are optional
516 		// if (pQuali.getFlavor() != 0)
517 		buf.append(':' + flavor(pQuali.getFlavor()));
518 		return buf.toString();
519 	}
520 
521 	/**
522 	 * <pre>
523 	 *        propertyDeclaration	=	typedElement [ defaultValue ] &quot;;&quot;
524 	 *        defaultValue			=	&quot;=&quot; initializer
525 	 * </pre>
526 	 *
527 	 * @param pProp
528 	 * @param pInd
529 	 * @return the MOF string
530 	 */
531 	public static String propertyDeclaration(CIMProperty<?> pProp, String pInd) {
532 		return valuedElement(pProp, pInd) + '\n';
533 	}
534 
535 	/**
536 	 * <pre>
537 	 *        valueInitializer		= [ qualifierList ] ( propertyName | referenceName ) &quot;=&quot;
538 	 * 									initializer &quot;;&quot;
539 	 * </pre>
540 	 *
541 	 * @param pProp
542 	 * @param pInd
543 	 * @return the MOF string
544 	 */
545 	public static String valueInitializer(CIMProperty<?> pProp, String pInd) {
546 		Object value = pProp.getValue();
547 		if (value != null) {
548 			return qualifierList(pProp, pInd) + pInd + pProp.getName() + " = " + initializer(value, pInd) + ";\n";
549 		}
550 		return "";
551 	}
552 
553 	/**
554 	 * <pre>
555 	 * dataType = DT_UINT8 | DT_SINT8 | DT_UINT16 | DT_SINT16 | DT_UINT32 | DT_SINT32 | DT_UINT64
556 	 * 		| DT_SINT64 | DT_REAL32 | DT_REAL64 | DT_CHAR16 | DT_STR | DT_BOOL | DT_DATETIME
557 	 * </pre>
558 	 *
559 	 * Additionally it handles reference types too.
560 	 *
561 	 * <pre>
562 	 *        objectType	=	objectRef
563 	 *        objectRef		=	className REF
564 	 * </pre>
565 	 *
566 	 * @param pType
567 	 * @return the MOF string
568 	 */
569 	public static String dataType(CIMDataType pType) {
570 		if (pType.getType() == CIMDataType.REFERENCE) return pType.getRefClassName() + ' ' + REF;
571 		String res = DATATYPE_MAP.get(pType);
572 		if (res == null) {
573 			String msg = "This function cannot handle typeCode: " + pType.getType() + "!";
574 			// TODO: tracing
575 			throw new IllegalArgumentException(msg);
576 		}
577 		return res;
578 	}
579 
580 	/**
581 	 * @param pTypedElement
582 	 * @return the MOF string
583 	 * @see #dataType(CIMDataType)
584 	 */
585 	public static String dataType(CIMTypedElement pTypedElement) {
586 		return dataType(pTypedElement.getDataType());
587 	}
588 
589 	/**
590 	 * objectHandle
591 	 *
592 	 * @param pPath
593 	 * @return the Untyped MOF String
594 	 */
595 	public static String objectHandle(CIMObjectPath pPath) {
596 		return objectHandle(pPath, false, false);
597 	}
598 
599 	/**
600 	 * objectHandle
601 	 *
602 	 * @param pPath
603 	 *            The path
604 	 * @param pTyped
605 	 *            If true the URI is typed
606 	 * @param pLocal
607 	 *            If true the path is local (omitting scheme, host and port)
608 	 * @return the URI string
609 	 */
610 	public static String objectHandle(CIMObjectPath pPath, boolean pTyped, boolean pLocal) {
611 		StringBuffer buf = new StringBuffer();
612 		if (!pLocal) {
613 			if (pPath.getScheme() != null) buf.append(pPath.getScheme() + ':');
614 			if (pPath.getHost() != null) buf.append("//" + pPath.getHost());
615 			if (pPath.getPort() != null) buf.append(':' + pPath.getPort());
616 		}
617 		if (pPath.getNamespace() != null) {
618 			if (!pLocal) buf.append('/');
619 			buf.append(pPath.getNamespace());
620 		}
621 		if (pTyped) buf.append(pathType(pPath)); else if (pPath.getObjectName() != null && buf.length() > 0) {
622 			buf.append(':');
623 		}
624 		if (pPath.getObjectName() != null) {
625 			buf.append(pPath.getObjectName() + keyValuePairs(pPath.getKeys(), pTyped, EMPTY));
626 		}
627 		return buf.toString();
628 	}
629 
630 	/**
631 	 * objectHandleAsRef
632 	 *
633 	 * @param pPath
634 	 * @return the Untyped MOF String
635 	 */
636 	public static String objectHandleAsRef(CIMObjectPath pPath) {
637 		return objectHandleAsRef(pPath, false);
638 	}
639 
640 	/**
641 	 * objectHandleAsRef
642 	 *
643 	 * @param pPath
644 	 * @param pTyped
645 	 * @return the MOF String
646 	 */
647 	public static String objectHandleAsRef(CIMObjectPath pPath, boolean pTyped) {
648 		StringBuffer buf = new StringBuffer();
649 		if (pPath.getNamespace() != null) buf.append(pPath.getNamespace());
650 		if (pTyped) buf.append(pathType(pPath));
651 		if (pPath.getObjectName() != null) {
652 			if (!pTyped && pPath.getNamespace() != null) buf.append(':');
653 			buf.append(pPath.getObjectName());
654 			buf.append(keyValuePairs(pPath.getKeys(), pTyped, EMPTY));
655 		}
656 		return buf.toString();
657 	}
658 
659 	/**
660 	 * <pre>
661 	 * constantValue = integerValue | realValue | charValue | stringValue | booleanValue | nullValue
662 	 * // | dateTimeValue | objectHandle
663 	 * </pre>
664 	 *
665 	 * @param pValuedElement
666 	 * @param pInd
667 	 * @return the MOF string
668 	 */
669 	public static String constantValue(CIMValuedElement<?> pValuedElement, String pInd) {
670 		return constantValue(pValuedElement.getValue(), pInd);
671 	}
672 
673 	/**
674 	 * constantValue
675 	 *
676 	 * @param pObj
677 	 * @param pTyped
678 	 * @param pInd
679 	 * @return the MOF string
680 	 * @see #constantValue(CIMValuedElement, String)
681 	 */
682 	public static String constantValue(Object pObj, boolean pTyped, String pInd) {
683 		String valStr;
684 		if (pObj == null) {
685 			valStr = NULL;
686 		} else if (pObj instanceof CIMObjectPath) {
687 			valStr = Util.quote(objectHandleAsRef((CIMObjectPath) pObj, pTyped));
688 		} else if (pObj instanceof String) {
689 			valStr = Util.quote(pObj.toString());
690 		} else if (pObj instanceof CIMDateTime) {
691 			valStr = Util.quote(pObj.toString());
692 		} else if (pObj instanceof Character) {
693 			valStr = charValue((Character) pObj);
694 		} else if (pObj instanceof Boolean) {
695 			valStr = ((Boolean) pObj).booleanValue() ? TRUE : FALSE;
696 		} else if (pObj instanceof CIMInstance) {
697 			valStr = '\n' + instanceDeclaration((CIMInstance) pObj, pInd) + '\n';
698 		} else if (pObj instanceof CIMClass) {
699 			valStr = '\n' + classDeclaration((CIMClass) pObj, pInd) + '\n' + pInd;
700 		} else {
701 			valStr = pObj.toString();
702 		}
703 		if (pTyped) {
704 			String typeStr;
705 			if (pObj instanceof CIMObjectPath) {
706 				typeStr = REFERENCE;
707 			} else {
708 				CIMDataType type = CIMDataType.getDataType(pObj);
709 				typeStr = dataType(type);
710 			}
711 			return "(" + typeStr + ")" + valStr;
712 		}
713 		return valStr;
714 	}
715 
716 	/**
717 	 * constantValue
718 	 *
719 	 * @param pObj
720 	 * @param pInd
721 	 * @return the untyped MOF String
722 	 */
723 	public static String constantValue(Object pObj, String pInd) {
724 		return constantValue(pObj, false, pInd);
725 	}
726 
727 	private static String pathType(CIMObjectPath pPath) {
728 		String typeInfo;
729 		if (pPath.getKeys().length > 0) {
730 			typeInfo = INSTANCE;
731 		} else if (pPath.getObjectName() != null) {
732 			typeInfo = CLASS;
733 		} else {
734 			typeInfo = NAMESPACE;
735 		}
736 		return "/(" + typeInfo + ")";
737 	}
738 
739 	private static String keyValuePairs(CIMProperty<?>[] pKeys, boolean pTyped, String pInd) {
740 		StringBuffer buf = new StringBuffer();
741 		if (pKeys != null && pKeys.length > 0) {
742 			buf.append('.');
743 			for (int i = 0; i < pKeys.length; i++) {
744 				CIMProperty<?> key = pKeys[i];
745 				if (i != 0) buf.append(',');
746 				buf.append(key.getName() + '=' + constantValue(key.getValue(), pTyped, pInd));
747 			}
748 		}
749 		return buf.toString();
750 	}
751 
752 	/**
753 	 * <pre>
754 	 *        parameterList		=	parameter *( &quot;,&quot; parameter )
755 	 *        parameter			=	[ qualifierList ] (dataType|objectRef) parameterName [ array ]
756 	 * </pre>
757 	 *
758 	 * @param pMethod
759 	 * @return the MOF string
760 	 */
761 	private static String parameterList(CIMMethod<?> pMethod, String pInd) {
762 		StringBuffer buf = new StringBuffer();
763 		CIMParameter<?>[] params = pMethod.getParameters();
764 		for (int i = 0; i < params.length; i++) {
765 			if (i > 0) buf.append(",\n");
766 			buf.append(parameter(params[i], pInd));
767 		}
768 		return buf.toString();
769 	}
770 
771 	private static class ScopeBuffer {
772 		private StringBuffer buf = new StringBuffer();
773 
774 		private int iScopes;
775 
776 		private int iCnt = 0;
777 
778 		/**
779 		 * Ctor.
780 		 *
781 		 * @param pScopes
782 		 */
783 		public ScopeBuffer(int pScopes) {
784 			this.iScopes = pScopes;
785 		}
786 
787 		/**
788 		 * append
789 		 *
790 		 * @param pStr
791 		 */
792 		public void append(String pStr) {
793 			this.buf.append(pStr);
794 		}
795 
796 		/**
797 		 * append
798 		 *
799 		 * @param pChar
800 		 */
801 		public void append(char pChar) {
802 			this.buf.append(pChar);
803 		}
804 
805 		/**
806 		 * append
807 		 *
808 		 * @param pMask
809 		 * @param pName
810 		 */
811 		public void append(int pMask, String pName) {
812 			if ((this.iScopes & pMask) > 0) {
813 				if (this.iCnt++ > 0) this.buf.append(',');
814 				this.buf.append(pName);
815 			}
816 		}
817 
818 		/**
819 		 * @see java.lang.Object#toString()
820 		 */
821 		@Override
822 		public String toString() {
823 			return this.buf.toString();
824 		}
825 	}
826 
827 	/**
828 	 * <pre>
829 	 *        qualifierParameter		=	&quot;(&quot; constantValue &quot;)&quot; | arrayInitializer
830 	 * </pre>
831 	 *
832 	 * @param pQuali
833 	 * @return the MOF string
834 	 */
835 	private static String qualifierParameter(CIMQualifier<?> pQuali) {
836 		return pQuali.getDataType().isArray() ? arrayInitializer(pQuali, EMPTY) : '(' + constantValue(pQuali, EMPTY) + ')';
837 	}
838 
839 	private static String charValue(Character pChar) {
840 		char ch = pChar.charValue();
841 		if (ch < 32) {
842 			return "'\\x" + Integer.toString(ch, 16) + '\'';
843 		}
844 		return "'" + ch + '\'';
845 	}
846 
847 	/**
848 	 * <pre>
849 	 *        arrayInitializer		=	&quot;{&quot; constantValue*( &quot;,&quot; constantValue)&quot;}&quot;
850 	 * </pre>
851 	 *
852 	 * @param pValue
853 	 * @param pInd
854 	 * @return the MOF string or empty string if the array has no elements or
855 	 *         null
856 	 */
857 	private static String arrayInitializer(Object pValue, String pInd) {
858 		if (pValue == null) return "";
859 		Object[] vA = (Object[]) pValue;
860 		StringBuffer buf = new StringBuffer();
861 		buf.append('{');
862 		for (int i = 0; i < vA.length; i++) {
863 			if (i > 0) buf.append(", ");
864 			buf.append(constantValue(vA[i], pInd));
865 		}
866 		buf.append('}');
867 		return buf.toString();
868 	}
869 
870 	/**
871 	 * @param pValuedElement
872 	 * @param pInd
873 	 * @return the MOF string or empty string if the value is null
874 	 * @see #arrayInitializer(Object, String)
875 	 */
876 	private static String arrayInitializer(CIMValuedElement<?> pValuedElement, String pInd) {
877 		return arrayInitializer(pValuedElement.getValue(), pInd);
878 	}
879 
880 	/**
881 	 * array = "[" [positiveDecimalValue] "]"
882 	 *
883 	 * @param pType
884 	 * @return the MOF string or empty string if not array type
885 	 */
886 	private static String array(CIMDataType pType) {
887 		if (!pType.isArray()) return "";
888 		if (pType.getSize() > 0) return "[" + pType.getSize() + ']';
889 		return "[]";
890 	}
891 
892 	/**
893 	 * @param pTypedElement
894 	 * @return the MOF string or empty string if not array type
895 	 * @see #array(CIMDataType)
896 	 */
897 	private static String array(CIMTypedElement pTypedElement) {
898 		return array(pTypedElement.getDataType());
899 	}
900 
901 	private static final TreeMap<CIMDataType, String> DATATYPE_MAP = new TreeMap<CIMDataType, String>(
902 		new Comparator<Object>() {
903 
904 			public int compare(Object pO1, Object pO2) {
905 				CIMDataType t1 = (CIMDataType) pO1;
906 				CIMDataType t2 = (CIMDataType) pO2;
907 				return t1.getType() - t2.getType();
908 			}
909 		}
910 	);
911 
912 	static {
913 		DATATYPE_MAP.put(CIMDataType.UINT8_T, DT_UINT8);
914 		DATATYPE_MAP.put(CIMDataType.UINT16_T, DT_UINT16);
915 		DATATYPE_MAP.put(CIMDataType.UINT32_T, DT_UINT32);
916 		DATATYPE_MAP.put(CIMDataType.UINT64_T, DT_UINT64);
917 		DATATYPE_MAP.put(CIMDataType.SINT8_T, DT_SINT8);
918 		DATATYPE_MAP.put(CIMDataType.SINT16_T, DT_SINT16);
919 		DATATYPE_MAP.put(CIMDataType.SINT32_T, DT_SINT32);
920 		DATATYPE_MAP.put(CIMDataType.SINT64_T, DT_SINT64);
921 		DATATYPE_MAP.put(CIMDataType.REAL32_T, DT_REAL32);
922 		DATATYPE_MAP.put(CIMDataType.REAL64_T, DT_REAL64);
923 		DATATYPE_MAP.put(CIMDataType.CHAR16_T, DT_CHAR16);
924 		DATATYPE_MAP.put(CIMDataType.STRING_T, DT_STR);
925 		DATATYPE_MAP.put(CIMDataType.BOOLEAN_T, DT_BOOL);
926 		DATATYPE_MAP.put(CIMDataType.DATETIME_T, DT_DATETIME);
927 		// FIXME: What to do with those types which are not specified by MOF's
928 		// BNF?
929 		DATATYPE_MAP.put(CIMDataType.INVALID_T, INVALID);
930 		// FIXME: What is the string representation of OBJECT?
931 		DATATYPE_MAP.put(CIMDataType.OBJECT_T, "object");
932 		DATATYPE_MAP.put(CIMDataType.CLASS_T, CLASS);
933 	}
934 
935 	/**
936 	 * defaultValue = "=" initializer
937 	 *
938 	 * @param pValuedElement
939 	 * @param pInd
940 	 * @return the MOF string or empty string if the value is null
941 	 */
942 	private static String defaultValue(CIMValuedElement<?> pValuedElement, String pInd) {
943 		Object value = pValuedElement.getValue();
944 		if (value == null) return "";
945 		return " = " + initializer(value, pInd);
946 	}
947 
948 	/**
949 	 * <pre>
950 	 * initializer = constantValue | arrayInitializer | referenceInitializer
951 	 * // referenceInitializer is handled by constantValue
952 	 * </pre>
953 	 *
954 	 * @param pValue
955 	 * @param pInd
956 	 * @return the MOF string
957 	 */
958 	private static String initializer(Object pValue, String pInd) {
959 		if (pValue instanceof Object[]) return arrayInitializer(pValue, pInd);
960 		return constantValue(pValue, pInd);
961 	}
962 }