JSR-043: JTAPI-1.4

javax.telephony.media
Interface Delegation

All Superinterfaces:
DelegationConstants, MediaConstants, MediaServiceConstants
All Known Implementing Classes:
Base_MediaService

public interface Delegation
extends DelegationConstants

An optional MediaService interface for structured handoff and return. Delegation allows an application to pass control of the media processing to another MediaService and then regain control.

delegateToService(String, int, String) is similar to releaseToService(String, int): the MediaGroup of this MediaService is bound to a new MediaService. However, the MediaGroup is not released from the invoking MediaService; instead, this MediaService is pushed onto a stack of previous Owners.

A MediaService on the ownerstack is still bound to the MediaGroup, but is not the current Owner of that MediaGroup; it is not allowed to invoke most operations on the MediaGroup. The method isOwner() indicates if this MediaSerice is currently the Owner of its MediaGroup. If the MediaService is not bound then isOwner returns false.

delegateToService also associates a String of catchTags with this MediaService on the ownerstack of the MediaGroup. These tags are used when processing MediaService.releaseToTag(String).

Returning from delegateToService

delegateToService waits until the MediaGroup is returned to this MediaService. While delegateToService is active, there are two ways to stop waiting for the MediaGroup to be returned:

When the MediaGroup is returned to this MediaService, the MediaProvider attempts to reconfigure it to the configuration in effect when delegateToService was initiated. If that reconfiguration fails, then the MediaGroup is configured with no Resources [ConfigSpec.emptyConfigSpec] and the method DelegationEvent.reconfigurationFailed() returns true.

Catch and Return tag usage

When the current owner releases the MediaGroup (using MediaService.releaseToTag(String) or one of its variants), the stack is popped and ownership returns to a previous owner. The particular owner to regain ownership is determined by the returnTag supplied in the release method, and the catchTags supplied in the delegateToService methods. The process is as follows:

Each previous owner on the stack (that is, each MediaService that has an open call to delegateToService), supplies a String of catchTags which is associated with that MediaService on the owner stack. When the current owner releases the MediaGroup using releaseToTag(String), the stack of previous owners is searched from the most recent owner to the least recent owner:

If the returnTags do not match the catchTags of any previous owner, then

In effect, the eldest owner on the stack catches all tags, and implements the disconnect/destroy behavior. This is the normal and expected effect when releaseToDestroy() or releaseToTag(tag_DestroyRequest) is called, or when release() is called and there is no previous owner.

Catch and Return tag Values

The catchTags and returnTags are Strings. By convention, each tag is formatted as the name of an S.100 Symbol: "Object_VENDOR_ItemName". Multiple tags are specified by concatenating the basic tag strings with a whitespace separator. Whitespace is not allowed within a tag name.

Some catch/return tags are pre-assigned, and have special interpretations:
Tag Name:Used for:
tag_NormalReturnsimple release
tag_DestroyRequestrelease and terminate call
tag_RemoveSessionrelease with no delegation
tag_SessionDeathspecial release if owner dies
tag_CatchAllcatch any/all tags
tag_CatchNonenever catches
tag_NeverReturnnever catches
null or ()same as tag_NormalReturn

Note: catching only tag_CatchNone keeps this MediaService bound to the MediaGroup, but ensures that ownership will not return to this MediaService. When delegateToService() completes this MediaService.isBound() will be false, and the MediaGroup will be passed to some previous owner, (the GroupProvider if none other).

Note: some tags are useful only for delegateToService(). Releasing to tag_CatchNone has no useful effect.

isOwner() and retrieve()

While the MediaGroup is delegated, the MediaService is bound (isBound() returns true), but the MediaService is not the owner (isOwner() returns false). Most MediaService methods and Resource methods are prohibited unless the MediaService is the owner. Those methods throw NotOwnerException (a RuntimeException) if invoked when the MediaService is not the current owner.

To regain ownership, one must either wait for delegation to complete, or use retrieve(). retrieve(Symbol) is like releaseToTag(String) in that it causes a non-local (that is, it may skip levels on the ownership stack) transfer of ownership. However, retrieve(Symbol) is initiated by a previous owner (which MediaService becomes the new, current owner). In contrast, releaseToTag(String) is initiated by the current owner.

Delegation is Optional

Note: Implementing the Delegation interface is optional. If the MediaService does not otherwise implement this interface, then
delegateToService(String,int,String) throws NoServiceAssignedException
retrieve() has no effect
releaseDelegated() throws NotDelegatedException
releaseToTag(String)same as release(), because there are no previous owners
releaseToDestroy()same as release(), because there are no previous owners
isOwner()same as isBound()

Conclusion

This interface is intended for use in application frameworks that: Developers creating such frameworks or creating applications for such frameworks may need to use this interface. In that case, the framework developer or application developer should document any non-standard tags being used.

In other cases, applications should only need the MediaService methods release() and releaseToService().

Since:
JTAPI-1.4

Fields inherited from interface javax.telephony.media.DelegationConstants
ev_Delegated, q_Released, q_Removed, q_Retrieved, q_Returned, tag_CatchAll, tag_CatchNone, tag_DestroyRequest, tag_NeverReturn, tag_NormalReturn, tag_RemoveSession, tag_SessionDeath, v_Released
 
Fields inherited from interface javax.telephony.media.MediaServiceConstants
ev_BindAndConnect, ev_BindToCall, ev_BindToServiceName, ev_BindToTerminal, ev_BindToTerminalName, ev_Configure, ev_Connected, ev_DelegateToService, ev_Disconnected, ev_GetConfigSpec, ev_GetConfiguration, ev_GetParameters, ev_GetTerminal, ev_GetTerminalName, ev_GetUserValues, ev_GroupStop, ev_Release, ev_ReleaseDelegated, ev_ReleaseToDestroy, ev_ReleaseToService, ev_ReleaseToTag, ev_Retrieve, ev_Retrieved, ev_SetParameters, ev_SetUserDictionary, ev_SetUserValues, ev_TerminalIdle, ev_TriggerRTC
 
Fields inherited from interface javax.telephony.media.MediaConstants
e_OK, q_Duration, q_Standard, q_Stop
 
Method Summary
 DelegationEvent delegateToService(java.lang.String serviceName, int timeout, java.lang.String catchTags)
          Transfer ownership of the bound MediaGroup to another MediaService, and wait for the MediaGroup to be returned.
 boolean isDelegated()
          Return true if this MediaService is delegating ownership so some other MediaService.
 boolean isOwner()
          Return true if this MediaService is currently the owner of a bound MediaGroup.
 void releaseDelegated()
          Release while delegation is active.
 void retrieve(Symbol cause)
          Terminate the delegation that is in progress on this MediaService.
 

Method Detail

delegateToService

public DelegationEvent delegateToService(java.lang.String serviceName,
                                         int timeout,
                                         java.lang.String catchTags)
                                  throws MediaBindException,
                                         MediaConfigException
Transfer ownership of the bound MediaGroup to another MediaService, and wait for the MediaGroup to be returned. This MediaService is bound to the group throughout the operation, but is not the owner while waiting for the MediaGroup to be returned.

A new owner is identified by the given serviceName. see MediaService.releaseToService(String, int) for details.

Unlike releaseToService(), delegateToService() does not release the current MediaService. Instead, the MediaService continues to be bound but it is not the owner; it is not allowed to invoke Resource methods.

If the MediaGroup is not returned to this MediaService when delegateToService completes (by the action of releaseToTag or retrieve or releaseDelegated), then no Exception is thrown.

If delegateToService returns without the MediaGroup because if was retrieved by a older/previous owner, then

If delegateToService returns without the MediaGroup because it was released by the newest/current owner to some Tag not caught by this MediaService, then Applications should check isBound() or getReturnTag() after returning from delegateToService (or when onDelegationDone is invoked on the Async.DelegationListener).

Note: cancelBindRequest() terminates delegateToService only if it is processed before the MediaGroup is bound to some other owner. To cancel delegation after MediaGroup is delegated, use retrieve().
See also: onDelegated()

Note: delegateToService(serviceName, timeout, tag_RemoveSession) is roughly equivalent to releaseToService(serviceName, timeout). They differ in the type of the return event and the associated MediaListener invocation. Using tag_RemoveSession in this way may work, but is not supported. releaseToService() is the preferred form to use.

Parameters:
serviceName - the service name of the recipient.
timeout - the time to wait for a service to become ready.
catchTags - a String of tags to control releaseToTag(String);
catchTags = null is equivalent to tag_NormalReturn.
Returns:
a DelegationEvent that indicates how the delegation terminated.
Throws:
NotBoundException - if not currently bound to a MediaGroup
NotOwnerException - if delegateToService in progress.
MediaBindException - one of: BindInProgressException, NoServiceAssignedException, NoServiceReadyException, BindCancelledException
BindCancelledException - if interrupted by cancelBindRequest.
NoServiceAssignedException - if serviceName is not recognised or is not mapped to any known serviceName.
NoServiceReadyException - if none of the MediaServices registered to serviceName are ready and none become ready within timeout milliseconds.
MediaConfigException - if the MediaGroup could not be configured for the recipient service.
See Also:
MediaService.releaseToService(String, int), Async.DelegationListener.onDelegateToServiceDone(MediaServiceEvent)

retrieve

public void retrieve(Symbol cause)
              throws NotBoundException,
                     MediaBindException,
                     NotDelegatedException
Terminate the delegation that is in progress on this MediaService. On successful completion, this MediaService is owner of the bound MediaGroup.

The sequence of processing is:

If retrieve is processed when this MediaService.isOwner() is true, because delegateToService has returned (or was never invoked), this method succeeds with no other effect.

If retrieve() is processed when this MediaService.isBound() is false, then it throws NotBoundException.

Note: the state of isOwner() and isBound() may change between the time retrieve() is invoked and when it is processed by the platform. Other owners may release or retrieve the MediaGroup.

Note: This method may have undesirable effects on the application to which the MediaGroup has been delegated, or may have undersirable effects on the user interface experience of a caller. This function is intended to be used within suites of coordinated applicatations where the effects are understood and acceptable. If you do not know the effect of this method on the application which is currently the owner, then do not use this method.

Future Enhancement Proposal
In some future release, retrieve() could be implemented by adding tag_Retrieval to the catchTags of the invoking MediaService, and delivering an event to the current owner using MediaServiceListener.onRetrieved(ev_RetrieveRequest). This instructs the current owner to invoke releaseToTag(tag_Retrieval) at its earliest convenience.

Note: the current owner (or any owner between the current and the requesting owner) could delay retrieval by setting an parameter p_RetrieveDelay to the maximum milliseconds to wait (up to a framework determined maximum) before responding to the retrieval request. That would give the owner time to say goodbye, and issue releaseToTag(tab_Retrieval). The framework could intervene after the specified delay to enforce timely retrieval. The current specification corresponds to p_RetrieveDelay = 0, which is appropriate for retrieving from a music-on-hold application when a live agent is available.

Parameters:
cause - a Symbol that becomes the return value for getRetrieveCause().
Throws:
NotBoundException - if not currently bound to a MediaGroup
MediaBindException - a BindInProgressException if a bind or release is in progress.
NotDelegatedException - (a RuntimeException) if delegateToService has completed or not been called.

releaseDelegated

public void releaseDelegated()
                      throws NotBoundException,
                             MediaBindException,
                             NotDelegatedException
Release while delegation is active. Remove this MediaService from the ownerstack of the bound MediaGroup. Terminates delegateToService, leaving this MediaService not bound.


pre-conditions: (isBound() && isDelegated())
post-conditions: (!isBound() && !isDelegated())

Note: may throw an Exception if the pre-conditions are not true when the request is actually processed by the platform. Processing by other owners may change these properties between the time the method is invoked and when it is processed.

Note: releaseDelegated() can succeed only if it is processed while delegateToService is active on this MediaService. This is the one case where the platform may refuse to release. This restriction protects against a race when the application tries to get off the ownerstack just after (but before the app has been informed that) the MediaService has regained ownership. [that is, the previous/current owner just released the MediaGroup to this MediaService.] With this restriction, when the application eventually gets the onDelegateDone() notification, it is and will continue to be the owner; when the platform eventually processes releaseDelegated() it will throw NotDelegatedException.

Throws:
NotBoundException - if not currently bound to a MediaGroup
MediaBindException - a BindInProgressException if a bind or release is in progress.
NotDelegatedException - (a RuntimeException) if delegateToService has completed or not been called.

isDelegated

public boolean isDelegated()
Return true if this MediaService is delegating ownership so some other MediaService.
Returns:
true if delegateToService is active.

isOwner

public boolean isOwner()
Return true if this MediaService is currently the owner of a bound MediaGroup.

isOwner() is: (isBound() && !isDelegated())

Returns:
true if this MediaService is bound and not delegated.

JSR-043: JTAPI-1.4

Send comments to: JSR-43@ectf.org