InquiryState.java

/*
 * Copyright © 2012 Nokia Corporation. All rights reserved.
 * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation. 
 * Oracle and Java are trademarks or registered trademarks of Oracle and/or its
 * affiliates. Other product and company names mentioned herein may be trademarks
 * or trade names of their respective owners. 
 * See LICENSE.TXT for license information.
 */ 
package com.nokia.example.bcexchanger.comm;

import java.io.IOException;
import java.util.Vector;

import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.obex.Operation;
import javax.obex.ResponseCodes;

/**
 * 
 * This class implements inquiry state. In inquiry state an active
 * device discovery is performed. No OBEX server commands are served.
 * 
 * This class extends ExchangerState abstract class. This class also
 * implements DiscoveryListener interface to receive Bluetooth inquiry
 * callbacks.
 * 
 * @see bcexchanger.comm.ExchangerState
 *      javax.bluetooth.DiscoveryListener Design Patterns: State
 * 
 */
public class InquiryState extends ExchangerState
        implements DiscoveryListener {

    private DiscoveryAgent agent;
    private Vector remoteDevices; // vector of found devices
    private int operation = ServiceDiscoveryState.GET;

    /**
     * Constructor
     * 
     * @param _parent -
     *          the class which is nesting the current state of the
     *          state machine
     */
    public InquiryState(ExchangerStateParent _parent, int oper)
            throws IOException {
        super(_parent);
        operation = oper;
        remoteDevices = new Vector();
        // initiate Bluetooth
        LocalDevice local = LocalDevice.getLocalDevice();
        agent = local.getDiscoveryAgent();
        // start Bluetooth inquiry
        agent.startInquiry(DiscoveryAgent.GIAC, this);
    }

    /*
     * Inquiry state does not allow to start any other business card
     * exchange process.
     * 
     * @see bcexchanger.comm.ExchangerState#startSending()
     */
    public void startSending(int op) throws IOException {
        throw new IOException(
                "Inquiry is in progress. Inquiry has to be cancelled before starting new sending process");
    }

    /*
     * InquiryState allows to cancel inquiry process.
     * 
     * @see bcexchanger.comm.ExchangerState#cancelSending()
     */
    public void cancelSending() {
        agent.cancelInquiry(this);
    }

    public void deviceDiscovered(RemoteDevice dev, DeviceClass devClass) {
        remoteDevices.addElement(dev);
    }

    public void inquiryCompleted(int code) {
        try {
            int completionCode = ExchangerComm.ERROR;

            // convert the inquiry completion code to application completion
            // code
            switch (code) {
                case DiscoveryListener.INQUIRY_COMPLETED:
                    completionCode = ExchangerComm.DONE;
                    break;
                case DiscoveryListener.INQUIRY_TERMINATED:
                    completionCode = ExchangerComm.CANCELED;
                    break;
                case DiscoveryListener.INQUIRY_ERROR:
                    completionCode = ExchangerComm.ERROR;
                    break;
            }
            parent.getListener().onInquiryComplete(completionCode); // signal
            // that
            // inquiry
            // is
            // done

            if (code == DiscoveryListener.INQUIRY_COMPLETED) { // no errors
                // or
                // cancellations
                parent.setState(new ServiceDiscoveryState(parent,
                        remoteDevices, operation));

            } else {
                parent.setState(new IdleState(parent));
            }

        } catch (Exception e) {
            parent.setState(new IdleState(parent));
        }
    }

    /*
     * Service discovery callbacks are not handled and not supposed to
     * occur, since service discovery process is not started
     * 
     * @see javax.bluetooth.DiscoveryListener#servicesDiscovered(int,
     *      javax.bluetooth.ServiceRecord[])
     */
    public void servicesDiscovered(int arg0, ServiceRecord[] arg1) {
        throw new RuntimeException(
                "Internal error #4: InquiryState.servicesDiscovered() should not be called");
    }

    /*
     * Service discovery callbacks are not handled and not supposed to
     * occur, since service discovery process is not started
     * 
     * @see javax.bluetooth.DiscoveryListener#serviceSearchCompleted(int,
     *      int)
     */
    public void serviceSearchCompleted(int arg0, int arg1) {
        throw new RuntimeException(
                "Internal error #5: InquiryState.serviceSearchCompleted() should not be called");
    }

    /*
     * Serving OBEX GET operation is supported only in IdleState
     * 
     * @see bcexchanger.comm.ExchangerState#onGet(javax.obex.Operation)
     */
    public int onGet(Operation op) {

        return ResponseCodes.OBEX_HTTP_CONFLICT;
    }

    /*
     * Serving OBEX GET operation is supported only in
     * IdleState
     * 
     * @see bcexchanger.comm.ExchangerState#onPut(javax.obex.Operation)
     */
    public int onPut(Operation op) {
        // onPut is supported only in IdleState
        return ResponseCodes.OBEX_HTTP_CONFLICT;
    }
}