View Javadoc
1   /*
2     (C) Copyright IBM Corp. 2006, 2013
3    
4     THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE 
5     ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE 
6     CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT.
7    
8     You can obtain a current copy of the Eclipse Public License from
9     http://www.opensource.org/licenses/eclipse-1.0.php
10   
11    @author : Endre Bak, ebak@de.ibm.com  
12   * 
13   * Flag       Date        Prog         Description
14   * -------------------------------------------------------------------------------
15   * 1565892    2006-10-06  ebak         Make SBLIM client JSR48 compliant
16   * 1669961    2006-04-16  lupusalex    CIMTypedElement.getType() =>getDataType()
17   * 1737123    2007-06-15  ebak         Differences to JSR48 public review draft
18   * 1783288    2007-09-10  ebak         CIMClass.isAssociation() not working for retrieved classes.
19   * 2003590    2008-06-30  blaschke-oss Change licensing from CPL to EPL
20   * 2524131    2009-01-21  raman_arora  Upgrade client to JDK 1.5 (Phase 1)
21   * 2531371    2009-02-10  raman_arora  Upgrade client to JDK 1.5 (Phase 2)
22   * 2750520    2009-04-10  blaschke-oss Code cleanup from empty statement et al
23   * 2763216    2009-04-14  blaschke-oss Code cleanup: visible spelling/grammar errors
24   * 2797550    2009-06-01  raman_arora  JSR48 compliance - add Java Generics
25   * 2823494    2009-08-03  rgummada     Change Boolean constructor to static
26   * 2935258    2010-01-22  blaschke-oss Sync up javax.cim.* javadoc with JSR48 1.0.0
27   * 2944842    2010-02-08  blaschke-oss Missing thrown ArrayIndexOutOfBoundsException
28   * 2975917    2010-03-24  blaschke-oss TCK: CIMClass.getProperty() does not handle null property
29   * 3400209    2011-08-31  blaschke-oss Highlighted Static Analysis (PMD) issues
30   * 3496301    2012-03-02  blaschke-oss Sync up javax.* javadoc with JSR48 1.0.0 Final
31   * 3500619    2012-03-16  blaschke-oss JSR48 1.0.0: CIMClass association/key clean up
32   * 3521119    2012-04-24  blaschke-oss JSR48 1.0.0: remove CIMObjectPath 2/3/4-parm ctors
33   * 3565581    2012-09-07  blaschke-oss TCK: remove unnecessary overriding methods
34   *    2719    2013-12-10  blaschke-oss TCK: CIM APIs should not generate NullPointerException
35   *    2716    2013-12-11  blaschke-oss Sync up javax.* javadoc with JSR48 1.0.0 Final V
36   */
37  
38  package org.metricshub.wbem.javax.cim;
39  
40  /*-
41   * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
42   * WBEM Java Client
43   * ჻჻჻჻჻჻
44   * Copyright 2023 - 2025 MetricsHub
45   * ჻჻჻჻჻჻
46   * Licensed under the Apache License, Version 2.0 (the "License");
47   * you may not use this file except in compliance with the License.
48   * You may obtain a copy of the License at
49   *
50   *      http://www.apache.org/licenses/LICENSE-2.0
51   *
52   * Unless required by applicable law or agreed to in writing, software
53   * distributed under the License is distributed on an "AS IS" BASIS,
54   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
55   * See the License for the specific language governing permissions and
56   * limitations under the License.
57   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
58   */
59  
60  import java.util.ArrayList;
61  import java.util.Arrays;
62  import java.util.TreeSet;
63  import org.metricshub.wbem.sblim.cimclient.internal.cim.CIMElementSorter;
64  import org.metricshub.wbem.sblim.cimclient.internal.cim.CIMQualifiedElementInterfaceImpl;
65  import org.metricshub.wbem.sblim.cimclient.internal.util.MOF;
66  
67  //Sync'd against JSR48 1.0.0 javadoc (version 1.7.0_03) on Tue Dec 10 07:02:50 EST 2013
68  /**
69   * This class represents a CIM class as defined by the Distributed Management
70   * Task Force (<a href=http://www.dmtf.org>DMTF</a>) CIM Infrastructure
71   * Specification (<a
72   * href=http://www.dmtf.org/standards/published_documents/DSP0004V2.3_final.pdf
73   * >DSP004</a>). A <code>CIMClass</code> has the following attributes:
74   * <ul>
75   * <li>an object path describing the location and name of the class</li>
76   * <li>superclass name (can be <code>null</code> if no superclass)</li>
77   * <li>an array of qualifiers for the class</li>
78   * <li>an array of properties</li>
79   * <li>an array of methods</li>
80   * </ul>
81   */
82  public class CIMClass extends CIMElement implements CIMQualifiedElementInterface, CIMNamedElementInterface {
83  	private static final long serialVersionUID = -5634561913210025100L;
84  
85  	private CIMQualifiedElementInterfaceImpl iQualiImpl;
86  
87  	private CIMObjectPath iObjPath;
88  
89  	private String iSuperClass;
90  
91  	private CIMClassProperty<?>[] iProps;
92  
93  	private CIMMethod<?>[] iMethods;
94  
95  	private boolean iIsKeyed;
96  
97  	private boolean iIsAssoc;
98  
99  	/**
100 	 * Creates and instantiates a Java object representing a CIM Class. This
101 	 * method may or may not validate the <code>pIsAssociation</code> and
102 	 * <code>pIsKeyed</code> parameters. If an invalid value is supplied (i.e.
103 	 * the class is an association, but the <code>pIsAssociation</code> was set
104 	 * to <code>false</code>), it may or may not be corrected.
105 	 *
106 	 * @param pPath
107 	 *            Object Name of the CIM class.
108 	 * @param pSuperClass
109 	 *            Name of the superclass.
110 	 * @param pQualifiers
111 	 *            List of qualifiers of the CIM class.
112 	 * @param pProperties
113 	 *            List of properties of the CIM class.
114 	 * @param pMethods
115 	 *            List of methods of the CIM class.
116 	 * @param pIsAssociation
117 	 *            <code>true</code> if the CIM class is an Association,
118 	 *            <code>false</code> otherwise.
119 	 * @param pIsKeyed
120 	 *            <code>true</code> if the CIM class has Keys,
121 	 *            <code>false</code> otherwise.
122 	 * @throws IllegalArgumentException
123 	 *             If pPath is null.
124 	 *
125 	 */
126 	public CIMClass(
127 		CIMObjectPath pPath,
128 		String pSuperClass,
129 		CIMQualifier<?>[] pQualifiers,
130 		CIMClassProperty<?>[] pProperties,
131 		CIMMethod<?>[] pMethods,
132 		boolean pIsAssociation,
133 		boolean pIsKeyed
134 	) {
135 		this(pPath, pSuperClass, pQualifiers, pProperties, pMethods);
136 		// if (this.isAssociation() != pIsAssociation) {
137 		// throw new IllegalArgumentException(
138 		// "pIsAssociation does not match pQualifiers! pIsAssociation is " +
139 		// pIsAssociation
140 		// + " while pQualifiers "
141 		// + (this.isAssociation() ? "contains" : "does not contain")
142 		// + " qualifier with association in class " +
143 		// this.iObjPath.getObjectName());
144 		// }
145 		// if (this.isKeyed() != pIsKeyed) {
146 		// throw new IllegalArgumentException(
147 		// "pIsKeyed does not match pProperties! pIsKeyed is " + pIsKeyed
148 		// + " while pProperties "
149 		// + (this.isKeyed() ? "contains" : "does not contain")
150 		// + " property with key qualifier in class " +
151 		// this.iObjPath.getObjectName());
152 		// }
153 	}
154 
155 	/**
156 	 * Creates and instantiates a Java object representing a CIM Class. This
157 	 * constructor will inspect the class to determine if it is an association
158 	 * or has keys.
159 	 *
160 	 * @param pName
161 	 *            Name of the CIM class.
162 	 * @param pSuperClass
163 	 *            Name of the superclass.
164 	 * @param pQualifiers
165 	 *            List of qualifiers of the CIM class.
166 	 * @param pProperties
167 	 *            List of properties of the CIM class.
168 	 * @param pMethods
169 	 *            List of methods of the CIM class.
170 	 * @throws IllegalArgumentException
171 	 *             If pName is null.
172 	 */
173 	public CIMClass(
174 		String pName,
175 		String pSuperClass,
176 		CIMQualifier<?>[] pQualifiers,
177 		CIMClassProperty<?>[] pProperties,
178 		CIMMethod<?>[] pMethods
179 	) {
180 		this(new CIMObjectPath(null, null, null, null, pName, null), pSuperClass, pQualifiers, pProperties, pMethods);
181 	}
182 
183 	/**
184 	 * This private constructor does the actual work for the two public
185 	 * constructors and sets the iIsAssoc and iIsKeyed instance variables based
186 	 * on whether there is qualifier with name="Association" and value=true and
187 	 * a property with a qualifier with name="Key" and value=true, respectively.
188 	 */
189 	private CIMClass(
190 		CIMObjectPath pPath,
191 		String pSuperClass,
192 		CIMQualifier<?>[] pQualifiers,
193 		CIMClassProperty<?>[] pProperties,
194 		CIMMethod<?>[] pMethods
195 	) {
196 		super(pPath == null ? null : pPath.getObjectName());
197 		this.iObjPath = pPath;
198 		this.iSuperClass = pSuperClass;
199 		this.iQualiImpl = new CIMQualifiedElementInterfaceImpl(pQualifiers);
200 		this.iProps = (CIMClassProperty[]) CIMElementSorter.sort(pProperties);
201 		this.iMethods = (CIMMethod[]) CIMElementSorter.sort(pMethods);
202 		this.iIsAssoc = this.iQualiImpl.hasQualifierValue("Association", Boolean.TRUE);
203 		this.iIsKeyed = hasKey(pProperties);
204 	}
205 
206 	/**
207 	 * Indicates whether the specified <code>CIMClass</code> is equal to this
208 	 * <code>CIMClass</code>.
209 	 *
210 	 * @param pObj
211 	 *            The <code>CIMClass</code> object with which to compare.
212 	 * @return <code>true</code> if this object is the same as the
213 	 *         <code>pObj</code> argument; <code>false</code> otherwise.
214 	 */
215 	@Override
216 	public boolean equals(Object pObj) {
217 		if (!(pObj instanceof CIMClass)) return false;
218 		CIMClass that = (CIMClass) pObj;
219 		if (!super.equals(that)) return false;
220 		if (
221 			this.iSuperClass == null ? that.iSuperClass != null : !this.iSuperClass.equalsIgnoreCase(that.iSuperClass)
222 		) return false;
223 		if (
224 			!this.iQualiImpl.equals(that.iQualiImpl) ||
225 			!Arrays.equals(this.iProps, that.iProps) ||
226 			!Arrays.equals(this.iMethods, that.iMethods) ||
227 			this.iIsAssoc != that.iIsAssoc ||
228 			isKeyed() != that.isKeyed()
229 		) return false;
230 		return true;
231 	}
232 
233 	/**
234 	 * This method returns a new <code>CIMClass</code> with properties filtered
235 	 * according to the input parameters. Inclusion of class origin and
236 	 * qualifiers can also be controlled. Methods will not be included in the
237 	 * class returned.
238 	 *
239 	 * @param pLocalOnly
240 	 *            If <code>true</code> only the elements defined in this class
241 	 *            are included; otherwise all elements are included.
242 	 * @param pIncludeQualifiers
243 	 *            If <code>true</code> qualifiers are included on all elements;
244 	 *            otherwise no qualifiers are included.
245 	 * @param pIncludeClassOrigin
246 	 *            If <code>true</code>, the ClassOrigin attribute is included.
247 	 * @param pPropertyList
248 	 *            If the <code>PropertyList</code> input parameter is not
249 	 *            <code>null</code>, the members of the array define one or more
250 	 *            Property names. The <code>CIMClass</code> returned does not
251 	 *            include elements for any Properties missing from this list. If
252 	 *            the <code>PropertyList</code> input parameter is an empty
253 	 *            array this signifies that no Properties are included in the
254 	 *            class returned. If the <code>PropertyList</code> input
255 	 *            parameter is <b><code>null</code></b> this specifies that all
256 	 *            Properties are included in the class returned. If the
257 	 *            <code>PropertyList</code> contains duplicate elements or
258 	 *            invalid property names, they are ignored.
259 	 * @return <code>CIMClass</code> matching the requested criteria.
260 	 */
261 	public CIMClass filterProperties(
262 		boolean pLocalOnly,
263 		boolean pIncludeQualifiers,
264 		boolean pIncludeClassOrigin,
265 		String[] pPropertyList
266 	) {
267 		ArrayList<CIMClassProperty<?>> newPropAList = new ArrayList<CIMClassProperty<?>>();
268 		// place pPropertyList into a set, for easy and fast search
269 		TreeSet<String> set;
270 		if (pPropertyList != null) {
271 			set = new TreeSet<String>();
272 			for (int i = 0; i < pPropertyList.length; i++) set.add(pPropertyList[i].toUpperCase());
273 		} else set = null;
274 		for (int i = 0; i < getPropertyCount(); i++) {
275 			CIMClassProperty<?> refProp = getProperty(i);
276 			if (pLocalOnly && refProp.isPropagated()) continue;
277 			if (set == null || set.contains(refProp.getName().toUpperCase())) newPropAList.add(
278 				new CIMClassProperty<Object>(
279 					refProp.getName(),
280 					refProp.getDataType(),
281 					refProp.getValue(),
282 					pIncludeQualifiers ? refProp.getQualifiers() : null,
283 					pIncludeQualifiers ? refProp.isKey() : false, // FIXME:
284 					// Should it depend on pIncludeQualifiers?
285 					refProp.isPropagated(),
286 					pIncludeClassOrigin ? refProp.getOriginClass() : null
287 				)
288 			);
289 		}
290 		return new CIMClass(
291 			getObjectPath(),
292 			getSuperClassName(),
293 			getQualifiers(),
294 			newPropAList.toArray(new CIMClassProperty[0]),
295 			null,
296 			isAssociation(),
297 			isKeyed()
298 		);
299 	}
300 
301 	/**
302 	 * Returns a list of key properties for this CIM class.
303 	 *
304 	 * @return The list of CIM properties that are keys for this CIM class.
305 	 */
306 	public CIMClassProperty<?>[] getKeys() {
307 		ArrayList<CIMClassProperty<?>> keyAList = new ArrayList<CIMClassProperty<?>>();
308 		for (int i = 0; i < getPropertyCount(); i++) {
309 			CIMClassProperty<?> prop = getProperty(i);
310 			if (prop.isKey()) keyAList.add(prop);
311 		}
312 		return keyAList.toArray(new CIMClassProperty[0]);
313 	}
314 
315 	/**
316 	 * Get a method by index.
317 	 *
318 	 * @param pIndex
319 	 *            The index of the method to retrieve.
320 	 * @return The <code>CIMMethod</code> at the specified index.
321 	 * @throws ArrayIndexOutOfBoundsException
322 	 */
323 	public CIMMethod<?> getMethod(int pIndex) throws ArrayIndexOutOfBoundsException {
324 		return this.iMethods[pIndex];
325 	}
326 
327 	/**
328 	 * Returns the specified CIM method in this CIM class.
329 	 *
330 	 * @param pName
331 	 *            The string name of the method to retrieve. The name may be
332 	 *            specified in the form <code>"originClass.methodName"</code>.
333 	 * @return The CIM method specified or <code>null</code> if the method does
334 	 *         not exist.
335 	 */
336 
337 	public CIMMethod<?> getMethod(String pName) {
338 		return getMethod(pName, null);
339 	}
340 
341 	/**
342 	 * Returns the CIM method specified by its name and optionally, its origin
343 	 * class. The origin class is the class in which the method is defined.
344 	 *
345 	 * @param pName
346 	 *            The string name of the method to get.
347 	 * @param pOriginClass
348 	 *            (Optional) The class in which the method was defined.
349 	 * @return The CIM method specified or <code>null</code> if the method does
350 	 *         not exist.
351 	 */
352 	public CIMMethod<?> getMethod(String pName, String pOriginClass) {
353 		CIMMethod<?> method = (CIMMethod<?>) CIMElementSorter.find(this.iMethods, pName);
354 		if (method == null) return null;
355 		if (pOriginClass == null || pOriginClass.equalsIgnoreCase(method.getOriginClass())) return method;
356 		return null;
357 	}
358 
359 	/**
360 	 * Get the number of methods defined in this CIM class.
361 	 *
362 	 * @return The number of methods defined in the CIM class.
363 	 */
364 	public int getMethodCount() {
365 		return this.iMethods == null ? 0 : this.iMethods.length;
366 	}
367 
368 	/**
369 	 * Get the CIM methods defined in this CIM class.
370 	 *
371 	 * @return The methods in this CIM class.
372 	 */
373 	public CIMMethod<?>[] getMethods() {
374 		return this.iMethods != null ? this.iMethods : new CIMMethod[0];
375 	}
376 
377 	/**
378 	 * This method returns the <code>CIMObjectPath</code> that represents this
379 	 * CIM class.
380 	 *
381 	 * @return The <code>CIMObjectPath</code> that represents this CIM class.
382 	 */
383 	public CIMObjectPath getObjectPath() {
384 		return this.iObjPath;
385 	}
386 
387 	/**
388 	 * Get the properties defined for this CIM class.
389 	 *
390 	 * @return The properties for this class.
391 	 */
392 	public CIMClassProperty<?>[] getProperties() {
393 		return this.iProps != null ? this.iProps : new CIMClassProperty[0];
394 	}
395 
396 	/**
397 	 * Get a class property by index.
398 	 *
399 	 * @param pIndex
400 	 *            The index of the class property to retrieve.
401 	 * @return The <code>CIMClassProperty</code> at the specified index.
402 	 * @throws ArrayIndexOutOfBoundsException
403 	 */
404 	public CIMClassProperty<?> getProperty(int pIndex) throws ArrayIndexOutOfBoundsException {
405 		return this.iProps[pIndex];
406 	}
407 
408 	/**
409 	 * Gets the specified property.
410 	 *
411 	 * @param pName
412 	 *            The text string for the name of the property.
413 	 * @return The property requested or <code>null</code> if the property does
414 	 *         not exist.
415 	 */
416 	public CIMClassProperty<?> getProperty(String pName) {
417 		return (CIMClassProperty<?>) CIMElementSorter.find(this.iProps, pName);
418 	}
419 
420 	/**
421 	 * Gets the specified property.
422 	 *
423 	 * @param pName
424 	 *            The string name of the property to get.
425 	 * @param pOriginClass
426 	 *            (Optional) The string name of the class in which the property
427 	 *            was defined.
428 	 * @return The property requested or <code>null</code> if the property does
429 	 *         not exist.
430 	 */
431 	public CIMClassProperty<?> getProperty(String pName, String pOriginClass) {
432 		CIMClassProperty<?> prop = (CIMClassProperty<?>) CIMElementSorter.find(this.iProps, pName);
433 		if (prop == null || pOriginClass == null) return prop;
434 		return pOriginClass.equalsIgnoreCase(prop.getOriginClass()) ? prop : null;
435 	}
436 
437 	/**
438 	 * Get the number of properties defined in this <code>CIMClass</code>.
439 	 *
440 	 * @return The number of properties defined in the <code>CIMClass</code>.
441 	 */
442 	public int getPropertyCount() {
443 		return this.iProps != null ? this.iProps.length : 0;
444 	}
445 
446 	/**
447 	 * Get a qualifier by index.
448 	 *
449 	 * @param pIndex
450 	 *            The index of the qualifier to retrieve.
451 	 * @return The qualifier at the specified index.
452 	 * @throws ArrayIndexOutOfBoundsException
453 	 */
454 	public CIMQualifier<?> getQualifier(int pIndex) throws ArrayIndexOutOfBoundsException {
455 		return this.iQualiImpl.getQualifier(pIndex);
456 	}
457 
458 	/**
459 	 * Gets a qualifier by name.
460 	 *
461 	 * @param pName
462 	 *            The name of the qualifier to get.
463 	 * @return The qualifier requested or <code>null</code> if the qualifier
464 	 *         does not exist.
465 	 */
466 	public CIMQualifier<?> getQualifier(String pName) {
467 		return this.iQualiImpl.getQualifier(pName);
468 	}
469 
470 	/**
471 	 * Get the number of qualifiers defined in this CIM class.
472 	 *
473 	 * @return The number of qualifiers defined in the CIM class.
474 	 */
475 	public int getQualifierCount() {
476 		return this.iQualiImpl.getQualifierCount();
477 	}
478 
479 	/**
480 	 * Returns the list of qualifiers for the CIM class.
481 	 *
482 	 * @return Qualifiers for this class.
483 	 */
484 	public CIMQualifier<?>[] getQualifiers() {
485 		return this.iQualiImpl.getQualifiers();
486 	}
487 
488 	/**
489 	 * Gets a qualifier value by name.
490 	 *
491 	 * @param pName
492 	 *            The name of the qualifier to get.
493 	 * @return <code>null</code> if the qualifier does not exist or value is
494 	 *         <code>null</code>, otherwise returns the reference to the
495 	 *         qualifier.
496 	 */
497 	public Object getQualifierValue(String pName) {
498 		return this.iQualiImpl.getQualifierValue(pName);
499 	}
500 
501 	/**
502 	 * Gets the name of the parent of this CIM class.
503 	 *
504 	 * @return The name of the parent class.
505 	 */
506 	public String getSuperClassName() {
507 		return this.iSuperClass;
508 	}
509 
510 	/**
511 	 * Checks whether the specified qualifier is one of the qualifiers in this
512 	 * CIM class.
513 	 *
514 	 * @param pName
515 	 *            The name of the qualifier.
516 	 * @return <code>true</code> if the qualifier exists in this CIM class,
517 	 *         otherwise <code>false</code>.
518 	 */
519 	public boolean hasQualifier(String pName) {
520 		return this.iQualiImpl.hasQualifier(pName);
521 	}
522 
523 	/**
524 	 * Checks whether the specified qualifier is one of the qualifiers defined
525 	 * for this class with the specified value. This method will return
526 	 * <code>false</code> if the qualifier is not applied or if the value does
527 	 * not match.
528 	 *
529 	 * @param pName
530 	 *            The name of the qualifier.
531 	 * @param pValue
532 	 *            The value to be tested.
533 	 * @return <code>true</code> if the qualifier exists and has the value,
534 	 *         otherwise <code>false</code>.
535 	 */
536 	public boolean hasQualifierValue(String pName, Object pValue) {
537 		return this.iQualiImpl.hasQualifierValue(pName, pValue);
538 	}
539 
540 	/**
541 	 * Identifies whether or not this CIM class is an association. An
542 	 * association is a relationship between two or more classes or instances of
543 	 * two or more classes. The properties of an association class include
544 	 * references, or pointers, to the two or more instances. All CIM classes
545 	 * can be included in one or more associations.
546 	 *
547 	 * @return <code>true</code> if this CIM class is an association; otherwise,
548 	 *         <code>false</code>.
549 	 */
550 	public boolean isAssociation() {
551 		return this.iIsAssoc;
552 	}
553 
554 	/**
555 	 * Identifies whether or not this class is keyed. Only keyed classes can
556 	 * have instances. Returns <code>true</code> if this CIM class has one or
557 	 * more key properties. Otherwise, returns <code>false</code>.
558 	 *
559 	 * @return <code>true</code> if this CIM class has a key property, otherwise
560 	 *         returns <code>false</code>.
561 	 */
562 	public boolean isKeyed() {
563 		return this.iIsKeyed;
564 	}
565 
566 	/**
567 	 * Returns a new CIM instance initialized with the default CIM properties,
568 	 * values and name of this CIM class.
569 	 *
570 	 * @return A CIM instance of this CIM class.
571 	 */
572 	public CIMInstance newInstance() {
573 		return new CIMInstance(this.iObjPath, this.iProps);
574 	}
575 
576 	/**
577 	 * Returns a <code>String</code> representation of the CIM class. This
578 	 * method is intended to be used only for debugging purposes, and the format
579 	 * of the returned string may vary between implementations. The returned
580 	 * string may be empty but may not be <code>null</code>.
581 	 *
582 	 * @return A <code>String</code> representation of this CIM class.
583 	 */
584 	@Override
585 	public String toString() {
586 		return MOF.classDeclaration(this, MOF.EMPTY);
587 	}
588 
589 	/**
590 	 * Checks whether an array of properties contains a key.
591 	 *
592 	 * @param pProps
593 	 *            Array of properties.
594 	 * @return <code>true</code> if at least one of the class properties is a
595 	 *         key, <code>false</code> otherwise.
596 	 */
597 	private static boolean hasKey(CIMClassProperty<?>[] pProps) {
598 		if (pProps == null) return false;
599 		for (int i = 0; i < pProps.length; i++) if (pProps[i].isKey()) return true;
600 		return false;
601 	}
602 }