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 }