1 package org.daisy.pipeline.tts.impl;
2
3 import java.io.IOException;
4 import java.util.Collections;
5 import java.util.IllformedLocaleException;
6 import java.util.Locale;
7
8 import net.sf.saxon.s9api.SaxonApiException;
9 import net.sf.saxon.s9api.XdmNode;
10
11 import org.daisy.common.properties.Properties;
12 import org.daisy.pipeline.tts.Voice;
13 import org.daisy.pipeline.tts.VoiceInfo.Gender;
14 import org.daisy.pipeline.tts.VoiceManager;
15 import org.daisy.pipeline.webservice.restlet.AuthenticatedResource;
16 import org.daisy.pipeline.webservice.xml.XmlUtils;
17
18 import org.restlet.data.MediaType;
19 import org.restlet.data.Status;
20 import org.restlet.ext.xml.DomRepresentation;
21 import org.restlet.representation.Representation;
22 import org.restlet.resource.Get;
23 import org.restlet.resource.Post;
24
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import org.w3c.dom.Document;
29 import org.w3c.dom.Element;
30
31 public class VoicesResource extends AuthenticatedResource {
32
33 private static final Logger logger = LoggerFactory.getLogger(VoicesResource.class.getName());
34
35 private VoicesWebServiceExtension provider;
36 private String engineAttr;
37 private String nameAttr;
38 private String langAttr;
39 private String genderAttr;
40
41 @SuppressWarnings("unchecked")
42 @Override
43 public void doInit() {
44 super.doInit();
45 if (!isAuthenticated()) {
46 return;
47 }
48 provider = (VoicesWebServiceExtension)getContext().getAttributes().get(VoicesWebServiceExtension.CONTEXT_ATTRIBUTE_KEY);
49 engineAttr = getQuery().getFirstValue("engine");
50 nameAttr = getQuery().getFirstValue("name");
51 langAttr = getQuery().getFirstValue("lang");
52 genderAttr = getQuery().getFirstValue("gender");
53 }
54
55
56
57
58
59
60 @Get("xml")
61 public Representation getResource() {
62 return getResource(null);
63 }
64
65
66
67
68 @Post("xml")
69 public Representation getResource(Representation ttsConfig) {
70 logRequest();
71 maybeEnableCORS();
72 if (!isAuthenticated()) {
73 setStatus(Status.CLIENT_ERROR_UNAUTHORIZED);
74 return null;
75 }
76 XdmNode configXML = null; {
77 if (ttsConfig != null)
78 try {
79 configXML = provider.getConfigXML(ttsConfig.getText());
80 } catch (IOException|SaxonApiException e) {
81 logger.error("bad request:", e);
82 setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
83 return getErrorRepresentation(e.getMessage());
84 }
85 }
86 VoiceManager voiceManager = null;
87 boolean omitRefs = false; {
88 synchronized (provider) {
89 voiceManager = provider.getVoiceManager(Properties.getSnapshot(), configXML, logger);
90 omitRefs = !provider.hasRememberedVoiceManager();
91 }
92 }
93 Iterable<Voice> availableVoices; {
94 Locale lang; {
95 try {
96 lang = langAttr == null ? null : (new Locale.Builder()).setLanguageTag(langAttr).build();
97 Gender gender = Gender.of(genderAttr);
98 if (gender != null || genderAttr == null) {
99 String voiceEngine = engineAttr;
100 String voiceName = nameAttr;
101 logger.debug("Getting voices for query " + getQuery());
102 availableVoices = voiceManager.findAvailableVoices(voiceEngine, voiceName, lang, gender);
103 } else {
104 logger.error("Could not parse gender '" + genderAttr + "'");
105 availableVoices = Collections.EMPTY_LIST;
106 }
107 } catch (IllformedLocaleException e) {
108 logger.error(e.getMessage());
109 availableVoices = Collections.EMPTY_LIST;
110 }
111 }
112 }
113 Document voicesDoc; {
114 voicesDoc = XmlUtils.createDom("voices");
115 Element voicesElem = voicesDoc.getDocumentElement();
116 String baseURL = getRequest().getRootRef().toString();
117 voicesElem.setAttribute("href", baseURL + VoicesWebServiceExtension.VOICES_ROUTE);
118 for (Voice v : availableVoices) {
119 Element voiceElem = voicesDoc.createElementNS(XmlUtils.NS_PIPELINE_DATA, "voice");
120 VoiceResource.addElementData(voiceElem, baseURL, v, omitRefs);
121 voicesElem.appendChild(voiceElem);
122 }
123 }
124 DomRepresentation dom; {
125 try {
126 dom = new DomRepresentation(MediaType.APPLICATION_XML, voicesDoc);
127 setStatus(Status.SUCCESS_OK);
128 } catch (Exception e) {
129 setStatus(Status.SERVER_ERROR_INTERNAL);
130 return getErrorRepresentation(e.getMessage());
131 }
132 }
133 logResponse(dom);
134 return dom;
135 }
136 }