package com.rayo.core.xml.providers; import java.net.URISyntaxException; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.Namespace; import org.dom4j.QName; import com.rayo.core.validation.Messages; import com.rayo.core.validation.ValidationException; import com.rayo.core.verb.Output; import com.rayo.core.verb.OutputCompleteEvent; import com.rayo.core.verb.PauseCommand; import com.rayo.core.verb.ResumeCommand; import com.rayo.core.verb.SeekCommand; import com.rayo.core.verb.SpeedDownCommand; import com.rayo.core.verb.SpeedUpCommand; import com.rayo.core.verb.VolumeDownCommand; import com.rayo.core.verb.VolumeUpCommand; import com.rayo.core.verb.OutputCompleteEvent.Reason; import com.voxeo.moho.media.output.OutputCommand.BargeinType; public class OutputProvider extends BaseProvider { // XML -> Object // ================================================================================ private static final Namespace NAMESPACE = new Namespace("", "urn:xmpp:rayo:output:1"); private static final Namespace COMPLETE_NAMESPACE = new Namespace("", "urn:xmpp:rayo:output:complete:1"); private static final QName PAUSE_QNAME = new QName("pause", NAMESPACE); private static final QName RESUME_QNAME = new QName("resume", NAMESPACE); private static final QName SEEK_QNAME = new QName("seek", NAMESPACE); private static final QName SPEED_UP_QNAME = new QName("speed-up", NAMESPACE); private static final QName SPEED_DOWN_QNAME = new QName("speed-down", NAMESPACE); private static final QName VOLUME_UP_QNAME = new QName("volume-up", NAMESPACE); private static final QName VOLUME_DOWN_QNAME = new QName("volume-down", NAMESPACE); @Override protected Object processElement(Element element) throws Exception { if (element.getName().equals("output")) { return buildOutput(element); } else if (PAUSE_QNAME.equals(element.getQName())) { return buildPauseCommand(element); } else if (RESUME_QNAME.equals(element.getQName())) { return buildResumeCommand(element); } else if (SEEK_QNAME.equals(element.getQName())) { return buildSeekCommand(element); } else if (SPEED_UP_QNAME.equals(element.getQName())) { return buildSpeedUpCommand(element); } else if (SPEED_DOWN_QNAME.equals(element.getQName())) { return buildSpeedDownCommand(element); } else if (VOLUME_UP_QNAME.equals(element.getQName())) { return buildVolumeUpCommand(element); } else if (VOLUME_DOWN_QNAME.equals(element.getQName())) { return buildVolumeDownCommand(element); } else if (element.getNamespace().equals(RAYO_COMPONENT_NAMESPACE)) { return buildCompleteCommand(element); } return null; } private Object buildCompleteCommand(Element element) { Element reasonElement = (Element)element.elements().get(0); String reasonValue = reasonElement.getName().toUpperCase(); Reason reason = Reason.valueOf(reasonValue); OutputCompleteEvent complete = new OutputCompleteEvent(); complete.setReason(reason); return complete; } private Object buildOutput(Element element) throws URISyntaxException { Output output = new Output(); output.setPrompt(extractSsml(element)); output.setVoice(element.attributeValue("voice")); if (element.attribute("broadcast") != null) { output.setBroadcast(toBoolean("broadcast", element)); } if (element.attribute("interrupt-on") != null) { output.setBargeinType(loadBargeinType(element)); } if (element.attribute("start-offset") != null) { output.setStartOffset(toDuration("start-offset", element)); } if (element.attribute("start-paused") != null) { output.setStartPaused(toBoolean("start-paused", element)); } if (element.attribute("repeat-interval") != null) { output.setRepeatInterval(toDuration("repeat-interval", element)); } if (element.attribute("repeat-times") != null) { output.setRepeatTimes(toInteger("repeat-times", element)); } if (element.attribute("max-time") != null) { output.setMaxTime(toDuration("max-time", element)); } return output; } private Object buildPauseCommand(Element element) { return new PauseCommand(); } private Object buildResumeCommand(Element element) { return new ResumeCommand(); } private Object buildSeekCommand(Element element) throws URISyntaxException { SeekCommand command = new SeekCommand(); if (element.attribute("direction") != null) { command.setDirection(toEnum(SeekCommand.Direction.class, "direction", element)); } if (element.attribute("amount") != null) { command.setAmount(toInteger("amount", element)); } return command; } private Object buildVolumeUpCommand(Element element) throws URISyntaxException { return new VolumeUpCommand(); } private Object buildVolumeDownCommand(Element element) throws URISyntaxException { return new VolumeDownCommand(); } private Object buildSpeedUpCommand(Element element) throws URISyntaxException { return new SpeedUpCommand(); } private Object buildSpeedDownCommand(Element element) throws URISyntaxException { return new SpeedDownCommand(); } // Object -> XML // ================================================================================ @Override protected void generateDocument(Object object, Document document) throws Exception { if (object instanceof Output) { createOutput((Output) object, document); } else if (object instanceof PauseCommand) { createPauseCommand((PauseCommand) object, document); } else if (object instanceof ResumeCommand) { createResumeCommand((ResumeCommand) object, document); } else if (object instanceof SeekCommand) { createSeekCommand((SeekCommand) object, document); } else if (object instanceof SpeedDownCommand) { createSpeedDownCommand((SpeedDownCommand) object, document); } else if (object instanceof SpeedUpCommand) { createSpeedUpCommand((SpeedUpCommand) object, document); } else if (object instanceof VolumeUpCommand) { createVolumeUpCommand((VolumeUpCommand) object, document); } else if (object instanceof VolumeDownCommand) { createVolumeDownCommand((VolumeDownCommand) object, document); } else if (object instanceof OutputCompleteEvent) { createOutputCompleteEvent((OutputCompleteEvent) object, document); } } private void createOutput(Output output, Document document) throws Exception { Element root = document.addElement(new QName("output", NAMESPACE)); if (output.getBargeinType() != null ) { root.addAttribute("interrupt-on", output.getBargeinType().name().toLowerCase()); } if (output.getStartOffset() != null ) { root.addAttribute("start-offset", String.valueOf(output.getStartOffset().getMillis())); } if (output.isStartPaused() != null ) { root.addAttribute("start-paused", String.valueOf(output.isStartPaused())); } if (output.getRepeatInterval() != null ) { root.addAttribute("repeat-interval", String.valueOf(output.getRepeatInterval().getMillis())); } if (output.getRepeatTimes() != null ) { root.addAttribute("repeat-times", String.valueOf(output.getRepeatTimes())); } if (output.getMaxTime() != null ) { root.addAttribute("max-time", String.valueOf(output.getMaxTime().getMillis())); } if (output.getVoice() != null ) { root.addAttribute("voice", output.getVoice()); } if (output.getPrompt() != null) { addSsml(output.getPrompt(), root); } if (output.getBroadcast() != null && output.getBroadcast()) { root.addAttribute("broadcast", String.valueOf(output.getBroadcast())); } } private void createPauseCommand(PauseCommand command, Document document) throws Exception { document.addElement(new QName("pause", NAMESPACE)); } private void createResumeCommand(ResumeCommand command, Document document) throws Exception { document.addElement(new QName("resume", NAMESPACE)); } private void createSeekCommand(SeekCommand command, Document document) throws Exception { Element seek = document.addElement(new QName("seek", NAMESPACE)); seek.addAttribute("amount", String.valueOf(command.getAmount())); seek.addAttribute("direction", command.getDirection().toString()); } private void createSpeedUpCommand(SpeedUpCommand command, Document document) throws Exception { document.addElement(new QName("speed-up", NAMESPACE)); } private void createSpeedDownCommand(SpeedDownCommand command, Document document) throws Exception { document.addElement(new QName("speed-down", NAMESPACE)); } private void createVolumeUpCommand(VolumeUpCommand command, Document document) throws Exception { document.addElement(new QName("volume-up", NAMESPACE)); } private void createVolumeDownCommand(VolumeDownCommand command, Document document) throws Exception { document.addElement(new QName("volume-down", NAMESPACE)); } private void createOutputCompleteEvent(OutputCompleteEvent event, Document document) throws Exception { addCompleteElement(document, event, COMPLETE_NAMESPACE); } protected BargeinType loadBargeinType(Element element) { try { return BargeinType.valueOf(element.attributeValue("interrupt-on").toUpperCase()); } catch (Exception e) { throw new ValidationException(Messages.INVALID_BARGEIN_TYPE); } } }