1 /*
2 (C) Copyright IBM Corp. 2006, 2012
3
4 THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE
5 ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE
6 CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT.
7
8 You can obtain a current copy of the Eclipse Public License from
9 http://www.opensource.org/licenses/eclipse-1.0.php
10
11 @author : Endre Bak, ebak@de.ibm.com
12 *
13 * Flag Date Prog Description
14 * -------------------------------------------------------------------------------
15 * 1565892 2006-10-06 ebak Make SBLIM client JSR48 compliant
16 * 1669961 2006-04-16 lupusalex CIMTypedElement.getType() =>getDataType()
17 * 1776114 2007-08-21 ebak Cannot derive instance of class CIM_IndicationSubscription
18 * 1855726 2008-02-11 blaschke-oss CIMInstance.deriveInstance is setting wrong CIMObjectPath
19 * 2003590 2008-06-30 blaschke-oss Change licensing from CPL to EPL
20 * 2204488 2008-10-28 raman_arora Fix code to remove compiler warnings
21 * 2524131 2009-01-21 raman_arora Upgrade client to JDK 1.5 (Phase 1)
22 * 2531371 2009-02-10 raman_arora Upgrade client to JDK 1.5 (Phase 2)
23 * 2797550 2009-06-01 raman_arora JSR48 compliance - add Java Generics
24 * 2935258 2010-01-22 blaschke-oss Sync up javax.cim.* javadoc with JSR48 1.0.0
25 * 2944842 2010-02-08 blaschke-oss Missing thrown ArrayIndexOutOfBoundsException
26 * 3529151 2012-08-22 blaschke-oss TCK: CIMInstance property APIs include keys from COP
27 */
28
29 package org.metricshub.wbem.javax.cim;
30
31 /*-
32 * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
33 * WBEM Java Client
34 * ჻჻჻჻჻჻
35 * Copyright 2023 - 2025 MetricsHub
36 * ჻჻჻჻჻჻
37 * Licensed under the Apache License, Version 2.0 (the "License");
38 * you may not use this file except in compliance with the License.
39 * You may obtain a copy of the License at
40 *
41 * http://www.apache.org/licenses/LICENSE-2.0
42 *
43 * Unless required by applicable law or agreed to in writing, software
44 * distributed under the License is distributed on an "AS IS" BASIS,
45 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
46 * See the License for the specific language governing permissions and
47 * limitations under the License.
48 * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
49 */
50
51 import java.io.Serializable;
52 import java.util.ArrayList;
53 import java.util.logging.Level;
54 import org.metricshub.wbem.sblim.cimclient.internal.cim.CIMElementSorter;
55 import org.metricshub.wbem.sblim.cimclient.internal.logging.LogAndTraceBroker;
56 import org.metricshub.wbem.sblim.cimclient.internal.util.MOF;
57 import org.metricshub.wbem.sblim.cimclient.internal.util.StringSorter;
58
59 //Sync'd against JSR48 1.0.0 javadoc (build 1.5.0_10) on Wed Jan 20 02:20:58 EST 2010
60 /**
61 * This class represents a CIM instance as defined by the Distributed Management
62 * Task Force (<a href=http://www.dmtf.org>DMTF</a>) CIM Infrastructure
63 * Specification (<a
64 * href=http://www.dmtf.org/standards/published_documents/DSP0004V2.3_final.pdf
65 * >DSP004</a>).
66 */
67 public class CIMInstance implements CIMNamedElementInterface, Serializable {
68 private static final long serialVersionUID = -249160087013230559L;
69
70 private static final CIMProperty<?>[] EMPTY_PROP_A = new CIMProperty[0];
71
72 private CIMObjectPath iObjPath;
73
74 private CIMProperty<?>[] iProps;
75
76 /**
77 * Constructs a <code>CIMInstance</code> object using the name and
78 * properties specified.
79 *
80 * @param pName
81 * The <code>CIMObjectPath</code> for this
82 * <code>CIMInstance</code>.
83 * @param pProps
84 * The properties for this <code>CIMInstance</code>.
85 * @throws IllegalArgumentException
86 * If <code>pName</code> is <code>null</code> or
87 * <code>pName.getObjectName()</code> is <code>null</code>.<br>
88 * [OPTIONAL] - If the key property values do not match the
89 * values in the property array. This is optional due to the
90 * cost of the verification. Some implementations may leave it
91 * up to the developer to ensure that the values match.
92 */
93 public CIMInstance(CIMObjectPath pName, CIMProperty<?>[] pProps) throws IllegalArgumentException {
94 if (pName == null) {
95 String msg = "CIMObjectPath parameter cannot be null!";
96 // TODO: tracing
97 throw new IllegalArgumentException(msg);
98 }
99 if (pName.getObjectName() == null) {
100 String msg = "ObjectName cannot be null!";
101 // TODO: tracing
102 throw new IllegalArgumentException(msg);
103 }
104
105 this.iObjPath = pName;
106 if (pProps != null) {
107 this.iProps = pProps;
108 CIMElementSorter.sort(this.iProps);
109 } else {
110 this.iProps = new CIMProperty[0];
111 }
112 }
113
114 /**
115 * Returns a <code>CIMInstance</code> with the updated
116 * <code>CIMObjectPath</code>.
117 *
118 * @param pPath
119 * The complete <code>CIMObjectPath</code> for this instance.
120 * @return A new <code>CIMInstance</code> with the updated
121 * <code>CIMObjectPath</code>.
122 */
123 public CIMInstance deriveInstance(CIMObjectPath pPath) {
124 return new CIMInstance(pPath, this.iProps);
125 }
126
127 /**
128 * Returns a <code>CIMInstance</code> with the updated values for the
129 * properties in <code>pPropA</code>. Any new properties are ignored.
130 *
131 * @param pPropA
132 * The array of properties to update.
133 * @return A new instance with the updated properties.
134 */
135 public CIMInstance deriveInstance(CIMProperty<?>[] pPropA) {
136 if (pPropA == null || pPropA.length == 0) return this;
137 CIMProperty<?>[] newPropA = new CIMProperty[getPropertyCount()];
138 for (int i = 0; i < newPropA.length; i++) newPropA[i] = this.iProps[i];
139 for (int i = 0; i < pPropA.length; i++) {
140 CIMProperty<?> newProp = pPropA[i];
141 int idx = CIMElementSorter.findIdx(newPropA, newProp.getName());
142 if (idx < 0) continue;
143 CIMProperty<?> oldProp = newPropA[idx];
144 /*
145 * 1776114 -> reference type comparison shouldn't be sensitive to
146 * the referenced class name due to derivation
147 */
148 if (!typesEqual(oldProp, newProp)) {
149 LogAndTraceBroker
150 .getBroker()
151 .trace(
152 Level.FINE,
153 "CIMInstance.deriveInstance() can update only property " +
154 "values but not property types!\n" +
155 "original property: " +
156 oldProp +
157 "\nnew property: " +
158 newProp
159 );
160 continue;
161 }
162 newPropA[idx] =
163 new CIMProperty<Object>(
164 oldProp.getName(),
165 newProp.getDataType(),
166 newProp.getValue(),
167 oldProp.isKey(),
168 oldProp.isPropagated(),
169 oldProp.getOriginClass()
170 );
171 }
172 return new CIMInstance(this.iObjPath, newPropA);
173 }
174
175 /**
176 * Indicates whether some other instance is equal to this one. Two
177 * <code>CIMInstances</code> are considered equal if the names are the same.
178 * This method does NOT compare each property value.
179 *
180 * @param pObj
181 * The object to compare.
182 * @return <code>true</code> if the specified path references the same
183 * instance, otherwise <code>false</code>.
184 */
185 @Override
186 public boolean equals(Object pObj) {
187 if (!(pObj instanceof CIMInstance)) return false;
188 CIMInstance that = (CIMInstance) pObj;
189 return this.iObjPath.equals(that.iObjPath);
190 }
191
192 /**
193 * This method returns a new <code>CIMInstance</code> with properties
194 * filtered according to the input parameters. Inclusion of class origin and
195 * qualifiers can also be controlled.
196 *
197 * @param pLocalOnly
198 * Include only the properties values that were instantiated in
199 * this instance.
200 * @param pIncludeClassOrigin
201 * classOrigins are only included if <code>true</code>.
202 * @param pPropertyList
203 * If the <code>pPropertyList</code> input parameter is not
204 * <code>null</code>, the members of the array define one or more
205 * Property names. The returned Instance does not include
206 * elements for any Properties missing from this list. If the
207 * <code>pPropertyList</code> input parameter is an empty array
208 * this signifies that no Properties are included in each
209 * returned class. If the <code>pPropertyList</code> input
210 * parameter is <code>null</code> this specifies that all
211 * Properties are included in each returned class. If the
212 * <code>pPropertyList</code> contains duplicate elements or
213 * invalid property names, they are ignored.
214 * @return <code>CIMInstance</code> matching the input filter.
215 */
216 public CIMInstance filterProperties(boolean pLocalOnly, boolean pIncludeClassOrigin, String[] pPropertyList) {
217 StringSorter.sort(pPropertyList);
218 ArrayList<CIMProperty<?>> propAList = new ArrayList<CIMProperty<?>>();
219 for (int i = 0; i < getPropertyCount(); i++) {
220 CIMProperty<?> prop = getProperty(i);
221 if (pLocalOnly && prop.isPropagated()) continue;
222 if (pPropertyList != null && !StringSorter.find(pPropertyList, prop.getName())) continue;
223 propAList.add(
224 new CIMProperty<Object>(
225 prop.getName(),
226 prop.getDataType(),
227 prop.getValue(),
228 prop.isKey(),
229 prop.isPropagated(),
230 pIncludeClassOrigin ? prop.getOriginClass() : null
231 )
232 );
233 }
234 return new CIMInstance(this.iObjPath, propAList.toArray(EMPTY_PROP_A));
235 }
236
237 /**
238 * Get the name of the class that instantiates this CIM instance.
239 *
240 * @return Name of class that instantiates this CIM instance.
241 */
242 public String getClassName() {
243 return this.iObjPath.getObjectName();
244 }
245
246 /**
247 * Get the key properties for this instance.
248 *
249 * @return An array of key properties.
250 */
251 public CIMProperty<?>[] getKeys() {
252 return this.iObjPath.getKeys();
253 }
254
255 /**
256 * Returns the <code>CIMObjectPath</code> that represents this instance.
257 *
258 * @return The <code>CIMObjectPath</code> that represents this instance.
259 */
260 public CIMObjectPath getObjectPath() {
261 return this.iObjPath;
262 }
263
264 /**
265 * Retrieve an array of the properties for this instance.
266 *
267 * @return An array of the CIM properties for this instance.
268 */
269 public CIMProperty<?>[] getProperties() {
270 return this.iProps == null ? new CIMProperty[0] : this.iProps;
271 }
272
273 /**
274 * Get a class property by index.
275 *
276 * @param pIndex
277 * The index of the class property to retrieve.
278 * @return The <code>CIMProperty</code> at the specified index.
279 * @throws ArrayIndexOutOfBoundsException
280 */
281 public CIMProperty<?> getProperty(int pIndex) throws ArrayIndexOutOfBoundsException {
282 return this.iProps[pIndex];
283 }
284
285 /**
286 * Returns the specified property.
287 *
288 * @param pName
289 * The text string for the name of the property.
290 * @return The property requested or <code>null</code> if the property does
291 * not exist.
292 */
293 public CIMProperty<?> getProperty(String pName) {
294 return getProperty(pName, null);
295 }
296
297 /**
298 * Returns the specified <code>CIMProperty</code>.
299 *
300 * @param pName
301 * The string name of the property to get.
302 * @param pOriginClass
303 * (Optional) The string name of the class in which the property
304 * was defined.
305 * @return <code>null</code> if the property does not exist, otherwise
306 * returns the CIM property.
307 */
308 public CIMProperty<?> getProperty(String pName, String pOriginClass) {
309 CIMProperty<?> prop = (CIMProperty<?>) CIMElementSorter.find(this.iProps, pName);
310 if (prop == null) return null;
311 if (pOriginClass == null) return prop;
312 if (pOriginClass.equalsIgnoreCase(prop.getOriginClass())) return prop;
313 return null;
314 }
315
316 /**
317 * Get the number of properties defined in this <code>CIMInstance</code>.
318 *
319 * @return The number of properties defined in the <code>CIMInstance</code>.
320 */
321 public int getPropertyCount() {
322 return this.iProps == null ? 0 : this.iProps.length;
323 }
324
325 /**
326 * Returns the value of a property of this CIM Instance.
327 *
328 * @param name
329 * The name of the property.
330 * @return The value for the specified property name or <code>null</code> if
331 * the property does not exist.
332 */
333 public Object getPropertyValue(String name) {
334 CIMProperty<?> prop = getProperty(name);
335 return prop == null ? null : prop.getValue();
336 }
337
338 /**
339 * Computes the hash code for this instance. The hash code will be the
340 * object path of the instance not including the host or namespace
341 * information.
342 *
343 * @return The integer representing the hash code for this object path.
344 */
345 @Override
346 public int hashCode() {
347 return toString().hashCode();
348 }
349
350 /**
351 * Returns a <code>String</code> representation of the
352 * <code>CIMInstance</code>. This method is intended to be used only for
353 * debugging purposes, and the format of the returned string may vary
354 * between implementations. The returned string may be empty but may not be
355 * <code>null</code>.
356 *
357 * @return String representation of this instance.
358 */
359 @Override
360 public String toString() {
361 return MOF.instanceDeclaration(this, MOF.EMPTY);
362 }
363
364 /**
365 * Indicates whether the data types of the two properties are equal.
366 *
367 * @param pProp0
368 * First property.
369 *@param pProp1
370 * Second property.
371 * @return <code>true</code> if the data types are the same,
372 * <code>false</code> otherwise.
373 */
374 private static boolean typesEqual(CIMProperty<?> pProp0, CIMProperty<?> pProp1) {
375 CIMDataType type0 = pProp0.getDataType(), type1 = pProp0.getDataType();
376 return type0.getType() == type1.getType() && type0.isArray() == type1.isArray();
377 }
378 }