/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * This software is the proprietary information of Sun Microsystems, Inc.
 * Use is subject to license terms.
 *
 * Copyright 2004 Sun Microsystems, Inc.  Tous droits réservés.
 * Ce logiciel est propriété de Sun Microsystems, Inc.
 * Distribué par des licences qui en restreignent l'utilisation.
 *
 * ident        "@(#)CIBService.java 1.37     04/07/15 SMI"
 *
 */

package com.sun.mfwk.cib;

import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;

import com.sun.mfwk.cib.CIBServiceMBean;
import com.sun.mfwk.cib.CIBServiceIf;
import com.sun.mfwk.cib.CIBMonitoredObject;

import com.sun.mfwk.cib.providers.CIBProviderHandler;

import com.sun.mfwk.cib.states.CIBOperationalStatusState;
import com.sun.mfwk.cib.states.CIBAvailabilityStatusState;
import com.sun.mfwk.cib.statistics.CIBServicePerfStats;
import com.sun.mfwk.cib.statistics.CIBStatistic;
import com.sun.mfwk.cib.config.CIBServiceConfiguration;

import javax.management.openmbean.CompositeData;
import javax.management.j2ee.statistics.Stats;
import javax.management.openmbean.OpenDataException;
import javax.management.InvalidAttributeValueException;
import javax.management.AttributeChangeNotification;
import javax.management.Attribute;


import javax.management.ObjectName;
import javax.management.j2ee.statistics.Stats;
import javax.management.j2ee.statistics.Statistic;

/**
 * Default implementation of a CIB Service MBean.
 */
public class CIBService
    extends CIBMonitoredObject
    implements CIBServiceMBean, CIBServiceIf {

  protected String myUri;

  protected Set myResourcesSet = new HashSet();
  protected ObjectName myApplicationObjectName;
  protected Set myExternalResourcesSet = new HashSet();

  // the various providers for a CIBService
  protected CIBServicePerfStats myServicePerfStatsProvider = null;
  protected CIBOperationalStatusState myOpStatusStateProvider = null;
  protected CIBAvailabilityStatusState myAvailStatusStateProvider = null;
  protected CIBServiceConfiguration myServiceConfigurationProvider = null;

  /**
   * @label consumedServices
   * @clientCardinality 1
   * @supplierCardinality 0..* 
   */
  private CIBExternalResource lnkCIBExternalResource;

  /**
   * @label consumedResources
   * @clientCardinality 1
   * @supplierCardinality 0..* 
   */
  private CIBResource lnkCIBResource;
  public CIBService() {
  }

  public CIBService(String theUri) {
    myUri = theUri;
  }

  // Retrieval of providers section
  /**
   *
   */
  protected void retrieveServiceConfigProvider() throws CIBException {
    // CIBProviderHandler is supposed to be set
    try {

      if (myServiceConfigurationProvider == null) {
        myServiceConfigurationProvider =
            (CIBServiceConfiguration) myProviderHandler.getConfiguration(this,
            CIBProviderHandler.SERVICE_CONFIG_TYPE);
      }
    }
    catch (Exception ex) {
      String message =
          " caught unexpected exception while retrieving Service Config provider";
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
      throw new CIBException(message, ex);
    }
  }

  /**
   *
   */
  protected void retrieveServicePerfStatsProvider() throws CIBException {
    // CIBProviderHandler is supposed to be set
    try {
      if (myServicePerfStatsProvider == null) {
        myServicePerfStatsProvider =
            (CIBServicePerfStats) myProviderHandler.getPerfStats(this,
            CIBProviderHandler.SERVICE_PERFSTATS_TYPE);
      }
    }
    catch (Exception ex) {
      String message =
          " caught unexpected exception while retrieving Service Perf Stats provider";
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
      throw new CIBException(message, ex);
    }
  }

  protected void retrieveOpStatusStateProvider() throws CIBException {
    // CIBProviderHandler is supposed to be set
    try {
      if (myOpStatusStateProvider == null) {
        myOpStatusStateProvider = myProviderHandler.getOperationalStatusState(this,
            CIBProviderHandler.SERVICE_STATE_TYPE);
      }
    }
    catch (Exception ex) {
      String message = " caught unexpected exception while retrieving Service Operational MfStatus provider";
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
      throw new CIBException(message, ex);
    }
  }

  protected void retrieveAvailStatusStateProvider() throws CIBException {
    try {
      // CIBProviderHandler is supposed to be set
      if (myAvailStatusStateProvider == null) {
        myAvailStatusStateProvider = myProviderHandler.
            getAvailabilityStatusState(this,
                                       CIBProviderHandler.SERVICE_STATE_TYPE);
      }
    }
    catch (Exception ex) {
      String message = " caught unexpected exception while retrieving Service Availibility MfStatus provider";
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
      throw new CIBException(message, ex);
    }
  }

  // from abstract superclass CIBMonitoredObject
  protected void retrieveStateProviders() throws CIBException {
    retrieveOpStatusStateProvider();
    retrieveAvailStatusStateProvider();
  }

  protected void initStateProviders() {
    try {
      myAvailStatusStateProvider.init();
      myOpStatusStateProvider.init();
    }
    catch (CIBException ex) {
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString +
                             " Caught CIBException " + ex +
                             " \n when trying to init state providers for : \n" +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
    }
  };

  protected void startStateProviders() {
  };

  protected void stopStateProviders() {
  }

  protected void destroyStateProviders() {
    try {
      myAvailStatusStateProvider.destroy();
      myAvailStatusStateProvider = null;

      myOpStatusStateProvider.destroy();
      myAvailStatusStateProvider = null;
    }
    catch (CIBException ex) {
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString +
                             " Caught CIBException " + ex +
                             " \n when trying to destroy state providers for : \n" +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
    }
  }

  protected void retrieveStatisticProviders() throws CIBException {
    retrieveServicePerfStatsProvider();
  }

  protected void initStatisticProviders() {
    try {
      myServicePerfStatsProvider.init();
    }
    catch (CIBException ex) {
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString +
                             " Caught CIBException " + ex +
                             " \n when trying to init statistic providers for : \n" +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
    }
  }

  protected void startStatisticProviders() {
  }

  protected void stopStatisticProviders() {
  }

  protected void destroyStatisticProviders() {
    try {
      myServicePerfStatsProvider.destroy();
      myServicePerfStatsProvider = null;
    }
    catch (CIBException ex) {
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString +
                             " Caught CIBException " + ex +
                             " \n when trying to destroy statistic providers for : \n" +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
    }
  }


  public void setStateProvider(boolean val) throws CIBException {

      if (!isRegistered) {
          CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString +
                                 "Impossible to enable/disable monitoring on connected servcies and resources !\n" +
                                 " CIBService " + objectName + "is unregistered, undefined mbeanserver " + 
                                 CIBMbeanNewLine +
                                 CIBMbeanLogMessageClosingString);
          throw new CIBException("Unregistered CIBService, cannot call setStateProvider on linked monitored objects");
      }
      else {
          // first propagate the enabling/disabling to connected resources and services
          ObjectName tmpOn;
          Boolean tmpBool = new Boolean(val);
          
          // enable/disable monitoring on all resources first
          for (Iterator j = myResourcesSet.iterator(); j.hasNext(); ) {
              tmpOn = (ObjectName) j.next();
              try {
                  mbeanServer.setAttribute(tmpOn, new Attribute("StateProvider", tmpBool));
              }
              catch (Exception e) {
                  CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString +
                                         "Caught exception : " + e +
                                         "\n while invoking setStateProvider method on CIB resource named :\n" +
                                         tmpOn + 
                                         " from CIB Service named :\n " + objectName + 
                                         CIBMbeanNewLine +
                                         CIBMbeanLogMessageClosingString);
                  throw new CIBException("Exception in CIBService while invoking setStateProvider on a linked resource" , e);
              }
          }

          // enable/disable monitoring on all external resources then
          for (Iterator j = myExternalResourcesSet.iterator(); j.hasNext(); ) {
              tmpOn = (ObjectName) j.next();
              try {
                  mbeanServer.setAttribute(tmpOn, new Attribute("StateProvider", tmpBool));
              }
              catch (Exception e) {
                  CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString +
                                         "Caught exception : " + e +
                                         "\n while invoking setStateProvider method on CIB external resource named :\n" +
                                         tmpOn + 
                                         " from CIB Service named :\n " + objectName + 
                                         CIBMbeanNewLine +
                                         CIBMbeanLogMessageClosingString);
                  throw new CIBException("Exception in CIBService while invoking setStateProvider on a linked external resource" , e);
              }
          }
      }

      // know we can enable/disable monitoring in the service itself
      super.setStateProvider(val);
  }

  public void setStatisticProvider(boolean val) throws CIBException {

      if (!isRegistered) {
          CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString +
                                 "Impossible to enable/disable monitoring on connected servcies and resources !\n" +
                                 " CIBService " + objectName + "is unregistered, undefined mbeanserver " + 
                                 CIBMbeanNewLine +
                                 CIBMbeanLogMessageClosingString);
          throw new CIBException("Unregistered CIBService, cannot call setStatisticProvider on linked monitored objects");
      }
      else {

          // first propagate the enabling/disabling to connected resources and services
          ObjectName tmpOn;
          Boolean tmpBool = new Boolean(val);

          // enable/disable monitoring on all resources first
          for (Iterator j = myResourcesSet.iterator(); j.hasNext(); ) {
              tmpOn = (ObjectName) j.next();
              try {
                  mbeanServer.setAttribute(tmpOn, new Attribute("StatisticProvider", tmpBool));
              }
              catch (Exception e) {
                  CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString +
                                         "Caught exception : " + e +
                                         "\n while invoking setStatisticProvider method on CIB resource named :\n" +
                                         tmpOn + 
                                         " from CIB Service named :\n " + objectName + 
                                         CIBMbeanNewLine +
                                         CIBMbeanLogMessageClosingString);
                  throw new CIBException("Exception in CIBService while invoking setStatisticProvider on a linked resource" , e);
              }
          }

          // enable/disable monitoring on all external resources then
          for (Iterator j = myExternalResourcesSet.iterator(); j.hasNext(); ) {
              tmpOn = (ObjectName) j.next();
              try {
                  mbeanServer.setAttribute(tmpOn, new Attribute("StatisticProvider", tmpBool));
              }
              catch (Exception e) {
                  CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString +
                                         "Caught exception : " + e +
                                         "\n while invoking setStatisticProvider method on CIB external resource named :\n" +
                                         tmpOn + 
                                         " from CIB Service named :\n " + objectName + 
                                         CIBMbeanNewLine +
                                         CIBMbeanLogMessageClosingString);
                  throw new CIBException("Exception in CIBService while invoking setStatisticProvider on a linked external resource" , e);
              }
          }
      }

      // know we can enable/disable monitoring in the service itself
      super.setStatisticProvider(val);
  }


  // Configuration provider
  protected void retrieveConfigurationProviders() throws CIBException {
    retrieveServiceConfigProvider();
  }

  protected void initConfigurationProviders() {
    try {
      myServiceConfigurationProvider.init();
    }
    catch (CIBException ex) {
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString +
                             " Caught CIBException " + ex +
                             " \n when trying to init configuration providers for : \n" +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
    }
  }

  protected void startConfigurationProviders() {
  }

  protected void stopConfigurationProviders() {
  }

  protected void destroyConfigurationProviders() {
    try {
      myServiceConfigurationProvider.destroy();
      myServiceConfigurationProvider = null;
    }
    catch (CIBException ex) {
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString +
                             " Caught CIBException " + ex +
                             " \n when trying to destroy config providers for : \n" +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
    }
  }

  // Mediation interface

  /**
   * Allows to set the application object Name to which the CIBService is
   * running
   * @param objectName ObjectName
   */
  public void setCIBApplication(ObjectName objectName) {
    myApplicationObjectName = objectName;
  }

  // MBean interface

  /**
   * Provides the service name identified by its URI
   * @return String
   */
  public String getUri() throws InvalidAttributeValueException {
    if (myUri != null) {
      return myUri;
    }
    try {
      // systematic retrieval of perf stats to ensure uptodate data
      CIBServiceConfiguration configProvider =
          (CIBServiceConfiguration) myProviderHandler.getConfiguration(this,
          CIBProviderHandler.SERVICE_CONFIG_TYPE);
      configProvider.init();
      return configProvider.getUri();
    }
    catch (CIBException ex) {
      String message = " Caught unexpected exception " + ex;
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
      return null;
    }

  }

  /**
   * Set the Uri of the Service
   * @param theUri String
   */
  public void setUri(String theUri) {
    myUri = theUri;
  }

  /**
   * Returns the name of the Related JesApplication : JesApplication.getApplicationName()
   * @return ObjectName
   */
  public ObjectName getApplication() throws InvalidAttributeValueException {
    if (myApplicationObjectName != null) {
      return myApplicationObjectName;
    }
    else {
      String message = " Unset Application for service ";
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
      throw new InvalidAttributeValueException(message);
    }
  }

  public ObjectName[] getResources() {
    return setToObjectNameArray(myResourcesSet);
  }

  /**
   * addCIBResource
   * @param objectName ObjectName
   */
  public void addCIBResource(ObjectName objectName) {
    myResourcesSet.add(objectName);
    // to be implemented
  }

  /**
   * removeCIBResource
   * @param objectName ObjectName
   */
  public void removeCIBResource(ObjectName objectName) throws CIBException {
    if (myResourcesSet.contains(objectName)) {
      myResourcesSet.remove(objectName);
    }
    else {
      String message = " Service " + this.objectName +
          " does not use Ressource " + objectName;
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                             "\n service object is :\n" + this +
                             CIBMbeanNewLine + CIBMbeanLogMessageClosingString);
      throw new CIBException(message);
    }
  }

  /**
   * addCIBExternalResource
   *
   * @param objectName ObjectName
   */
  public void addCIBExternalResource(ObjectName objectName) {
    myExternalResourcesSet.add(objectName);
  }

  /**
   * removeCIBExternalResource
   *
   * @param objectName ObjectName
   */
  public void removeCIBExternalResource(ObjectName objectName) throws
      CIBException {
    if (myExternalResourcesSet.contains(objectName)) {
      myExternalResourcesSet.remove(objectName);
    }
    else {
      String message = " Service " + this.objectName +
          " does not use ExternalRessource " + objectName;
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                             "\n service object is :\n" + this +
                             CIBMbeanNewLine + CIBMbeanLogMessageClosingString);
      throw new CIBException(message);
    }

  }

  /**
   * getExternalResources
   *
   * @return ObjectName[]
   */
  public ObjectName[] getExternalResources() {
    return setToObjectNameArray(myExternalResourcesSet);
  }

  /**
   * getExternalResourceByUri
   *
   * @param uri String
   * @return ObjectName
   */
  public ObjectName getExternalResourceByUri(String uri) throws CIBException {
    String message = "Could not find ExternalResource with URI : " + uri + "\n";
    if (!isRegistered) {
      throw new CIBException(message);
    }
    else {
      ObjectName elem;
      for (Iterator j = myExternalResourcesSet.iterator(); j.hasNext(); ) {
        elem = (ObjectName) j.next();
        try {
          String tmpUri = (String) mbeanServer.getAttribute(elem, "ProviderUri");
          if (tmpUri.equals(uri)) {
            return elem;
          }
        }
        catch (Exception e) {
          CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString +
                                 "Caught exception : " + e +
                                 "\n while retrieving External Resource with uri " + uri +
                                 " in the mbean server.\n Service objet is : \n" +
                                 this +CIBMbeanNewLine +
                                 CIBMbeanLogMessageClosingString);
        }
      }
      throw new CIBException(message);
    }
  }


  /**
   * Returns the Stats object provided by the CIBProviderHandler
   * Gets a CIBStats object for all available statistics.
   * @return Stats
   */
  public Stats getStats() throws CIBException {
    if (!isCurrentlyProvidingStatistics) {
      return null;
    }
    else {
      try {
        // systematic retrieval of perf stats to ensure uptodate data
        CIBServicePerfStats servicePerfStatsProvider =
            (CIBServicePerfStats) myProviderHandler.getPerfStats(this,
            CIBProviderHandler.SERVICE_PERFSTATS_TYPE);
        servicePerfStatsProvider.init();
        return servicePerfStatsProvider;
      }
      catch (CIBException ex) {
        String message = " Unexpected exception " + ex +
            " while calling getStats on Service : " + this.objectName;
        CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString +
                               message + this +CIBMbeanNewLine +
                               CIBMbeanLogMessageClosingString);
        throw ex;
      }
    }
  }

  /**
   * Gets a CIB Statistic as a standard serializable JMX Open Type
   *
   * @param name String
   * @return CompositeData
   */
  public CompositeData getOpenStatistic(String name) throws
      CIBAttributeNotFoundException, CIBException {
    if (!isCurrentlyProvidingStatistics) {
      return null;
    }
    else {
      try {
        // systematic retrieval of perf stats to ensure uptodate data
        CIBStatistic cibStatistic;
        CIBServicePerfStats servicePerfStatsProvider =
            (CIBServicePerfStats) myProviderHandler.getPerfStats(this,
            CIBProviderHandler.SERVICE_PERFSTATS_TYPE);
        servicePerfStatsProvider.init();
        if ( (cibStatistic = (CIBStatistic) servicePerfStatsProvider.
              getStatistic(name)) != null) {
          return cibStatistic.toCompositeData();
        }
        else {
          String message = " Unexisting statistic " + name + " in Service : " +
              this.objectName;
          CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                                 this +CIBMbeanNewLine +
                                 CIBMbeanLogMessageClosingString);
          throw new CIBAttributeNotFoundException(message,
                                                  " CIBServicePerfStats ", name);
        }
      }
      catch (Exception e) {
        if (e instanceof OpenDataException) {
          String message = " Caught unexpected OpenType exception " + e;
          CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                                 this +CIBMbeanNewLine +
                                 CIBMbeanLogMessageClosingString);
          throw new CIBException(message, e);
        }
        else {
          String message = " caught unexpected exception : \n" + e +
              "\n in Service : \n " + this.objectName;
          CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                                 this +CIBMbeanNewLine +
                                 CIBMbeanLogMessageClosingString);
          throw new CIBException(message, e);
        }
      }
    }
  }

  /**
   *  Gets all CIBStatistics encoded as serializable JMX Open Types.
   *  If no statistics is found null is returned.
   *
   * @param names String[]
   * @return CompositeData[]
   */
  public CompositeData[] getOpenStatistics(String[] names) throws CIBException {
    if (!isCurrentlyProvidingStatistics) {
      return null;
    }
    else {
      try {
        // systematic retrieval of perf stats to ensure uptodate data
        Statistic[] statisticArray = null;
        int nb_names = names.length;
        CIBServicePerfStats servicePerfStatsProvider =
            (CIBServicePerfStats) myProviderHandler.getPerfStats(this,
            CIBProviderHandler.SERVICE_PERFSTATS_TYPE);
        servicePerfStatsProvider.init();

        if (((statisticArray = servicePerfStatsProvider.getStatistics()) == null) ||
            (statisticArray.length == 0)) {
          return null;
        }
        else {
          CompositeData[] openStatistics = new CompositeData[nb_names];
          for (int i = nb_names - 1; i >= 0; i--) {
            try {
              CIBStatistic stat = (CIBStatistic) servicePerfStatsProvider.
                  getStatistic(names[i]);
              if (stat == null) {
                openStatistics[i] = null;
              }
              else {
                openStatistics[i] = stat.toCompositeData();
              }
            }
            catch (Exception e) {
              CIBMbeanLogger.info(CIBMbeanLogMessageHeaderString +
                                  "exception while retrieving statistic named : " +
                                  names[i] +
                                  "in perfstats provider for Service : \n" +
                                  this +CIBMbeanNewLine +
                                  CIBMbeanLogMessageClosingString);
              openStatistics[i] = null;
            }
          }
          return openStatistics;
        }
      }
      catch (Exception e) {
        if (e instanceof OpenDataException) {
          String message = " Caught unexpected OpenType exception " + e;
          CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                                 this +CIBMbeanNewLine +
                                 CIBMbeanLogMessageClosingString);
        }
        throw new CIBException(e);
      }
    }
  }

  /**
   * Gets a CIBStats object encoded as a standard serializable JMX Open Type
   *
   * @return javax.management.openmbean.CompositeData
   */
  public CompositeData getOpenStats() throws CIBException {
    if (!isCurrentlyProvidingStatistics) {
      return null;
    }
    else {
      try {
        // systematic retrieval of perf stats to ensure uptodate data
        CIBServicePerfStats servicePerfStatsProvider =
            (CIBServicePerfStats) myProviderHandler.getPerfStats(this,
            CIBProviderHandler.SERVICE_PERFSTATS_TYPE);
        servicePerfStatsProvider.init();
        return servicePerfStatsProvider.toCompositeData();
      }
      catch (Exception ex) {
        if (ex instanceof OpenDataException) {
          String message = " Caught unexpected OpenType exception " + ex;
          CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                                 this +CIBMbeanNewLine +
                                 CIBMbeanLogMessageClosingString);
        }
        throw new CIBException(ex);
      }
    }
  }

  /**
   * Gets all available statistic names
   *
   * @return String[]
   */
  public String[] getStatisticNames() throws CIBException {

    try {
      if (!isCurrentlyProvidingStatistics) {
        return null;
      }
      else {
        // systematic retrieval of perf stats to ensure uptodate data
        CIBServicePerfStats servicePerfStatsProvider =
            (CIBServicePerfStats) myProviderHandler.getPerfStats(this,
            CIBProviderHandler.SERVICE_PERFSTATS_TYPE);
        servicePerfStatsProvider.init();
        return servicePerfStatsProvider.getStatisticNames();
      }
    }
    catch (Exception ex) {
      throw new CIBException(" Caught unexpected exception ", ex);
    }
  }

  /**
   * Get the Operational MfStatus of the monitored object
   * @return int
   */
  public int getOperationalStatusState() throws CIBException {
    if (!isCurrentlyProvidingState) return -1;

    try {
      int result;
      CIBOperationalStatusState opStatusProvider = myProviderHandler.
          getOperationalStatusState(this, CIBProviderHandler.SERVICE_STATE_TYPE);
      opStatusProvider.init();
      result = opStatusProvider.getState();
      if ((result != opStatus) &&
          (isEventProvider())) {
        eventBroadcaster.sendNotification(
          new AttributeChangeNotification(this, eventNumber++, System.currentTimeMillis(), null,
                                          "OperationalStatusState", "int",
                                          new Integer(opStatus), new Integer(result)));
      }
      opStatus = result;
      return opStatus;
    }
    catch (CIBIOException ex) {
      String message =
          " caught IO exception in CIB SDK while calling getOperationalStatusState ";
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
      throw new CIBException(
          " unexpected IO exception in CIB SDK implemetation", ex);
    }
  }

  /**
   * Get the time when the operational status last changed
   * @return long
   */
  public long getOperationalStatusLastChange() throws CIBException {
    if (!isCurrentlyProvidingState) {
      return -1;
    }
    try {
      CIBOperationalStatusState opStatusProvider = myProviderHandler.
          getOperationalStatusState(this, CIBProviderHandler.SERVICE_STATE_TYPE);
      opStatusProvider.init();
      return opStatusProvider.getLastChange();
    }
    catch (CIBIOException ex) {
      String message =
          " caught IO exception in CIB SDK while calling getOperationalStatusLastChange ";
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
      throw new CIBException(
          " unexpected IO exception in CIB SDK implemetation", ex);
    }
  }

  /**
   * Get the time when the Operational status entered into the running state
   * @return long
   */

  public long getOperationalStatusStartTime() throws CIBException {
    if (!isCurrentlyProvidingState) {
      return -1;
    }
    try {

      CIBOperationalStatusState opStatusProvider = myProviderHandler.
          getOperationalStatusState(this, CIBProviderHandler.SERVICE_STATE_TYPE);
      opStatusProvider.init();
      return opStatusProvider.getStartTime();
    }
    catch (CIBIOException ex) {
      String message =
          " caught IO exception in CIB SDK while calling getOperationalStatusStartTime ";
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
      throw new CIBException(
          " unexpected IO exception in CIB SDK implementation", ex);
    }
  }

  /**
   * Get the Availability State of the Monitored object
   * @return int
   */
  public int getAvailabilityStatusState() throws CIBException {
    if (!isCurrentlyProvidingState) return -1;

    try {
      int result;
      CIBAvailabilityStatusState availStatusProvider =
          myProviderHandler.getAvailabilityStatusState(this,
          CIBProviderHandler.SERVICE_STATE_TYPE);
      availStatusProvider.init();
      result = availStatusProvider.getState();
      if ((result != availStatus) &&
          (isEventProvider())) {
        eventBroadcaster.sendNotification(
          new AttributeChangeNotification(this, eventNumber++, System.currentTimeMillis(), null,
                                          "AvailabilityStatusState", "int",
                                          new Integer(opStatus), new Integer(result)));
      }
      availStatus = result;
      return availStatus;

    }
    catch (CIBIOException ex) {
      String message =
          " caught IO exception in CIB SDK while calling getOperationalStatusState ";
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
      throw new CIBException(
          " unexpected IO exception in CIB SDK implementation", ex);
    }
  }

  /**
   * Get the time when the availability status last changed
   * @return long
   */
  public long getAvailabilityStatusLastChange() throws CIBException {
    if (!isCurrentlyProvidingState) return -1;

    try {
      CIBAvailabilityStatusState availStatusProvider =
          myProviderHandler.getAvailabilityStatusState(this,
          CIBProviderHandler.SERVICE_STATE_TYPE);
      availStatusProvider.init();
      return availStatusProvider.getLastChange();
    }
    catch (CIBIOException ex) {
      String message =
          " caught IO exception in CIB SDK while calling getAvailibilityStatusLastChange ";
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
      throw new CIBException(
          " unexpected IO exception in CIB SDK implementation", ex);
    }
  }

  /**
   * Returns the time the first time the object entered into the degraded state
   * @return long
   */

  public long getAvailabilityStatusDegradedTime() throws CIBException {
    if (!isCurrentlyProvidingState) return -1;

    try {
      CIBAvailabilityStatusState availStatusProvider =
          myProviderHandler.getAvailabilityStatusState(this,
          CIBProviderHandler.SERVICE_STATE_TYPE);
      availStatusProvider.init();
      return availStatusProvider.getDegradedTime();
    }
    catch (CIBIOException ex) {
      String message = " caught IO exception in CIB SDK while calling getAvailibilityStatusDegradedTime ";
      CIBMbeanLogger.warning(CIBMbeanLogMessageHeaderString + message +
                             this +CIBMbeanNewLine +
                             CIBMbeanLogMessageClosingString);
      throw new CIBException(
          " unexpected IO exception in CIB SDK implementation", ex);
    }
  }

  // Private methods
  private ObjectName[] setToObjectNameArray(Set theSet) {
    ObjectName[] result = null;
    ObjectName elem = null;
    result = new ObjectName[theSet.size()];
    int i = 0;
    for (Iterator j = theSet.iterator(); j.hasNext(); ) {
      elem = (ObjectName) j.next();
      result[i] = elem;
      i++;
    }
    return result;
  }

}
