This document provides an overview of the Call Control Extension Package to the Java Telephony API. The Call Control Package extends the Core API by providing more advanced features and more detailed information about the call model. The more advanced features take the form of additional method on the call control objects: Call, Connection, Terminal, Address, and TerminalConnection. The Call Control Package provides more detailed information about the call model in the form of an extended set of states on the Connection and TerminalConnection objects.
The topics covered by the overview document are described below. Details about the interfaces in the Call Control Package are found in the Call Control Package Specification
This section outlines, for each interface defined in the Call Control Package, the methods and features provided. It is meant to provide a general overview of the additional features of each object so application developers may ascertain whether the Call Control Package satisifies their requirements.
In addition to provided additional features to the Java Telephony API, the Call Control Package provides additional information about the current state of telephone calls in the call model. This additional information takes the form of an expanded set of states for the Connection and TerminalConnection objects, above the set of states provided by the core package for each of these objects. The intent of these expanded set of states is for the implementation to describe more accurately to the application what is going on in a telephone call. Most of the methods in the package rely upon and are defined in terms of these expanded states.
If an application wants to use the Call Control Package, it is expected that it will only monitor the states provided by the Call Control Package, and not monitor the core states. In several cases, the Call Control Package does not expand upon a state and uses the exact states as in the core with the same meaning.
As mentioned above, the Call Control Package expands upon the states in the core Connection and TerminalConnection objects. Listed below are the states found in the CallControlConnection and CallControlTerminalConnection interfaces which expand upon their respective object's core states. With each state is a brief, real-world description of their meaning.
In the overview of the core Connection states, a finite state machine described the allowable transitions from one Connection state to the other. This state diagram provides insight to the application developer on how Connections may move from one state to another. The following diagram is the analogous state diagram for the CallControlConnection states. Because the CallControlConnection interface possesses more states than the core, the state diagram is more complex. Fortunately, applications which perform only the simple tasks provided by the core need not concern themselves with this more complicated state diagram.
To make the state diagram more clear, the ESTABLISHED state has been replicated three times. All of the transitions into the ESTABLISHED state can be viewed as the union of all of the transitions into each separate ESTABLISHED state below. Similarly, all of the transitions out of the ESTABLISHED state can be viewed as the unijon of all of the transitions out of each separate ESTABLISHED state below. The FAILED, DISCONNECTED, and UNKNOWN states are unique because they have transitions to and from virtually every other state. The asterisk (*) next to the transition arrows denote this. There are several exceptions, however. There are no transitions out of the DISCONNECTED state and the IDLE state may not transition into the DISCONNECTED state. All states may transition into the FAILED state except for the DISCONNECTED state. Also, the FAILED state may transition only to the DISCONNECTED state and the UNKNOWN state.
In addition to the allowable transitions of Connection states in the Call Control Package, the mapping of the Connection states to the CallControlConnection states is important. This mapping implies that when the CallControlConnection state is a certain states, it implies the Connection state must be a certain state. Although applications should only monitor one set of states, it is neccessary to provide this mapping to maintain consistency.
The following chart describes the state of the Connection in the Call Control Package (on the right) and the state of the Connection in the core package (on the left). Note that applications may obtain the core Connection state via the method Connection.getState() and applications may obtain the Call Control Package Connection states via the CallControlConnection.getCallControlState() method.
In the overview of the core TerminalConnection states, a finite state machine described the allowable transitions from one TerminalConnection state to the other. This state diagram provides insight to the application developer on how TerminalConnections may move from one state to another. The following diagram is the analogous state diagram for the CallControlTerminalConnection states.
In addition to the allowable transitions of TerminalConnection states in the Call Control Package, the mapping of the TerminalConnection states to the CallControlTerminalConnection states is important. This mapping implies that when the CallControlConnection state is a certain states, it implies the TerminalConnection state must be a certain state. Although applications should only monitor one set of states, it is neccessary to provide this mapping to maintain consistency.
The following chart describes the state of the TerminalConnection in the Call Control Package (on the right) and the state of the TerminalConnection in the core package (on the left). Note that applications may obtain the core TerminalConnection state via the method TerminalConnection.getState() and applications may obtain the Call Control Package TerminalConnection states via the CallControlTerminalConnection.getCallControlState() method.
The Overview document for the core Java Telephony API presented a timeline diagram of the state transitions for Connections and TerminalConnections in a likely scenario resulting from a Call.connect() invocation. These diagrams are the best means to understand the API during different situations. In this section, a similar diagram is presented describing the outcome of placing a telephone call in terms of the CallControl states.
In the diagram below, time is the vertical axis where time increases going down the page. The solid vertical lines denote various objects: Call, Terminal, and Address. The solid horizontal lines between the Call and Address represent a Connection and the dotted horizontal lines between the Address and Terminal represent TerminalConnections. Each discrete change in the call model is denoted by a number along the left-hand side of the page. More than one change may occur to the call model during a single discrete step; the application sees these changes as happening all at once.
In the scenario below, the originating side has one Terminal associated with it and the destination side has two Terminals (denoted in the diagram as 'A' and 'B') associated with it. The switch is configured to bridge all Terminals which are not actively part of a telephone call but share an address which is active. This scenario shows how a telephone call is placed and completed to one of the destination Terminals. Then, the second terminal joins the call using the join() method from this package. Finally, the originator hangs up his phone and the entire call becomes disconnected.
The following code example placing a telephone call using the core Call.connect() method. It, however, looks for the states provided by the Call Control package.
import java.telephony.*; import java.telephony.events.*; import java.telephony.callcontrol.*; import java.telephony.callcontrol.events.*; /* * The MyCallObserver class implements the CallControlCallObserver * interface and receives all events associated with the Call. */ public class MyCallObserver implements CallControlCallObserver { public void callChangedEvent(CallEv[] evlist) { for (int i = 0; i < evlist.length; i++) { if (evlist[i] instanceof ConnEv) { String name = null; try { Connection connection = evlist[i].getConnection(); Address addr = connection.getAddress(); name = addr.getName(); } catch (Exception excp) { // Handle Exceptions } String msg = "Connection to Address: " + name + " is "); if (evlist[i].getID() == CallCtlConnInitiatedEv.ID) { System.out.println(msg + "INITIATED"); } else if (evlist[i].getID() == CallCtlConnDialingEv.ID) { System.out.println(msg + "DIALING"); } else if (evlist[i].getID() == CallCtlConnEstablishedEv.ID) { System.out.println(msg + "ESTABLISHED"); } else if (evlist[i].getID() == CallCtlConnAlertingEv.ID) { System.out.println(msg + "ALERTING"); } else if (evlist[i].getID() == CallCtlConnDisconnectedEv.ID) { System.out.println(msg + "DISCONNECTED"); } } } } } /* * Places a telephone call from 476111 to 5551212 */ public class SampleOutcall { public static final void main(String args[]) { /* * Create a provider by first obtaining the default implementation of * JTAPI and then the default provider of that implementation. */ Provider myprovider = null; try { JtapiPeer peer = JtapiPeerFactory.getJtapiPeer(null); myprovider = peer.getProvider(null); } catch (Exception excp) { System.out.println("Can't get Provider: " + excp.toString()); System.exit(0); } /* * We need to get the appropriate objects associated with the * originating side of the telephone call. We ask the Address for a list * of Terminals on it and arbitrarily choose one. */ Address origaddr = null; Terminal origterm = null; try { origaddr = myprovider.getAddress("4761111"); /* Just get some Terminal on this Address */ Terminal[] terminals = origaddr.getTerminals(); if (terminals == null) { System.out.println("No Terminals on Address."); System.exit(0); } origterm = terminals[0]; } catch (Exception excp) { // Handle exceptions; } /* * Create the telephone call object and add an observer. */ Call mycall = null; try { mycall = myprovider.createCall(); mycall.addObserver(new MyCallObserver()); } catch (Exception excp) { // Handle exceptions } /* * Place the telephone call. */ try { Connection c[] = mycall.connect(origterm, origaddr, "5551212"); } catch (Exception excp) { // Handle all Exceptions } } }
The following code example illustrates how an application answers a Call at a particular Terminal. It shows how application accept calls when (and if) they are offered to it. This code example greatly resembles the core InCall code example.
import java.telephony.*; import java.telephony.events.*; import java.telephony.callcontrol.*; import java.telephony.callcontrol.events.*; /* * The MyObserver class implements the CallControlCallObserver and * recieves all Call-related events. */ public class MyObserver implements CallControlCallObserver { public void callChangedEvent(CallEv[] evlist) { for (int i = 0; i < evlist.length; i++) { if (evlist[i] instanceof TermConnEv) { TerminalConnection termconn = null; String name = null; try { TermConnEv tcev = (TermConnEv)evlist[i]; TerminalConnection termconn = tcev.getTerminalConnection(); Terminal term = termconn.getTerminal(); String name = term.getName(); } catch (Exception excp) { // Handle exceptions. } String msg = "TerminalConnection to Terminal: " + name + " is "; if (evlist[i].getID() == CallCtlTermConnTalkingEv.ID) { System.out.println(msg + "TALKING"); } else if (evlist[i].getID() == CallCtlTermConnRingingEv.ID) { System.out.println(msg + "RINGING") /* Answer the telephone Call */ try { termconn.answer(); } catch (Exception excp) { // Handle Exceptions; } } else if (evlist[i].getID() == CallCtlTermConnDroppedEv.ID) { System.out.println(msg + "DROPPED"); } } } } } /* * Create a provider and monitor a particular terminal for an incoming call. */ public class SampleIncall { public static final void main(String args[]) { /* * Create a provider by first obtaining the default implementation of * JTAPI and then the default provider of that implementation. */ Provider myprovider = null; try { JtapiPeer peer = JtapiPeerFactory.getJtapiPeer(null); myprovider = peer.getProvider(null); } catch (Exception excp) { System.out.println("Can't get Provider: " + excp.toString()); System.exit(0); } /* * Get the terminal we wish to monitor and add a call observer to that * Terminal. This will place a call observer on all call which come to * that terminal. We are assuming that Terminals are named after some * primary telephone number on them. */ try { Terminal terminal = myprovider.getTerminal("4761111"); terminal.addCallObserver(new MyCallObserver()); } } }