View Javadoc
1   /*
2     CIMXMLParserImpl.java
3   
4     (C) Copyright IBM Corp. 2005, 2013
5   
6     THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE
7     ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE
8     CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT.
9   
10    You can obtain a current copy of the Eclipse Public License from
11    http://www.opensource.org/licenses/eclipse-1.0.php
12  
13    @author : Roberto Pineiro, IBM, roberto.pineiro@us.ibm.com
14   * @author : Chung-hao Tan, IBM, chungtan@us.ibm.com
15   * 
16   * 
17   * Change History
18   * Flag       Date        Prog         Description
19   *------------------------------------------------------------------------------- 
20   * 1464860    2006-05-15  lupusalex    No default value for VALUETYPE assumed
21   * 1535756    2006-08-07  lupusalex    Make code warning free
22   * 1547910    2006-09-05  ebak         parseIMETHODCALL() CIMObjectPath parsing problem
23   * 1547908    2006-09-05  ebak         parseKEYBINDING() creates incorrect reference type
24   * 1545915    2006-09-05  ebak         Wrong parsing of IMETHODCALL request
25   * 1660756    2007-03-02  ebak         Embedded object support
26   * 1689085    2007-04-10  ebak         Embedded object enhancements for Pegasus
27   * 1669961    2006-04-16  lupusalex    CIMTypedElement.getType() =>getDataType()
28   * 1712656    2007-05-04  ebak         Correct type identification for SVC CIMOM
29   * 1714878    2007-05-08  ebak         Empty string property values are parsed as nulls
30   * 1737141    2007-06-18  ebak         Sync up with JSR48 evolution
31   * 1769504	  2007-08-15  ebak         Type identification for VALUETYPE="numeric"
32   * 1783288    2007-09-10  ebak         CIMClass.isAssociation() not working for retrieved classes.
33   * 1820763    2007-10-29  ebak         Supporting the EmbeddedInstance qualifier
34   * 1827728    2007-11-20  ebak         rework: embeddedInstances: attribute EmbeddedObject not set
35   * 1848607    2007-12-11  ebak         Strict EmbeddedObject types
36   * 1944875    2008-05-29  blaschke-oss Indications with embedded objects are not accepted
37   * 2003590    2008-06-30  blaschke-oss Change licensing from CPL to EPL
38   * 2210455    2008-10-30  blaschke-oss Enhance javadoc, fix potential null pointers
39   * 2524131    2009-01-21  raman_arora  Upgrade client to JDK 1.5 (Phase 1)
40   * 2531371    2009-02-10  raman_arora  Upgrade client to JDK 1.5 (Phase 2)
41   * 2714989    2009-03-26  blaschke-oss Code cleanup from redundant null check et al
42   * 2763216    2009-04-14  blaschke-oss Code cleanup: visible spelling/grammar errors
43   * 2797550    2009-06-01  raman_arora  JSR48 compliance - add Java Generics
44   * 2823494    2009-08-03  rgummada     Change Boolean constructor to static
45   * 2860081    2009-09-17  raman_arora  Pull Enumeration Feature (DOM Parser)
46   * 2957387    2010-03-03  blaschke-oss EmbededObject XML attribute must not be all uppercases
47   * 3023143    2010-07-01  blaschke-oss CIMXMLParserImpl uses # constructor instead of valueOf
48   * 3027479    2010-07-09  blaschke-oss Dead store to local variable
49   * 3027615    2010-07-12  blaschke-oss Use CLASS_ARRAY_T instead of new CIMDataType(CLASS,0)
50   * 3293248    2011-05-03  blaschke-oss Support for CIM_ERROR instances within ERROR
51   * 3297028    2011-05-03  blaschke-oss Instances contain CIMClassProperty with DOM parser
52   * 3411944    2011-09-20  blaschke-oss createJavaObject exception with hex uint
53   * 3513353    2012-03-30  blaschke-oss TCK: CIMDataType arrays must have length >= 1
54   * 3513349    2012-03-31  blaschke-oss TCK: CIMDataType must not accept null string
55   * 3466280    2012-04-23  blaschke-oss get instance failure for CIM_IndicationSubscription
56   * 3521119    2012-04-24  blaschke-oss JSR48 1.0.0: remove CIMObjectPath 2/3/4-parm ctors
57   * 3526679    2012-05-14  blaschke-oss DOM parser ignores ERROR node CODE
58   * 3572993    2012-10-01  blaschke-oss parseDouble("2.2250738585072012e-308") DoS vulnerability
59   * 3598613    2013-01-11  blaschke-oss different data type in cim instance and cim object path
60   *    2616    2013-02-23  blaschke-oss Add new API WBEMClientSBLIM.sendIndication()
61   *    2636    2013-05-08  blaschke-oss Nested embedded instances cause CIMXMLParseException
62   *    2640    2013-05-11  blaschke-oss Multiple CDATA parsing broken in DOM parser
63   *    2668    2013-09-24  blaschke-oss Potential null pointer exception in parseCIM
64   *    2669    2013-09-24  blaschke-oss Potential null pointer exception in parseMESSAGE
65   *    2670    2013-09-25  blaschke-oss NAME attribute not required by DOM parser
66   *    2671    2013-09-25  blaschke-oss Potential null pointer exception in parseERROR
67   *    2675    2013-09-27  blaschke-oss CIMXMLParseException messages should contain element name
68   *    2676    2013-09-27  blaschke-oss parseMULTI(EXP)REQ looking for wrong child elements
69   *    2678    2013-09-30  blaschke-oss parseMULTI___ allows one SIMPLE___ child element
70   *    2679    2013-10-01  blaschke-oss parseIMETHODCALL requires one IPARAMVALUE child element
71   *    2680    2013-10-02  blaschke-oss IPARAMVALUE parsing broken on DOM/SAX
72   *    2681    2013-10-02  blaschke-oss parseQUALIFIERDECLARATION does not require TYPE attribute
73   *    2683    2013-10-07  blaschke-oss KEYVALUE VALUETYPE optional, "string" default
74   *    2684    2013-10-07  blaschke-oss parseEXPMETHODRESPONSE has several issues
75   *    2685    2013-10-07  blaschke-oss Element.getAttribute returns empty string if no attribute
76   *    2686    2013-10-10  blaschke-oss parseEXPPARAMVALUE allows 2+ children, prohibits 0 
77   *    2688    2013-10-10  blaschke-oss parseMETHODCALL looks for CIMName attribute instead of NAME
78   *    2537    2013-10-17  blaschke-oss Add new data types for PARAMVALUE
79   *    2691    2013-10-18  blaschke-oss RETURNVALUE should not require PARAMTYPE attribute
80   *    2694    2013-10-25  blaschke-oss NAME attribute not required by DOM parser (part 2)
81   *    2695    2013-10-25  blaschke-oss parseMETHODCALL allows LOCALCLASSPATH and LOCALINSTANCEPATH
82   *    2696    2013-10-29  blaschke-oss parseIRETURNVALUE ignores VALUE and VALUE.ARRAY
83   *    2699    2013-11-05  blaschke-oss parseQUALIFIER does not require TYPE attribute
84   *    2700    2013-11-07  blaschke-oss PROPERTY does not require TYPE attribute
85   *    2701    2013-11-07  blaschke-oss PROPERTY.ARRAY does not require TYPE attribute
86   *    2702    2013-11-07  blaschke-oss Bad PROPERTY.ARRAY ARRAYSIZE generates NumberFormatException
87   *    2703    2013-11-08  blaschke-oss MethodNode should not require TYPE attribute
88   *    2704    2013-11-11  blaschke-oss PARAMETER does not require TYPE attribute
89   *    2705    2013-11-11  blaschke-oss PARAMETER.ARRAY does not require TYPE attribute
90   *    2706    2013-11-11  blaschke-oss Bad PARAMETER.REFARRAY ARRAYSIZE generates NumberFormatException
91   *    2707    2013-11-12  blaschke-oss INSTANCENAME ignores KEYVALUE and VALUE.REFERENCE children
92   *    2710    2013-11-13  blaschke-oss parseVALUEOBJECTWITH(LOCAL)PATH ignores (LOCAL)CLASSPATH child
93   *    2711    2013-11-13  blaschke-oss LOCALNAMESPACEPATH allows 0 NAMESPACE children
94   *    2713    2013-11-22  blaschke-oss Enforce loose validation of CIM-XML documents
95   *    2715    2013-11-26  blaschke-oss Add VALUE.NULL support
96   *    2538    2013-11-28  blaschke-oss CR14: Support new CORRELATOR element
97   */
98  
99  package org.metricshub.wbem.sblim.cimclient.internal.cimxml;
100 
101 /*-
102  * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
103  * WBEM Java Client
104  * ჻჻჻჻჻჻
105  * Copyright 2023 - 2025 MetricsHub
106  * ჻჻჻჻჻჻
107  * Licensed under the Apache License, Version 2.0 (the "License");
108  * you may not use this file except in compliance with the License.
109  * You may obtain a copy of the License at
110  *
111  *      http://www.apache.org/licenses/LICENSE-2.0
112  *
113  * Unless required by applicable law or agreed to in writing, software
114  * distributed under the License is distributed on an "AS IS" BASIS,
115  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
116  * See the License for the specific language governing permissions and
117  * limitations under the License.
118  * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
119  */
120 
121 import java.io.StringReader;
122 import java.math.BigInteger;
123 import java.util.Comparator;
124 import java.util.HashMap;
125 import java.util.TreeMap;
126 import java.util.Vector;
127 import java.util.logging.Level;
128 import org.metricshub.wbem.javax.cim.CIMArgument;
129 import org.metricshub.wbem.javax.cim.CIMClass;
130 import org.metricshub.wbem.javax.cim.CIMClassProperty;
131 import org.metricshub.wbem.javax.cim.CIMDataType;
132 import org.metricshub.wbem.javax.cim.CIMDateTime;
133 import org.metricshub.wbem.javax.cim.CIMDateTimeAbsolute;
134 import org.metricshub.wbem.javax.cim.CIMDateTimeInterval;
135 import org.metricshub.wbem.javax.cim.CIMFlavor;
136 import org.metricshub.wbem.javax.cim.CIMInstance;
137 import org.metricshub.wbem.javax.cim.CIMMethod;
138 import org.metricshub.wbem.javax.cim.CIMNamedElementInterface;
139 import org.metricshub.wbem.javax.cim.CIMObjectPath;
140 import org.metricshub.wbem.javax.cim.CIMParameter;
141 import org.metricshub.wbem.javax.cim.CIMProperty;
142 import org.metricshub.wbem.javax.cim.CIMQualifier;
143 import org.metricshub.wbem.javax.cim.CIMQualifierType;
144 import org.metricshub.wbem.javax.cim.CIMScope;
145 import org.metricshub.wbem.javax.cim.UnsignedInteger16;
146 import org.metricshub.wbem.javax.cim.UnsignedInteger32;
147 import org.metricshub.wbem.javax.cim.UnsignedInteger64;
148 import org.metricshub.wbem.javax.cim.UnsignedInteger8;
149 import org.metricshub.wbem.javax.wbem.WBEMException;
150 import org.metricshub.wbem.sblim.cimclient.internal.cim.CIMHelper;
151 import org.metricshub.wbem.sblim.cimclient.internal.cim.CIMQualifiedElementInterfaceImpl;
152 import org.metricshub.wbem.sblim.cimclient.internal.logging.LogAndTraceBroker;
153 import org.metricshub.wbem.sblim.cimclient.internal.util.MOF;
154 import org.metricshub.wbem.sblim.cimclient.internal.util.Util;
155 import org.metricshub.wbem.sblim.cimclient.internal.util.WBEMConfiguration;
156 import org.metricshub.wbem.sblim.cimclient.internal.util.XMLHostStr;
157 import org.w3c.dom.Attr;
158 import org.w3c.dom.Document;
159 import org.w3c.dom.Element;
160 import org.w3c.dom.NamedNodeMap;
161 import org.w3c.dom.Node;
162 import org.w3c.dom.NodeList;
163 import org.w3c.dom.Text;
164 import org.xml.sax.InputSource;
165 
166 /**
167  * Class CIMXMLParserImpl is the main class of CIM-XML DOM parser.
168  *
169  */
170 public class CIMXMLParserImpl {
171 	/*
172 	 * ebak: local object path - should be used by parseLOCALCLASSPATH(),
173 	 * parseLOCALINSTANCEPATH(), parseCLASSNAME(), parseINSTANCENAME(),
174 	 * parseCLASS() and parseINSTANCE()
175 	 */
176 	private static LocalPathBuilder cLocalPathBuilder = new LocalPathBuilder(null);
177 
178 	/**
179 	 * setLocalObjectPath
180 	 *
181 	 * @param pLocalOp
182 	 *            - empty fields of parsed objectpaths will be substituted by
183 	 *            fields coming from this parameter
184 	 */
185 	public static void setLocalObjectPath(CIMObjectPath pLocalOp) {
186 		cLocalPathBuilder = new LocalPathBuilder(pLocalOp);
187 	}
188 
189 	/*
190 	 * / local object path
191 	 */
192 
193 	/**
194 	 * parseCIM
195 	 *
196 	 * @param pCimE
197 	 * @return CIMMessage
198 	 * @throws CIMXMLParseException
199 	 */
200 	public static CIMMessage parseCIM(Element pCimE) throws CIMXMLParseException {
201 		// <!ELEMENT CIM (MESSAGE|DECLARATION)>
202 		// <!ATTLIST CIM %CIMVERSION;%DTDVERSION;>
203 		Attr cim_cimversionA = (Attr) searchAttribute(pCimE, "CIMVERSION");
204 		if (cim_cimversionA == null) throw new CIMXMLParseException("CIM element missing CIMVERSION attribute!");
205 		String cimversion = cim_cimversionA.getNodeValue();
206 
207 		Attr cim_dtdversionA = (Attr) searchAttribute(pCimE, "DTDVERSION");
208 		if (cim_dtdversionA == null) throw new CIMXMLParseException("CIM element missing DTDVERSION attribute!");
209 		String dtdversion = cim_dtdversionA.getNodeValue();
210 
211 		// MESSAGE
212 		Element messageA[] = searchNodes(pCimE, "MESSAGE", 0, 1, false);
213 		if (messageA != null) {
214 			CIMMessage message = parseMESSAGE(cimversion, dtdversion, messageA[0]);
215 			message.setCIMVersion(cimversion);
216 			message.setDTDVersion(dtdversion);
217 			return message;
218 		}
219 
220 		// DECLARATION
221 		if (searchNodes(pCimE, "DECLARATION", 0, 1, false) != null) throw new CIMXMLParseException(
222 			"DECLARATION element not supported!"
223 		);
224 
225 		throw new CIMXMLParseException("CIM element missing required child element!");
226 	}
227 
228 	// ////////////////////////////////////////////////////////////////////////////////////////
229 	// Value Elements
230 	// ////////////////////////////////////////////////////////////////////////////////////////
231 
232 	/**
233 	 * parseVALUE - supports the non-standard TYPE attribute
234 	 *
235 	 * @param pValueE
236 	 * @return TypedValue, type is null if no TYPE attribute was found, the
237 	 *         value is always String, the caller method have to convert it.
238 	 * @throws CIMXMLParseException
239 	 */
240 	public static TypedValue parseVALUE(Element pValueE) throws CIMXMLParseException {
241 		// <! ELEMENT VALUE (#PCDATA)>
242 
243 		String typeStr = attribute(pValueE, "TYPE");
244 		CIMDataType type = typeStr == null ? null : parseScalarTypeStr(typeStr);
245 		// ebak: empty VALUE element is parsed as empty String
246 		NodeList list = pValueE.getChildNodes();
247 		StringBuilder valueStr = new StringBuilder();
248 		for (int i = 0; i < list.getLength(); i++) {
249 			Text t = (Text) list.item(i);
250 			if (t != null) {
251 				String nodeValue = t.getNodeValue();
252 				if (nodeValue != null) valueStr.append(nodeValue);
253 			}
254 		}
255 		return new TypedValue(type, valueStr.toString());
256 	}
257 
258 	/**
259 	 * parseVALUEARRAY - supports the non-standard TYPE attribute
260 	 *
261 	 * @param pValueArrayE
262 	 * @return TypedValue, type is null if no TYPE attribute was found, the
263 	 *         value is always String[], the caller method have to convert it.
264 	 * @throws CIMXMLParseException
265 	 */
266 	public static TypedValue parseVALUEARRAY(Element pValueArrayE) throws CIMXMLParseException {
267 		// <! ELEMENT VALUE.ARRAY (VALUE|VALUE.NULL)*>
268 		String typeStr = attribute(pValueArrayE, "TYPE");
269 		CIMDataType type = typeStr == null ? null : parseArrayTypeStr(typeStr);
270 
271 		// Process node list here, order of VALUE/VALUE.NULL IS important
272 		NodeList nl = pValueArrayE.getChildNodes();
273 		if (nl == null || nl.getLength() == 0) return new TypedValue(type, new String[0]);
274 		Vector<String> resStringV = new Vector<String>();
275 		for (int i = 0; i < nl.getLength(); i++) {
276 			Node n = nl.item(i);
277 			if (n instanceof Text && "".equalsIgnoreCase(n.getNodeValue().trim())) continue;
278 			String name = n.getNodeName();
279 			if (name.equals("VALUE")) {
280 				resStringV.add((String) parseVALUE((Element) n).getValue());
281 			} else if (name.equals("VALUE.NULL")) {
282 				resStringV.add(null);
283 			} else if (NODENAME_HASH.containsKey(name)) {
284 				throw new CIMXMLParseException("VALUE.ARRAY element contains invalid child element " + name + "!");
285 			}
286 		}
287 		return new TypedValue(type, resStringV.toArray(new String[0]));
288 	}
289 
290 	/**
291 	 * parseVALUEREFERENCE
292 	 *
293 	 * @param pValuereferenceE
294 	 * @return CIMObjectPath
295 	 * @throws CIMXMLParseException
296 	 */
297 	public static CIMObjectPath parseVALUEREFERENCE(Element pValuereferenceE) throws CIMXMLParseException {
298 		// <!ELEMENT VALUE.REFERENCE
299 		// (CLASSPATH|LOCALCLASSPATH|CLASSNAME|INSTANCEPATH|LOCALINSTANCEPATH|INSTANCENAME)>
300 
301 		// CLASSPATH
302 		Element classpathA[] = searchNodes(pValuereferenceE, "CLASSPATH", 0, 1, false);
303 		if (classpathA != null) {
304 			CIMObjectPath op = parseCLASSPATH(classpathA[0]);
305 			return op;
306 		}
307 
308 		// LOCALCLASSPATH
309 		Element localclasspathA[] = searchNodes(pValuereferenceE, "LOCALCLASSPATH", 0, 1, false);
310 		if (localclasspathA != null) {
311 			CIMObjectPath op = parseLOCALCLASSPATH(localclasspathA[0]);
312 			return op;
313 		}
314 
315 		// CLASSNAME
316 		Element classnameA[] = searchNodes(pValuereferenceE, "CLASSNAME", 0, 1, false);
317 		if (classnameA != null) {
318 			CIMObjectPath op = parseCLASSNAME(classnameA[0]);
319 			if (op != null && op.getNamespace() != null) {
320 				// LocalPathBuilder includes default namespace in CLASSNAME
321 				// elements, needs to be stripped
322 				op =
323 					new CIMObjectPath(
324 						op.getScheme(),
325 						op.getHost(),
326 						op.getPort(),
327 						null,
328 						op.getObjectName(),
329 						op.getKeys(),
330 						op.getXmlSchemaName()
331 					);
332 			}
333 			return op;
334 		}
335 
336 		// INSTANCEPATH
337 		Element instancepathA[] = searchNodes(pValuereferenceE, "INSTANCEPATH", 0, 1, false);
338 		if (instancepathA != null) {
339 			CIMObjectPath op = parseINSTANCEPATH(instancepathA[0]);
340 			return op;
341 		}
342 
343 		// LOCALINSTANCEPATH
344 		Element localinstancepathA[] = searchNodes(pValuereferenceE, "LOCALINSTANCEPATH", 0, 1, false);
345 		if (localinstancepathA != null) {
346 			CIMObjectPath op = parseLOCALINSTANCEPATH(localinstancepathA[0]);
347 			return op;
348 		}
349 
350 		// INSTANCENAME
351 		Element instancenameA[] = searchNodes(pValuereferenceE, "INSTANCENAME", 0, 1, false);
352 		if (instancenameA != null) {
353 			CIMObjectPath op = parseINSTANCENAME(instancenameA[0]);
354 			if (op != null && op.getNamespace() != null) {
355 				// LocalPathBuilder includes default namespace in INSTANCENAME
356 				// elements, needs to be stripped
357 				op =
358 					new CIMObjectPath(
359 						op.getScheme(),
360 						op.getHost(),
361 						op.getPort(),
362 						null,
363 						op.getObjectName(),
364 						op.getKeys(),
365 						op.getXmlSchemaName()
366 					);
367 			}
368 			return op;
369 		}
370 
371 		throw new CIMXMLParseException("VALUE.REFERENCE element missing required child element!");
372 	}
373 
374 	/**
375 	 * parseVALUEREFARRAY
376 	 *
377 	 * @param pValueRefArrayE
378 	 * @return CIMObjectPath[]
379 	 * @throws CIMXMLParseException
380 	 */
381 	public static CIMObjectPath[] parseVALUEREFARRAY(Element pValueRefArrayE) throws CIMXMLParseException {
382 		// <! ELEMENT VALUE.REFARRAY (VALUE.REFERENCE|VALUE.NULL)*>
383 
384 		// Process node list here, order of VALUE.REFERENCE/VALUE.NULL IS
385 		// important
386 		NodeList nl = pValueRefArrayE.getChildNodes();
387 		if (nl == null || nl.getLength() == 0) return new CIMObjectPath[0];
388 		Vector<CIMObjectPath> resObjectPathV = new Vector<CIMObjectPath>();
389 		for (int i = 0; i < nl.getLength(); i++) {
390 			Node n = nl.item(i);
391 			if (n instanceof Text && "".equalsIgnoreCase(n.getNodeValue().trim())) continue;
392 			String name = n.getNodeName();
393 			if (name.equals("VALUE.REFERENCE")) {
394 				resObjectPathV.add(parseVALUEREFERENCE((Element) n));
395 			} else if (name.equals("VALUE.NULL")) {
396 				resObjectPathV.add(null);
397 			} else if (NODENAME_HASH.containsKey(name)) {
398 				throw new CIMXMLParseException("VALUE.REFARRAY element contains invalid child element " + name + "!");
399 			}
400 		}
401 		return resObjectPathV.toArray(new CIMObjectPath[0]);
402 	}
403 
404 	/**
405 	 * parseVALUEOBJECT
406 	 *
407 	 * @param pValueObjectE
408 	 * @return CIMNamedElementInterface (CIMClass|CIMInstance)
409 	 * @throws CIMXMLParseException
410 	 */
411 	public static CIMNamedElementInterface parseVALUEOBJECT(Element pValueObjectE) throws CIMXMLParseException {
412 		// <! ELEMENT VALUE.OBJECT (CLASS|INSTANCE)>
413 
414 		// CLASS
415 		Element classA[] = searchNodes(pValueObjectE, "CLASS", 0, 1, false);
416 		if (classA != null) {
417 			CIMClass obj = parseCLASS(classA[0]);
418 			return obj;
419 		}
420 
421 		// INSTANCE
422 		Element instanceA[] = searchNodes(pValueObjectE, "INSTANCE", 0, 1, false);
423 		if (instanceA != null) {
424 			CIMInstance obj = parseINSTANCE(instanceA[0]);
425 			return obj;
426 		}
427 
428 		throw new CIMXMLParseException("VALUE.OBJECT element missing required child element!");
429 	}
430 
431 	private static final String nodesVALUENAMEDINSTANCE[] = { "INSTANCENAME", "INSTANCE" };
432 
433 	/**
434 	 * parseVALUENAMEDINSTANCE
435 	 *
436 	 * @param pValueNamedInstanceE
437 	 * @return CIMInstance
438 	 * @throws CIMXMLParseException
439 	 */
440 	public static CIMInstance parseVALUENAMEDINSTANCE(Element pValueNamedInstanceE) throws CIMXMLParseException {
441 		// <! ELEMENT VALUE.NAMEDINSTANCE (INSTANCENAME,INSTANCE)>
442 
443 		// INSTANCENAME
444 		Element instancenameA[] = searchNodes(pValueNamedInstanceE, "INSTANCENAME", 1, 1, true);
445 		if (instancenameA == null) {
446 			throw new CIMXMLParseException("VALUE.NAMEDINSTANCE element missing INSTANCENAME child element!");
447 		}
448 		CIMObjectPath op = parseINSTANCENAME(instancenameA[0]);
449 
450 		// INSTANCE
451 		Element instanceA[] = searchNodes(pValueNamedInstanceE, "INSTANCE", 1, 1, true);
452 		if (instanceA == null) {
453 			throw new CIMXMLParseException("VALUE.NAMEDINSTANCE element missing INSTANCE child element!");
454 		}
455 		CIMInstance inst = parseINSTANCE(instanceA[0], op); // BB mod
456 		checkOtherNodes(pValueNamedInstanceE, nodesVALUENAMEDINSTANCE);
457 		return inst;
458 	}
459 
460 	private static final String nodesVALUEINSTANCEWITHPATH[] = { "INSTANCEPATH", "INSTANCE" };
461 
462 	/**
463 	 * parseVALUEINSTANCEWITHPATH
464 	 *
465 	 * @param pValueNamedInstanceE
466 	 * @return CIMInstance
467 	 * @throws CIMXMLParseException
468 	 */
469 	public static CIMInstance parseVALUEINSTANCEWITHPATH(Element pValueNamedInstanceE) throws CIMXMLParseException {
470 		// <! ELEMENT VALUE.INSTANCEWITHPATH (INSTANCEPATH,INSTANCE)>
471 
472 		// INSTANCEPATH
473 		Element instancepathA[] = searchNodes(pValueNamedInstanceE, "INSTANCEPATH", 1, 1, true);
474 		if (instancepathA == null) {
475 			throw new CIMXMLParseException("VALUE.INSTANCEWITHPATH element missing INSTANCEPATH child element!");
476 		}
477 		CIMObjectPath op = parseINSTANCEPATH(instancepathA[0]);
478 
479 		// INSTANCE
480 		Element instanceA[] = searchNodes(pValueNamedInstanceE, "INSTANCE", 1, 1, true);
481 		if (instanceA == null) {
482 			throw new CIMXMLParseException("VALUE.INSTANCEWITHPATH element missing INSTANCE child element!");
483 		}
484 		CIMInstance inst = parseINSTANCE(instanceA[0], op); // BB mod
485 		checkOtherNodes(pValueNamedInstanceE, nodesVALUEINSTANCEWITHPATH);
486 		return inst;
487 	}
488 
489 	private static final String nodesVALUENAMEDOBJECTi[] = { "INSTANCENAME", "INSTANCE" };
490 
491 	/**
492 	 * parseVALUENAMEDOBJECT
493 	 *
494 	 * @param pValueNamedObjectE
495 	 * @return CIMNamedElementInterface
496 	 * @throws CIMXMLParseException
497 	 */
498 	public static CIMNamedElementInterface parseVALUENAMEDOBJECT(Element pValueNamedObjectE) throws CIMXMLParseException {
499 		// <! ELEMENT VALUE.NAMEDOBJECT (CLASS|(INSTANCENAME,INSTANCE))>
500 
501 		// CLASS
502 		Element classA[] = searchNodes(pValueNamedObjectE, "CLASS", 0, 1, false);
503 		if (classA != null) {
504 			CIMClass obj = parseCLASS(classA[0]);
505 			// checkOtherNodes(pValueNamedObjectE, nodesVALUENAMEDOBJECTc);
506 			return obj;
507 		}
508 
509 		// INSTANCENAME
510 		Element instancenameA[] = searchNodes(pValueNamedObjectE, "INSTANCENAME", 0, 1, true);
511 		if (instancenameA != null) {
512 			CIMObjectPath op = parseINSTANCENAME(instancenameA[0]);
513 
514 			// INSTANCE
515 			Element instanceA[] = searchNodes(pValueNamedObjectE, "INSTANCE", 0, 1, true);
516 			if (instanceA == null) {
517 				throw new CIMXMLParseException("VALUE.NAMEDOBJECT element missing INSTANCE child element!");
518 			}
519 			CIMInstance inst = parseINSTANCE(instanceA[0], op); // BB mod
520 			checkOtherNodes(pValueNamedObjectE, nodesVALUENAMEDOBJECTi);
521 			return inst;
522 		}
523 
524 		throw new CIMXMLParseException("VALUE.NAMEDOBJECT element missing required child element!");
525 	}
526 
527 	private static final String nodesVALUEOBJECTWITHPATHcls[] = { "CLASSPATH", "CLASS" };
528 
529 	private static final String nodesVALUEOBJECTWITHPATHins[] = { "INSTANCEPATH", "INSTANCE" };
530 
531 	/**
532 	 * parseVALUEOBJECTWITHPATH
533 	 *
534 	 * @param pValueObjectWithPathE
535 	 * @return CIMNamedElementInterface
536 	 * @throws CIMXMLParseException
537 	 */
538 	public static CIMNamedElementInterface parseVALUEOBJECTWITHPATH(Element pValueObjectWithPathE)
539 		throws CIMXMLParseException {
540 		// <! ELEMENT VALUE.OBJECTWITHPATH
541 		// ((CLASSPATH,CLASS)|(INSTANCEPATH,INSTANCE))>
542 
543 		// CLASSPATH
544 		Element classpathA[] = searchNodes(pValueObjectWithPathE, "CLASSPATH", 0, 1, true);
545 		if (classpathA != null) {
546 			CIMObjectPath op = parseCLASSPATH(classpathA[0]);
547 
548 			// CLASS
549 			Element classA[] = searchNodes(pValueObjectWithPathE, "CLASS", 0, 1, true);
550 			if (classA == null) {
551 				throw new CIMXMLParseException("VALUE.OBJECTWITHPATH element missing CLASS child element!");
552 			}
553 
554 			CIMClass obj = parseCLASS(classA[0], op);
555 			checkOtherNodes(pValueObjectWithPathE, nodesVALUEOBJECTWITHPATHcls);
556 			return obj;
557 		}
558 
559 		// INSTANCEPATH
560 		Element instancepathA[] = searchNodes(pValueObjectWithPathE, "INSTANCEPATH", 0, 1, true);
561 		if (instancepathA != null) {
562 			CIMObjectPath op = parseINSTANCEPATH(instancepathA[0]);
563 
564 			// INSTANCE
565 			Element instanceA[] = searchNodes(pValueObjectWithPathE, "INSTANCE", 0, 1, true);
566 			if (instanceA == null) {
567 				throw new CIMXMLParseException("VALUE.OBJECTWITHPATH element missing INSTANCE child element!");
568 			}
569 			CIMInstance inst = parseINSTANCE(instanceA[0], op); // BB mod
570 			checkOtherNodes(pValueObjectWithPathE, nodesVALUEOBJECTWITHPATHins);
571 			return inst;
572 		}
573 
574 		throw new CIMXMLParseException("VALUE.OBJECTWITHPATH element missing required child element!");
575 	}
576 
577 	private static final String nodesVALUEOBJECTWITHLOCALPATHcls[] = { "LOCALCLASSPATH", "CLASS" };
578 
579 	private static final String nodesVALUEOBJECTWITHLOCALPATHins[] = { "LOCALINSTANCEPATH", "INSTANCE" };
580 
581 	/**
582 	 * parseVALUEOBJECTWITHLOCALPATH
583 	 *
584 	 * @param pValueObjectWithLocalPathE
585 	 * @return CIMNamedElementInterface
586 	 * @throws CIMXMLParseException
587 	 */
588 	public static CIMNamedElementInterface parseVALUEOBJECTWITHLOCALPATH(Element pValueObjectWithLocalPathE)
589 		throws CIMXMLParseException {
590 		// <! ELEMENT VALUE.OBJECTWITHLOCALPATH
591 		// ((LOCALCLASSPATH,CLASS)|(LOCALINSTANCEPATH,INSTANCE))>
592 
593 		// LOCALCLASSPATH
594 		Element localclasspathA[] = searchNodes(pValueObjectWithLocalPathE, "LOCALCLASSPATH", 0, 1, true);
595 		if (localclasspathA != null) {
596 			CIMObjectPath op = parseLOCALCLASSPATH(localclasspathA[0]);
597 
598 			// CLASS
599 			Element classA[] = searchNodes(pValueObjectWithLocalPathE, "CLASS", 0, 1, true);
600 			if (classA == null) {
601 				throw new CIMXMLParseException("VALUE.OBJECTWITHLOCALPATH element missing CLASS child element!");
602 			}
603 
604 			CIMClass obj = parseCLASS(classA[0], op);
605 			checkOtherNodes(pValueObjectWithLocalPathE, nodesVALUEOBJECTWITHLOCALPATHcls);
606 			return obj;
607 		}
608 
609 		// LOCALINSTANCEPATH
610 		Element localinstancepathA[] = searchNodes(pValueObjectWithLocalPathE, "LOCALINSTANCEPATH", 0, 1, true);
611 		if (localinstancepathA != null) {
612 			CIMObjectPath op = parseLOCALINSTANCEPATH(localinstancepathA[0]);
613 
614 			// INSTANCE
615 			Element instanceA[] = searchNodes(pValueObjectWithLocalPathE, "INSTANCE", 0, 1, true);
616 			if (instanceA == null) {
617 				throw new CIMXMLParseException("VALUE.OBJECTWITHLOCALPATH element missing INSTANCE child element!");
618 			}
619 			CIMInstance inst = parseINSTANCE(instanceA[0], op); // BB mod
620 			checkOtherNodes(pValueObjectWithLocalPathE, nodesVALUEOBJECTWITHLOCALPATHins);
621 			return inst;
622 		}
623 
624 		throw new CIMXMLParseException("VALUE.OBJECTWITHLOCALPATH element missing required child element!");
625 	}
626 
627 	// ////////////////////////////////////////////////////////////////////////////////////////
628 	// Naming and Location elements
629 	// ////////////////////////////////////////////////////////////////////////////////////////
630 
631 	private static final String nodesNAMESPACEPATH[] = { "HOST", "LOCALNAMESPACEPATH" };
632 
633 	/**
634 	 * parseNAMESPACEPATH
635 	 *
636 	 * @param pNameSpacePathE
637 	 * @return CIMObjectPath
638 	 * @throws CIMXMLParseException
639 	 */
640 	public static CIMObjectPath parseNAMESPACEPATH(Element pNameSpacePathE) throws CIMXMLParseException {
641 		// <!ELEMENT NAMESPACEPATH (HOST,LOCALNAMESPACEPATH)>
642 		// HOST
643 		Element hostA[] = searchNodes(pNameSpacePathE, "HOST", 1, 1, true);
644 		if (hostA == null) {
645 			throw new CIMXMLParseException("NAMESPACEPATH element missing HOST child element!");
646 		}
647 		XMLHostStr xmlHostStr = new XMLHostStr(parseHOST(hostA[0]));
648 		// LOCALNAMESPACE
649 		Element localnamespacepathA[] = searchNodes(pNameSpacePathE, "LOCALNAMESPACEPATH", 1, 1, true);
650 		if (localnamespacepathA == null) {
651 			throw new CIMXMLParseException("NAMESPACEPATH element missing LOCALNAMESPACEPATH child element!");
652 		}
653 		String nameSpace = parseLOCALNAMESPACEPATH(localnamespacepathA[0]);
654 		/*
655 		 * CIMObjectPath( String scheme, String host, String port, String
656 		 * namespace, String objectName, CIMProperty[] keys )
657 		 */
658 		checkOtherNodes(pNameSpacePathE, nodesNAMESPACEPATH);
659 		return new CIMObjectPath(
660 			xmlHostStr.getProtocol(),
661 			xmlHostStr.getHost(),
662 			xmlHostStr.getPort(),
663 			nameSpace,
664 			null,
665 			null
666 		);
667 	}
668 
669 	/**
670 	 * parseLOCALNAMESPACEPATH
671 	 *
672 	 * @param pLocalNameSpaceE
673 	 * @return String
674 	 * @throws CIMXMLParseException
675 	 */
676 	public static String parseLOCALNAMESPACEPATH(Element pLocalNameSpaceE) throws CIMXMLParseException {
677 		// <!ELEMENT LOCALNAMESPACE (NAMESPACE+))>
678 
679 		Element[] nameSpaceElementA = searchNodes(pLocalNameSpaceE, "NAMESPACE", 1, Integer.MAX_VALUE, false);
680 		if (nameSpaceElementA == null) {
681 			if (
682 				WBEMConfiguration.getGlobalConfiguration().allowEmptyLocalNameSpacePath() && cLocalPathBuilder != null
683 			) return cLocalPathBuilder.getBasePath().getNamespace();
684 			throw new CIMXMLParseException("LOCALNAMESPACEPATH element missing NAMESPACE child element!");
685 		}
686 		StringBuffer sb = new StringBuffer();
687 		for (int i = 0; i < nameSpaceElementA.length; i++) {
688 			Element namespaceE = nameSpaceElementA[i];
689 			String s = parseNAMESPACE(namespaceE);
690 			if (i > 0) sb.append("/" + s); else sb.append(s);
691 		}
692 		return sb.toString();
693 	}
694 
695 	/**
696 	 * parseHOST
697 	 *
698 	 * @param pHostE
699 	 * @return String
700 	 */
701 	public static String parseHOST(Element pHostE) {
702 		// <!ELEMENT HOST (#PCDATA)>
703 
704 		Text valueT = (Text) searchFirstChild(pHostE);
705 		String host = valueT.getNodeValue();
706 		return host;
707 	}
708 
709 	private static final String nodesNAMESPACE[] = {};
710 
711 	/**
712 	 * parseNAMESPACE
713 	 *
714 	 * @param pNameSpaceE
715 	 * @return String
716 	 * @throws CIMXMLParseException
717 	 */
718 	public static String parseNAMESPACE(Element pNameSpaceE) throws CIMXMLParseException {
719 		// <!ELEMENT NAMESPACE EMPTY>
720 		// <!ATTLIST NAMESPACE %NAME;>
721 
722 		Attr namespace_nameA = (Attr) searchAttribute(pNameSpaceE, "NAME");
723 		if (namespace_nameA == null) throw new CIMXMLParseException("NAMESPACE element missing NAME attribute!");
724 		String n = namespace_nameA.getValue();
725 		checkOtherNodes(pNameSpaceE, nodesNAMESPACE);
726 		return n;
727 	}
728 
729 	private static final String nodesCLASSPATH[] = { "NAMESPACEPATH", "CLASSNAME" };
730 
731 	/**
732 	 * parseCLASSPATH
733 	 *
734 	 * @param pClassPathE
735 	 * @return CIMObjectPath
736 	 * @throws CIMXMLParseException
737 	 */
738 	public static CIMObjectPath parseCLASSPATH(Element pClassPathE) throws CIMXMLParseException {
739 		// <!ELEMENT CLASSPATH (NAMESPACEPATH,CLASSNAME)>
740 
741 		// NAMESPACEPATH
742 		Element namespacepathA[] = searchNodes(pClassPathE, "NAMESPACEPATH", 1, 1, true);
743 		if (namespacepathA == null) {
744 			throw new CIMXMLParseException("CLASSPATH element missing NAMESPACEPATH child element!");
745 		}
746 		CIMObjectPath nsPath = parseNAMESPACEPATH(namespacepathA[0]);
747 		// CLASSNAME
748 		Element classnameA[] = searchNodes(pClassPathE, "CLASSNAME", 1, 1, true);
749 		if (classnameA == null) {
750 			throw new CIMXMLParseException("CLASSPATH element missing CLASSNAME child element!");
751 		}
752 		String className = parseClassName(classnameA[0]);
753 		/*
754 		 * CIMObjectPath( String scheme, String host, String port, String
755 		 * namespace, String objectName, CIMProperty[] keys )
756 		 */
757 		checkOtherNodes(pClassPathE, nodesCLASSPATH);
758 		return new CIMObjectPath(
759 			nsPath.getScheme(),
760 			nsPath.getHost(),
761 			nsPath.getPort(),
762 			nsPath.getNamespace(),
763 			className,
764 			null
765 		);
766 	}
767 
768 	private static final String nodesLOCALCLASSPATH[] = { "LOCALNAMESPACEPATH", "CLASSNAME" };
769 
770 	/**
771 	 * parseLOCALCLASSPATH
772 	 *
773 	 * @param pClassPathE
774 	 * @return CIMObjectPath
775 	 * @throws CIMXMLParseException
776 	 */
777 	public static CIMObjectPath parseLOCALCLASSPATH(Element pClassPathE) throws CIMXMLParseException {
778 		// <!ELEMENT LOCALCLASSPATH (LOCALNAMESPACEPATH,CLASSNAME)>
779 
780 		// NAMESPACEPATH
781 		Element localnamespacepathA[] = searchNodes(pClassPathE, "LOCALNAMESPACEPATH", 1, 1, true);
782 		if (localnamespacepathA == null) {
783 			throw new CIMXMLParseException("LOCALCLASSPATH element missing LOCALNAMESPACEPATH child element!");
784 		}
785 		String nameSpace = parseLOCALNAMESPACEPATH(localnamespacepathA[0]);
786 
787 		// CLASSNAME
788 		Element classnameA[] = searchNodes(pClassPathE, "CLASSNAME", 1, 1, true);
789 		if (classnameA == null) {
790 			throw new CIMXMLParseException("LOCALCLASSPATH element missing CLASSNAME child element!");
791 		}
792 		CIMObjectPath op = parseCLASSNAME(classnameA[0]);
793 		checkOtherNodes(pClassPathE, nodesLOCALCLASSPATH);
794 		return cLocalPathBuilder.build(op.getObjectName(), nameSpace);
795 	}
796 
797 	private static final String nodesCLASSNAME[] = {};
798 
799 	/**
800 	 * parseClassName
801 	 *
802 	 * @param pClassNameE
803 	 * @return String
804 	 * @throws CIMXMLParseException
805 	 */
806 	public static String parseClassName(Element pClassNameE) throws CIMXMLParseException {
807 		// <!ELEMENT CLASSNAME EMPTY>
808 		// <!ATTLIST CLASSNAME %NAME;>
809 		Attr classname_nameA = (Attr) searchAttribute(pClassNameE, "NAME");
810 		if (classname_nameA == null) throw new CIMXMLParseException("CLASSNAME element missing NAME attribute!");
811 		checkOtherNodes(pClassNameE, nodesCLASSNAME);
812 		return classname_nameA.getNodeValue();
813 	}
814 
815 	/**
816 	 * parseCLASSNAME
817 	 *
818 	 * @param pClassNameE
819 	 * @return CIMObjectPath
820 	 * @throws CIMXMLParseException
821 	 */
822 	public static CIMObjectPath parseCLASSNAME(Element pClassNameE) throws CIMXMLParseException {
823 		return cLocalPathBuilder.build(parseClassName(pClassNameE), null);
824 	}
825 
826 	private static final String nodesINSTANCEPATH[] = { "NAMESPACEPATH", "INSTANCENAME" };
827 
828 	/**
829 	 * parseINSTANCEPATH
830 	 *
831 	 * @param pInstancePathE
832 	 * @return CIMObjectPath
833 	 * @throws CIMXMLParseException
834 	 */
835 	public static CIMObjectPath parseINSTANCEPATH(Element pInstancePathE) throws CIMXMLParseException {
836 		// <!ELEMENT INSTANCEPATH (NAMESPACEPATH,INSTANCENAME)>
837 
838 		// NAMESPACEPATH
839 		Element namespacepathA[] = searchNodes(pInstancePathE, "NAMESPACEPATH", 1, 1, true);
840 		if (namespacepathA == null) {
841 			throw new CIMXMLParseException("INSTANCEPATH element missing NAMESPACEPATH child element!");
842 		}
843 		CIMObjectPath nsPath = parseNAMESPACEPATH(namespacepathA[0]);
844 		// INSTANCENAME
845 		Element instancenameA[] = searchNodes(pInstancePathE, "INSTANCENAME", 1, 1, true);
846 		if (instancenameA == null) {
847 			throw new CIMXMLParseException("INSTANCEPATH element missing INSTANCENAME child element!");
848 		}
849 		CIMObjectPath op = parseINSTANCENAME(instancenameA[0]);
850 		// ebak: change host and namespace
851 		checkOtherNodes(pInstancePathE, nodesINSTANCEPATH);
852 		return new CIMObjectPath(
853 			nsPath.getScheme(),
854 			nsPath.getHost(),
855 			nsPath.getPort(),
856 			nsPath.getNamespace(),
857 			op.getObjectName(),
858 			op.getKeys()
859 		);
860 	}
861 
862 	private static final String nodesLOCALINSTANCEPATH[] = { "LOCALNAMESPACEPATH", "INSTANCENAME" };
863 
864 	/**
865 	 * parseLOCALINSTANCEPATH
866 	 *
867 	 * @param pLocalInstancePathE
868 	 * @return CIMObjectPath
869 	 * @throws CIMXMLParseException
870 	 */
871 	public static CIMObjectPath parseLOCALINSTANCEPATH(Element pLocalInstancePathE) throws CIMXMLParseException {
872 		// <!ELEMENT LOCALINSTANCEPATH (LOCALNAMESPACEPATH,INSTANCENAME)>
873 
874 		// LOCALNAMESPACEPATH
875 		Element localnamespacepathA[] = searchNodes(pLocalInstancePathE, "LOCALNAMESPACEPATH", 1, 1, true);
876 		if (localnamespacepathA == null) {
877 			throw new CIMXMLParseException("LOCALINSTANCEPATH element missing LOCALNAMESPACEPATH child element!");
878 		}
879 		String nameSpace = parseLOCALNAMESPACEPATH(localnamespacepathA[0]);
880 
881 		// INSTANCENAME
882 		Element instancenameA[] = searchNodes(pLocalInstancePathE, "INSTANCENAME", 1, 1, true);
883 		if (instancenameA == null) {
884 			throw new CIMXMLParseException("LOCALINSTANCEPATH element missing INSTANCENAME child element!");
885 		}
886 		CIMObjectPath op = parseINSTANCENAME(instancenameA[0]);
887 		/*
888 		 * CIMObjectPath(String objectName, String namespace, CIMProperty[]
889 		 * keys)
890 		 */
891 		checkOtherNodes(pLocalInstancePathE, nodesLOCALINSTANCEPATH);
892 		return cLocalPathBuilder.build(op.getObjectName(), nameSpace, op.getKeys());
893 	}
894 
895 	private static final String nodesINSTANCENAME[] = { "KEYBINDING", "KEYVALUE", "VALUE.REFERENCE" };
896 
897 	/**
898 	 * parseINSTANCENAME
899 	 *
900 	 * @param pInstanceNameE
901 	 * @return CIMObjectPath
902 	 * @throws CIMXMLParseException
903 	 */
904 	public static CIMObjectPath parseINSTANCENAME(Element pInstanceNameE) throws CIMXMLParseException {
905 		// <!ELEMENT INSTANCENAME (KEYBINDING*|KEYVALUE?|VALUE.REFERENCE?)>
906 		// <!ATTLIST INSTANCENAME %CLASSNAME;>
907 		Attr instance_classnameA = (Attr) searchAttribute(pInstanceNameE, "CLASSNAME");
908 		if (instance_classnameA == null) throw new CIMXMLParseException(
909 			"INSTANCENAME element missing CLASSNAME attribute!"
910 		);
911 		String opClassName = instance_classnameA.getNodeValue();
912 
913 		// KEYBINDING
914 		Element[] keyBindingElementA = searchNodes(pInstanceNameE, "KEYBINDING", 0, Integer.MAX_VALUE, false);
915 		if (keyBindingElementA != null) {
916 			CIMProperty<?>[] keys = new CIMProperty[keyBindingElementA.length];
917 			for (int i = 0; i < keyBindingElementA.length; i++) {
918 				Element keybindingE = keyBindingElementA[i];
919 				keys[i] = parseKEYBINDING(keybindingE);
920 			}
921 			return cLocalPathBuilder.build(opClassName, null, keys);
922 		}
923 
924 		// KEYVALUE
925 		Element keyvalueA[] = searchNodes(pInstanceNameE, "KEYVALUE", 0, 1, false);
926 		if (keyvalueA != null) {
927 			CIMProperty<?>[] keys = new CIMProperty[1];
928 			TypedValue propTypedVal = parseKEYVALUE(keyvalueA[0]);
929 			keys[0] = new CIMProperty<Object>("", propTypedVal.getType(), propTypedVal.getValue(), true, false, null);
930 			return cLocalPathBuilder.build(opClassName, null, keys);
931 		}
932 
933 		// VALUE.REFERENCE
934 		Element valuereferenceA[] = searchNodes(pInstanceNameE, "VALUE.REFERENCE", 0, 1, false);
935 		if (valuereferenceA != null) {
936 			CIMProperty<?>[] keys = new CIMProperty[1];
937 			CIMObjectPath op = parseVALUEREFERENCE(valuereferenceA[0]);
938 			keys[0] = new CIMProperty<CIMObjectPath>("", new CIMDataType(op.getObjectName()), op, true, false, null);
939 			return cLocalPathBuilder.build(opClassName, null, keys);
940 		}
941 
942 		checkOtherNodes(pInstanceNameE, nodesINSTANCENAME);
943 
944 		return new CIMObjectPath(null, null, null, null, opClassName, null);
945 	}
946 
947 	/**
948 	 * parseOBJECTPATH
949 	 *
950 	 * @param pObjectPathE
951 	 * @return CIMObjectPath
952 	 * @throws CIMXMLParseException
953 	 */
954 	public static CIMObjectPath parseOBJECTPATH(Element pObjectPathE) throws CIMXMLParseException {
955 		// <!ELEMENT OBJECTPATH (INSTANCEPATH|CLASSPATH) >
956 
957 		// INSTANCEPATH
958 		Element instancepathA[] = searchNodes(pObjectPathE, "INSTANCEPATH", 0, 1, false);
959 		if (instancepathA != null) {
960 			CIMObjectPath op = parseINSTANCEPATH(instancepathA[0]);
961 			return op;
962 		}
963 
964 		// CLASSPATH
965 		Element classpathA[] = searchNodes(pObjectPathE, "CLASSPATH", 0, 1, false);
966 		if (classpathA != null) {
967 			CIMObjectPath op = parseCLASSPATH(classpathA[0]);
968 			return op;
969 		}
970 
971 		throw new CIMXMLParseException("OBJECTPATH element missing required child element!");
972 	}
973 
974 	/**
975 	 * parseKEYBINDING
976 	 *
977 	 * @param pKeyBindingE
978 	 * @return CIMProperty
979 	 * @throws CIMXMLParseException
980 	 */
981 	public static CIMProperty<?> parseKEYBINDING(Element pKeyBindingE) throws CIMXMLParseException {
982 		// <!ELEMENT KEYBINDING (KEYVALUE|VALUE.REFERENCE) >
983 		// <!ATTLIST KEYBINDING %NAME;>
984 
985 		Attr keybinding_nameA = (Attr) searchAttribute(pKeyBindingE, "NAME");
986 		if (keybinding_nameA == null) throw new CIMXMLParseException("KEYBINDING element missing NAME attribute!");
987 		String propName = keybinding_nameA.getValue();
988 
989 		// KEYVALUE
990 		Element keyvalueA[] = searchNodes(pKeyBindingE, "KEYVALUE", 0, 1, false);
991 		if (keyvalueA != null) {
992 			TypedValue propTypedVal = parseKEYVALUE(keyvalueA[0]);
993 			return new CIMProperty<Object>(propName, propTypedVal.getType(), propTypedVal.getValue(), true, false, null);
994 		}
995 
996 		// VALUE.REFERENCE
997 		Element valuereferenceA[] = searchNodes(pKeyBindingE, "VALUE.REFERENCE", 0, 1, false);
998 		if (valuereferenceA != null) {
999 			CIMObjectPath op = parseVALUEREFERENCE(valuereferenceA[0]);
1000 			return new CIMProperty<CIMObjectPath>(propName, new CIMDataType(op.getObjectName()), op, true, false, null);
1001 		}
1002 
1003 		throw new CIMXMLParseException("KEYBINDING element missing required child element!");
1004 	}
1005 
1006 	private static final TreeMap<String, CIMDataType> TYPESTR_MAP = new TreeMap<String, CIMDataType>(
1007 		new Comparator<Object>() {
1008 
1009 			public int compare(Object pO1, Object pO2) {
1010 				return ((String) pO1).compareToIgnoreCase((String) pO2);
1011 			}
1012 		}
1013 	);
1014 
1015 	static {
1016 		TYPESTR_MAP.put(MOF.DT_UINT8, CIMDataType.UINT8_T);
1017 		TYPESTR_MAP.put(MOF.DT_UINT16, CIMDataType.UINT16_T);
1018 		TYPESTR_MAP.put(MOF.DT_UINT32, CIMDataType.UINT32_T);
1019 		TYPESTR_MAP.put(MOF.DT_UINT64, CIMDataType.UINT64_T);
1020 		TYPESTR_MAP.put(MOF.DT_SINT8, CIMDataType.SINT8_T);
1021 		TYPESTR_MAP.put(MOF.DT_SINT16, CIMDataType.SINT16_T);
1022 		TYPESTR_MAP.put(MOF.DT_SINT32, CIMDataType.SINT32_T);
1023 		TYPESTR_MAP.put(MOF.DT_SINT64, CIMDataType.SINT64_T);
1024 		TYPESTR_MAP.put(MOF.DT_REAL32, CIMDataType.REAL32_T);
1025 		TYPESTR_MAP.put(MOF.DT_REAL64, CIMDataType.REAL64_T);
1026 		TYPESTR_MAP.put(MOF.DT_CHAR16, CIMDataType.CHAR16_T);
1027 		TYPESTR_MAP.put(MOF.DT_STR, CIMDataType.STRING_T);
1028 		TYPESTR_MAP.put(MOF.DT_BOOL, CIMDataType.BOOLEAN_T);
1029 		TYPESTR_MAP.put(MOF.DT_DATETIME, CIMDataType.DATETIME_T);
1030 		// FIXME: ebak: What to do with those types which are not specified by
1031 		// MOF's BNF?
1032 		TYPESTR_MAP.put(MOF.INVALID, CIMDataType.INVALID_T);
1033 		// FIXME: ebak: What is the string representation of OBJECT?
1034 		TYPESTR_MAP.put("object", CIMDataType.OBJECT_T);
1035 		TYPESTR_MAP.put(MOF.CLASS, CIMDataType.CLASS_T);
1036 		TYPESTR_MAP.put(MOF.REFERENCE, new CIMDataType(""));
1037 	}
1038 
1039 	/**
1040 	 * parseScalarTypeStr
1041 	 *
1042 	 * @param pTypeStr
1043 	 * @return CIMDataType
1044 	 * @throws CIMXMLParseException
1045 	 */
1046 	public static CIMDataType parseScalarTypeStr(String pTypeStr) throws CIMXMLParseException {
1047 		return parseTypeStr(pTypeStr, false);
1048 	}
1049 
1050 	/**
1051 	 * parseArrayTypeStr
1052 	 *
1053 	 * @param pTypeStr
1054 	 * @return CIMDataType
1055 	 * @throws CIMXMLParseException
1056 	 */
1057 	public static CIMDataType parseArrayTypeStr(String pTypeStr) throws CIMXMLParseException {
1058 		return parseTypeStr(pTypeStr, true);
1059 	}
1060 
1061 	/**
1062 	 * parseTypeStr
1063 	 *
1064 	 * @param pTypeStr
1065 	 * @param pArray
1066 	 * @return CIMDataType
1067 	 * @throws CIMXMLParseException
1068 	 */
1069 	public static CIMDataType parseTypeStr(String pTypeStr, boolean pArray) throws CIMXMLParseException {
1070 		if (pTypeStr == null) return pArray ? CIMDataType.STRING_ARRAY_T : CIMDataType.STRING_T;
1071 		CIMDataType type = TYPESTR_MAP.get(pTypeStr);
1072 		if (type == null) throw new CIMXMLParseException("Unknown TYPE string:" + pTypeStr);
1073 		if (pArray) {
1074 			if (type.getType() == CIMDataType.REFERENCE) return new CIMDataType(type.getRefClassName(), 0);
1075 			return CIMHelper.UnboundedArrayDataType(type.getType());
1076 		}
1077 		return type;
1078 	}
1079 
1080 	/**
1081 	 * parseKEYVALUE
1082 	 *
1083 	 * @param pKeyValueE
1084 	 * @return TypedValue
1085 	 * @throws CIMXMLParseException
1086 	 */
1087 	public static TypedValue parseKEYVALUE(Element pKeyValueE) throws CIMXMLParseException {
1088 		/*
1089 		 * <!ELEMENT KEYVALUE (#PCDATA)> <!ATTLIST KEYVALUE VALUETYPE
1090 		 * (string|boolean|numeric) 'string') %CIMType; #IMPLIED>
1091 		 */
1092 		// ebak: if TYPE attribute is included there is no need to deal with
1093 		// VALUETYPE attribute
1094 		String typeStr = attribute(pKeyValueE, "TYPE");
1095 
1096 		Text valueT = (Text) searchFirstChild(pKeyValueE);
1097 		String valueStr = valueT == null ? null : valueT.getNodeValue();
1098 
1099 		if (typeStr == null) {
1100 			String valueTypeStr = attribute(pKeyValueE, "VALUETYPE");
1101 			if (valueTypeStr == null) valueTypeStr = "string";
1102 			ValueTypeHandler vtHandler = new ValueTypeHandler(valueTypeStr, valueStr);
1103 			return new TypedValue(vtHandler.getType(), vtHandler.getValue());
1104 		}
1105 		Object value = valueStr == null ? "" : createJavaObject(typeStr, valueStr);
1106 		return new TypedValue(parseScalarTypeStr(typeStr), value);
1107 	}
1108 
1109 	/**
1110 	 * Class ValueTypeHandler determines the value and type of a KEYVALUE XML
1111 	 * element, when the VALUETYPE attribute is provided instead of the exact
1112 	 * TYPE attribute. There is a very similar code section in the PULL and SAX
1113 	 * parser, but that section wasn't made common since in ideal case the DOM
1114 	 * parser will be removed.
1115 	 */
1116 	private static class ValueTypeHandler {
1117 		private CIMDataType iType;
1118 
1119 		private Object iValue;
1120 
1121 		/**
1122 		 *
1123 		 * Ctor.
1124 		 *
1125 		 * @param pValueTypeStr
1126 		 * @param pValueStr
1127 		 * @throws CIMXMLParseException
1128 		 */
1129 		public ValueTypeHandler(String pValueTypeStr, String pValueStr) throws CIMXMLParseException {
1130 			if (pValueTypeStr == null) throw new CIMXMLParseException("KEYVALUE element missing VALUETYPE attribute!");
1131 
1132 			if (pValueTypeStr.equals("numeric")) {
1133 				if (!setUInt64(pValueStr) && !setSInt64(pValueStr) && !setReal64(pValueStr)) throw new CIMXMLParseException(
1134 					"Unparseable \"number\" value: " + pValueStr + " !"
1135 				);
1136 			} else if (pValueTypeStr.equals(MOF.DT_STR)) {
1137 				if (!setDTAbsolute(pValueStr) && !setDTInterval(pValueStr)) {
1138 					this.iValue = pValueStr;
1139 					this.iType = CIMDataType.STRING_T;
1140 				}
1141 			} else if (pValueTypeStr.equals(MOF.DT_BOOL)) {
1142 				if (!setBoolean(pValueStr)) throw new CIMXMLParseException(
1143 					"Unparseable \"boolean\" value: " + pValueStr + " !"
1144 				);
1145 			} else {
1146 				throw new CIMXMLParseException(
1147 					"KEYVALUE element's VALUETYPE attribute must be " +
1148 					MOF.DT_STR +
1149 					", " +
1150 					MOF.DT_BOOL +
1151 					" or numeric! " +
1152 					pValueStr +
1153 					" is not allowed!"
1154 				);
1155 			}
1156 		}
1157 
1158 		/**
1159 		 *
1160 		 * getType
1161 		 *
1162 		 * @return CIMDataType
1163 		 */
1164 		public CIMDataType getType() {
1165 			return this.iType;
1166 		}
1167 
1168 		/**
1169 		 *
1170 		 * getValue
1171 		 *
1172 		 * @return Object
1173 		 */
1174 		public Object getValue() {
1175 			return this.iValue;
1176 		}
1177 
1178 		private boolean setUInt64(String pValue) {
1179 			try {
1180 				this.iValue = new UnsignedInteger64(pValue);
1181 			} catch (NumberFormatException e) {
1182 				return false;
1183 			}
1184 			this.iType = CIMDataType.UINT64_T;
1185 			return true;
1186 		}
1187 
1188 		private boolean setSInt64(String pValue) {
1189 			try {
1190 				this.iValue = new Long(pValue);
1191 			} catch (NumberFormatException e) {
1192 				return false;
1193 			}
1194 			this.iType = CIMDataType.SINT64_T;
1195 			return true;
1196 		}
1197 
1198 		private boolean setReal64(String pValue) {
1199 			try {
1200 				if (WBEMConfiguration.getGlobalConfiguration().verifyJavaLangDoubleStrings()) {
1201 					if (Util.isBadDoubleString(pValue)) return false;
1202 				}
1203 				this.iValue = new Double(pValue);
1204 			} catch (NumberFormatException e) {
1205 				return false;
1206 			}
1207 			this.iType = CIMDataType.REAL64_T;
1208 			return true;
1209 		}
1210 
1211 		private boolean setBoolean(String pValue) {
1212 			this.iValue = Boolean.valueOf(pValue);
1213 			this.iType = CIMDataType.BOOLEAN_T;
1214 			return true;
1215 		}
1216 
1217 		private boolean setDTAbsolute(String pValue) {
1218 			try {
1219 				this.iValue = new CIMDateTimeAbsolute(pValue);
1220 			} catch (IllegalArgumentException e) {
1221 				return false;
1222 			}
1223 			this.iType = CIMDataType.DATETIME_T;
1224 			return true;
1225 		}
1226 
1227 		private boolean setDTInterval(String pValue) {
1228 			try {
1229 				this.iValue = new CIMDateTimeInterval(pValue);
1230 			} catch (IllegalArgumentException e) {
1231 				return false;
1232 			}
1233 			this.iType = CIMDataType.DATETIME_T;
1234 			return true;
1235 		}
1236 	}
1237 
1238 	// ////////////////////////////////////////////////////////////////////////////////////////
1239 	// Object Definition Elements
1240 	// ////////////////////////////////////////////////////////////////////////////////////////
1241 
1242 	private static String attribute(Element pElement, String pName) {
1243 		String attrib = pElement.getAttribute(pName);
1244 		if (attrib == null || attrib.length() == 0) return null;
1245 		return attrib;
1246 	}
1247 
1248 	private static final String[] nodesCLASS = {
1249 		"QUALIFIER",
1250 		"PROPERTY",
1251 		"PROPERTY.ARRAY",
1252 		"PROPERTY.REFERENCE",
1253 		"METHOD"
1254 	};
1255 
1256 	/**
1257 	 * parseCLASS
1258 	 *
1259 	 * @param pClassE
1260 	 * @return CIMClass
1261 	 * @throws CIMXMLParseException
1262 	 */
1263 	public static CIMClass parseCLASS(Element pClassE) throws CIMXMLParseException {
1264 		return parseCLASS(pClassE, null);
1265 	}
1266 
1267 	/**
1268 	 * parseCLASS
1269 	 *
1270 	 * @param pClassE
1271 	 * @param pObjectPath
1272 	 * @return CIMClass
1273 	 * @throws CIMXMLParseException
1274 	 */
1275 	public static CIMClass parseCLASS(Element pClassE, CIMObjectPath pObjectPath) throws CIMXMLParseException {
1276 		// <!ELEMENT CLASS (QUALIFIER*,
1277 		// (PROPERTY|PROPERTY.ARRAY|PROPERTY.REFERENCE)*,METHOD*)>
1278 		// <!ATTLIST CLASS %NAME;%SUPERCLASS;>
1279 
1280 		Attr class_nameA = (Attr) searchAttribute(pClassE, "NAME");
1281 		if (class_nameA == null) throw new CIMXMLParseException("CLASS element missing NAME attribute!");
1282 		String name = class_nameA.getNodeValue();
1283 
1284 		// Attr superclass_nameA = (Attr)searchAttribute(classE, "SUPERCLASS");
1285 		// String supername = superclass_nameA.getNodeValue();
1286 
1287 		String superClass = attribute(pClassE, "SUPERCLASS");
1288 
1289 		// QUALIFIER
1290 		CIMQualifier<?>[] qualis = parseQUALIFIERS(pClassE);
1291 
1292 		// PROPERTY
1293 		CIMClassProperty<?>[] props = parseCLASSPROPERTIES(pClassE);
1294 
1295 		// METHOD
1296 		Element[] methodElementA = searchNodes(pClassE, "METHOD", 0, Integer.MAX_VALUE, true);
1297 		CIMMethod<?>[] methods;
1298 		if (methodElementA != null) {
1299 			methods = new CIMMethod[methodElementA.length];
1300 			for (int i = 0; i < methodElementA.length; i++) {
1301 				Element methodE = methodElementA[i];
1302 				methods[i] = parseMETHOD(methodE);
1303 			}
1304 		} else {
1305 			methods = null;
1306 		}
1307 
1308 		/*
1309 		 * CIMClass( String name, String superclass, CIMQualifier[] qualifiers,
1310 		 * CIMClassProperty[] props, CIMMethod[] methods )
1311 		 *
1312 		 * return new CIMClass( name, superClass, qualis, props, methods );
1313 		 *
1314 		 * This constructor can provide localPath info. CIMClass( CIMObjectPath
1315 		 * path, String superclass, CIMQualifier[] qualifiers,
1316 		 * CIMClassProperty[] props, CIMMethod[] pMethods, boolean
1317 		 * pIsAssociation, boolean pIsKeyed )
1318 		 */
1319 		checkOtherNodes(pClassE, nodesCLASS);
1320 
1321 		return new CIMClass(
1322 			pObjectPath == null ? cLocalPathBuilder.build(name, null) : pObjectPath,
1323 			superClass,
1324 			qualis,
1325 			props,
1326 			methods,
1327 			hasAssocQuali(qualis),
1328 			hasKeyProp(props)
1329 		);
1330 	}
1331 
1332 	private static boolean hasAssocQuali(CIMQualifier<?>[] pQualis) {
1333 		if (pQualis == null) return false;
1334 		for (int i = 0; i < pQualis.length; i++) {
1335 			CIMQualifier<?> quali = pQualis[i];
1336 			if ("ASSOCIATION".equalsIgnoreCase(quali.getName()) && Boolean.TRUE.equals(quali.getValue())) return true;
1337 		}
1338 		return false;
1339 	}
1340 
1341 	private static boolean hasKeyProp(CIMProperty<?>[] pProps) {
1342 		if (pProps == null) return false;
1343 		for (int i = 0; i < pProps.length; i++) if (pProps[i].isKey()) return true;
1344 		return false;
1345 	}
1346 
1347 	private static CIMParameter<?>[] parseParameters(Element pMethodE) throws CIMXMLParseException {
1348 		// PARAMETER
1349 		Vector<CIMParameter<Object>> paramV = new Vector<CIMParameter<Object>>();
1350 		Element[] paramElementA = searchNodes(pMethodE, "PARAMETER");
1351 		if (paramElementA != null) {
1352 			for (int i = 0; i < paramElementA.length; i++) {
1353 				Element parameterE = paramElementA[i];
1354 				CIMParameter<Object> p = parsePARAMETER(parameterE);
1355 				paramV.add(p);
1356 			}
1357 		}
1358 
1359 		Element[] paramRefElementA = searchNodes(pMethodE, "PARAMETER.REFERENCE");
1360 		if (paramRefElementA != null) {
1361 			for (int i = 0; i < paramRefElementA.length; i++) {
1362 				Element parameterE = paramRefElementA[i];
1363 				CIMParameter<Object> p = parsePARAMETERREFERENCE(parameterE);
1364 				paramV.add(p);
1365 			}
1366 		}
1367 
1368 		Element[] paramArrayElementA = searchNodes(pMethodE, "PARAMETER.ARRAY");
1369 		if (paramArrayElementA != null) {
1370 			for (int i = 0; i < paramArrayElementA.length; i++) {
1371 				Element parameterE = paramArrayElementA[i];
1372 				CIMParameter<Object> p = parsePARAMETERARRAY(parameterE);
1373 				paramV.add(p);
1374 			}
1375 		}
1376 
1377 		Element[] paramRefArrayElementA = searchNodes(pMethodE, "PARAMETER.REFARRAY");
1378 		if (paramRefArrayElementA != null) {
1379 			for (int i = 0; i < paramRefArrayElementA.length; i++) {
1380 				Element parameterE = paramRefArrayElementA[i];
1381 				CIMParameter<Object> p = parsePARAMETERREFARRAY(parameterE);
1382 				paramV.add(p);
1383 			}
1384 		}
1385 
1386 		return paramV.toArray(new CIMParameter[0]);
1387 	}
1388 
1389 	private static final String nodesMETHOD[] = {
1390 		"QUALIFIER",
1391 		"PARAMETER",
1392 		"PARAMETER.REFERENCE",
1393 		"PARAMETER.ARRAY",
1394 		"PARAMETER.REFARRAY"
1395 	};
1396 
1397 	/**
1398 	 * parseMETHOD
1399 	 *
1400 	 * @param pMethodE
1401 	 * @return CIMMethod
1402 	 * @throws CIMXMLParseException
1403 	 */
1404 	public static CIMMethod<Object> parseMETHOD(Element pMethodE) throws CIMXMLParseException {
1405 		// <!ELEMENT METHOD
1406 		// (QUALIFIER*,(PARAMETER|PARAMETER.REFERENCE|PARAMETER.ARRAY|PARAMETER.REFARRAY)*)>
1407 		// <!ATTLIST METHOD
1408 		// %CIMName;
1409 		// %CIMType; #IMPLIED
1410 		// %ClassOrigin;
1411 		// %Propagated;>
1412 
1413 		String name = attribute(pMethodE, "NAME");
1414 		if (name == null) throw new CIMXMLParseException("METHOD element missing NAME attribute!");
1415 		EmbObjHandler embObjHandler = new EmbObjHandler(pMethodE);
1416 		CIMDataType type = embObjHandler.getType();
1417 		if (type != null && type.isArray()) throw new CIMXMLParseException("Method's type cannot be Array!");
1418 		String classOrigin = attribute(pMethodE, "CLASSORIGIN");
1419 		String propagatedStr = pMethodE.getAttribute("PROPAGATED");
1420 		boolean propagated = "true".equalsIgnoreCase(propagatedStr);
1421 
1422 		checkOtherNodes(pMethodE, nodesMETHOD);
1423 
1424 		// PARAMETERS
1425 		CIMParameter<?>[] params = parseParameters(pMethodE);
1426 		// CIMMethod(String name, CIMDataType type, CIMQualifier[] qualifiers,
1427 		// CIMParameter[] parameters, boolean propagated, String originClass)
1428 		return new CIMMethod<Object>(name, type, embObjHandler.getQualifiers(), params, propagated, classOrigin);
1429 	}
1430 
1431 	private static final String nodesPARAMETER[] = { "QUALIFIER" };
1432 
1433 	/**
1434 	 * parsePARAMETER
1435 	 *
1436 	 * @param pParamE
1437 	 * @return CIMParameter
1438 	 * @throws CIMXMLParseException
1439 	 */
1440 	public static CIMParameter<Object> parsePARAMETER(Element pParamE) throws CIMXMLParseException {
1441 		String name = attribute(pParamE, "NAME");
1442 		if (name == null) throw new CIMXMLParseException("PARAMETER element missing NAME attribute!");
1443 		if (attribute(pParamE, "TYPE") == null) throw new CIMXMLParseException("PARAMETER element missing TYPE attribute!");
1444 		checkOtherNodes(pParamE, nodesPARAMETER);
1445 		EmbObjHandler iEmbObjHandler = new EmbObjHandler(pParamE);
1446 		// CIMParameter(String name, CIMDataType type, CIMQualifier[]
1447 		// qualifiers)
1448 		return new CIMParameter<Object>(name, iEmbObjHandler.getType(), iEmbObjHandler.getQualifiers());
1449 	}
1450 
1451 	private static final String nodesPARAMETERREFERENCE[] = { "QUALIFIER" };
1452 
1453 	/**
1454 	 * parsePARAMETERREFERENCE
1455 	 *
1456 	 * @param pParamE
1457 	 * @return CIMParameter
1458 	 * @throws CIMXMLParseException
1459 	 */
1460 	public static CIMParameter<Object> parsePARAMETERREFERENCE(Element pParamE) throws CIMXMLParseException {
1461 		String name = attribute(pParamE, "NAME");
1462 		if (name == null) throw new CIMXMLParseException("PARAMETER.REFERENCE element missing NAME attribute!");
1463 		String referenceClass = attribute(pParamE, "REFERENCECLASS");
1464 		CIMDataType type = new CIMDataType(referenceClass != null ? referenceClass : "");
1465 		checkOtherNodes(pParamE, nodesPARAMETERREFERENCE);
1466 		// QUALIFIER
1467 		CIMQualifier<?>[] qualis = parseQUALIFIERS(pParamE);
1468 		return new CIMParameter<Object>(name, type, qualis);
1469 	}
1470 
1471 	private static final String nodesPARAMETERARRAY[] = { "QUALIFIER" };
1472 
1473 	/**
1474 	 * parsePARAMETERARRAY
1475 	 *
1476 	 * @param pParamE
1477 	 * @return CIMParameter
1478 	 * @throws CIMXMLParseException
1479 	 */
1480 	public static CIMParameter<Object> parsePARAMETERARRAY(Element pParamE) throws CIMXMLParseException {
1481 		String name = attribute(pParamE, "NAME");
1482 		if (name == null) throw new CIMXMLParseException("PARAMETER.ARRAY element missing NAME attribute!");
1483 		if (attribute(pParamE, "TYPE") == null) throw new CIMXMLParseException(
1484 			"PARAMETER.ARRAY element missing TYPE attribute!"
1485 		);
1486 		String arraySizeStr = pParamE.getAttribute("ARRAYSIZE");
1487 		try {
1488 			if (arraySizeStr.length() > 0) Integer.parseInt(arraySizeStr);
1489 		} catch (NumberFormatException e) {
1490 			throw new CIMXMLParseException(arraySizeStr + " is not a valid ARRAYSIZE attribute for PARAMETER.ARRAY!");
1491 		}
1492 		checkOtherNodes(pParamE, nodesPARAMETERARRAY);
1493 		EmbObjHandler iEmbObjHandler = new EmbObjHandler(pParamE);
1494 		return new CIMParameter<Object>(name, iEmbObjHandler.getArrayType(), iEmbObjHandler.getQualifiers());
1495 	}
1496 
1497 	private static final String nodesPARAMETERREFARRAY[] = { "QUALIFIER" };
1498 
1499 	/**
1500 	 * parsePARAMETERREFARRAY
1501 	 *
1502 	 * @param pParamE
1503 	 * @return CIMParameter
1504 	 * @throws CIMXMLParseException
1505 	 */
1506 	public static CIMParameter<Object> parsePARAMETERREFARRAY(Element pParamE) throws CIMXMLParseException {
1507 		String name = attribute(pParamE, "NAME");
1508 		if (name == null) throw new CIMXMLParseException("PARAMETER.REFARRAY element missing NAME attribute!");
1509 
1510 		String referenceClass = attribute(pParamE, "REFERENCECLASS");
1511 
1512 		int arraySize = 0; // unlimited
1513 		String arraySizeStr = pParamE.getAttribute("ARRAYSIZE");
1514 		try {
1515 			if (arraySizeStr.length() > 0) arraySize = Integer.parseInt(arraySizeStr);
1516 		} catch (NumberFormatException e) {
1517 			throw new CIMXMLParseException(arraySizeStr + " is not a valid ARRAYSIZE attribute for PARAMETER.REFARRAY!");
1518 		}
1519 
1520 		CIMDataType type = new CIMDataType((referenceClass != null) ? referenceClass : "", arraySize);
1521 
1522 		// QUALIFIER
1523 		checkOtherNodes(pParamE, nodesPARAMETERREFARRAY);
1524 		CIMQualifier<?>[] qualis = parseQUALIFIERS(pParamE);
1525 		return new CIMParameter<Object>(name, type, qualis);
1526 	}
1527 
1528 	/**
1529 	 * parseINSTANCE
1530 	 *
1531 	 * @param pInstanceE
1532 	 * @return CIMInstance
1533 	 * @throws CIMXMLParseException
1534 	 */
1535 	public static CIMInstance parseINSTANCE(Element pInstanceE) throws CIMXMLParseException {
1536 		return parseINSTANCE(pInstanceE, null);
1537 	}
1538 
1539 	private static final String[] nodesINSTANCE = { "QUALIFIER", "PROPERTY", "PROPERTY.ARRAY", "PROPERTY.REFERENCE" };
1540 
1541 	/**
1542 	 * parseINSTANCE
1543 	 *
1544 	 * @param pInstanceE
1545 	 * @param pObjPath
1546 	 * @return CIMInstance
1547 	 * @throws CIMXMLParseException
1548 	 */
1549 	public static CIMInstance parseINSTANCE(Element pInstanceE, CIMObjectPath pObjPath) throws CIMXMLParseException {
1550 		// <!ELEMENT INSTANCE (QUALIFIER*,
1551 		// (PROPERTY|PROPERTY.ARRAY|PROPERTY.REFERENCE)*)>
1552 		// <!ATTLIST INSTANCE %CLASSNAME;>
1553 
1554 		// BB mod CIMInstance inst = new CIMInstance();
1555 		String className = attribute(pInstanceE, "CLASSNAME");
1556 		if (className == null) throw new CIMXMLParseException("INSTANCE element missing CLASSNAME attribute!");
1557 		// QUALIFIER
1558 		// FIXME: in JSR48 CIMInstance doesn't have qualifiers
1559 		// CIMQualifier[] qualis = parseQUALIFIERS(pInstanceE);
1560 		// PROPERTY
1561 		CIMProperty<?>[] props = parsePROPERTIES(pInstanceE);
1562 
1563 		checkOtherNodes(pInstanceE, nodesINSTANCE);
1564 
1565 		if (pObjPath == null) return new CIMInstance(cLocalPathBuilder.build(className, null), props);
1566 		if (
1567 			WBEMConfiguration.getGlobalConfiguration().synchronizeNumericKeyDataTypes()
1568 		) return CIMHelper.CIMInstanceWithSynchonizedNumericKeyDataTypes(pObjPath, props);
1569 		return new CIMInstance(pObjPath, props);
1570 	}
1571 
1572 	/**
1573 	 * ebak: Access to enclosing method parseQUALIFIERS(Element) from the type
1574 	 * CIMXMLParserImpl is emulated by a synthetic accessor method. Increasing
1575 	 * its visibility will improve your performance
1576 	 *
1577 	 * @param pElement
1578 	 * @return CIMQualifier[]
1579 	 * @throws CIMXMLParseException
1580 	 */
1581 	public static CIMQualifier<?>[] parseQUALIFIERS(Element pElement) throws CIMXMLParseException {
1582 		Element[] qualiElementA = searchNodes(pElement, "QUALIFIER");
1583 		CIMQualifier<?>[] qualis;
1584 		if (qualiElementA != null) {
1585 			qualis = new CIMQualifier[qualiElementA.length];
1586 			for (int i = 0; i < qualiElementA.length; i++) {
1587 				Element qualifierE = qualiElementA[i];
1588 				qualis[i] = parseQUALIFIER(qualifierE);
1589 			}
1590 		} else qualis = null;
1591 		return qualis;
1592 	}
1593 
1594 	/**
1595 	 * <pre>
1596 	 *  ENTITY % QualifierFlavor &quot;
1597 	 *  OVERRIDABLE    (true|false)  'true'
1598 	 *  TOSUBCLASS     (true|false)  'true'
1599 	 *  TOINSTANCE     (true|false)  'false'
1600 	 *  TRANSLATABLE   (true|false)  'false'&quot;
1601 	 * </pre>
1602 	 *
1603 	 * @param pElement
1604 	 * @return int - CIMFlavor bit mixture
1605 	 */
1606 	private static int parseFLAVORS(Element pElement) {
1607 		int flavors = 0;
1608 		if (!getBoolAttribute(pElement, "OVERRIDABLE", true)) flavors |= CIMFlavor.DISABLEOVERRIDE;
1609 		if (!getBoolAttribute(pElement, "TOSUBCLASS", true)) flavors |= CIMFlavor.RESTRICTED;
1610 		if (getBoolAttribute(pElement, "TRANSLATABLE", false)) flavors |= CIMFlavor.TRANSLATE;
1611 		return flavors;
1612 	}
1613 
1614 	private static TypedValue parseSingleValue(Element pElement) throws CIMXMLParseException {
1615 		return parseSingleValue(pElement, VALUE | VALUEA);
1616 	}
1617 
1618 	private static final int VALUE = 1, VALUEA = 2, VALUEREF = 4, VALUEREFA = 8;
1619 
1620 	private static TypedValue parseSingleValue(Element pElement, int pMask) throws CIMXMLParseException {
1621 		boolean foundSingleValue = false;
1622 		String typeStr = attribute(pElement, "TYPE");
1623 		// ebak: there was an ESS fix in the base implementation
1624 		if (typeStr == null) typeStr = attribute(pElement, "PARAMTYPE");
1625 		CIMDataType type = null;
1626 		Object value = null;
1627 		if ((pMask & VALUE) > 0) {
1628 			Element valueE = (Element) searchFirstNode(pElement, "VALUE");
1629 			if (valueE != null) {
1630 				TypedValue tVal = parseVALUE(valueE);
1631 				String valueStr = (String) tVal.getValue();
1632 				type = typeStr == null ? tVal.getType() : parseScalarTypeStr(typeStr);
1633 				value = createJavaObject(type == null ? null : type.toString(), valueStr);
1634 				foundSingleValue = true;
1635 			}
1636 		}
1637 		if (!foundSingleValue && (pMask & VALUEREF) > 0) {
1638 			// VALUE.REFERENCE
1639 			Element valuereferenceE = (Element) searchFirstNode(pElement, "VALUE.REFERENCE");
1640 			if (valuereferenceE != null) {
1641 				CIMObjectPath op = parseVALUEREFERENCE(valuereferenceE);
1642 				value = op;
1643 				type = new CIMDataType(op.getObjectName());
1644 				foundSingleValue = true;
1645 			}
1646 		}
1647 		if (!foundSingleValue && (pMask & VALUEA) > 0) {
1648 			// VALUE.ARRAY
1649 			Element valuearrayE = (Element) searchFirstNode(pElement, "VALUE.ARRAY");
1650 			if (valuearrayE != null) {
1651 				TypedValue tValA = parseVALUEARRAY(valuearrayE);
1652 				type = typeStr == null ? tValA.getType() : parseArrayTypeStr(typeStr);
1653 				String[] valStrA = (String[]) tValA.getValue();
1654 				if (valStrA != null) {
1655 					Object[] values = new Object[valStrA.length];
1656 					for (int i = 0; i < valStrA.length; i++) {
1657 						values[i] = createJavaObject(type == null ? null : type.toString(), valStrA[i]);
1658 					}
1659 					value = values;
1660 				}
1661 				foundSingleValue = true;
1662 			}
1663 		}
1664 		if (!foundSingleValue && (pMask & VALUEREFA) > 0) {
1665 			// VALUE.REFARRAY
1666 			Element valueRefArrayE = (Element) searchFirstNode(pElement, "VALUE.REFARRAY");
1667 			if (valueRefArrayE != null) {
1668 				type = new CIMDataType("", 0);
1669 				CIMObjectPath[] opA = parseVALUEREFARRAY(valueRefArrayE);
1670 				value = opA;
1671 				foundSingleValue = true;
1672 			}
1673 		}
1674 		if (!foundSingleValue) {
1675 			if (value instanceof Object[]) type = CIMDataType.STRING_ARRAY_T; else if (value != null) type =
1676 				CIMDataType.STRING_T; else type = CIMDataType.STRING_T; // /throw new
1677 			// CIMXMLParseException("null
1678 			// type with null value!");
1679 		}
1680 		return new TypedValue(type, value);
1681 	}
1682 
1683 	private static final String nodesQUALIFIER[] = { "VALUE", "VALUE.ARRAY" };
1684 
1685 	/**
1686 	 * parseQUALIFIER
1687 	 *
1688 	 * @param pQualifierE
1689 	 * @return CIMQualifier
1690 	 * @throws CIMXMLParseException
1691 	 */
1692 	public static CIMQualifier<?> parseQUALIFIER(Element pQualifierE) throws CIMXMLParseException {
1693 		// <!ELEMENT QUALIFIER (VALUE|VALUE.ARRAY)>
1694 		// <!ATTLIST QUALIFIER %NAME;%TYPE;%PROPAGATED;%QUALIFIERFLAVOR;>
1695 
1696 		String name = attribute(pQualifierE, "NAME");
1697 		if (name == null) throw new CIMXMLParseException("QUALIFIER element missing NAME attribute!");
1698 		String typeStr = attribute(pQualifierE, "TYPE");
1699 		if (typeStr == null && !hasTypeAttrsInNodes(pQualifierE)) throw new CIMXMLParseException(
1700 			"QUALIFIER element missing TYPE attribute!"
1701 		);
1702 		boolean propagated = MOF.TRUE.equalsIgnoreCase(pQualifierE.getAttribute("PROPAGATED"));
1703 		// FLAVORS
1704 		int flavors = parseFLAVORS(pQualifierE);
1705 		// VALUE
1706 		if (
1707 			searchNodes(pQualifierE, "VALUE", 0, 1, false) != null ||
1708 			searchNodes(pQualifierE, "VALUE.ARRAY", 0, 1, false) != null
1709 		) {
1710 			TypedValue typedValue = parseSingleValue(pQualifierE);
1711 			if (typedValue.getType() == null) throw new CIMXMLParseException("Qualifier's type is null!");
1712 			// CIMQualifier(String pName, CIMDataType pType, Object pValue, int
1713 			// pFlavor)
1714 			return new CIMQualifier<Object>(name, typedValue.getType(), typedValue.getValue(), flavors, propagated);
1715 		}
1716 		checkOtherNodes(pQualifierE, nodesQUALIFIER);
1717 
1718 		CIMDataType type = parseScalarTypeStr(typeStr);
1719 		return new CIMQualifier<Object>(name, type != null ? type : CIMDataType.STRING_T, null, flavors, propagated);
1720 	}
1721 
1722 	/**
1723 	 * parseQUALIFIERDECLARATION
1724 	 *
1725 	 * @param pQualifierTypeE
1726 	 * @return CIMQualifierType
1727 	 * @throws CIMXMLParseException
1728 	 */
1729 	public static CIMQualifierType<Object> parseQUALIFIERDECLARATION(Element pQualifierTypeE)
1730 		throws CIMXMLParseException {
1731 		// <!ELEMENT QUALIFIER.DECLARATION (SCOPE?,(VALUE|VALUE.ARRAY)?)>
1732 		// <!ATTLIST QUALIFIER.DECLARATION
1733 		// %CIMName;
1734 		// %CIMType; #REQUIRED
1735 		// ISARRAY (true|false) #IMPLIED
1736 		// %ArraySize;
1737 		// %QualifierFlavor;>
1738 
1739 		String name = attribute(pQualifierTypeE, "NAME");
1740 		if (name == null) throw new CIMXMLParseException("QUALIFIER.DECLARATION element missing NAME attribute!");
1741 		String type = attribute(pQualifierTypeE, "TYPE");
1742 		if (type == null && !hasTypeAttrsInNodes(pQualifierTypeE)) throw new CIMXMLParseException(
1743 			"QUALIFIER.DECLARATION element missing TYPE attribute!"
1744 		);
1745 
1746 		// SCOPES
1747 		// ebak: there should be only 1 scope node
1748 		Element scopeElementA[] = searchNodes(pQualifierTypeE, "SCOPE", 0, 1, true);
1749 		int scopes = scopeElementA == null ? 0 : parseSCOPES(scopeElementA[0]);
1750 		// QUALIFIERS
1751 		// CIMQualifier[] qualis = parseQUALIFIERS(pQualifierTypeE);
1752 
1753 		CIMDataType qdType;
1754 		Object qdValue;
1755 
1756 		String nodes[] = null;
1757 
1758 		if (searchNodes(pQualifierTypeE, "VALUE", 0, 1, true) != null) {
1759 			nodes = new String[] { "SCOPE", "VALUE" };
1760 		} else if (searchNodes(pQualifierTypeE, "VALUE.ARRAY", 0, 1, true) != null) {
1761 			nodes = new String[] { "SCOPE", "VALUE.ARRAY" };
1762 		}
1763 
1764 		// VALUE
1765 		if (nodes != null) {
1766 			TypedValue typedValue = parseSingleValue(pQualifierTypeE);
1767 			qdType = typedValue.getType();
1768 			qdValue = typedValue.getValue();
1769 			boolean isArray = hasTrueAttribute(pQualifierTypeE, "ISARRAY");
1770 			String arraySizeStr = attribute(pQualifierTypeE, "ARRAYSIZE");
1771 			try {
1772 				int arraySize = (arraySizeStr == null ? (isArray ? 0 : -1) : Integer.parseInt(arraySizeStr));
1773 				if (isArray || arraySize >= 0) {
1774 					qdType =
1775 						(arraySize > 0)
1776 							? new CIMDataType(qdType.getType(), arraySize)
1777 							: CIMHelper.UnboundedArrayDataType(qdType.getType());
1778 				}
1779 			} catch (NumberFormatException e) {
1780 				throw new CIMXMLParseException(arraySizeStr + " is not a valid ARRAYSIZE attribute for QUALIFIER.DECLARATION!");
1781 			}
1782 		} else {
1783 			nodes = new String[] { "SCOPE" };
1784 			qdType = parseScalarTypeStr(type);
1785 			if (qdType == null) qdType = CIMDataType.STRING_T;
1786 			qdValue = null;
1787 		}
1788 		checkOtherNodes(pQualifierTypeE, nodes);
1789 
1790 		// FIXME: ebak: what about the flavors?
1791 		return new CIMQualifierType<Object>(
1792 			new CIMObjectPath(null, null, null, null, name, null),
1793 			qdType,
1794 			qdValue,
1795 			scopes,
1796 			0
1797 		);
1798 	}
1799 
1800 	private static boolean hasTrueAttribute(Element pElement, String pName) {
1801 		String valueStr = pElement.getAttribute(pName);
1802 		return MOF.TRUE.equalsIgnoreCase(valueStr);
1803 	}
1804 
1805 	private static boolean getBoolAttribute(Element pElement, String pName, boolean pDefVal) {
1806 		String val = pElement.getAttribute(pName);
1807 		if (MOF.TRUE.equalsIgnoreCase(val)) return true;
1808 		if (MOF.FALSE.equalsIgnoreCase(val)) return false;
1809 		return pDefVal;
1810 	}
1811 
1812 	/**
1813 	 * parseSCOPES
1814 	 *
1815 	 * @param pScopeE
1816 	 * @return int
1817 	 */
1818 	public static int parseSCOPES(Element pScopeE) {
1819 		int scopes = 0;
1820 		if (hasTrueAttribute(pScopeE, "CLASS")) scopes |= CIMScope.CLASS;
1821 		if (hasTrueAttribute(pScopeE, "ASSOCIATION")) scopes |= CIMScope.ASSOCIATION;
1822 		if (hasTrueAttribute(pScopeE, "REFERENCE")) scopes |= CIMScope.REFERENCE;
1823 		if (hasTrueAttribute(pScopeE, "PROPERTY")) scopes |= CIMScope.PROPERTY;
1824 		if (hasTrueAttribute(pScopeE, "METHOD")) scopes |= CIMScope.METHOD;
1825 		if (hasTrueAttribute(pScopeE, "PARAMETER")) scopes |= CIMScope.PARAMETER;
1826 		if (hasTrueAttribute(pScopeE, "INDICATION")) scopes |= CIMScope.INDICATION;
1827 		return scopes;
1828 	}
1829 
1830 	private static Vector<CIMClassProperty<?>> parseClassPropsToVec(Element pElement) throws CIMXMLParseException {
1831 		Element[] propElementA = searchNodes(pElement, "PROPERTY");
1832 		Vector<CIMClassProperty<?>> propVec = new Vector<CIMClassProperty<?>>();
1833 		if (propElementA != null) {
1834 			for (int i = 0; i < propElementA.length; i++) {
1835 				Element propertyE = propElementA[i];
1836 				propVec.add(parseCLASSPROPERTY(propertyE));
1837 			}
1838 		}
1839 
1840 		// PROPERTY.ARRAY
1841 		Element[] propArrayElementA = searchNodes(pElement, "PROPERTY.ARRAY");
1842 		if (propArrayElementA != null) {
1843 			for (int i = 0; i < propArrayElementA.length; i++) {
1844 				Element propertyarrayE = propArrayElementA[i];
1845 				propVec.add(parseCLASSPROPERTYARRAY(propertyarrayE));
1846 			}
1847 		}
1848 
1849 		// PROPERTY.REFERENCE
1850 		Element[] propRefElementA = searchNodes(pElement, "PROPERTY.REFERENCE");
1851 		if (propRefElementA != null) {
1852 			for (int i = 0; i < propRefElementA.length; i++) {
1853 				Element propertyreferenceE = propRefElementA[i];
1854 				propVec.add(parseCLASSPROPERTYREFERENCE(propertyreferenceE));
1855 			}
1856 		}
1857 		return propVec;
1858 	}
1859 
1860 	/**
1861 	 * parsePROPERTIES
1862 	 *
1863 	 * @param pElement
1864 	 * @return CIMProperty[]
1865 	 * @throws CIMXMLParseException
1866 	 */
1867 	public static CIMProperty<?>[] parsePROPERTIES(Element pElement) throws CIMXMLParseException {
1868 		Vector<CIMClassProperty<?>> classPropVec = parseClassPropsToVec(pElement);
1869 		// The following does not convert Vector<CIMClassProperty> to
1870 		// CIMProperty[], it is still CIMClassProperty[]!!! You can treat it
1871 		// like a CIMProperty (property.getValue(), etc.) but (property
1872 		// instanceof CIMProperty) will return false!
1873 		// return classPropVec.toArray(new CIMProperty[0]);
1874 
1875 		int arraySize = classPropVec.size();
1876 		CIMProperty<?>[] retA = new CIMProperty[arraySize];
1877 		for (int i = 0; i < arraySize; i++) {
1878 			CIMClassProperty<?> prop = classPropVec.get(i);
1879 			retA[i] =
1880 				new CIMProperty<Object>(
1881 					prop.getName(),
1882 					prop.getDataType(),
1883 					prop.getValue(),
1884 					prop.isKey(),
1885 					prop.isPropagated(),
1886 					prop.getOriginClass()
1887 				);
1888 		}
1889 		return retA;
1890 	}
1891 
1892 	/**
1893 	 * parseCLASSPROPERTIES
1894 	 *
1895 	 * @param pElement
1896 	 * @return CIMClassProperty[]
1897 	 * @throws CIMXMLParseException
1898 	 */
1899 	public static CIMClassProperty<?>[] parseCLASSPROPERTIES(Element pElement) throws CIMXMLParseException {
1900 		Vector<CIMClassProperty<?>> classPropVec = parseClassPropsToVec(pElement);
1901 		return classPropVec.toArray(new CIMClassProperty[0]);
1902 	}
1903 
1904 	/**
1905 	 * parsePROPERTY
1906 	 *
1907 	 * @param pPropertyE
1908 	 * @return CIMProperty
1909 	 * @throws CIMXMLParseException
1910 	 */
1911 	public static CIMProperty<?> parsePROPERTY(Element pPropertyE) throws CIMXMLParseException {
1912 		return parseCLASSPROPERTY(pPropertyE);
1913 	}
1914 
1915 	private static class EmbObjHandler {
1916 		private CIMQualifier<?>[] iQualiA;
1917 
1918 		private boolean iHasEmbObjAttr, iHasEmbInstAttr, iHasEmbObjQuali, iHasEmbInstQuali, iKeyed;
1919 
1920 		private CIMDataType iRawType, iType;
1921 
1922 		private Object iRawValue, iValue;
1923 
1924 		private Element iElement;
1925 
1926 		private boolean iStrictParsing = WBEMConfiguration.getGlobalConfiguration().strictEmbObjTypes();
1927 
1928 		/**
1929 		 * Ctor.
1930 		 *
1931 		 * @param pElement
1932 		 * @throws CIMXMLParseException
1933 		 */
1934 		public EmbObjHandler(Element pElement) throws CIMXMLParseException {
1935 			this.iElement = pElement;
1936 			handleQualis();
1937 			handleAttribs();
1938 			Element valueE = (Element) searchFirstNode(pElement, "VALUE");
1939 			if (valueE != null) {
1940 				TypedValue tv = parseVALUE(valueE);
1941 				if (this.iRawType == null) this.iRawType = tv.getType();
1942 				if (this.iRawType == null) this.iRawType = CIMDataType.STRING_T;
1943 				this.iRawValue = tv.getValue();
1944 			} else {
1945 				valueE = (Element) searchFirstNode(pElement, "VALUE.ARRAY");
1946 				if (valueE != null) {
1947 					TypedValue tv = parseVALUEARRAY(valueE);
1948 					if (this.iRawType == null) this.iRawType = tv.getType();
1949 					if (this.iRawType == null) this.iRawType = CIMDataType.STRING_ARRAY_T;
1950 					this.iRawValue = tv.getValue();
1951 				}
1952 			}
1953 		}
1954 
1955 		private void handleQualis() throws CIMXMLParseException {
1956 			this.iQualiA = parseQUALIFIERS(this.iElement);
1957 			if (this.iQualiA != null) {
1958 				for (int idx = 0; idx < this.iQualiA.length; idx++) {
1959 					String qualiName = this.iQualiA[idx].getName();
1960 					if ("EmbeddedObject".equalsIgnoreCase(qualiName)) {
1961 						this.iHasEmbObjQuali = true;
1962 					} else if ("EMBEDDEDINSTANCE".equalsIgnoreCase(qualiName)) {
1963 						this.iHasEmbInstQuali = true;
1964 					} else if ("KEY".equalsIgnoreCase(qualiName)) {
1965 						this.iKeyed = true;
1966 					}
1967 					if ((this.iHasEmbObjQuali || this.iHasEmbInstQuali) && this.iKeyed) return;
1968 				}
1969 			}
1970 		}
1971 
1972 		private void handleAttribs() throws CIMXMLParseException {
1973 			String typeStr = this.iElement.getAttribute("TYPE");
1974 			if (typeStr == null || typeStr.length() == 0) {
1975 				typeStr = this.iElement.getAttribute("PARAMTYPE");
1976 				if (typeStr == null || typeStr.length() == 0) {
1977 					/*
1978 					 * throw new CIMXMLParseException( iElement.getNodeName()+"
1979 					 * must contain a TYPE or PARAMTYPE attribute!" );
1980 					 */
1981 					/*
1982 					 * ebak: Workaround for SVC's TYPE attribute in VALUE and
1983 					 * VALUE.ARRAY element.
1984 					 */
1985 					typeStr = null;
1986 				}
1987 			}
1988 			// ebak: iRawType can be filled from contained VALUE or VALUE.ARRAY
1989 			// element (SVC)
1990 			if (typeStr != null) this.iRawType = parseScalarTypeStr(typeStr);
1991 
1992 			// DSPs call for EmbeddedObject AND XML is case sensitive, BUT there
1993 			// are probably CIMOMs out there that still use EMBEDDEDOBJECT
1994 			String embObjAttrStr = this.iElement.getAttribute("EmbeddedObject");
1995 			if (embObjAttrStr == null || embObjAttrStr.length() == 0) {
1996 				embObjAttrStr = this.iElement.getAttribute("EMBEDDEDOBJECT");
1997 			}
1998 			if (embObjAttrStr == null || embObjAttrStr.length() == 0) {
1999 				this.iHasEmbObjAttr = this.iHasEmbInstAttr = false;
2000 			} else if ("object".equalsIgnoreCase(embObjAttrStr)) {
2001 				this.iHasEmbObjAttr = true;
2002 				this.iHasEmbInstAttr = false;
2003 			} else if ("instance".equalsIgnoreCase(embObjAttrStr)) {
2004 				this.iHasEmbObjAttr = false;
2005 				this.iHasEmbInstAttr = true;
2006 			} else throw new CIMXMLParseException("EmbeddedObject attribute cannot contain \"" + embObjAttrStr + "\" value!");
2007 		}
2008 
2009 		/**
2010 		 * getQualifiers
2011 		 *
2012 		 * @return CIMQualifier[]
2013 		 * @throws CIMXMLParseException
2014 		 */
2015 		public CIMQualifier<?>[] getQualifiers() throws CIMXMLParseException {
2016 			transform();
2017 			CIMQualifiedElementInterfaceImpl qualiImpl = new CIMQualifiedElementInterfaceImpl(
2018 				this.iQualiA,
2019 				isKeyed(),
2020 				this.iType == null || this.iType.getType() == CIMDataType.STRING
2021 			);
2022 			return qualiImpl.getQualifiers();
2023 		}
2024 
2025 		/**
2026 		 * isKeyed
2027 		 *
2028 		 * @return boolean
2029 		 */
2030 		public boolean isKeyed() {
2031 			return this.iKeyed;
2032 		}
2033 
2034 		/**
2035 		 * isEmbeddedObject
2036 		 *
2037 		 * @return boolean
2038 		 */
2039 		private boolean isEmbeddedObject() {
2040 			return this.iHasEmbObjAttr || this.iHasEmbInstAttr || this.iHasEmbObjQuali || this.iHasEmbInstQuali;
2041 		}
2042 
2043 		/**
2044 		 * isEmbeddedClass
2045 		 *
2046 		 * @return boolean
2047 		 */
2048 		private boolean isEmbeddedClass() {
2049 			return this.iHasEmbObjAttr || this.iHasEmbObjQuali;
2050 		}
2051 
2052 		/**
2053 		 * isEmbeddedInstance
2054 		 *
2055 		 * @return boolean
2056 		 */
2057 		private boolean isEmbeddedInstance() {
2058 			return this.iHasEmbInstAttr || this.iHasEmbInstQuali;
2059 		}
2060 
2061 		/**
2062 		 * getType
2063 		 *
2064 		 * @return CIMDataType
2065 		 * @throws CIMXMLParseException
2066 		 */
2067 		public CIMDataType getType() throws CIMXMLParseException {
2068 			transform();
2069 			return this.iType;
2070 		}
2071 
2072 		/**
2073 		 * getArrayType
2074 		 *
2075 		 * @return CIMDataType
2076 		 * @throws CIMXMLParseException
2077 		 */
2078 		public CIMDataType getArrayType() throws CIMXMLParseException {
2079 			transform();
2080 			return this.iType.isArray() ? this.iType : CIMHelper.UnboundedArrayDataType(this.iType.getType());
2081 		}
2082 
2083 		/**
2084 		 * getValue
2085 		 *
2086 		 * @return Object
2087 		 * @throws CIMXMLParseException
2088 		 */
2089 		public Object getValue() throws CIMXMLParseException {
2090 			transform();
2091 			return this.iValue;
2092 		}
2093 
2094 		private void transform() throws CIMXMLParseException {
2095 			if (this.iType != null) return;
2096 			if (this.iRawValue == null) {
2097 				if (isEmbeddedObject()) {
2098 					if (this.iRawType != CIMDataType.STRING_T) throw new CIMXMLParseException(
2099 						"Embedded Object CIM-XML element's type must be string. " + this.iRawType + " is invalid!"
2100 					);
2101 					if (this.iStrictParsing) {
2102 						/*
2103 						 * In case of strict parsing Object means CIMClass,
2104 						 * Instance means CIMInstance. Pegasus 2.7.0 seems to
2105 						 * handle it this way.
2106 						 */
2107 						this.iType = isEmbeddedInstance() ? CIMDataType.OBJECT_T : CIMDataType.CLASS_T;
2108 					} else {
2109 						/*
2110 						 * for valueless EmbeddedObject="object" the type is
2111 						 * undeterminable since Pegasus's CIMObject can contain
2112 						 * both CIMClass and CIMInstance
2113 						 */
2114 						this.iType = isEmbeddedInstance() ? CIMDataType.OBJECT_T : CIMDataType.STRING_T;
2115 					}
2116 				} else {
2117 					this.iType = this.iRawType;
2118 				}
2119 				this.iValue = null;
2120 			} else {
2121 				if (isEmbeddedObject()) {
2122 					transformEmbObj();
2123 				} else {
2124 					transformNormObj();
2125 				}
2126 			}
2127 		}
2128 
2129 		private void transformEmbObj() throws CIMXMLParseException {
2130 			if (this.iRawValue instanceof String) {
2131 				this.iValue = parseXmlStr((String) this.iRawValue);
2132 				this.iType = getCIMObjType(this.iValue);
2133 			} else {
2134 				this.iValue = parseXmlStrA((String[]) this.iRawValue);
2135 				this.iType = getCIMObjAType((Object[]) this.iValue);
2136 			}
2137 			if (isEmbeddedInstance() && this.iType.getType() != CIMDataType.OBJECT) throw new CIMXMLParseException(
2138 				this.iElement.getNodeName() + " element is an EmbeddedInstance with non INSTANCE value. " + "It's not valid!"
2139 			);
2140 			if (
2141 				isEmbeddedClass() && this.iType.getType() != CIMDataType.CLASS && this.iType.getType() != CIMDataType.OBJECT
2142 			) throw new CIMXMLParseException(
2143 				this.iElement.getNodeName() + " element is an EmbeddedObject with non CLASS/INSTANCE value. It's not valid!"
2144 			);
2145 		}
2146 
2147 		private void transformNormObj() throws CIMXMLParseException {
2148 			if (this.iRawValue instanceof String) {
2149 				this.iType = this.iRawType;
2150 				this.iValue = createJavaObject(this.iType == null ? null : this.iType.toString(), (String) this.iRawValue);
2151 			} else {
2152 				String[] rawValueA = (String[]) this.iRawValue;
2153 				String typeStr = this.iRawType.toString();
2154 				Object[] objA = new Object[rawValueA.length];
2155 				for (int i = 0; i < objA.length; i++) objA[i] = createJavaObject(typeStr, rawValueA[i]);
2156 				this.iType = CIMHelper.UnboundedArrayDataType(this.iRawType.getType());
2157 				this.iValue = objA;
2158 			}
2159 		}
2160 
2161 		/**
2162 		 * parseXmlStr
2163 		 *
2164 		 * @param pXmlStr
2165 		 * @return CIMClass or CIMInstance
2166 		 * @throws CIMXMLParseException
2167 		 */
2168 		public static Object parseXmlStr(String pXmlStr) throws CIMXMLParseException {
2169 			// ebak: workaround for null array elements -> parse empty EmbObj
2170 			// string as null
2171 			if (pXmlStr == null || pXmlStr.length() == 0) return null;
2172 			try {
2173 				CIMClientXML_HelperImpl builder = new CIMClientXML_HelperImpl();
2174 				Document doc = builder.parse(new InputSource(new StringReader(pXmlStr)));
2175 				return parseObject(doc.getDocumentElement());
2176 			} catch (CIMXMLParseException e) {
2177 				throw e;
2178 			} catch (Exception e) {
2179 				throw new CIMXMLParseException(e.getMessage() + "\npXmlStr=" + pXmlStr);
2180 			}
2181 		}
2182 
2183 		/**
2184 		 * parseXmlStrA
2185 		 *
2186 		 * @param pXmlStrA
2187 		 * @return Object[]
2188 		 * @throws CIMXMLParseException
2189 		 */
2190 		public static Object[] parseXmlStrA(String[] pXmlStrA) throws CIMXMLParseException {
2191 			if (pXmlStrA == null || pXmlStrA.length == 0) return null;
2192 			Object[] objA = new Object[pXmlStrA.length];
2193 			for (int i = 0; i < objA.length; i++) {
2194 				String xmlStr = pXmlStrA[i];
2195 				objA[i] = xmlStr == null ? null : parseXmlStr(xmlStr);
2196 			}
2197 			return objA;
2198 		}
2199 
2200 		/**
2201 		 * getCIMObjType
2202 		 *
2203 		 * @param pCIMObj
2204 		 * @return CIMDataType
2205 		 * @throws CIMXMLParseException
2206 		 */
2207 		public static CIMDataType getCIMObjType(Object pCIMObj) throws CIMXMLParseException {
2208 			if (pCIMObj == null) throw new CIMXMLParseException("cannot have null CIM object! (CIMClass or CIMInstance)");
2209 			if (pCIMObj instanceof CIMInstance) return CIMDataType.OBJECT_T;
2210 			if (pCIMObj instanceof CIMClass) return CIMDataType.CLASS_T;
2211 			throw new CIMXMLParseException(pCIMObj.getClass().getName() + " is not a CIM object! (CIMClass or CIMInstance)");
2212 		}
2213 
2214 		/**
2215 		 * getCIMObjAType
2216 		 *
2217 		 * @param pCIMObjA
2218 		 * @return CIMDataType
2219 		 * @throws CIMXMLParseException
2220 		 */
2221 		public static CIMDataType getCIMObjAType(Object[] pCIMObjA) throws CIMXMLParseException {
2222 			if (pCIMObjA == null || pCIMObjA.length == 0) return CIMDataType.STRING_ARRAY_T;
2223 			CIMDataType type = null;
2224 			for (int i = 0; i < pCIMObjA.length; i++) {
2225 				if (pCIMObjA[i] == null) continue;
2226 				CIMDataType currType = getCIMObjType(pCIMObjA[i]);
2227 				if (type == null) {
2228 					type = currType;
2229 				} else if (type != currType) {
2230 					throw new CIMXMLParseException("Embedded Object arrays with different types are not supported");
2231 				}
2232 			}
2233 			if (type == CIMDataType.OBJECT_T) return CIMDataType.OBJECT_ARRAY_T;
2234 			if (type == CIMDataType.CLASS_T) return CIMDataType.CLASS_ARRAY_T;
2235 			return CIMDataType.STRING_ARRAY_T;
2236 		}
2237 	}
2238 
2239 	private static final String nodesPROPERTY[] = { "QUALIFIER", "VALUE" };
2240 
2241 	/**
2242 	 * parseCLASSPROPERTY
2243 	 *
2244 	 * @param pPropertyE
2245 	 * @return CIMClassProperty
2246 	 * @throws CIMXMLParseException
2247 	 */
2248 	public static CIMClassProperty<Object> parseCLASSPROPERTY(Element pPropertyE) throws CIMXMLParseException {
2249 		// <!ELEMENT PROPERTY (QUALIFIER*,VALUE?)>
2250 		// <!ATTLIST PROPERTY %NAME;%TYPE;%CLASSORIGIN;%PROPAGATED;>
2251 
2252 		Attr property_nameA = (Attr) searchAttribute(pPropertyE, "NAME");
2253 		if (property_nameA == null) throw new CIMXMLParseException("PROPERTY element missing NAME attribute!");
2254 		String name = property_nameA.getNodeValue();
2255 		if (attribute(pPropertyE, "TYPE") == null && !hasTypeAttrsInNodes(pPropertyE)) throw new CIMXMLParseException(
2256 			"PROPERTY element missing TYPE attribute!"
2257 		);
2258 
2259 		String classOrigin = pPropertyE.getAttribute("CLASSORIGIN");
2260 		if (classOrigin != null && classOrigin.length() == 0) classOrigin = null;
2261 
2262 		String propagatedStr = pPropertyE.getAttribute("PROPAGATED");
2263 		boolean propagated = MOF.TRUE.equalsIgnoreCase(propagatedStr);
2264 
2265 		// only QUALIFIER(s) and 0/1 VALUE
2266 		searchNodes(pPropertyE, "VALUE", 0, 1, true);
2267 		checkOtherNodes(pPropertyE, nodesPROPERTY);
2268 
2269 		// QUALIFIER
2270 		// ebak: EmbeddedObject support
2271 		EmbObjHandler embObjHandler = new EmbObjHandler(pPropertyE);
2272 		/*
2273 		 * CIMClassProperty(String pName, CIMDataType pType, Object pValue,
2274 		 * CIMQualifier[] pQualifiers, boolean pKey, boolean propagated, String
2275 		 * originClass)
2276 		 */
2277 		return new CIMClassProperty<Object>(
2278 			name,
2279 			embObjHandler.getType(),
2280 			embObjHandler.getValue(),
2281 			embObjHandler.getQualifiers(),
2282 			embObjHandler.isKeyed(),
2283 			propagated,
2284 			classOrigin
2285 		);
2286 	}
2287 
2288 	/**
2289 	 * parsePROPERTYARRAY
2290 	 *
2291 	 * @param pPropertyArrayE
2292 	 * @return CIMProperty
2293 	 * @throws CIMXMLParseException
2294 	 */
2295 	public static CIMProperty<Object> parsePROPERTYARRAY(Element pPropertyArrayE) throws CIMXMLParseException {
2296 		return parseCLASSPROPERTYARRAY(pPropertyArrayE);
2297 	}
2298 
2299 	private static final String nodesPROPERTYARRAY[] = { "QUALIFIER", "VALUE.ARRAY" };
2300 
2301 	/**
2302 	 * parseCLASSPROPERTYARRAY
2303 	 *
2304 	 * @param pPropArrayE
2305 	 * @return CIMClassProperty
2306 	 * @throws CIMXMLParseException
2307 	 */
2308 	public static CIMClassProperty<Object> parseCLASSPROPERTYARRAY(Element pPropArrayE) throws CIMXMLParseException {
2309 		// <!ELEMENT PROPERTY.ARRAY (QUALIFIER*,VALUE.ARRAY?)>
2310 		// <!ATTLIST PROPERTY.ARRAY
2311 		// %NAME;%TYPE;%ARRAYSIZE;%CLASSORIGIN;%PROPAGATED;>
2312 
2313 		String name = attribute(pPropArrayE, "NAME");
2314 		if (name == null) throw new CIMXMLParseException("PROPERTY.ARRAY element missing NAME attribute!");
2315 		if (attribute(pPropArrayE, "TYPE") == null && !hasTypeAttrsInNodes(pPropArrayE)) throw new CIMXMLParseException(
2316 			"PROPERTY.ARRAY element missing TYPE attribute!"
2317 		);
2318 
2319 		String valueArraysizeStr = pPropArrayE.getAttribute("ARRAYSIZE");
2320 		try {
2321 			if (valueArraysizeStr.length() > 0) Integer.parseInt(valueArraysizeStr);
2322 		} catch (NumberFormatException e) {
2323 			throw new CIMXMLParseException(valueArraysizeStr + " is not a valid ARRAYSIZE attribute for VALUE.ARRAY!");
2324 		}
2325 
2326 		String classOrigin = pPropArrayE.getAttribute("CLASSORIGIN");
2327 		if (classOrigin != null && classOrigin.length() == 0) classOrigin = null;
2328 
2329 		String valuePropagatedStr = pPropArrayE.getAttribute("PROPAGATED");
2330 		boolean propagated = (valuePropagatedStr != null && valuePropagatedStr.equalsIgnoreCase(MOF.TRUE));
2331 
2332 		// only QUALIFIER(s) and 0/1 VALUE.ARRAY
2333 		searchNodes(pPropArrayE, "VALUE.ARRAY", 0, 1, true);
2334 		checkOtherNodes(pPropArrayE, nodesPROPERTYARRAY);
2335 
2336 		// QUALIFIER
2337 		// ebak: EmbeddedObject support
2338 		EmbObjHandler embObjHandler = new EmbObjHandler(pPropArrayE);
2339 		return new CIMClassProperty<Object>(
2340 			name,
2341 			embObjHandler.getArrayType(),
2342 			embObjHandler.getValue(),
2343 			embObjHandler.getQualifiers(),
2344 			embObjHandler.isKeyed(),
2345 			propagated,
2346 			classOrigin
2347 		);
2348 	}
2349 
2350 	/**
2351 	 * parsePROPERTYREFERENCE
2352 	 *
2353 	 * @param pPropRefE
2354 	 * @return CIMProperty
2355 	 * @throws CIMXMLParseException
2356 	 */
2357 	public static CIMProperty<Object> parsePROPERTYREFERENCE(Element pPropRefE) throws CIMXMLParseException {
2358 		return parseCLASSPROPERTYREFERENCE(pPropRefE);
2359 	}
2360 
2361 	private static final String nodesPROPERTYREFERENCE[] = { "QUALIFIER", "VALUE.REFERENCE" };
2362 
2363 	/**
2364 	 * parseCLASSPROPERTYREFERENCE
2365 	 *
2366 	 * @param pPropRefE
2367 	 * @return CIMClassProperty
2368 	 * @throws CIMXMLParseException
2369 	 */
2370 	public static CIMClassProperty<Object> parseCLASSPROPERTYREFERENCE(Element pPropRefE) throws CIMXMLParseException {
2371 		// <!ELEMENT PROPERTY.REFERENCE (QUALIFIER*,VALUE.REFERENCE?)>
2372 		// <!ATTLIST PROPERTY.REFERENCE
2373 		// %NAME;%REFERENCECLASS;%CLASSORIGIN;%PROPAGATED;>
2374 
2375 		String name = attribute(pPropRefE, "NAME");
2376 		if (name == null) throw new CIMXMLParseException("PROPERTY.REFERENCE element missing NAME attribute!");
2377 
2378 		String classOrigin = pPropRefE.getAttribute("CLASSORIGIN");
2379 		if (classOrigin != null && classOrigin.length() == 0) classOrigin = null;
2380 
2381 		String referenceClass = pPropRefE.getAttribute("REFERENCECLASS");
2382 
2383 		String propagatedStr = pPropRefE.getAttribute("PROPAGATED");
2384 		boolean propagated = MOF.TRUE.equalsIgnoreCase(propagatedStr);
2385 
2386 		// QUALIFIER
2387 		CIMQualifier<?>[] qualis = parseQUALIFIERS(pPropRefE);
2388 
2389 		CIMDataType type = new CIMDataType(referenceClass != null ? referenceClass : "");
2390 		// VALUE.REFERENCE
2391 		Element valueRefA[] = searchNodes(pPropRefE, "VALUE.REFERENCE", 0, 1, true);
2392 		Object value = valueRefA != null ? parseVALUEREFERENCE(valueRefA[0]) : null;
2393 
2394 		// return a CIMProperty without a CIMValue
2395 		checkOtherNodes(pPropRefE, nodesPROPERTYREFERENCE);
2396 		CIMQualifiedElementInterfaceImpl qualiImpl = new CIMQualifiedElementInterfaceImpl(qualis);
2397 		return new CIMClassProperty<Object>(name, type, value, qualis, qualiImpl.isKeyed(), propagated, classOrigin);
2398 	}
2399 
2400 	/**
2401 	 * parseMESSAGE
2402 	 *
2403 	 * @param pCimVersion
2404 	 * @param pDtdVersion
2405 	 * @param pMessageE
2406 	 * @return CIMMessage
2407 	 * @throws CIMXMLParseException
2408 	 */
2409 	public static CIMMessage parseMESSAGE(String pCimVersion, String pDtdVersion, Element pMessageE)
2410 		throws CIMXMLParseException {
2411 		// <!ELEMENT MESSAGE
2412 		// (SIMPLEREQ|MULTIREQ|SIMPLERSP|MULTIRSP|SIMPLEEXPREQ|MULTIEXPREQ|SIMPLEEXPRSP|MULTIEXPRSP)>
2413 		// <!ATTLIST MESSAGE %ID;%PROTOCOLVERSION;>
2414 
2415 		Attr idA = (Attr) searchAttribute(pMessageE, "ID");
2416 		if (idA == null) throw new CIMXMLParseException("MESSAGE element missing ID attribute!");
2417 		String id = idA.getNodeValue();
2418 
2419 		Attr protocolA = (Attr) searchAttribute(pMessageE, "PROTOCOLVERSION");
2420 		if (protocolA == null) throw new CIMXMLParseException("MESSAGE element missing PROTOCOLVERSION attribute!");
2421 		// TODO
2422 		if (pCimVersion.equals("2.0") && pDtdVersion.equals("2.0")) {
2423 			// Attr message_idA = (Attr)searchAttribute(messageE, "ID");
2424 			// String messadeID = message_idA.getNodeValue();
2425 
2426 			// Attr message_protocolversionA = (Attr)searchAttribute(messageE,
2427 			// "PROTOCOLVERSION");
2428 			// String protocolversion = message_protocolversionA.getNodeValue();
2429 
2430 			// SIMPLERSP
2431 			Element simplerspA[] = searchNodes(pMessageE, "SIMPLERSP", 0, 1, false);
2432 			if (simplerspA != null) {
2433 				CIMResponse response = parseSIMPLERSP(simplerspA[0]);
2434 				response.setMethod("SIMPLERSP");
2435 				response.setId(id);
2436 				return response;
2437 			}
2438 			Element multirspA[] = searchNodes(pMessageE, "MULTIRSP", 0, 1, false);
2439 			if (multirspA != null) {
2440 				CIMResponse response = parseMULTIRSP(multirspA[0]);
2441 				response.setMethod("MULTIRSP");
2442 				response.setId(id);
2443 				return response;
2444 			}
2445 			// SIMPLEEXPREQ
2446 			Element simpleexpreqA[] = searchNodes(pMessageE, "SIMPLEEXPREQ", 0, 1, false);
2447 			if (simpleexpreqA != null) {
2448 				CIMRequest request = parseSIMPLEEXPREQ(simpleexpreqA[0]);
2449 				request.setMethod("SIMPLEEXPREQ");
2450 				request.setId(id);
2451 				return request;
2452 			}
2453 
2454 			// MULTIEXPREQ
2455 			Element multiexpreqA[] = searchNodes(pMessageE, "MULTIEXPREQ", 0, 1, false);
2456 			if (multiexpreqA != null) {
2457 				CIMRequest request = parseMULTIEXPREQ(multiexpreqA[0]);
2458 				request.setMethod("MULTIEXPREQ");
2459 				request.setId(id);
2460 				return request;
2461 			}
2462 			// SIMPLEEXPRSP
2463 			Element simpleexprspA[] = searchNodes(pMessageE, "SIMPLEEXPRSP", 0, 1, false);
2464 			if (simpleexprspA != null) {
2465 				CIMResponse response = parseSIMPLEEXPRSP(simpleexprspA[0]);
2466 				response.setMethod("SIMPLEEXPRSP");
2467 				response.setId(id);
2468 				return response;
2469 			}
2470 			// MULTIEXPRSP
2471 			Element multiexprspA[] = searchNodes(pMessageE, "MULTIEXPRSP", 0, 1, false);
2472 			if (multiexprspA != null) {
2473 				CIMResponse response = parseMULTIEXPRSP(multiexprspA[0]);
2474 				response.setMethod("MULTIEXPRSP");
2475 				response.setId(id);
2476 				return response;
2477 			}
2478 
2479 			// SIMPLEREQ
2480 			Element simplereqA[] = searchNodes(pMessageE, "SIMPLEREQ", 0, 1, false);
2481 			if (simplereqA != null) {
2482 				CIMRequest request = parseSIMPLEREQ(simplereqA[0]);
2483 				request.setMethod("SIMPLEREQ");
2484 				request.setId(id);
2485 				return request;
2486 			}
2487 
2488 			// MULTIREQ
2489 			Element multireqA[] = searchNodes(pMessageE, "MULTIREQ", 0, 1, false);
2490 			if (multireqA != null) {
2491 				CIMRequest request = parseMULTIREQ(multireqA[0]);
2492 				request.setMethod("MULTIREQ");
2493 				request.setId(id);
2494 				return request;
2495 			}
2496 			throw new CIMXMLParseException("MESSAGE element missing required child element!");
2497 		}
2498 		// TODO, look for the specific error message in the spec
2499 		throw new CIMXMLParseException("DTD not supported");
2500 	}
2501 
2502 	private static final String nodesPARAMVALUE[] = {
2503 		"VALUE",
2504 		"VALUE.REFERENCE",
2505 		"VALUE.ARRAY",
2506 		"VALUE.REFARRAY",
2507 		"CLASSNAME",
2508 		"INSTANCENAME",
2509 		"CLASS",
2510 		"INSTANCE",
2511 		"VALUE.NAMEDINSTANCE"
2512 	};
2513 
2514 	/**
2515 	 * parsePARAMVALUE
2516 	 *
2517 	 * @param pParamValueE
2518 	 * @return CIMArgument
2519 	 * @throws CIMXMLParseException
2520 	 */
2521 	public static CIMArgument<Object> parsePARAMVALUE(Element pParamValueE) throws CIMXMLParseException {
2522 		// <!ELEMENT PARAMVALUE
2523 		// (VALUE|VALUE.REFERENCE|VALUE.ARRAY|VALUE.REFARRAYCLASSNAME|
2524 		// INSTANCENAME|CLASS|INSTANCE|VALUE.NAMEDINSTANCE)?>)
2525 		// <!ATTLIST PARAMTYPE %NAME;%PARAMTYPE%>
2526 		String name = attribute(pParamValueE, "NAME");
2527 		if (name == null) throw new CIMXMLParseException("PARAMVALUE element missing NAME attribute!");
2528 		// FIXME: ebak: The base implementation didn't contain VALUE.REFARRAY
2529 		// handling. Why?
2530 		// ebak: embedded object support, different parsing for VALUE and
2531 		// VALUE.ARRAY sub elements
2532 		if (
2533 			searchNodes(pParamValueE, "VALUE.REFERENCE", 0, 1, false) != null ||
2534 			searchNodes(pParamValueE, "VALUE.REFARRAY", 0, 1, false) != null
2535 		) {
2536 			TypedValue typedValue = parseSingleValue(pParamValueE, VALUEREF | VALUEREFA);
2537 			CIMDataType type = typedValue.getType();
2538 			Object value = typedValue.getValue();
2539 			if (type == null) throw new CIMXMLParseException("PARAMVALUE element type is null!");
2540 			return new CIMArgument<Object>(name, type, value);
2541 		}
2542 		if (
2543 			searchNodes(pParamValueE, "VALUE", 0, 1, false) != null ||
2544 			searchNodes(pParamValueE, "VALUE.ARRAY", 0, 1, false) != null ||
2545 			!hasNodes(pParamValueE)
2546 		) {
2547 			EmbObjHandler embObjHandler = new EmbObjHandler(pParamValueE);
2548 			return new CIMArgument<Object>(name, embObjHandler.getType(), embObjHandler.getValue());
2549 		}
2550 
2551 		// CLASSNAME
2552 		Element classNameA[] = searchNodes(pParamValueE, "CLASSNAME", 0, 1, false);
2553 		if (classNameA != null) {
2554 			CIMObjectPath op = parseCLASSNAME(classNameA[0]);
2555 			CIMDataType type = new CIMDataType(op.getObjectName());
2556 			return new CIMArgument<Object>(name, type, op);
2557 		}
2558 
2559 		// INSTANCENAME
2560 		Element instNameA[] = searchNodes(pParamValueE, "INSTANCENAME", 0, 1, false);
2561 		if (instNameA != null) {
2562 			CIMObjectPath op = parseINSTANCENAME(instNameA[0]);
2563 			CIMDataType type = new CIMDataType(op.getObjectName());
2564 			return new CIMArgument<Object>(name, type, op);
2565 		}
2566 
2567 		// CLASS
2568 		Element classA[] = searchNodes(pParamValueE, "CLASS", 0, 1, false);
2569 		if (classA != null) {
2570 			CIMClass cl = parseCLASS(classA[0]);
2571 			return new CIMArgument<Object>(name, CIMDataType.CLASS_T, cl);
2572 		}
2573 
2574 		// INSTANCE
2575 		Element instanceA[] = searchNodes(pParamValueE, "INSTANCE", 0, 1, false);
2576 		if (instanceA != null) {
2577 			CIMInstance inst = parseINSTANCE(instanceA[0]);
2578 			return new CIMArgument<Object>(name, CIMDataType.OBJECT_T, inst);
2579 		}
2580 
2581 		// VALUE.NAMEDINSTANCE
2582 		Element valuenamedisntanceA[] = searchNodes(pParamValueE, "VALUE.NAMEDINSTANCE", 0, 1, false);
2583 		if (valuenamedisntanceA != null) {
2584 			CIMInstance inst = parseVALUENAMEDINSTANCE(valuenamedisntanceA[0]);
2585 			return new CIMArgument<Object>(name, CIMDataType.OBJECT_T, inst);
2586 		}
2587 		checkOtherNodes(pParamValueE, nodesPARAMVALUE);
2588 		return new CIMArgument<Object>(name, CIMDataType.STRING_T, null);
2589 	}
2590 
2591 	private static final String nodesIPARAMVALUE[] = {
2592 		"VALUE",
2593 		"VALUE.ARRAY",
2594 		"VALUE.REFERENCE",
2595 		"CLASSNAME",
2596 		"INSTANCENAME",
2597 		"QUALIFIER.DECLARATION",
2598 		"CLASS",
2599 		"INSTANCE",
2600 		"VALUE.NAMEDINSTANCE"
2601 	};
2602 
2603 	/**
2604 	 * parseIPARAMVALUE
2605 	 *
2606 	 * @param pParamValueE
2607 	 * @return CIMArgument
2608 	 * @throws CIMXMLParseException
2609 	 */
2610 	public static CIMArgument<Object> parseIPARAMVALUE(Element pParamValueE) throws CIMXMLParseException {
2611 		// <!ELEMENT IPARAMVALUE
2612 		// (VALUE|VALUE.ARRAY|VALUE.REFERENCE|CLASSNAME|INSTANCENAME|QUALIFIER.DECLARATION|
2613 		// CLASS|INSTANCE|VALUE.NAMEDINSTANCE)?>
2614 		// <!ATTLIST IPARAMVALUE
2615 		// %CIMName;>
2616 
2617 		String name = attribute(pParamValueE, "NAME");
2618 		if (name == null) throw new CIMXMLParseException("IPARAMVALUE element missing NAME attribute!");
2619 		// this can parse VALUE, VALUE.ARRAY and VALUE.REFERENCE
2620 		if (
2621 			searchNodes(pParamValueE, "VALUE", 0, 1, false) != null ||
2622 			searchNodes(pParamValueE, "VALUE.ARRAY", 0, 1, false) != null ||
2623 			searchNodes(pParamValueE, "VALUE.REFERENCE", 0, 1, false) != null
2624 		) {
2625 			TypedValue typedValue = parseSingleValue(pParamValueE, VALUE | VALUEA | VALUEREF);
2626 			if (typedValue.getType() != null) {
2627 				return new CIMArgument<Object>(name, typedValue.getType(), typedValue.getValue());
2628 			}
2629 		}
2630 		// we can have different types too which cannot be handled by
2631 		// parseSingleValue()
2632 
2633 		// INSTANCENAME
2634 		Element instNameA[] = searchNodes(pParamValueE, "INSTANCENAME", 0, 1, false);
2635 		if (instNameA != null) {
2636 			CIMObjectPath op = parseINSTANCENAME(instNameA[0]);
2637 			CIMDataType type = new CIMDataType(op.getObjectName());
2638 			return new CIMArgument<Object>(name, type, op);
2639 		}
2640 
2641 		// CLASSNAME
2642 		Element classNameA[] = searchNodes(pParamValueE, "CLASSNAME", 0, 1, false);
2643 		if (classNameA != null) {
2644 			CIMObjectPath op = parseCLASSNAME(classNameA[0]);
2645 			CIMDataType type = new CIMDataType(op.getObjectName());
2646 			return new CIMArgument<Object>(name, type, op);
2647 		}
2648 
2649 		// QUALIFIER.DECLARATION
2650 		Element qualiDeclarationA[] = searchNodes(pParamValueE, "QUALIFIER.DECLARATION", 0, 1, false);
2651 		if (qualiDeclarationA != null) {
2652 			CIMQualifierType<Object> qualiType = parseQUALIFIERDECLARATION(qualiDeclarationA[0]);
2653 			// FIXME: ebak: Does it surely have to be mapped to type:
2654 			// REFERENCE????
2655 			return new CIMArgument<Object>(name, new CIMDataType(qualiType.getName()), qualiType);
2656 		}
2657 
2658 		// CLASS
2659 		Element classA[] = searchNodes(pParamValueE, "CLASS", 0, 1, false);
2660 		if (classA != null) {
2661 			CIMClass cl = parseCLASS(classA[0]);
2662 			return new CIMArgument<Object>(name, CIMDataType.CLASS_T, cl);
2663 		}
2664 
2665 		// INSTANCE
2666 		Element instanceA[] = searchNodes(pParamValueE, "INSTANCE", 0, 1, false);
2667 		if (instanceA != null) {
2668 			CIMInstance inst = parseINSTANCE(instanceA[0]);
2669 			return new CIMArgument<Object>(name, CIMDataType.OBJECT_T, inst);
2670 		}
2671 
2672 		// VALUE.NAMEDINSTANCE
2673 		Element valuenamedisntanceA[] = searchNodes(pParamValueE, "VALUE.NAMEDINSTANCE", 0, 1, false);
2674 		if (valuenamedisntanceA != null) {
2675 			CIMInstance inst = parseVALUENAMEDINSTANCE(valuenamedisntanceA[0]);
2676 			return new CIMArgument<Object>(name, CIMDataType.OBJECT_T, inst);
2677 		}
2678 
2679 		checkOtherNodes(pParamValueE, nodesIPARAMVALUE);
2680 		return new CIMArgument<Object>(name, CIMDataType.STRING_T, null);
2681 	}
2682 
2683 	/**
2684 	 * parseSIMPLERSP
2685 	 *
2686 	 * @param pSimpleRspE
2687 	 * @return CIMResponse
2688 	 * @throws CIMXMLParseException
2689 	 */
2690 	public static CIMResponse parseSIMPLERSP(Element pSimpleRspE) throws CIMXMLParseException {
2691 		// <!ELEMENT SIMPLERSP (METHODRESPONSE|IMETHODRESPONSE)>
2692 
2693 		// METHODRESPONSE
2694 		Element methodresponseA[] = searchNodes(pSimpleRspE, "METHODRESPONSE", 0, 1, false);
2695 		if (methodresponseA != null) {
2696 			return parseMETHODRESPONSE(methodresponseA[0]);
2697 		}
2698 
2699 		// IMETHODRESPONSE
2700 		Element imethodresponseA[] = searchNodes(pSimpleRspE, "IMETHODRESPONSE", 0, 1, false);
2701 		if (imethodresponseA != null) {
2702 			return parseIMETHODRESPONSE(imethodresponseA[0]);
2703 		}
2704 
2705 		throw new CIMXMLParseException("SIMPLERSP element missing required child element!");
2706 	}
2707 
2708 	/**
2709 	 * parseMULTIRSP
2710 	 *
2711 	 * @param pSimpleRspE
2712 	 * @return CIMResponse
2713 	 * @throws CIMXMLParseException
2714 	 */
2715 	public static CIMResponse parseMULTIRSP(Element pSimpleRspE) throws CIMXMLParseException {
2716 		// <!ELEMENT MULTIRSP (SIMPLERSP,SIMPLERSP+)>
2717 
2718 		Element[] multiRespElementA = searchNodes(pSimpleRspE, "SIMPLERSP", 2, Integer.MAX_VALUE, false);
2719 		if (multiRespElementA != null) {
2720 			CIMResponse multiRsp = new CIMResponse();
2721 			for (int i = 0; i < multiRespElementA.length; i++) {
2722 				Element methodresponseE = multiRespElementA[i];
2723 				CIMResponse rsp = parseSIMPLERSP(methodresponseE);
2724 				rsp.setMethod("SIMPLERSP");
2725 				multiRsp.addResponse(rsp);
2726 			}
2727 			return multiRsp;
2728 		}
2729 
2730 		throw new CIMXMLParseException("MULTIRSP element missing SIMPLERSP child element!");
2731 	}
2732 
2733 	private static final String nodesSIMPLEREQ[] = { "CORRELATOR", "METHODCALL", "IMETHODCALL" };
2734 
2735 	/**
2736 	 * parseSIMPLEREQ
2737 	 *
2738 	 * @param pSimpleReqE
2739 	 * @return CIMRequest
2740 	 * @throws CIMXMLParseException
2741 	 */
2742 	public static CIMRequest parseSIMPLEREQ(Element pSimpleReqE) throws CIMXMLParseException {
2743 		// <!ELEMENT SIMPLEREQ (CORRELATOR*, (METHODCALL | IMETHODCALL))>
2744 		CIMRequest request = null;
2745 
2746 		// METHODCALL
2747 		Element methodcallA[] = searchNodes(pSimpleReqE, "METHODCALL", 0, 1, true);
2748 		if (methodcallA != null) {
2749 			request = parseMETHODCALL(methodcallA[0]);
2750 		}
2751 
2752 		// IMETHODCALL
2753 		Element imethodcallA[] = searchNodes(pSimpleReqE, "IMETHODCALL", 0, 1, true);
2754 		if (imethodcallA != null) {
2755 			if (request != null) {
2756 				throw new CIMXMLParseException("SIMPLEREQ element cannot have METHODCALL and IMETHODCALL child elements!");
2757 			}
2758 			request = parseIMETHODCALL(imethodcallA[0]);
2759 		}
2760 
2761 		if (request == null) throw new CIMXMLParseException("SIMPLEREQ element missing required child element!");
2762 
2763 		// CORRELATOR
2764 		Element[] correlatorA = searchNodes(pSimpleReqE, "CORRELATOR", 0, Integer.MAX_VALUE, true);
2765 		if (correlatorA != null) {
2766 			for (int i = 0; i < correlatorA.length; i++) // TODO: return to WBEMClient API if JSR48 changes
2767 			parseCORRELATOR(correlatorA[i]);
2768 		}
2769 
2770 		checkOtherNodes(pSimpleReqE, nodesSIMPLEREQ);
2771 		return request;
2772 	}
2773 
2774 	/**
2775 	 * parseMULTIREQ
2776 	 *
2777 	 * @param pMultiReqE
2778 	 * @return CIMRequest
2779 	 * @throws CIMXMLParseException
2780 	 */
2781 	public static CIMRequest parseMULTIREQ(Element pMultiReqE) throws CIMXMLParseException {
2782 		// <!ELEMENT MULTIREQ (SIMPLEREQ,SIMPLEREQ+)>
2783 
2784 		Element[] methodReqElementA = searchNodes(pMultiReqE, "SIMPLEREQ", 2, Integer.MAX_VALUE, false);
2785 		if (methodReqElementA != null) {
2786 			CIMRequest multiReq = new CIMRequest();
2787 			for (int i = 0; i < methodReqElementA.length; i++) {
2788 				Element methodrequestE = methodReqElementA[i];
2789 				CIMRequest req = parseSIMPLEREQ(methodrequestE);
2790 				req.setMethod("SIMPLEREQ");
2791 
2792 				multiReq.addRequest(req);
2793 			}
2794 			return multiReq;
2795 		}
2796 		throw new CIMXMLParseException("MULTIREQ element missing SIMPLEREQ child element!");
2797 	}
2798 
2799 	private static final String nodesMETHODCALL[] = { "LOCALCLASSPATH", "LOCALINSTANCEPATH", "PARAMVALUE" };
2800 
2801 	/**
2802 	 * parseMETHODCALL
2803 	 *
2804 	 * @param pMethodCallE
2805 	 * @return CIMRequest
2806 	 * @throws CIMXMLParseException
2807 	 */
2808 	public static CIMRequest parseMETHODCALL(Element pMethodCallE) throws CIMXMLParseException {
2809 		// <!ELEMENT METHODCALL
2810 		// ((LOCALCLASSPATH|LOCALINSTANCEPATH),PARAMVALUE*)>
2811 		// <!ATTLIST METHODCALL
2812 		// %CIMName;>
2813 
2814 		CIMRequest request = new CIMRequest();
2815 		String methodname = attribute(pMethodCallE, "NAME");
2816 		if (methodname == null) throw new CIMXMLParseException("METHODCALL element missing NAME attribute!");
2817 		request.setMethodName(methodname);
2818 
2819 		// EXPMETHODCALL
2820 		boolean localclasspathFound = false;
2821 		Element localclasspathA[] = searchNodes(pMethodCallE, "LOCALCLASSPATH", 0, 1, true);
2822 		if (localclasspathA != null) {
2823 			CIMObjectPath path = parseLOCALCLASSPATH(localclasspathA[0]);
2824 
2825 			request.setObjectPath(path);
2826 			localclasspathFound = true;
2827 		}
2828 
2829 		Element localinstancepathA[] = searchNodes(pMethodCallE, "LOCALINSTANCEPATH", 0, 1, true);
2830 		if (localinstancepathA != null) {
2831 			if (localclasspathFound) throw new CIMXMLParseException(
2832 				"METHODCALL element cannot have both LOCALCLASSPATH and LOCALINSTANCEPATH child elements!"
2833 			);
2834 
2835 			CIMObjectPath path = parseLOCALINSTANCEPATH(localinstancepathA[0]);
2836 
2837 			request.setObjectPath(path);
2838 		} else {
2839 			if (!localclasspathFound) throw new CIMXMLParseException("METHODCALL element missing required child element!");
2840 		}
2841 
2842 		Element[] paramValueElementA = searchNodes(pMethodCallE, "PARAMVALUE", 0, Integer.MAX_VALUE, true);
2843 
2844 		if (paramValueElementA != null) {
2845 			CIMArgument<?>[] argA = new CIMArgument[paramValueElementA.length];
2846 			for (int i = 0; i < paramValueElementA.length; i++) {
2847 				Element paramvalueE = paramValueElementA[i];
2848 				argA[i] = parsePARAMVALUE(paramvalueE);
2849 			}
2850 			request.addParamValue(argA);
2851 		}
2852 
2853 		checkOtherNodes(pMethodCallE, nodesMETHODCALL);
2854 		return request;
2855 	}
2856 
2857 	private static final String nodesIMETHODCALL[] = { "LOCALNAMESPACEPATH", "IPARAMVALUE" };
2858 
2859 	/**
2860 	 * parseIMETHODCALL
2861 	 *
2862 	 * @param pIMethodCallE
2863 	 * @return CIMRequest
2864 	 * @throws CIMXMLParseException
2865 	 */
2866 	public static CIMRequest parseIMETHODCALL(Element pIMethodCallE) throws CIMXMLParseException {
2867 		// <!ELEMENT IMETHODCALL (LOCALNAMESPACEPATH,IPARAMVALUE*)>
2868 		// <!ATTLIST IMETHODCALL
2869 		// %CIMName;>
2870 
2871 		CIMRequest request = new CIMRequest();
2872 		String methodname = attribute(pIMethodCallE, "NAME"); // ebak:
2873 		// CIMName->NAME
2874 		if (methodname == null) throw new CIMXMLParseException("IMETHODCALL element missing NAME attribute!");
2875 		request.setMethodName(methodname);
2876 
2877 		// METHODCALL
2878 		Element localnamespacepathA[] = searchNodes(pIMethodCallE, "LOCALNAMESPACEPATH", 1, 1, true);
2879 		if (localnamespacepathA != null) {
2880 			String nameSpace = parseLOCALNAMESPACEPATH(localnamespacepathA[0]);
2881 			request.setNameSpace(nameSpace);
2882 		}
2883 
2884 		Element[] iParamValElementA = searchNodes(pIMethodCallE, "IPARAMVALUE", 0, Integer.MAX_VALUE, true); // ebak:
2885 		// PARAMVALUE->IPARAMVALUE
2886 
2887 		if (iParamValElementA != null) {
2888 			CIMArgument<?>[] argA = new CIMArgument[iParamValElementA.length];
2889 			for (int i = 0; i < iParamValElementA.length; i++) {
2890 				Element paramvalueE = iParamValElementA[i];
2891 				CIMArgument<Object> arg = parseIPARAMVALUE(paramvalueE);
2892 				/*
2893 				 * ebak: local nameSpacePath should be added to those reference
2894 				 * arguments which don't contain namespace
2895 				 */
2896 				Object value = arg.getValue();
2897 				if (value instanceof CIMObjectPath) {
2898 					CIMObjectPath op = (CIMObjectPath) value;
2899 					if (op.getNamespace() == null || op.getNamespace().length() == 0) {
2900 						arg =
2901 							new CIMArgument<Object>(
2902 								arg.getName(),
2903 								arg.getDataType(),
2904 								// CIMObjectPath(String scheme, String host, String
2905 								// port, String namespace, String objectName,
2906 								// CIMProperty[] keys)
2907 								new CIMObjectPath(
2908 									op.getScheme(),
2909 									op.getHost(),
2910 									op.getPort(),
2911 									request.getNameSpace(),
2912 									op.getObjectName(),
2913 									op.getKeys()
2914 								)
2915 							);
2916 					}
2917 				}
2918 				argA[i] = arg;
2919 			}
2920 			request.addParamValue(argA);
2921 		}
2922 
2923 		checkOtherNodes(pIMethodCallE, nodesIMETHODCALL);
2924 		return request;
2925 	}
2926 
2927 	private static final String nodesSIMPLEEXPREQ[] = { "CORRELATOR", "EXPMETHODCALL" };
2928 
2929 	/**
2930 	 * parseSIMPLEEXPREQ
2931 	 *
2932 	 * @param pSimpleExpReqE
2933 	 * @return CIMRequest
2934 	 * @throws CIMXMLParseException
2935 	 */
2936 	public static CIMRequest parseSIMPLEEXPREQ(Element pSimpleExpReqE) throws CIMXMLParseException {
2937 		// <!ELEMENT SIMPLEEXPREQ (CORRELATOR*, EXPMETHODCALL)>
2938 		CIMRequest request = null;
2939 
2940 		// EXPMETHODCALL
2941 		Element[] expmethodcallA = searchNodes(pSimpleExpReqE, "EXPMETHODCALL", 1, 1, true);
2942 		if (expmethodcallA != null) {
2943 			request = parseEXPMETHODCALL(expmethodcallA[0]);
2944 		} else {
2945 			throw new CIMXMLParseException("SIMPLEEXPREQ element missing EXPMETHODCALL child element!");
2946 		}
2947 
2948 		// CORRELATOR
2949 		Element[] correlatorA = searchNodes(pSimpleExpReqE, "CORRELATOR", 0, Integer.MAX_VALUE, true);
2950 		if (correlatorA != null) {
2951 			for (int i = 0; i < correlatorA.length; i++) // TODO: return to WBEMClient API if JSR48 changes
2952 			parseCORRELATOR(correlatorA[i]);
2953 		}
2954 
2955 		checkOtherNodes(pSimpleExpReqE, nodesSIMPLEEXPREQ);
2956 		return request;
2957 	}
2958 
2959 	/**
2960 	 * parseMULTIEXPREQ
2961 	 *
2962 	 * @param pMultiExpReqE
2963 	 * @return CIMRequest
2964 	 * @throws CIMXMLParseException
2965 	 */
2966 	public static CIMRequest parseMULTIEXPREQ(Element pMultiExpReqE) throws CIMXMLParseException {
2967 		// <!ELEMENT SIMPLEEXPREQ (METHODRESPONSE)>
2968 
2969 		Element[] methodReqElementA = searchNodes(pMultiExpReqE, "SIMPLEEXPREQ", 2, Integer.MAX_VALUE, false);
2970 		if (methodReqElementA != null) {
2971 			CIMRequest multiReq = new CIMRequest();
2972 			for (int i = 0; i < methodReqElementA.length; i++) {
2973 				Element methodrequestE = methodReqElementA[i];
2974 				CIMRequest req = parseSIMPLEEXPREQ(methodrequestE);
2975 				req.setMethod("SIMPLEEXPREQ");
2976 
2977 				multiReq.addRequest(req);
2978 			}
2979 			return multiReq;
2980 		}
2981 		throw new CIMXMLParseException("MULTIEXPREQ element missing SIMPLEEXPREQ child element!");
2982 	}
2983 
2984 	private static final String nodesEXPMETHODCALL[] = { "EXPPARAMVALUE" };
2985 
2986 	/**
2987 	 * parseEXPMETHODCALL
2988 	 *
2989 	 * @param pExpMethodCallE
2990 	 * @return CIMRequest
2991 	 * @throws CIMXMLParseException
2992 	 */
2993 	public static CIMRequest parseEXPMETHODCALL(Element pExpMethodCallE) throws CIMXMLParseException {
2994 		// <!ELEMENT EXPMETHODCALL (EXPPARAMVALUE*)>
2995 
2996 		// EXPMETHODCALL
2997 		CIMRequest request = new CIMRequest();
2998 		String methodname = attribute(pExpMethodCallE, "NAME");
2999 		if (methodname == null) throw new CIMXMLParseException("EXPMETHODCALL element missing NAME attribute!");
3000 		request.setMethodName(methodname);
3001 
3002 		Element[] paramValElementA = searchNodes(pExpMethodCallE, "EXPPARAMVALUE", 0, Integer.MAX_VALUE, false);
3003 		Vector<CIMInstance> v = new Vector<CIMInstance>();
3004 		if (paramValElementA != null) {
3005 			for (int i = 0; i < paramValElementA.length; i++) {
3006 				Element expparamvalueE = paramValElementA[i];
3007 				CIMInstance inst = parseEXPPARAMVALUE(expparamvalueE);
3008 				v.add(inst);
3009 			}
3010 		}
3011 		request.addParamValue(v);
3012 		checkOtherNodes(pExpMethodCallE, nodesEXPMETHODCALL);
3013 		return request;
3014 	}
3015 
3016 	private static final String nodesEXPPARAMVALUE[] = { "INSTANCE" };
3017 
3018 	/**
3019 	 * parseEXPPARAMVALUE
3020 	 *
3021 	 * @param pExpParamValueE
3022 	 * @return CIMInstance
3023 	 * @throws CIMXMLParseException
3024 	 */
3025 	public static CIMInstance parseEXPPARAMVALUE(Element pExpParamValueE) throws CIMXMLParseException {
3026 		// <!ELEMENT EXPPARAMVALUE (INSTANCE?)>
3027 		// <!ATTLIST EXPPARAMVALUE
3028 		// %CIMName;>
3029 		// INSTANCE
3030 		if (attribute(pExpParamValueE, "NAME") == null) throw new CIMXMLParseException(
3031 			"EXPPARAMVALUE element missing NAME attribute!"
3032 		);
3033 
3034 		Element[] instanceA = searchNodes(pExpParamValueE, "INSTANCE", 0, 1, false);
3035 		if (instanceA != null) {
3036 			CIMInstance inst = parseINSTANCE(instanceA[0]);
3037 			return inst;
3038 		}
3039 
3040 		checkOtherNodes(pExpParamValueE, nodesEXPPARAMVALUE);
3041 
3042 		return null;
3043 	}
3044 
3045 	private static final String nodesMETHODRESPONSE[] = { "ERROR", "RETURNVALUE", "PARAMVALUE" };
3046 
3047 	/**
3048 	 * parseMETHODRESPONSE
3049 	 *
3050 	 * @param pMethodResponseE
3051 	 * @return CIMResponse
3052 	 * @throws CIMXMLParseException
3053 	 */
3054 	public static CIMResponse parseMETHODRESPONSE(Element pMethodResponseE) throws CIMXMLParseException {
3055 		// <!ELEMENT METHODRESPONSE (ERROR|(RETURNVALUE?,PARAMVALUE*))>
3056 		if (attribute(pMethodResponseE, "NAME") == null) throw new CIMXMLParseException(
3057 			"METHODRESPONSE element missing NAME attribute!"
3058 		);
3059 
3060 		CIMResponse response = new CIMResponse();
3061 
3062 		// ERROR
3063 		Element errorA[] = searchNodes(pMethodResponseE, "ERROR", 0, 1, false);
3064 		if (errorA != null) {
3065 			WBEMException exception = parseERROR(errorA[0]);
3066 			response.setError(exception);
3067 			return response;
3068 		}
3069 
3070 		// RETURNVALUE
3071 		Element[] retValElementA = searchNodes(pMethodResponseE, "RETURNVALUE", 0, 1, true);
3072 		if (retValElementA != null) {
3073 			Vector<Object> v = new Vector<Object>();
3074 			for (int i = 0; i < retValElementA.length; i++) {
3075 				Element returnvalueE = retValElementA[i];
3076 				v.add(parseRETURNVALUE(returnvalueE));
3077 			}
3078 			response.setReturnValue(v);
3079 		}
3080 
3081 		// PARAMVALUE
3082 		Element[] paramValElementA = searchNodes(pMethodResponseE, "PARAMVALUE", 0, Integer.MAX_VALUE, true);
3083 		if (paramValElementA != null) {
3084 			Vector<Object> v = new Vector<Object>();
3085 			for (int i = 0; i < paramValElementA.length; i++) {
3086 				Element paramvalueE = paramValElementA[i];
3087 				CIMArgument<?> arg = parsePARAMVALUE(paramvalueE);
3088 				v.add(arg);
3089 			}
3090 			response.addParamValue(v);
3091 		}
3092 
3093 		// PARAMVALUE (ESS fix)
3094 		if (retValElementA != null) {
3095 			for (int i = 0; i < retValElementA.length; i++) {
3096 				Element retValE = retValElementA[i];
3097 
3098 				paramValElementA = searchNodes(retValE, "PARAMVALUE");
3099 				if (paramValElementA != null) {
3100 					Vector<CIMArgument<Object>> v = new Vector<CIMArgument<Object>>();
3101 					for (int j = 0; j < paramValElementA.length; j++) {
3102 						Element paramvalueE = paramValElementA[j];
3103 						CIMArgument<Object> arg = parsePARAMVALUE(paramvalueE);
3104 						v.add(arg);
3105 					}
3106 					response.addParamValue(v);
3107 				}
3108 			}
3109 		}
3110 		checkOtherNodes(pMethodResponseE, nodesMETHODRESPONSE);
3111 
3112 		return response;
3113 	}
3114 
3115 	private static final String nodesIMETHODRESPONSE[] = { "ERROR", "IRETURNVALUE", "PARAMVALUE" };
3116 
3117 	/**
3118 	 * parseIMETHODRESPONSE
3119 	 *
3120 	 * @param pIMethodResponseE
3121 	 * @return CIMResponse
3122 	 * @throws CIMXMLParseException
3123 	 */
3124 	public static CIMResponse parseIMETHODRESPONSE(Element pIMethodResponseE) throws CIMXMLParseException {
3125 		// <!ELEMENT IMETHODRESPONSE (ERROR|(IRETURNVALUE?, PARAMVALUE*))>
3126 		if (attribute(pIMethodResponseE, "NAME") == null) throw new CIMXMLParseException(
3127 			"IMETHODRESPONSE element missing NAME attribute!"
3128 		);
3129 
3130 		CIMResponse response = new CIMResponse();
3131 		// ERROR
3132 		Element[] errorA = searchNodes(pIMethodResponseE, "ERROR", 0, 1, false);
3133 		if (errorA != null) {
3134 			WBEMException exception = parseERROR(errorA[0]);
3135 			response.setError(exception);
3136 			return response;
3137 		}
3138 
3139 		// IRETURNVALUE
3140 		Element[] retValElementA = searchNodes(pIMethodResponseE, "IRETURNVALUE", 0, 1, true);
3141 		if (retValElementA != null) {
3142 			for (int i = 0; i < retValElementA.length; i++) {
3143 				Element ireturnvalueE = retValElementA[i];
3144 
3145 				Vector<Object> rtnV = parseIRETURNVALUE(ireturnvalueE);
3146 				response.setReturnValue(rtnV);
3147 			}
3148 		}
3149 
3150 		// PARAMVALUE
3151 		Element[] paramValElementA = searchNodes(pIMethodResponseE, "PARAMVALUE", 0, Integer.MAX_VALUE, true);
3152 		if (paramValElementA != null) {
3153 			Vector<Object> v = new Vector<Object>();
3154 			for (int i = 0; i < paramValElementA.length; i++) {
3155 				Element paramvalueE = paramValElementA[i];
3156 				CIMArgument<?> arg = parsePARAMVALUE(paramvalueE);
3157 				v.add(arg);
3158 			}
3159 			response.addParamValue(v);
3160 		}
3161 		checkOtherNodes(pIMethodResponseE, nodesIMETHODRESPONSE);
3162 
3163 		return response;
3164 	}
3165 
3166 	private static final String nodesERROR[] = { "INSTANCE" };
3167 
3168 	/**
3169 	 * parseERROR
3170 	 *
3171 	 * @param pErrorE
3172 	 * @return WBEMException
3173 	 * @throws CIMXMLParseException
3174 	 */
3175 	public static WBEMException parseERROR(Element pErrorE) throws CIMXMLParseException {
3176 		// <!ELEMENT ERROR (INSTANCE*)>
3177 		// <!ATTLSIT ERROR %CODE;%DESCRIPTION;>
3178 
3179 		Attr error_codeA = (Attr) searchAttribute(pErrorE, "CODE");
3180 		if (error_codeA == null) throw new CIMXMLParseException("ERROR element missing CODE attribute!");
3181 		String code = error_codeA.getNodeValue();
3182 		int errorCode = 0;
3183 		try {
3184 			if (code.length() > 0) errorCode = Integer.parseInt(code);
3185 		} catch (Exception e) {
3186 			LogAndTraceBroker.getBroker().trace(Level.WARNING, "exception while parsing error code from XML", e);
3187 			errorCode = WBEMException.CIM_ERR_FAILED;
3188 		}
3189 		Attr error_descriptionA = (Attr) searchAttribute(pErrorE, "DESCRIPTION");
3190 		String description = "";
3191 		if (error_descriptionA != null) {
3192 			description = error_descriptionA.getNodeValue();
3193 		}
3194 
3195 		Vector<Object> rtnV = new Vector<Object>();
3196 
3197 		// INSTANCE
3198 		Element[] instElementA = searchNodes(pErrorE, "INSTANCE", 0, Integer.MAX_VALUE, false);
3199 		if (instElementA != null) {
3200 			for (int i = 0; i < instElementA.length; i++) {
3201 				Element instanceE = instElementA[i];
3202 				CIMInstance inst = parseINSTANCE(instanceE);
3203 				rtnV.add(inst);
3204 			}
3205 		}
3206 		checkOtherNodes(pErrorE, nodesERROR);
3207 
3208 		// throw new CIMException(CIMException.getErrorName(errorCode),
3209 		// description.substring(description.indexOf(':')+1));
3210 		if (!rtnV.isEmpty()) return new WBEMException(
3211 			errorCode,
3212 			"ErrorCode:" + errorCode + " description:" + description,
3213 			rtnV.toArray(new CIMInstance[0])
3214 		);
3215 		return new WBEMException(errorCode, "ErrorCode:" + errorCode + " description:" + description);
3216 	}
3217 
3218 	private static final String nodesRETURNVALUE[] = { "VALUE", "VALUE.REFERENCE" };
3219 
3220 	/**
3221 	 * parseRETURNVALUE
3222 	 *
3223 	 * @param pRetValE
3224 	 * @return Object
3225 	 * @throws CIMXMLParseException
3226 	 */
3227 	public static Object parseRETURNVALUE(Element pRetValE) throws CIMXMLParseException {
3228 		// <!ELEMENT RETURNVALUE (VALUE|VALUE.REFERENCE)?>
3229 		// <!ATTLSIT RETURNVALUE %PARAMTYPE;>
3230 		// ebak: embedded object support: different parsing of VALUE sub element
3231 		checkOtherNodes(pRetValE, nodesRETURNVALUE);
3232 		if (searchNodes(pRetValE, "VALUE", 0, 1, false) != null) {
3233 			EmbObjHandler embObjHandler = new EmbObjHandler(pRetValE);
3234 			return embObjHandler.getValue();
3235 		}
3236 		if (searchNodes(pRetValE, "VALUE.REFERENCE", 0, 1, false) != null) {
3237 			TypedValue typedVal = parseSingleValue(pRetValE, VALUEREF);
3238 			Object value = typedVal.getValue();
3239 			return value;
3240 		}
3241 		checkOtherNodes(pRetValE, nodesRETURNVALUE);
3242 		return null;
3243 	}
3244 
3245 	private static final String nodesIRETURNVALUE[] = {
3246 		"CLASSNAME",
3247 		"INSTANCENAME",
3248 		"VALUE",
3249 		"VALUE.OBJECTWITHPATH",
3250 		"VALUE.OBJECTWITHLOCALPATH",
3251 		"VALUE.OBJECT",
3252 		"OBJECTPATH",
3253 		"QUALIFIER.DECLARATION",
3254 		"VALUE.ARRAY",
3255 		"VALUE.REFERENCE",
3256 		"CLASS",
3257 		"INSTANCE",
3258 		"INSTANCEPATH",
3259 		"VALUE.NAMEDINSTANCE"
3260 	};
3261 
3262 	/**
3263 	 * parseIRETURNVALUE
3264 	 *
3265 	 * @param pIRetValE
3266 	 * @return Vector
3267 	 * @throws CIMXMLParseException
3268 	 */
3269 	public static Vector<Object> parseIRETURNVALUE(Element pIRetValE) throws CIMXMLParseException {
3270 		// <!ELEMENT IRETURNVALUE (CLASSNAME*|INSTANCENAME*|INSTANCEPATH*
3271 		// |VALUE*|VALUE.OBJECTWITHPATH*|VALUE.OBJECTWITHLOCALPATH*|VALUE.OBJECT*
3272 		// |OBJECTPATH*|QUALIFIER.DECLARATION*|VALUE.ARRAY|VALUE.REFERENCE*
3273 		// |CLASS*|INSTANCE*|VALUE.NAMEDINSTANCE*|VALUE.INSTANCEWITHPATH)>
3274 
3275 		Vector<Object> rtnV = new Vector<Object>();
3276 
3277 		// CLASS
3278 		Element[] classElementA = searchNodes(pIRetValE, "CLASS", 0, Integer.MAX_VALUE, false);
3279 		if (classElementA != null) {
3280 			for (int i = 0; i < classElementA.length; i++) {
3281 				Element classE = classElementA[i];
3282 				CIMClass c = parseCLASS(classE);
3283 				rtnV.add(c);
3284 			}
3285 			return rtnV;
3286 		}
3287 
3288 		// INSTANCE
3289 		Element[] instElementA = searchNodes(pIRetValE, "INSTANCE", 0, Integer.MAX_VALUE, false);
3290 		if (instElementA != null) {
3291 			for (int i = 0; i < instElementA.length; i++) {
3292 				Element instanceE = instElementA[i];
3293 				CIMInstance inst = parseINSTANCE(instanceE);
3294 				rtnV.add(inst);
3295 			}
3296 			return rtnV;
3297 		}
3298 
3299 		// CLASSNAME
3300 		Element[] classNameElementA = searchNodes(pIRetValE, "CLASSNAME", 0, Integer.MAX_VALUE, false);
3301 		if (classNameElementA != null) {
3302 			for (int i = 0; i < classNameElementA.length; i++) {
3303 				Element classnameE = classNameElementA[i];
3304 				CIMObjectPath op = parseCLASSNAME(classnameE);
3305 				rtnV.add(op);
3306 			}
3307 			return rtnV;
3308 		}
3309 
3310 		// INSTANCENAME
3311 		Element[] instNameElementA = searchNodes(pIRetValE, "INSTANCENAME", 0, Integer.MAX_VALUE, false);
3312 		if (instNameElementA != null) {
3313 			for (int i = 0; i < instNameElementA.length; i++) {
3314 				Element instancenameE = instNameElementA[i];
3315 				CIMObjectPath op = parseINSTANCENAME(instancenameE);
3316 				rtnV.add(op);
3317 			}
3318 			return rtnV;
3319 		}
3320 
3321 		// INSTANCEPATH
3322 		Element[] instpathElementA = searchNodes(pIRetValE, "INSTANCEPATH", 0, Integer.MAX_VALUE, false);
3323 		if (instpathElementA != null) {
3324 			for (int i = 0; i < instpathElementA.length; i++) {
3325 				Element instancePathE = instpathElementA[i];
3326 				CIMObjectPath op = parseINSTANCEPATH(instancePathE);
3327 				rtnV.add(op);
3328 			}
3329 			return rtnV;
3330 		}
3331 
3332 		// OBJECTPATH
3333 		Element[] objPathElementA = searchNodes(pIRetValE, "OBJECTPATH", 0, Integer.MAX_VALUE, false);
3334 		if (objPathElementA != null) {
3335 			for (int i = 0; i < objPathElementA.length; i++) {
3336 				Element objectpathE = objPathElementA[i];
3337 				CIMObjectPath op = parseOBJECTPATH(objectpathE);
3338 				rtnV.add(op);
3339 			}
3340 			return rtnV;
3341 		}
3342 
3343 		// VALUE
3344 		Element[] valueElementA = searchNodes(pIRetValE, "VALUE", 0, Integer.MAX_VALUE, false);
3345 		if (valueElementA != null) {
3346 			for (int i = 0; i < valueElementA.length; i++) {
3347 				Element valueE = valueElementA[i];
3348 				TypedValue tv = parseVALUE(valueE);
3349 				rtnV.add(tv.getValue());
3350 			}
3351 			return rtnV;
3352 		}
3353 
3354 		// VALUE.ARRAY
3355 		Element[] valueArrayElementA = searchNodes(pIRetValE, "VALUE.ARRAY", 0, 1, false);
3356 		if (valueArrayElementA != null) {
3357 			Element valuearrayE = valueArrayElementA[0];
3358 			TypedValue tv = parseVALUEARRAY(valuearrayE);
3359 			rtnV.add(tv.getValue());
3360 			return rtnV;
3361 		}
3362 
3363 		// VALUE.REFERENCE
3364 		Element[] valRefElementA = searchNodes(pIRetValE, "VALUE.REFERENCE", 0, 1, false);
3365 		if (valRefElementA != null) {
3366 			Element valuereferenceE = valRefElementA[0];
3367 			CIMObjectPath op = parseVALUEREFERENCE(valuereferenceE);
3368 			rtnV.add(op);
3369 			return rtnV;
3370 		}
3371 
3372 		// VALUE.OBJECT
3373 		Element[] valObjElementA = searchNodes(pIRetValE, "VALUE.OBJECT", 0, Integer.MAX_VALUE, false);
3374 		if (valObjElementA != null) {
3375 			for (int i = 0; i < valObjElementA.length; i++) {
3376 				Element valueobjectE = valObjElementA[i];
3377 				CIMNamedElementInterface obj = parseVALUEOBJECT(valueobjectE);
3378 				rtnV.add(obj);
3379 			}
3380 			return rtnV;
3381 		}
3382 
3383 		// VALUE.NAMEDINSTANCE
3384 		Element[] valNamedInstElementA = searchNodes(pIRetValE, "VALUE.NAMEDINSTANCE", 0, Integer.MAX_VALUE, false);
3385 		if (valNamedInstElementA != null) {
3386 			for (int i = 0; i < valNamedInstElementA.length; i++) {
3387 				Element valuenamedisntanceE = valNamedInstElementA[i];
3388 				CIMInstance inst = parseVALUENAMEDINSTANCE(valuenamedisntanceE);
3389 				rtnV.add(inst);
3390 			}
3391 			return rtnV;
3392 		}
3393 
3394 		// VALUE.INSTANCEWITHPATH
3395 		Element[] valInstWithPathElementA = searchNodes(pIRetValE, "VALUE.INSTANCEWITHPATH", 0, Integer.MAX_VALUE, false);
3396 		if (valInstWithPathElementA != null) {
3397 			for (int i = 0; i < valInstWithPathElementA.length; i++) {
3398 				Element valueinstancewithpathE = valInstWithPathElementA[i];
3399 				CIMInstance inst = parseVALUEINSTANCEWITHPATH(valueinstancewithpathE);
3400 				rtnV.add(inst);
3401 			}
3402 			return rtnV;
3403 		}
3404 
3405 		// VALUE.OBJECTWITHPATH
3406 		Element[] valObjWithPathElementA = searchNodes(pIRetValE, "VALUE.OBJECTWITHPATH", 0, Integer.MAX_VALUE, false);
3407 		if (valObjWithPathElementA != null) {
3408 			for (int i = 0; i < valObjWithPathElementA.length; i++) {
3409 				Element valueobjectwithpathE = valObjWithPathElementA[i];
3410 				CIMNamedElementInterface namedIF = parseVALUEOBJECTWITHPATH(valueobjectwithpathE);
3411 				rtnV.add(namedIF);
3412 			}
3413 			return rtnV;
3414 		}
3415 
3416 		// VALUE.OBJECTWITHLOCALPATH
3417 		Element[] valObjWithLocalPathElementA = searchNodes(
3418 			pIRetValE,
3419 			"VALUE.OBJECTWITHLOCALPATH",
3420 			0,
3421 			Integer.MAX_VALUE,
3422 			false
3423 		);
3424 		if (valObjWithLocalPathElementA != null) {
3425 			for (int i = 0; i < valObjWithLocalPathElementA.length; i++) {
3426 				Element valueobjectwithlocalpathE = valObjWithLocalPathElementA[i];
3427 				CIMNamedElementInterface namedIF = parseVALUEOBJECTWITHLOCALPATH(valueobjectwithlocalpathE);
3428 				rtnV.add(namedIF);
3429 			}
3430 			return rtnV;
3431 		}
3432 
3433 		// QUALIFIER.DECLARATION
3434 		Element[] qualiDeclElementA = searchNodes(pIRetValE, "QUALIFIER.DECLARATION", 0, Integer.MAX_VALUE, false);
3435 		if (qualiDeclElementA != null) {
3436 			for (int i = 0; i < qualiDeclElementA.length; i++) {
3437 				Element qualifierdeclarationE = qualiDeclElementA[i];
3438 				CIMQualifierType<Object> o = parseQUALIFIERDECLARATION(qualifierdeclarationE);
3439 				rtnV.add(o);
3440 			}
3441 			return rtnV;
3442 		}
3443 		checkOtherNodes(pIRetValE, nodesIRETURNVALUE);
3444 		return rtnV;
3445 	}
3446 
3447 	/**
3448 	 * parseObject
3449 	 *
3450 	 * @param pRootE
3451 	 * @return Object
3452 	 * @throws CIMXMLParseException
3453 	 */
3454 	public static Object parseObject(Element pRootE) throws CIMXMLParseException {
3455 		Object o = null;
3456 		String nodeName = pRootE.getNodeName();
3457 		if (nodeName.equalsIgnoreCase("INSTANCE")) {
3458 			o = parseINSTANCE(pRootE);
3459 		} else if (nodeName.equalsIgnoreCase("VALUE.NAMEDINSTANCE")) {
3460 			o = parseVALUENAMEDINSTANCE(pRootE);
3461 		} else if (nodeName.equalsIgnoreCase("VALUE.NAMEDOBJECT")) {
3462 			o = parseVALUENAMEDOBJECT(pRootE);
3463 		} else if (nodeName.equalsIgnoreCase("VALUE.OBJECTWITHPATH")) {
3464 			o = parseVALUEOBJECTWITHPATH(pRootE);
3465 		} else if (nodeName.equalsIgnoreCase("VALUE.OBJECTWITHLOCALPATH")) {
3466 			o = parseVALUEOBJECTWITHLOCALPATH(pRootE);
3467 		} else if (nodeName.equalsIgnoreCase("CLASS")) {
3468 			o = parseCLASS(pRootE);
3469 		} else if (nodeName.equalsIgnoreCase("CLASSPATH")) {
3470 			o = parseCLASSPATH(pRootE);
3471 		} else if (nodeName.equalsIgnoreCase("LOCALCLASSPATH")) {
3472 			o = parseLOCALCLASSPATH(pRootE);
3473 		} else if (nodeName.equalsIgnoreCase("OBJECTPATH")) {
3474 			o = parseOBJECTPATH(pRootE);
3475 		} else if (nodeName.equalsIgnoreCase("CLASSNAME")) {
3476 			o = parseCLASSNAME(pRootE);
3477 		} else if (nodeName.equalsIgnoreCase("INSTANCEPATH")) {
3478 			o = parseINSTANCEPATH(pRootE);
3479 		} else if (nodeName.equalsIgnoreCase("LOCALINSTANCEPATH")) {
3480 			o = parseLOCALINSTANCEPATH(pRootE);
3481 		} else if (nodeName.equalsIgnoreCase("INSTANCENAME")) {
3482 			o = parseINSTANCENAME(pRootE);
3483 		} else if (nodeName.equalsIgnoreCase("QUALIFIER")) {
3484 			o = parseQUALIFIER(pRootE);
3485 		} else if (nodeName.equalsIgnoreCase("PROPERTY")) {
3486 			o = parsePROPERTY(pRootE);
3487 		} else if (nodeName.equalsIgnoreCase("PROPERTY.ARRAY")) {
3488 			o = parsePROPERTYARRAY(pRootE);
3489 		} else if (nodeName.equalsIgnoreCase("PROPERTY.REFERENCE")) {
3490 			o = parsePROPERTYREFERENCE(pRootE);
3491 		} else if (nodeName.equalsIgnoreCase("METHOD")) {
3492 			o = parseMETHOD(pRootE);
3493 		} else if (nodeName.equalsIgnoreCase("PARAMETER")) {
3494 			o = parsePARAMETER(pRootE);
3495 		} else if (nodeName.equalsIgnoreCase("PARAMETER.REFERENCE")) {
3496 			o = parsePARAMETERREFERENCE(pRootE);
3497 		} else if (nodeName.equalsIgnoreCase("PARAMETER.ARRAY")) {
3498 			o = parsePARAMETERARRAY(pRootE);
3499 		} else if (nodeName.equalsIgnoreCase("PARAMETER.REFARRAY")) {
3500 			o = parsePARAMETERREFARRAY(pRootE);
3501 		}
3502 		return o;
3503 	}
3504 
3505 	// ///////////////////////////////////////////////////////////////////////////////////////////
3506 
3507 	/**
3508 	 * hasNodes
3509 	 *
3510 	 * @param pParentE
3511 	 * @return boolean
3512 	 */
3513 	private static boolean hasNodes(Element pParentE) {
3514 		NodeList nl = pParentE.getChildNodes();
3515 		if (nl == null || nl.getLength() == 0) return false;
3516 		for (int i = 0; i < nl.getLength(); i++) {
3517 			Node n = nl.item(i);
3518 			if (!(n instanceof Text) || !("".equalsIgnoreCase(n.getNodeValue().trim()))) return true;
3519 		}
3520 		return false;
3521 	}
3522 
3523 	/**
3524 	 * hasTypeAttrsInNodes
3525 	 *
3526 	 * SVC CIMOM sends typed CIM-XML elements in a non-standard way. The TYPE
3527 	 * attribute is included in the VALUE or VALUE.ARRAY element not in the
3528 	 * enclosing element as the standard says.
3529 	 *
3530 	 * @param pParentE
3531 	 * @return boolean
3532 	 */
3533 	private static boolean hasTypeAttrsInNodes(Element pParentE) {
3534 		NodeList nl = pParentE.getChildNodes();
3535 		if (nl == null || nl.getLength() == 0) return false;
3536 		for (int i = 0; i < nl.getLength(); i++) {
3537 			Node n = nl.item(i);
3538 			String name = n.getNodeName();
3539 			if ("VALUE".equalsIgnoreCase(name) || "VALUE.ARRAY".equalsIgnoreCase(name)) {
3540 				NamedNodeMap nm = n.getAttributes();
3541 				if (nm != null && (nm.getNamedItem("TYPE") != null || nm.getNamedItem("PARAMTYPE") != null)) return true;
3542 			}
3543 		}
3544 		return false;
3545 	}
3546 
3547 	private static final HashMap<String, String> NODENAME_HASH = new HashMap<String, String>();
3548 
3549 	private static void initNodeNameHash(String[] pEnumA) {
3550 		for (int i = 0; i < pEnumA.length; i++) NODENAME_HASH.put(pEnumA[i], pEnumA[i]);
3551 	}
3552 
3553 	static {
3554 		initNodeNameHash(
3555 			new String[] {
3556 				"CIM",
3557 				"DECLARATION",
3558 				"DECLGROUP",
3559 				"DECLGROUP.WITHNAME",
3560 				"DECLGROUP.WITHPATH",
3561 				"QUALIFIER.DECLARATION",
3562 				"SCOPE",
3563 				"VALUE",
3564 				"VALUE.ARRAY",
3565 				"VALUE.REFERENCE",
3566 				"VALUE.REFARRAY",
3567 				"VALUE.OBJECT",
3568 				"VALUE.NAMEDINSTANCE",
3569 				"VALUE.NAMEDOBJECT",
3570 				"VALUE.OBJECTWITHLOCALPATH",
3571 				"VALUE.OBJECTWITHPATH",
3572 				"VALUE.NULL",
3573 				"VALUE.INSTANCEWITHPATH",
3574 				"NAMESPACEPATH",
3575 				"LOCALNAMESPACEPATH",
3576 				"HOST",
3577 				"NAMESPACE",
3578 				"CLASSPATH",
3579 				"LOCALCLASSPATH",
3580 				"CLASSNAME",
3581 				"INSTANCEPATH",
3582 				"LOCALINSTANCEPATH",
3583 				"INSTANCENAME",
3584 				"OBJECTPATH",
3585 				"KEYBINDING",
3586 				"KEYVALUE",
3587 				"CLASS",
3588 				"INSTANCE",
3589 				"QUALIFIER",
3590 				"PROPERTY",
3591 				"PROPERTY.ARRAY",
3592 				"PROPERTY.REFERENCE",
3593 				"METHOD",
3594 				"PARAMETER",
3595 				"PARAMETER.REFERENCE",
3596 				"PARAMETER.ARRAY",
3597 				"PARAMETER.REFARRAY",
3598 				"MESSAGE",
3599 				"MULTIREQ",
3600 				"MULTIEXPREQ",
3601 				"SIMPLEREQ",
3602 				"SIMPLEEXPREQ",
3603 				"IMETHODCALL",
3604 				"METHODCALL",
3605 				"EXPMETHODCALL",
3606 				"PARAMVALUE",
3607 				"IPARAMVALUE",
3608 				"EXPPARAMVALUE",
3609 				"MULTIRSP",
3610 				"MULTIEXPRSP",
3611 				"SIMPLERSP",
3612 				"SIMPLEEXPRSP",
3613 				"METHODRESPONSE",
3614 				"EXPMETHODRESPONSE",
3615 				"IMETHODRESPONSE",
3616 				"ERROR",
3617 				"RETURNVALUE",
3618 				"IRETURNVALUE",
3619 				"CORRELATOR"
3620 			}
3621 		);
3622 	}
3623 
3624 	/**
3625 	 * checkOtherNodes
3626 	 *
3627 	 * @param pParentE
3628 	 * @param pAllowedChildNodes
3629 	 */
3630 	private static void checkOtherNodes(Element pParentE, String[] pAllowedChildNodes) throws CIMXMLParseException {
3631 		NodeList nl = pParentE.getChildNodes();
3632 		if (nl == null || nl.getLength() == 0) return;
3633 		for (int i = 0; i < nl.getLength(); i++) {
3634 			Node n = nl.item(i);
3635 			if (n instanceof Text && "".equalsIgnoreCase(n.getNodeValue().trim())) continue;
3636 			boolean found = false;
3637 			String name = n.getNodeName().toUpperCase();
3638 			for (int j = 0; j < pAllowedChildNodes.length; j++) {
3639 				if (pAllowedChildNodes[j].equalsIgnoreCase(name)) {
3640 					found = true;
3641 					break;
3642 				}
3643 			}
3644 			if (!found && NODENAME_HASH.containsKey(name)) throw new CIMXMLParseException(
3645 				pParentE.getNodeName() + " element contains invalid child element " + name + "!"
3646 			);
3647 		}
3648 	}
3649 
3650 	/**
3651 	 * searchNodes
3652 	 *
3653 	 * @param pParentE
3654 	 * @param pTagName
3655 	 * @return Element[]
3656 	 */
3657 	public static Element[] searchNodes(Element pParentE, String pTagName) {
3658 		// return all of child nodes immediately below the parent
3659 		// return null if not found
3660 		NodeList nl = pParentE.getChildNodes();
3661 		if (nl == null || nl.getLength() == 0) return null;
3662 		Vector<Node> resElementV = new Vector<Node>();
3663 		for (int i = 0; i < nl.getLength(); i++) {
3664 			Node n = nl.item(i);
3665 			if (n.getNodeName().equals(pTagName)) {
3666 				resElementV.add(n);
3667 			}
3668 		}
3669 		return resElementV.toArray(new Element[0]);
3670 	}
3671 
3672 	/**
3673 	 * searchNodes
3674 	 *
3675 	 * @param pParentE
3676 	 * @param pTagName
3677 	 * @param pMin
3678 	 * @param pMax
3679 	 * @param pAllowOtherNodes
3680 	 * @return Element[]
3681 	 * @throws CIMXMLParseException
3682 	 */
3683 	public static Element[] searchNodes(Element pParentE, String pTagName, int pMin, int pMax, boolean pAllowOtherNodes)
3684 		throws CIMXMLParseException {
3685 		// return all child nodes immediately below parent, null if none found
3686 
3687 		NodeList nl = pParentE.getChildNodes();
3688 		if (nl == null || nl.getLength() == 0) {
3689 			if (pMin > 0) throw new CIMXMLParseException(
3690 				pParentE.getNodeName() + " element must have at least " + pMin + " " + pTagName + " child element(s)!"
3691 			);
3692 			return null;
3693 		}
3694 
3695 		String otherNode = null;
3696 		Vector<Node> resElementV = new Vector<Node>();
3697 		for (int i = 0; i < nl.getLength(); i++) {
3698 			Node n = nl.item(i);
3699 			String name = n.getNodeName().toUpperCase();
3700 			if (name.equals(pTagName)) {
3701 				resElementV.add(n);
3702 			} else if (NODENAME_HASH.containsKey(name)) {
3703 				otherNode = name;
3704 			}
3705 		}
3706 
3707 		if (resElementV.size() < pMin) throw new CIMXMLParseException(
3708 			pParentE.getNodeName() + " element must have at least " + pMin + " " + pTagName + " child element(s)!"
3709 		);
3710 		if (resElementV.size() > pMax) throw new CIMXMLParseException(
3711 			pParentE.getNodeName() + " element can have no more than " + pMax + " " + pTagName + " child element(s)!"
3712 		);
3713 		if (resElementV.size() > 0 && !pAllowOtherNodes && otherNode != null) throw new CIMXMLParseException(
3714 			pParentE.getNodeName() +
3715 			" element cannot have " +
3716 			otherNode +
3717 			" child element(s) when it already has " +
3718 			pTagName +
3719 			" element(s)!"
3720 		);
3721 		if (resElementV.size() == 0) return null;
3722 
3723 		return resElementV.toArray(new Element[0]);
3724 	}
3725 
3726 	/**
3727 	 * searchFirstNode
3728 	 *
3729 	 * @param pParentE
3730 	 * @param pTagName
3731 	 * @return Node
3732 	 */
3733 	public static Node searchFirstNode(Element pParentE, String pTagName) {
3734 		// return the first node which matches to the specific name
3735 		// return null if not found
3736 		NodeList nl = pParentE.getChildNodes();
3737 		for (int i = 0; i < nl.getLength(); i++) {
3738 			Node n = nl.item(i);
3739 			if (n.getNodeName().equals(pTagName)) {
3740 				return n;
3741 			}
3742 		}
3743 		return null;
3744 	}
3745 
3746 	/**
3747 	 * searchAttribute
3748 	 *
3749 	 * @param pParentN
3750 	 * @param pAttrName
3751 	 * @return Node
3752 	 */
3753 	public static Node searchAttribute(Node pParentN, String pAttrName) {
3754 		// return the attribute node with the specific name
3755 		NamedNodeMap nnm = pParentN.getAttributes();
3756 		return nnm.getNamedItem(pAttrName);
3757 	}
3758 
3759 	/**
3760 	 * searchFirstChild
3761 	 *
3762 	 * @param pParentE
3763 	 * @return Node
3764 	 */
3765 	public static Node searchFirstChild(Element pParentE) {
3766 		// return the first node which matches to the specific name
3767 		// return null if not found
3768 		return pParentE.getFirstChild();
3769 	}
3770 
3771 	/**
3772 	 * createJavaObject
3773 	 *
3774 	 * @param pTypeStr
3775 	 * @param pValue
3776 	 * @return Object
3777 	 * @throws CIMXMLParseException
3778 	 */
3779 	public static Object createJavaObject(String pTypeStr, String pValue) throws CIMXMLParseException {
3780 		// return a java object with the specific type
3781 		if (pTypeStr == null) pTypeStr = MOF.DT_STR;
3782 		if (MOF.NULL.equalsIgnoreCase(pTypeStr)) return null;
3783 		Object o = null;
3784 		CIMDataType cimType = parseTypeStr(pTypeStr, false);
3785 		int radix = 10;
3786 
3787 		if (pTypeStr.toLowerCase().startsWith("sint") || pTypeStr.toLowerCase().startsWith("uint")) {
3788 			pValue = pValue.toLowerCase();
3789 			if (pValue.startsWith("0x") || pValue.startsWith("+0x") || pValue.startsWith("-0x")) {
3790 				radix = 16;
3791 				if (pValue.startsWith("-")) pValue = "-" + pValue.substring(3); else pValue =
3792 					pValue.substring(pValue.indexOf('x') + 1);
3793 			}
3794 		}
3795 
3796 		switch (cimType.getType()) {
3797 			case CIMDataType.UINT8:
3798 				o = new UnsignedInteger8(Short.parseShort(pValue, radix));
3799 				break;
3800 			case CIMDataType.UINT16:
3801 				o = new UnsignedInteger16(Integer.parseInt(pValue, radix));
3802 				break;
3803 			case CIMDataType.UINT32:
3804 				o = new UnsignedInteger32(Long.parseLong(pValue, radix));
3805 				break;
3806 			case CIMDataType.UINT64:
3807 				o = new UnsignedInteger64(new BigInteger(pValue, radix));
3808 				break;
3809 			case CIMDataType.SINT8:
3810 				o = Byte.valueOf(pValue, radix);
3811 				break;
3812 			case CIMDataType.SINT16:
3813 				o = Short.valueOf(pValue, radix);
3814 				break;
3815 			case CIMDataType.SINT32:
3816 				o = Integer.valueOf(pValue, radix);
3817 				break;
3818 			case CIMDataType.SINT64:
3819 				o = Long.valueOf(pValue, radix);
3820 				break;
3821 			case CIMDataType.STRING:
3822 				o = pValue;
3823 				break;
3824 			case CIMDataType.BOOLEAN:
3825 				o = Boolean.valueOf(pValue);
3826 				break;
3827 			case CIMDataType.REAL32:
3828 				o = new Float(pValue);
3829 				break;
3830 			case CIMDataType.REAL64:
3831 				if (WBEMConfiguration.getGlobalConfiguration().verifyJavaLangDoubleStrings()) {
3832 					if (Util.isBadDoubleString(pValue)) throw new IllegalArgumentException(
3833 						"Double value string hangs older JVMs!\n" + pValue
3834 					);
3835 				}
3836 				o = new Double(pValue);
3837 				break;
3838 			case CIMDataType.DATETIME:
3839 				o = getDateTime(pValue);
3840 				break;
3841 			case CIMDataType.REFERENCE:
3842 				o = new CIMObjectPath(pValue);
3843 				break;
3844 			case CIMDataType.CHAR16:
3845 				o = Character.valueOf(pValue.charAt(0));
3846 				break;
3847 			// case CIMDataType.OBJECT: o = new CIMInstance(); break; //TODO
3848 			// case CIMDataType.CLASS: o = new CIMClass(value); break; //TODO
3849 		}
3850 		return o;
3851 	}
3852 
3853 	private static CIMDateTime getDateTime(String pValue) throws CIMXMLParseException {
3854 		try {
3855 			return new CIMDateTimeAbsolute(pValue);
3856 		} catch (IllegalArgumentException eAbs) {
3857 			try {
3858 				return new CIMDateTimeInterval(pValue);
3859 			} catch (IllegalArgumentException eInt) {
3860 				throw new CIMXMLParseException(
3861 					"Failed to parse dateTime string: " +
3862 					pValue +
3863 					"!\n" +
3864 					"CIMDateTimeAbsolute parsing error:\n" +
3865 					eAbs.getMessage() +
3866 					"\n" +
3867 					"CIMDateTimeInterval parsing error:\n" +
3868 					eInt.getMessage()
3869 				);
3870 			}
3871 		}
3872 	}
3873 
3874 	/**
3875 	 * parseSIMPLEEXPRSP
3876 	 *
3877 	 * @param pSimpleExpRspE
3878 	 * @return CIMResponse
3879 	 * @throws CIMXMLParseException
3880 	 */
3881 	public static CIMResponse parseSIMPLEEXPRSP(Element pSimpleExpRspE) throws CIMXMLParseException {
3882 		// <!ELEMENT SIMPLEEXPRSP (EXPMETHODRESPONSE)>
3883 
3884 		// EXPMETHODRESPONSE
3885 		Element[] expmethodresponseA = searchNodes(pSimpleExpRspE, "EXPMETHODRESPONSE", 1, 1, false);
3886 		if (expmethodresponseA != null) return parseEXPMETHODRESPONSE(expmethodresponseA[0]);
3887 
3888 		throw new CIMXMLParseException("SIMPLEEXPRSP element missing EXPMETHODRESPONSE child element!");
3889 	}
3890 
3891 	/**
3892 	 * parseMULTIEXPRSP
3893 	 *
3894 	 * @param pMultiExpRspE
3895 	 * @return CIMResponse
3896 	 * @throws CIMXMLParseException
3897 	 */
3898 	public static CIMResponse parseMULTIEXPRSP(Element pMultiExpRspE) throws CIMXMLParseException {
3899 		// <!ELEMENT MULTIEXPRSP (SIMPLEEXPRSP,SIMPLEEXPRSP+)>
3900 
3901 		Element[] multiExpRespElementA = searchNodes(pMultiExpRspE, "SIMPLEEXPRSP", 2, Integer.MAX_VALUE, false);
3902 		if (multiExpRespElementA != null) {
3903 			CIMResponse multiExpRsp = new CIMResponse();
3904 			for (int i = 0; i < multiExpRespElementA.length; i++) {
3905 				Element methodresponseE = multiExpRespElementA[i];
3906 				CIMResponse rsp = parseSIMPLEEXPRSP(methodresponseE);
3907 				rsp.setMethod("SIMPLEEXPRSP");
3908 				multiExpRsp.addResponse(rsp);
3909 			}
3910 			return multiExpRsp;
3911 		}
3912 
3913 		throw new CIMXMLParseException("MULTIEXPRSP element missing SIMPLEEXPRSP child element!");
3914 	}
3915 
3916 	private static final String[] nodesEXPMETHODRESPONSE = { "ERROR", "IRETURNVALUE" };
3917 
3918 	/**
3919 	 * parseEXPMETHODRESPONSE
3920 	 *
3921 	 * @param pExpMethodResponseE
3922 	 * @return CIMResponse
3923 	 * @throws CIMXMLParseException
3924 	 */
3925 	public static CIMResponse parseEXPMETHODRESPONSE(Element pExpMethodResponseE) throws CIMXMLParseException {
3926 		// <!ELEMENT EXPMETHODRESPONSE (ERROR | IRETURNVALUE?)>
3927 
3928 		CIMResponse response = new CIMResponse();
3929 
3930 		if (attribute(pExpMethodResponseE, "NAME") == null) throw new CIMXMLParseException(
3931 			"EXPMETHODRESPONSE element missing NAME attribute!"
3932 		);
3933 
3934 		// ERROR
3935 		Element[] errorA = searchNodes(pExpMethodResponseE, "ERROR", 0, 1, false);
3936 		if (errorA != null) {
3937 			WBEMException exception = parseERROR(errorA[0]);
3938 			response.setError(exception);
3939 			return response;
3940 		}
3941 
3942 		// RETURNVALUE
3943 		Element[] retValElementA = searchNodes(pExpMethodResponseE, "IRETURNVALUE", 0, 1, false);
3944 		if (retValElementA != null) {
3945 			Vector<Object> v = new Vector<Object>();
3946 			Element returnvalueE = retValElementA[0];
3947 			v.add(parseIRETURNVALUE(returnvalueE));
3948 			response.setReturnValue(v);
3949 			return response;
3950 		}
3951 
3952 		checkOtherNodes(pExpMethodResponseE, nodesEXPMETHODRESPONSE);
3953 
3954 		return response;
3955 	}
3956 
3957 	private static final String nodesCORRELATOR[] = { "VALUE" };
3958 
3959 	/**
3960 	 * parseCORRELATOR
3961 	 *
3962 	 * @param pCorrelatorE
3963 	 * @throws CIMXMLParseException
3964 	 * */
3965 	public static void parseCORRELATOR(Element pCorrelatorE) throws CIMXMLParseException {
3966 		// <!ELEMENT CORRELATOR (VALUE)>
3967 		// <!ATTLIST CORRELATOR %CIMName; %CIMType; #REQUIRED>
3968 		String name = attribute(pCorrelatorE, "NAME");
3969 		if (name == null) throw new CIMXMLParseException("CORRELATOR element missing NAME attribute!");
3970 		String type = attribute(pCorrelatorE, "TYPE");
3971 		if (type == null) throw new CIMXMLParseException("CORRELATOR element missing TYPE attribute!");
3972 
3973 		// VALUE
3974 		Element[] valueA = searchNodes(pCorrelatorE, "VALUE", 1, 1, false);
3975 		if (valueA != null) {
3976 			// TypedValue tVal = parseVALUE(valueA[0]);
3977 		}
3978 
3979 		checkOtherNodes(pCorrelatorE, nodesCORRELATOR);
3980 	}
3981 }