ObjectNormalizer::ObjectNormalizer( const CIMClass& cimClass, Boolean includeQualifiers, Boolean includeClassOrigin, const CIMNamespaceName& nameSpace, SharedPtr<NormalizerContext>& context) : _cimClass(cimClass), _includeQualifiers(includeQualifiers), _includeClassOrigin(includeClassOrigin), _context(context), _nameSpace(nameSpace) { if (!_cimClass.isUninitialized()) { // ATTN: the following code is intended to expedite normalizing // instances and instance object paths by establishing the keys // once now rather than multiple times later. it is biased // toward providers that return many instances with many properties. // build a reference object path within the class Array<CIMKeyBinding> keys; for (Uint32 i = 0, n = _cimClass.getPropertyCount(); i < n; i++) { CIMConstProperty referenceProperty = _cimClass.getProperty(i); Uint32 pos = referenceProperty.findQualifier("key"); if ((pos != PEG_NOT_FOUND) && (referenceProperty.getQualifier(pos).getValue().equal( CIMValue(true)))) { if (referenceProperty.getType() == CIMTYPE_REFERENCE) { // ATTN: a fake reference is inserted in the key so that // the _BubbleSort() method in CIMObjectPath does not // throw and exception. It implicitly validates keys of // type REFERENCE so just place a dummy value for now. // The value will be replaced by the normalized object // later. keys.append(CIMKeyBinding(referenceProperty.getName(), "class.key=\"value\"", CIMKeyBinding::REFERENCE)); } else { keys.append(CIMKeyBinding(referenceProperty.getName(), referenceProperty.getValue())); } } } // update class object path CIMObjectPath cimObjectPath(_cimClass.getPath()); cimObjectPath.setKeyBindings(keys); _cimClass.setPath(cimObjectPath); } }
CIMProperty ObjectNormalizer::processProperty( CIMConstProperty& referenceProperty, CIMConstProperty& instProperty, Boolean includeQualifiers, Boolean includeClassOrigin, NormalizerContext* context, const CIMNamespaceName& nameSpace) { // check name if (!referenceProperty.getName().equal(instProperty.getName())) { MessageLoaderParms message( "Common.ObjectNormalizer.INVALID_PROPERTY_NAME", "Invalid property name: $0", instProperty.getName().getString()); throw CIMException(CIM_ERR_FAILED, message); } // check type CIMType referencePropType = referenceProperty.getType(); CIMType instPropType = instProperty.getType(); if (referencePropType != instPropType) { MessageLoaderParms message( "Common.ObjectNormalizer.INVALID_PROPERTY_TYPE", "Invalid property type: $0", instProperty.getName().getString()); throw CIMException(CIM_ERR_FAILED, message); } // TODO: check array size? CIMProperty normalizedProperty( referenceProperty.getName(), referenceProperty.getValue(), // default value referenceProperty.getArraySize(), referenceProperty.getReferenceClassName(), CIMName(), false); // TODO: check override (especially for references)? // update value if (!instProperty.getValue().isNull()) { normalizedProperty.setValue(instProperty.getValue()); } // update class origin if (includeClassOrigin) { normalizedProperty.setClassOrigin(referenceProperty.getClassOrigin()); } // add qualifiers if (includeQualifiers) { // propagate class property qualifiers for (Uint32 i=0, n = referenceProperty.getQualifierCount(); i < n; i++) { CIMConstQualifier referenceQualifier = referenceProperty.getQualifier(i); Uint32 pos = instProperty.findQualifier(referenceQualifier.getName()); // update value if qualifier is present in the specified property if (pos != PEG_NOT_FOUND) { CIMConstQualifier cimQualifier = instProperty.getQualifier(pos); CIMQualifier normalizedQualifier = _processQualifier( referenceQualifier, cimQualifier); normalizedProperty.addQualifier(normalizedQualifier); } else { normalizedProperty.addQualifier(referenceQualifier.clone()); } } } #ifdef PEGASUS_SNIA_INTEROP_COMPATIBILITY else if (referenceProperty.getType() == CIMTYPE_INSTANCE) { Uin32 refPos = referenceProperty.findQualifier( PEGASUS_QUALIFIERNAME_EMBEDDEDINSTANCE); Uin32 cimPos = instProperty.findQualifier( PEGASUS_QUALIFIERNAME_EMBEDDEDINSTANCE); if (refPos != PEG_NOT_FOUND && cimPos == PEG_NOT_FOUND) { instProperty.addQualifier(refProperty.getQualifier(pos)); } } #endif // Check the type of the embedded instance against the class specified by // the EmbeddedInstance qualifier. We can only do this if the context // is non-zero. if (context != 0) { if (referenceProperty.getType() == CIMTYPE_INSTANCE) { Uint32 pos = referenceProperty.findQualifier( PEGASUS_QUALIFIERNAME_EMBEDDEDINSTANCE); PEGASUS_ASSERT(pos != PEG_NOT_FOUND); String qualClassStr; referenceProperty.getQualifier(pos).getValue().get( qualClassStr); CIMName embedInstClassName(qualClassStr); Array<CIMName> embeddedInstSubclasses = context->enumerateClassNames(nameSpace, embedInstClassName, true); embeddedInstSubclasses.append(embedInstClassName); Array<CIMInstance> embeddedInstances; if (referenceProperty.isArray()) { instProperty.getValue().get(embeddedInstances); } else { CIMInstance embeddedInst; instProperty.getValue().get(embeddedInst); embeddedInstances.append(embeddedInst); } Array<CIMClass> embeddedClassDefs; for (Uint32 i = 0, n = embeddedInstances.size(); i < n; ++i) { CIMInstance& currentInstance = embeddedInstances[i]; CIMName currentClassName = currentInstance.getClassName(); if (Contains(embeddedInstSubclasses, currentClassName)) { CIMClass embeddedClassDef; bool found = false; for (Uint32 j = 0, m = embeddedClassDefs.size(); j < m; ++j) { CIMClass& tmpClassDef = embeddedClassDefs[j]; if (tmpClassDef.getClassName() == currentClassName) { embeddedClassDef = tmpClassDef; found = true; } } if (!found) { embeddedClassDef = context->getClass(nameSpace, currentClassName); embeddedClassDefs.append(embeddedClassDef); } SharedPtr<NormalizerContext> tmpContext(context->clone()); ObjectNormalizer tmpNormalizer(embeddedClassDef, includeQualifiers, includeClassOrigin, nameSpace, tmpContext); if (currentInstance.getPath().getKeyBindings().size()==0) { currentInstance.setPath( currentInstance.buildPath(embeddedClassDef)); } embeddedInstances[i] = tmpNormalizer.processInstance(currentInstance); } else { MessageLoaderParms message( "Common.ObjectNormalizer." "INVALID_EMBEDDED_INSTANCE_TYPE", "Found embedded instance of type $0: was expecting " "$1 for property $2", currentClassName.getString(), qualClassStr, instProperty.getName().getString()); throw CIMException(CIM_ERR_FAILED, message); } } if (referenceProperty.isArray()) { normalizedProperty.setValue(CIMValue(embeddedInstances)); } else { normalizedProperty.setValue(CIMValue(embeddedInstances[0])); } } } return normalizedProperty; }
void CIMPropertyRep::resolve( DeclContext* declContext, const CIMNamespaceName& nameSpace, Boolean isInstancePart, const CIMConstProperty& inheritedProperty, Boolean propagateQualifiers) { PEGASUS_ASSERT(!inheritedProperty.isUninitialized()); // Check the type: if (!inheritedProperty.getValue().typeCompatible(_value)) { if (!( (inheritedProperty.getValue().getType() == CIMTYPE_OBJECT) && (_value.getType() == CIMTYPE_STRING) && (_qualifiers.find(PEGASUS_QUALIFIERNAME_EMBEDDEDOBJECT) != PEG_NOT_FOUND) && (inheritedProperty.getValue().isArray() == _value.isArray()) ) && !( (inheritedProperty.getValue().getType() == CIMTYPE_INSTANCE) && (_value.getType() == CIMTYPE_STRING) && (_qualifiers.find(PEGASUS_QUALIFIERNAME_EMBEDDEDINSTANCE) != PEG_NOT_FOUND) && (inheritedProperty.getValue().isArray() == _value.isArray()) )) { throw TypeMismatchException(); } } // Validate the qualifiers of the property (according to // superClass's property with the same name). This method // will throw an exception if the validation fails. CIMScope scope = CIMScope::PROPERTY; if (_value.getType() == CIMTYPE_REFERENCE) scope = CIMScope::REFERENCE; // Test the reference class name against the inherited property if (_value.getType() == CIMTYPE_REFERENCE || _value.getType() == CIMTYPE_INSTANCE) { CIMName inheritedClassName; Array<CIMName> classNames; if (_value.getType() == CIMTYPE_INSTANCE) { Uint32 pos = inheritedProperty.findQualifier( PEGASUS_QUALIFIERNAME_EMBEDDEDINSTANCE); if (pos != PEG_NOT_FOUND) { String qualStr; inheritedProperty.getQualifier(pos).getValue().get(qualStr); inheritedClassName = qualStr; } if (_value.isArray()) { Array<CIMInstance> embeddedInstances; _value.get(embeddedInstances); for (Uint32 i = 0, n = embeddedInstances.size(); i < n; ++i) { classNames.append(embeddedInstances[i].getClassName()); } } else { CIMInstance embeddedInst; _value.get(embeddedInst); classNames.append(embeddedInst.getClassName()); } } else { CIMName referenceClass; if (_referenceClassName.isNull()) { CIMObjectPath reference; _value.get(reference); referenceClass = reference.getClassName(); } else { referenceClass = _referenceClassName; } inheritedClassName = inheritedProperty.getReferenceClassName(); classNames.append(referenceClass); } // This algorithm is friendly to arrays of embedded instances. It // remembers the class names that are found to be subclasses of the // inherited class name retrieved from the inherited property. This // ensures that any branch in the inheritance hierarchy will only be // traversed once. This provides significant optimization given that // most elements of an array of embedded instances will probably be of // very closely related types. Array<CIMName> successTree; successTree.append(inheritedClassName); for (Uint32 i = 0, n = classNames.size(); i < n; ++i) { Array<CIMName> traversalHistory; CIMName currentName = classNames[i]; Boolean found = false; while (!found && !currentName.isNull()) { for (Uint32 j = 0, m = successTree.size(); j < m; ++j) { if (currentName == successTree[j]) { found = true; break; } } if (!found) { traversalHistory.append(currentName); CIMClass currentClass = declContext->lookupClass( nameSpace, currentName); if (currentClass.isUninitialized()) { throw PEGASUS_CIM_EXCEPTION( CIM_ERR_INVALID_PARAMETER, currentName.getString()); } currentName = currentClass.getSuperClassName(); } } if (!found) { throw TypeMismatchException(); } successTree.appendArray(traversalHistory); } } _qualifiers.resolve( declContext, nameSpace, scope, isInstancePart, inheritedProperty._rep->_qualifiers, propagateQualifiers); _classOrigin = inheritedProperty.getClassOrigin(); }