/*****************************************************************************
 *
 * Implementation of InstanceProvider getInstance method.
 *
 *****************************************************************************/
void InteropProvider::getInstance(
    const OperationContext & context,
    const CIMObjectPath & instanceName,
    const Boolean includeQualifiers,
    const Boolean includeClassOrigin,
    const CIMPropertyList & propertyList,
    InstanceResponseHandler & handler)
{
    PEG_METHOD_ENTER(TRC_CONTROLPROVIDER, "InteropProvider::getInstance");

    initProvider();

    // test for legal namespace for this provider. Exception if not
    //namespaceSupported(instanceName);
    // NOTE: Above is commented out because the routing tables will always
    // do the right thing and that's the only way requests get here.

    handler.processing();

    CIMInstance myInstance = localGetInstance(
        context,
        instanceName,
        propertyList);

    handler.deliver(myInstance);

    handler.complete();

    PEG_METHOD_EXIT();
}
//
// Class that determines whether or not the origin class in an association
// operation is valid for the given association class, and also determines
// the origin and target "roles". These values generally correspond to the
// role and resultRole parameter of an associators/associatorNames operation.
//
bool InteropProvider::validAssocClassForObject(
    const OperationContext & context,
    const CIMName & assocClass, 
    const CIMObjectPath & objectName,
    const CIMNamespaceName & opNamespace,
    String & originProperty, 
    String & targetProperty)
{
    PEG_METHOD_ENTER(TRC_CONTROLPROVIDER,
        "InteropProvider::validAssocClassForObject()");
    TARGET_CLASS assocClassEnum = translateClassInput(assocClass);
    TARGET_CLASS originClassEnum;
    CIMName originClass = objectName.getClassName();
    // If the association class is PG_ElementConformsToProfile, we'll have to
    // do some special processing in case the origin instance for the operation
    // is managed by another provider.
    if(assocClassEnum == PG_ELEMENTCONFORMSTOPROFILE)
    {
        // Test if the origin is an element managed by another provider
        // that has implemented a registered profile.
        if(opNamespace != PEGASUS_NAMESPACENAME_INTEROP ||
            (originClass != PEGASUS_CLASSNAME_PG_REGISTEREDPROFILE &&
             originClass != PEGASUS_CLASSNAME_PG_OBJECTMANAGER ))
        {
            //
            // Search the cached conformingElements list for the originClass,
            // returning false if it is not found
            //
            bool found = false;

            PEGASUS_ASSERT(conformingElements.size() ==
                elementNamespaces.size());
            for(Uint32 i = 0, n = conformingElements.size(); i < n; ++i)
            {
                CIMNameArray & elementList = conformingElements[i];
                CIMNamespaceArray & namespaceList = elementNamespaces[i];
                PEGASUS_ASSERT(elementList.size() == namespaceList.size());
                for(Uint32 j = 0, m = elementList.size(); j < m; ++j)
                {
                    CIMName & curElement = elementList[j];
                    if((curElement == originClass ||
                      curElement.getString().find(PEGASUS_DYNAMIC) == 0) &&
                      opNamespace == namespaceList[j])
                    {
                        found = true;
                        break;
                    }
                }
                if(found)
                    break;
            }

            if(!found)
            {
                PEG_METHOD_EXIT();
                return false;
            }
        }
    }
    else
    {
        // Otherwise, just get the enum value representing the origin class
        // for this operation
        originClassEnum = translateClassInput(originClass);
    }

    CIMName expectedTargetRole;
    CIMName expectedOriginRole;

    Array<CIMName> propNames;
    String profileName;
    CIMPropertyList propertyList;
    CIMInstance tmpInstance;
    Uint32 index;
    propNames.clear();
    
    //
    // Set the target and origin role values. Note that if these values are
    // not set following the switch block, that implies that the origin class
    // is not valid for the supplied association class.
    //
    switch(assocClassEnum)
    {
      case PG_NAMESPACEINMANAGER:
          if(originClassEnum == PG_OBJECTMANAGER)
          {
              expectedTargetRole = PROPERTY_DEPENDENT;
              expectedOriginRole = PROPERTY_ANTECEDENT;
          }
          else if(originClassEnum == PG_NAMESPACE)
          {
              expectedTargetRole = PROPERTY_ANTECEDENT;
              expectedOriginRole = PROPERTY_DEPENDENT;
          }
          break;
      case PG_COMMMECHANISMFORMANAGER:
          if(originClassEnum == PG_OBJECTMANAGER)
          {
              expectedTargetRole = PROPERTY_DEPENDENT;
              expectedOriginRole = PROPERTY_ANTECEDENT;
          }
          else if(originClassEnum == PG_CIMXMLCOMMUNICATIONMECHANISM)
          {
              expectedTargetRole = PROPERTY_ANTECEDENT;
              expectedOriginRole = PROPERTY_DEPENDENT;
          }
          break;
      case PG_ELEMENTCONFORMSTOPROFILE:
          if(originClass.equal(PEGASUS_CLASSNAME_PG_REGISTEREDPROFILE))
          {
              expectedTargetRole =
                  ELEMENTCONFORMSTOPROFILE_PROPERTY_MANAGEDELEMENT;
              expectedOriginRole =
                  ELEMENTCONFORMSTOPROFILE_PROPERTY_CONFORMANTSTANDARD;
          }
          else
          {
              expectedTargetRole =
                  ELEMENTCONFORMSTOPROFILE_PROPERTY_CONFORMANTSTANDARD;
              expectedOriginRole =
                  ELEMENTCONFORMSTOPROFILE_PROPERTY_MANAGEDELEMENT;
          }
          break;
      case PG_ELEMENTCONFORMSTOPROFILE_RP_RP:
          propNames.append(CIMName("RegisteredName"));
          propertyList = CIMPropertyList(propNames);
          tmpInstance = localGetInstance(
              context, 
              objectName,
              propertyList);
          if (!tmpInstance.isUninitialized())
          {
              index = tmpInstance.findProperty("RegisteredName");
              if (index != PEG_NOT_FOUND)
              {
                  const CIMValue &tmpVal = 
                      tmpInstance.getProperty(index).getValue();
                  if (!tmpVal.isNull())
                  {
                      tmpVal.get(profileName);
                  }
              }
          }
          if (String::compareNoCase(profileName, String("SMI-S")) == 0)
          {
              expectedTargetRole =
                  ELEMENTCONFORMSTOPROFILE_PROPERTY_MANAGEDELEMENT;
              expectedOriginRole =
                  ELEMENTCONFORMSTOPROFILE_PROPERTY_CONFORMANTSTANDARD;
          }
          else
          {
              expectedTargetRole =
                  ELEMENTCONFORMSTOPROFILE_PROPERTY_CONFORMANTSTANDARD;
              expectedOriginRole =
                  ELEMENTCONFORMSTOPROFILE_PROPERTY_MANAGEDELEMENT;
          }
          break;
      case PG_SUBPROFILEREQUIRESPROFILE:
          if(originClassEnum == PG_REGISTEREDPROFILE)
          {
              expectedTargetRole = PROPERTY_DEPENDENT;
              expectedOriginRole = PROPERTY_ANTECEDENT;
          }
          else if(originClassEnum == PG_REGISTEREDSUBPROFILE)
          {
              expectedTargetRole = PROPERTY_ANTECEDENT;
              expectedOriginRole = PROPERTY_DEPENDENT;
          }
          break;
      case PG_REFERENCEDPROFILE:
          if (originClassEnum == PG_REGISTEREDSUBPROFILE)
          {
              expectedTargetRole = PROPERTY_ANTECEDENT;
              expectedOriginRole = PROPERTY_DEPENDENT;
          }
          else if (originClassEnum == PG_REGISTEREDPROFILE)
          {
              if ((targetProperty.size() != 0) &&
                  (originProperty.size() != 0) &&
                  String::equalNoCase(targetProperty, originProperty))
              {
                  return false;
              }
              if (targetProperty.size() != 0)
              {
                  if (!(String::equalNoCase(targetProperty, "Antecedent") ||
                      String::equalNoCase(targetProperty, "Dependent") ))
                  {
                      return false;
                  }
              }
              if (originProperty.size() != 0)
              {
                  if (!(String::equalNoCase(originProperty, "Antecedent") ||
                      String::equalNoCase(originProperty, "Dependent") ))
                  {
                      return false;
                  }
              }
              if (String::equalNoCase(originProperty, "Antecedent") &&
                  targetProperty.size() == 0)
              {
                  targetProperty = String("Dependent");
              }
              if (String::equalNoCase(originProperty, "Dependent") &&
                  targetProperty.size() == 0)
              {
                  targetProperty = String("Antecedent");
              }
              if (String::equalNoCase(targetProperty, "Antecedent") &&
                  originProperty.size() == 0)
              {
                  originProperty = String("Dependent");
              }
              if (String::equalNoCase(targetProperty, "Dependent") &&
                  originProperty.size() == 0)
              {
                  originProperty = String("Antecedent");
              }
              return true;
          }
          break;
      case PG_ELEMENTSOFTWAREIDENTITY:
          if(originClassEnum == PG_SOFTWAREIDENTITY)
          {
              expectedTargetRole = PROPERTY_DEPENDENT;
              expectedOriginRole = PROPERTY_ANTECEDENT;
          }
          else if(originClassEnum == PG_REGISTEREDPROFILE ||
              originClassEnum == PG_REGISTEREDSUBPROFILE)
          {
              expectedTargetRole = PROPERTY_ANTECEDENT;
              expectedOriginRole = PROPERTY_DEPENDENT;
          }
          break;
      case PG_INSTALLEDSOFTWAREIDENTITY:
          if(originClassEnum == PG_SOFTWAREIDENTITY)
          {
              expectedTargetRole = INSTALLEDSOFTWAREIDENTITY_PROPERTY_SYSTEM;
              expectedOriginRole =
                  INSTALLEDSOFTWAREIDENTITY_PROPERTY_INSTALLEDSOFTWARE;
          }
          else if(originClassEnum == PG_COMPUTERSYSTEM)
          {
              expectedTargetRole =
                  INSTALLEDSOFTWAREIDENTITY_PROPERTY_INSTALLEDSOFTWARE;
              expectedOriginRole = INSTALLEDSOFTWAREIDENTITY_PROPERTY_SYSTEM;
          }
          break;
      case PG_HOSTEDACCESSPOINT:
          if(originClassEnum == PG_COMPUTERSYSTEM)
          {
              expectedTargetRole = PROPERTY_DEPENDENT;
              expectedOriginRole = PROPERTY_ANTECEDENT;
          }
          else if(originClassEnum == PG_CIMXMLCOMMUNICATIONMECHANISM)
          {
              expectedTargetRole = PROPERTY_ANTECEDENT;
              expectedOriginRole = PROPERTY_DEPENDENT;
          }
      case PG_HOSTEDOBJECTMANAGER:
          if(originClassEnum == PG_COMPUTERSYSTEM)
          {
              expectedTargetRole = PROPERTY_DEPENDENT;
              expectedOriginRole = PROPERTY_ANTECEDENT;
          }
          else if(originClassEnum == PG_OBJECTMANAGER)
          {
              expectedTargetRole = PROPERTY_ANTECEDENT;
              expectedOriginRole = PROPERTY_DEPENDENT;
          }
          break;
#ifdef PEGASUS_ENABLE_DMTF_INDICATION_PROFILE_SUPPORT
      case PG_HOSTEDINDICATIONSERVICE:
          if(originClassEnum == PG_COMPUTERSYSTEM)
          {
              expectedTargetRole = PROPERTY_DEPENDENT;
              expectedOriginRole = PROPERTY_ANTECEDENT;
          }
          break;
#endif
      default:
          break;
    }

    //
    // The rest of this method checks to see if target role and origin roles
    // were found for the association and origin class combination and, if
    // found, checks against the input target and origin roles if provided.
    // Failure for any of these tests points to an invalid association
    // traversal request.
    //
    if(expectedTargetRole.isNull() ||
        expectedOriginRole.isNull())
    {
        PEG_METHOD_EXIT();
        return false;
    }

    if(targetProperty.size() == 0)
    {
        targetProperty = expectedTargetRole.getString();
    }
    else if(!expectedTargetRole.equal(targetProperty))
    {
        PEG_METHOD_EXIT();
        return false;
    }

    if(originProperty.size() == 0)
    {
        originProperty = expectedOriginRole.getString();
    }
    else if(!expectedOriginRole.equal(originProperty))
    {
        PEG_METHOD_EXIT();
        return false;
    }

    PEG_METHOD_EXIT();
    return true;
}