/*
 * BaseProviderImpl.java
 *
 * Generated by {productTitle}  {versionName} - {utilityTitle}
 *
 * {copywrite}
 */
package {packageName}.common;

import java.util.logging.Logger;

import javax.cim.CIMInstance;
import javax.cim.CIMObjectPath;
import javax.wbem.WBEMException;
import javax.wbem.WBEMOperation;
import javax.wbem.WBEMOperationErrors;
import javax.wbem.provider.ProviderHandle;

import com.ws.wbem.CloseableAddableIterator;
import com.ws.wbem.IndicationManager;
import com.ws.wbem.jserver.JServerConstants;

/**
 * This class provides functionality common to all providers. Subclasses should
 * only have to implement the 'getAllInstances' function (inherited from
 * ProviderImplIF) in order to have a working provider.<BR>
 * <BR>
 * An implementation can override any of the functions to perform a custom
 * operation, for example this code is fairly inefficient when performing the
 * 'getInstance' operation. An implementation may specialize this function in
 * order to provide a more efficient version.
 * 
 */
public abstract class BaseProviderImpl implements ProviderImplIF {

	// The name of the class, including schema name
	private final String mClassName;

	// Handle to the WBEM Server
	private static ProviderHandle mHandle;

	// TODO: Use the J Server log, modify this to use a different log file
	protected static final Logger mLogger = Logger
			.getLogger(JServerConstants.JSERVER_LOGGER_NAME);

	// IndicationManager contains helper methods to authorize, activate and
	// deactivate filters as well as keeping track of the active filters and
	// creating indication instances
	IndicationManager mIndicationManager;
	
	@Override	
	public void activateFilter(final CIMInstance filter,
			final CIMInstance listenerDestination,
			final CIMInstance subscription) throws WBEMException {
		if (null != mIndicationManager) {
			mIndicationManager.activateFilter(filter, subscription);
		}
	}

	@Override
	public void authorizeFilter(final CIMInstance filter,
			final CIMInstance listenerDestination,
			final CIMInstance subscription) throws WBEMException {
		if (null != mIndicationManager) {
			mIndicationManager.authorizeFilter(filter);
		}
	}

	@Override
	public void deActivateFilter(final CIMInstance filter,
			final CIMInstance listenerDestination,
			final CIMInstance subscription) throws WBEMException {
		if (null != mIndicationManager) {
			mIndicationManager.deactivateFilter(filter, subscription);
		}
	}

	/**
	 * Constructs the basic instrumentation object
	 * 
	 * @param pClzName
	 *            The name of the CIM Class this implementation is for
	 */
	protected BaseProviderImpl(final String pClzName) {
		if (null == pClzName) {
			throw new NullPointerException("Class name can not be null");
		}
		mClassName = pClzName;
	}

	/**
	 * close will be called prior to unloading the provider. Close will not be
	 * called for each request, but only at the very end of the lifecycle, prior
	 * to unloading.
	 */
	@Override
	public void close() throws WBEMException {
	}

	@Override
	public String getClassName() {
		return mClassName;
	}

	/**
	 * Gets a handle to the WBEM Server so a provider can perform an 'up call'
	 * 
	 * @return The handle to the WBEMServer
	 */
	public ProviderHandle getWBEMServerHandle() {
		return mHandle;
	}
	
	/**
	 * Gets a handle to the IndicationManager
	 * 
	 * @return The handle to the IndicationManager
	 */
	public IndicationManager getIndicationManager() {
		return mIndicationManager;
	}

	/**
	 * Default implementation is to return not supported, override
	 */
	@Override
	public void deleteInstance(final CIMObjectPath op) throws WBEMException {
		throw WBEMOperationErrors.getOperationNotSupportedByProviderException(
				op, WBEMOperation.DELETEINSTANCE, op.getObjectName());
	}

	@Override
	public CIMObjectPath createInstance(final CIMInstance ci)
			throws WBEMException {
		throw WBEMOperationErrors.getOperationNotSupportedByProviderException(
				ci.getObjectPath(), WBEMOperation.CREATEINSTANCE,
				ci.getClassName());
	}
	
	@Override
    public CIMInstance getInstance(final CIMObjectPath op,
            final String[] propertyList) throws WBEMException {
        // TODO: This function is very inefficient as it enumerates all
        // instances and then tries to match the passed in objectpath to what
        // is returned. If the provider has more then a couple of instances then
        // this implementation should be changed to be more efficient
        CIMInstance ret = null;
        // Create an instance iterator
        final CloseableAddableIterator<CIMInstance> iter = new CloseableAddableIterator<CIMInstance>();
        // Get all of the instances from the implementation
        getAllInstances(iter, op, propertyList, null, 
                WBEMOperation.GETINSTANCE);
        // iterate all instances until we find a match
        while (iter.hasNext() && null == ret) {
            final CIMInstance inst = iter.next();
            final CIMObjectPath obj = inst.getObjectPath();
            // see if the instance matches what is being searched for
            if (op.equalsModelPath(obj)) {
                // set the return value, will cause while loop to exit
                ret = inst;
            }
        }
        // if not found, throw exception
        if (null == ret) {
            // not found
            throw WBEMOperationErrors.getInstanceNotFoundException(op,
                    WBEMOperation.GETINSTANCE, op.getObjectName());
        }
        // found instance, return it
        return ret;
    }

    @SuppressWarnings("deprecation")
	@Override	
	public void execQuery(final CloseableAddableIterator<CIMInstance> iter,
			final CIMObjectPath op, final String query, final String ql)
			throws WBEMException {
		iter.setException(WBEMOperationErrors
				.getOperationNotSupportedByProviderException(op,
						WBEMOperation.EXECUTEQUERY, op.getObjectName()));
		iter.done();

	}

	/**
	 * Subclasses should override this function to perform any one time
	 * initialization, it will only be called once.
	 * 
	 * @throws WBEMException
	 *             If the provider can not be loaded
	 */
	public abstract void initialize() throws WBEMException;

	@Override
	public final void initialize(final ProviderHandle handle)
			throws WBEMException {
		if (null == getWBEMServerHandle()) {
			// Store the handle to the WBEM Server
			setWBEMServerHandle(handle);
		}
		final String[] supportedQueries = getSupportedIndicationQueries();
		// get supported queries to determine if provider is using the
		// IndicationManager class
		if (null != supportedQueries && supportedQueries.length > 0) {
			// create new IndicationManager object
			mIndicationManager = new IndicationManager(handle, getClassName(),
					mLogger);
			// use IndicationManager object to register the queries that this
			// provider supports
			mIndicationManager.registerSupportedFilterQueries(supportedQueries);

		} else {
			// not using IndicationManager, set to null
			mIndicationManager = null;
		}
		initialize();
	}

	/**
	 * Returns a array of strings that represent all the filter queries that
	 * this provider will support
	 * 
	 * @return Array of Strings containing all the indication filter queries
	 *         that this provider will support
	 */
	protected String[] getSupportedIndicationQueries() {
		return null;
	}

	private synchronized static void setWBEMServerHandle(
			final ProviderHandle handle) {
		if (null == mHandle) {
			mHandle = handle;
		}
	}

	@Override
	public void modifyInstance(final CIMInstance ci, final String[] propertyList)
			throws WBEMException {
		throw WBEMOperationErrors.getOperationNotSupportedByProviderException(
				ci.getObjectPath(), WBEMOperation.MODIFYINSTANCE,
				ci.getClassName());
	}
}
