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 }