/**
* Copyright 2010-2011 Voxeo Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License.
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package com.voxeo.moho.remote.impl.media;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.apache.log4j.Logger;
import com.rayo.core.verb.InputMode;
import com.rayo.core.verb.VerbCompleteReason;
import com.rayo.core.verb.VerbRef;
import com.voxeo.moho.MediaException;
import com.voxeo.moho.common.event.MohoInputCompleteEvent;
import com.voxeo.moho.common.util.SettableResultFuture;
import com.voxeo.moho.event.EventSource;
import com.voxeo.moho.event.InputCompleteEvent;
import com.voxeo.moho.media.Input;
import com.voxeo.moho.remote.impl.JID;
import com.voxeo.moho.remote.impl.MediaServiceSupport;
import com.voxeo.moho.remote.impl.RayoListener;
import com.voxeo.rayo.client.XmppException;
import com.voxeo.rayo.client.xmpp.stanza.IQ;
import com.voxeo.rayo.client.xmpp.stanza.Presence;
//TODO exception and IQ error handling
public class InputImpl<T extends EventSource> implements Input<T>, RayoListener {
private static final Logger LOG = Logger.getLogger(InputImpl.class);
protected SettableResultFuture<InputCompleteEvent<T>> _future = new SettableResultFuture<InputCompleteEvent<T>>();
protected VerbRef _verbRef;
protected MediaServiceSupport<T> _call;
protected T _todo;
public InputImpl(final VerbRef verbRef, final MediaServiceSupport<T> call, T todo) {
_verbRef = verbRef;
_call = call;
_todo = todo;
_call.addComponentListener(_verbRef.getVerbId(), this);
}
public void done(final InputCompleteEvent<T> event) {
_future.setResult(event);
_call.removeComponentListener(_verbRef.getVerbId());
}
public void done(final MediaException exception) {
_future.setException(exception);
_call.removeComponentListener(_verbRef.getVerbId());
}
@Override
public void stop() {
if (!_future.isDone()) {
try {
IQ iq = _call.getMohoRemote().getRayoClient().stop(_verbRef);
if (iq.isError()) {
com.voxeo.rayo.client.xmpp.stanza.Error error = iq.getError();
throw new MediaException(error.getCondition() + error.getText());
}
}
catch (XmppException e) {
LOG.error("", e);
throw new MediaException(e);
}
}
}
@Override
public boolean cancel(final boolean mayInterruptIfRunning) {
return _future.cancel(mayInterruptIfRunning);
}
@Override
public InputCompleteEvent<T> get() throws InterruptedException, ExecutionException {
return _future.get();
}
@Override
public InputCompleteEvent<T> get(final long timeout, final TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException {
return _future.get(timeout, unit);
}
@Override
public boolean isCancelled() {
return _future.isCancelled();
}
@Override
public boolean isDone() {
return _future.isDone();
}
@Override
public void onRayoEvent(JID from, Presence presence) {
LOG.debug("InputImpl Recived presence, processing:"+ presence);
Object obj = presence.getExtension().getObject();
if (obj instanceof com.rayo.core.verb.VerbCompleteEvent) {
com.rayo.core.verb.VerbCompleteEvent event = (com.rayo.core.verb.VerbCompleteEvent) obj;
MohoInputCompleteEvent<T> mohoEvent = new MohoInputCompleteEvent<T>(_todo,
getMohoInputCompleteReasonByRayoReason(event.getReason()), event.getErrorText(), this);
if (event instanceof com.rayo.core.verb.InputCompleteEvent) {
mohoEvent.setConcept(((com.rayo.core.verb.InputCompleteEvent) event).getConcept());
mohoEvent.setConfidence(((com.rayo.core.verb.InputCompleteEvent) event).getConfidence());
com.voxeo.moho.media.InputMode mode = null;
if (((com.rayo.core.verb.InputCompleteEvent) event).getMode() == InputMode.DTMF) {
mode = com.voxeo.moho.media.InputMode.DTMF;
}
else if (((com.rayo.core.verb.InputCompleteEvent) event).getMode() == InputMode.VOICE) {
mode = com.voxeo.moho.media.InputMode.SPEECH;
}
else {
mode = com.voxeo.moho.media.InputMode.ANY;
}
mohoEvent.setInputMode(mode);
mohoEvent.setInterpretation(((com.rayo.core.verb.InputCompleteEvent) event).getInterpretation());
mohoEvent.setNlsml(((com.rayo.core.verb.InputCompleteEvent) event).getNlsml());
mohoEvent.setTag(((com.rayo.core.verb.InputCompleteEvent) event).getTag());
mohoEvent.setUtterance(((com.rayo.core.verb.InputCompleteEvent) event).getUtterance());
}
this.done(mohoEvent);
_call.dispatch(mohoEvent);
}
else {
LOG.error("InputImpl Can't process presence:" + presence);
}
}
protected InputCompleteEvent.Cause getMohoInputCompleteReasonByRayoReason(VerbCompleteReason reason) {
InputCompleteEvent.Cause cause = InputCompleteEvent.Cause.ERROR;
if (reason instanceof com.rayo.core.verb.InputCompleteEvent.Reason) {
if (reason == com.rayo.core.verb.InputCompleteEvent.Reason.MATCH) {
cause = InputCompleteEvent.Cause.MATCH;
}
else if (reason == com.rayo.core.verb.InputCompleteEvent.Reason.NOINPUT) {
cause = InputCompleteEvent.Cause.INI_TIMEOUT;
}
else if (reason == com.rayo.core.verb.InputCompleteEvent.Reason.TIMEOUT) {
cause = InputCompleteEvent.Cause.MAX_TIMEOUT;
}
else if (reason == com.rayo.core.verb.InputCompleteEvent.Reason.NOMATCH) {
cause = InputCompleteEvent.Cause.NO_MATCH;
}
}
else if (reason instanceof com.rayo.core.verb.VerbCompleteEvent.Reason) {
if (reason == com.rayo.core.verb.VerbCompleteEvent.Reason.HANGUP) {
return InputCompleteEvent.Cause.DISCONNECT;
}
else if (reason == com.rayo.core.verb.VerbCompleteEvent.Reason.STOP) {
return InputCompleteEvent.Cause.CANCEL;
}
else if (reason == com.rayo.core.verb.VerbCompleteEvent.Reason.ERROR) {
return InputCompleteEvent.Cause.ERROR;
}
}
return cause;
}
@Override
public void onRayoCommandResult(JID from, IQ iq) {
LOG.warn("Unprocessed IQ:"+iq);
}
public String getVerbId() {
return _verbRef.getVerbId();
}
}