PEGASUS_NAMESPACE_BEGIN

/*****************************************************************************
 *
 * Implementation of AssociationProvider associators method
 *
 *****************************************************************************/
void InteropProvider::associators(
    const OperationContext & context,
    const CIMObjectPath & objectName,
    const CIMName & associationClass,
    const CIMName & resultClass,
    const String & role,
    const String & resultRole,
    const Boolean includeQualifiers,
    const Boolean includeClassOrigin,
    const CIMPropertyList & propertyList,
    ObjectResponseHandler & handler)
{
    PEG_METHOD_ENTER(TRC_CONTROLPROVIDER,
            "InteropProvider::associators()");
    initProvider();
    PEG_TRACE((TRC_CONTROLPROVIDER, Tracer::LEVEL4,
        "%s associators. objectName= %s, assocClass= %s resultClass= %s "
            "role= %s resultRole %s, includeQualifiers= %s, "
            "includeClassOrigin= %s, PropertyList= %s",
        thisProvider,
        (const char *)objectName.toString().getCString(),
        (const char *)associationClass.getString().getCString(),
        (const char *)resultClass.getString().getCString(),
        (const char *)role.getCString(),
        (const char *)resultRole.getCString(),
                      boolToString(includeQualifiers),
                      boolToString(includeClassOrigin),
        (const char *)propertyListToString(propertyList).getCString()));

    handler.processing();
    String originRole = role;
    String targetRole = resultRole;
    Uint32 numIterations = 1;
    //
    // The localReferences call retrieves instances of the desired association
    // class and sets the originRole and targetRole properties if currently
    // empty.
    //
    if (associationClass.equal(PEGASUS_CLASSNAME_PG_REFERENCEDPROFILE))
    {
        if (originRole.size() == 0 && targetRole.size() == 0)
        {
            originRole = String("Antecedent");
            targetRole = String("Dependent");
            numIterations = 2;
        }
    }
    for (Uint32 i = 0; i < numIterations; ++i)
    {
        Array<CIMInstance> refs = localReferences(
            context,
            objectName,
            associationClass,
            originRole,
            targetRole,
            CIMPropertyList(),
            resultClass);

        if( refs.size() )
        {
            Array<CIMInstance> refObjs = 
                getReferencedInstances(refs,targetRole,context,propertyList);
            ConstArrayIterator<CIMInstance> refsIterator(refObjs);
            for(Uint32 i = 0; i < refsIterator.size(); i++)
            {
                handler.deliver(refsIterator[i]);
            }
        }

        if (numIterations == 2)
        {
            originRole = String("Dependent");
            targetRole = String("Antecedent");
        }
    }
    handler.complete();

    PEG_METHOD_EXIT();
}
//
// Local version of enumerateInstances to be used by other functions in the
// provider. Note that this delivers instances as a group rather than one
// at a time. This design point may need to be revisited if this provider
// is used in environments such that returning segmented responses would have
// significant performance advantages. For now, that doesn't seem to be the
// case.
//
Array<CIMInstance> InteropProvider::localEnumerateInstances(
    const OperationContext & context,
    const CIMObjectPath & ref,
    const CIMPropertyList& propertyList)
{
    PEG_METHOD_ENTER(TRC_CONTROLPROVIDER,
        "InteropProvider::localEnumerateInstances()");
    const CIMName & className = ref.getClassName();
    PEG_TRACE((TRC_CONTROLPROVIDER, Tracer::LEVEL4,
        "%s enumerateInstances. referenc= %s , PropertyList= %s",
        thisProvider,
        (const char *)className.getString().getCString(),
        (const char *)propertyListToString(propertyList).getCString()));

    // Verify that ClassName is correct and get its enum value
    TARGET_CLASS classEnum  = translateClassInput(className);

    Array<CIMInstance> instances;    
    switch(classEnum)
    {
        case PG_OBJECTMANAGER:
        {
            instances.append(getObjectManagerInstance());
            break;
        }
        case PG_CIMXMLCOMMUNICATIONMECHANISM:
        {
            instances = enumCIMXMLCommunicationMechanismInstances();
            break;
        }
        case PG_NAMESPACEINMANAGER:
        {
            instances = enumNamespaceInManagerInstances();
            break;
        }
        case PG_COMMMECHANISMFORMANAGER:
        {
            instances = enumCommMechanismForManagerInstances();
            break;
        }
        case PG_NAMESPACE:
        {
            instances = enumNamespaceInstances();
            break;
        }
        case PG_REGISTEREDPROFILE:
        {
            instances = enumRegisteredProfileInstances();
            break;
        }
        case PG_REGISTEREDSUBPROFILE:
        {
            instances = enumRegisteredSubProfileInstances();
            break;
        }
        case PG_REFERENCEDPROFILE:
        {
            instances = enumReferencedProfileInstances();
            break;
        }
        case PG_ELEMENTCONFORMSTOPROFILE:
        {
            instances = enumElementConformsToProfileInstances(context,
                ref.getNameSpace());
            break;
        }
        case PG_ELEMENTCONFORMSTOPROFILE_RP_RP:
        {
            instances = enumElementConformsToProfileRPRPInstances(
                context,
                ref.getNameSpace());
            break;
        }
        case PG_SUBPROFILEREQUIRESPROFILE:
        {
            instances = enumSubProfileRequiresProfileInstances();
            break;
        }
        case PG_SOFTWAREIDENTITY:
        {
            instances = enumSoftwareIdentityInstances();
            break;
        }
        case PG_ELEMENTSOFTWAREIDENTITY:
        {
            instances = enumElementSoftwareIdentityInstances();
            break;
        }
        case PG_INSTALLEDSOFTWAREIDENTITY:
        {
            instances = enumInstalledSoftwareIdentityInstances();
            break;
        }
        case PG_COMPUTERSYSTEM:
        {
            instances.append(getComputerSystemInstance());
            break;
        }
        case PG_HOSTEDOBJECTMANAGER:
        {
            instances.append(getHostedObjectManagerInstance());
            break;
        }
        case PG_HOSTEDACCESSPOINT:
        {
            instances = enumHostedAccessPointInstances();
            break;
        }
        //We don't support enumerate CIM_Namespace instances. PG_Namespace is
        //supported.
        case CIM_NAMESPACE:
        {
            break;
        }
        case PG_PROVIDERPROFILECAPABILITIES:
        {
            instances = enumProviderProfileCapabilityInstances(false, false);
            break;
        }

#ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
        case PG_ELEMENTCAPABILITIES:
        {
            instances = enumElementCapabilityInstances(context);
            break;
        }
        case PG_HOSTEDINDICATIONSERVICE:
        {
            instances = enumHostedIndicationServiceInstances(context);
            break;
        }
        case PG_SERVICEAFFECTSELEMENT:
        {
            instances = enumServiceAffectsElementInstances(context);
            break;
        }
#endif
        default:
            PEG_METHOD_EXIT();
            throw CIMNotSupportedException(className.getString() +
              " not supported by Interop Provider enumerate");
    }

    // Filter and deliver the resulting instances
    for (Uint32 i = 0 ; i < instances.size() ; i++)
    {
        normalizeInstance(instances[i], ref, false,
            false, propertyList);
    }

    PEG_METHOD_EXIT();
    return instances;
}
/*****************************************************************************
 *
 * Implementation of AssociationProvider references method
 *
 *****************************************************************************/
void InteropProvider::references(
    const OperationContext & context,
    const CIMObjectPath & objectName,
    const CIMName & resultClass,
    const String & role,
    const Boolean includeQualifiers,
    const Boolean includeClassOrigin,
    const CIMPropertyList & propertyList,
    ObjectResponseHandler & handler)
{
    PEG_METHOD_ENTER(TRC_CONTROLPROVIDER,
        "InteropProvider::references()");
    initProvider();
    PEG_TRACE((TRC_CONTROLPROVIDER, Tracer::LEVEL4,
        "%s references. objectName= %s, resultClass= %s role= %s "
            "includeQualifiers= %s, includeClassOrigin= %s, PropertyList= %s",
        thisProvider,
        (const char *)objectName.toString().getCString(),
        (const char *)resultClass.getString().getCString(),
        (const char *)role.getCString(),
                      boolToString(includeQualifiers),
                      boolToString(includeClassOrigin),
        (const char *)propertyListToString(propertyList).getCString()));

    handler.processing();
    String tmpRole = role;
    String tmpTarget;
    Uint32 numIterations = 1;
    //
    // Makes call to internal references method to get result, supplying the
    // role parameter, but obviously not setting a resultRole/target parameter.
    //
    if (resultClass.equal(PEGASUS_CLASSNAME_PG_REFERENCEDPROFILE))
    {
        if (tmpRole.size() == 0)
        {
            tmpRole = String("Antecedent");
            tmpTarget = String("Dependent");
            numIterations = 2;
        }
    }
    for (Uint32 i = 0; i < numIterations; ++i)
    {
        Array<CIMInstance> refs = localReferences(
            context,
            objectName,
            resultClass,
            tmpRole,
            tmpTarget);
        for (Uint32 j = 0, n = refs.size(); j < n; ++j)
        {
            refs[j].filter(includeQualifiers, includeClassOrigin, propertyList);
            handler.deliver((CIMObject)refs[j]);
        }
        if (numIterations == 2)
        {
            tmpRole = String("Dependent");
            tmpTarget = String("Antecedent");
        }
    }
    handler.complete();
    PEG_METHOD_EXIT();
}
//
// Local version of getInstance to be used by other functions in the the
// provider. Returns a single instance. Note that it always returns an
// instance. If none was found, it is uninialitized.
//
CIMInstance InteropProvider::localGetInstance(
    const OperationContext & context,
    const CIMObjectPath & instanceName,
    const CIMPropertyList & propertyList)
{
    PEG_METHOD_ENTER(TRC_CONTROLPROVIDER, "InteropProvider::localGetInstance");

    PEG_TRACE((TRC_CONTROLPROVIDER, Tracer::LEVEL4,
        "%s getInstance. instanceName= %s , PropertyList= %s",
        thisProvider,
        (const char *)instanceName.toString().getCString(),
        (const char *)propertyListToString(propertyList).getCString()));

    // Test if we're looking for something outside of our namespace. This will
    // happen during associators calls from PG_RegisteredProfile instances
    // through the PG_ElementConformsToProfile association
    CIMNamespaceName opNamespace = instanceName.getNameSpace();
    CIMName opClass = instanceName.getClassName();
    if(opNamespace != PEGASUS_NAMESPACENAME_INTEROP &&
        opClass != PEGASUS_CLASSNAME_PG_ELEMENTCONFORMSTOPROFILE
        // Get CIM_IndicationService instance from IndicationService.
#ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
        || opClass == PEGASUS_CLASSNAME_CIM_INDICATIONSERVICE
#endif
        )
    {
        AutoMutex mut(interopMut);
        CIMInstance gotInstance = cimomHandle.getInstance(
                                         context,
                                         opNamespace,
                                         instanceName, 
                                         false, 
                                         false, 
                                         false, 
                                         propertyList);
        PEG_METHOD_EXIT();
        return gotInstance;
    }

    // Create reference from host, namespace, class components of
    // instance name
    CIMObjectPath ref;
    ref.setHost(instanceName.getHost());
    ref.setClassName(opClass);
    ref.setNameSpace(opNamespace);

    // Enumerate instances for this class. Returns all instances
    // Note that this returns paths setup and instances already
    // filtered per the input criteria.
    Array<CIMInstance> instances =  localEnumerateInstances(
        context,
        ref,
        propertyList);

    // deliver a single instance if found.
    CIMInstance retInstance;

    bool found = false;
    for(Uint32 i = 0, n = instances.size(); i < n; i++)
    {
        CIMObjectPath currentInstRef = instances[i].getPath();
        currentInstRef.setHost(instanceName.getHost());
        currentInstRef.setNameSpace(instanceName.getNameSpace());
        if(instanceName == currentInstRef)
        {
            retInstance = instances[i];
            found = true;
            break;
        }
    }

    if(!found)
    {
      cout << "Coule not find instance: " << instanceName.toString() << endl;
    }
    PEG_METHOD_EXIT();
    return retInstance;
}