/**
* Copyright 2002 DFKI GmbH.
* All Rights Reserved. Use is subject to license terms.
*
* This file is part of MARY TTS.
*
* MARY TTS is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package marytts.language.de.preprocess;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* An expansion pattern implementation for duration patterns.
*
* @author Marc Schröder
*/
public class DurationEP extends ExpansionPattern {
private final String[] _knownTypes = { "duration", "duration:hms", "duration:hm", "duration:h" };
/**
* Every subclass has its own list knownTypes, an internal string representation of known types. These are possible values of
* the <code>type</code> attribute to the <code>say-as</code> element, as defined in MaryXML.dtd. If there is more than one
* known type, the first type (<code>knownTypes[0]</code>) is expected to be the most general one, of which the others are
* specializations.
*/
private final List<String> knownTypes = Arrays.asList(_knownTypes);
public List<String> knownTypes() {
return knownTypes;
}
// Domain-specific primitives:
protected final String sHour = "(?:0?[0-9]|1[0-9]|2[0-4])";
protected final String sMinute = "(?:[0-5][0-9])";
protected final String sSecond = sMinute;
protected final String sSep = "(?:\\:|\\.)";
protected final String sFinal = "(?:h|Std\\.)";
protected final String sMatchingChars = "[0-9:\\.hStd]";
// Now the actual match patterns:
protected final Pattern reHour = Pattern.compile("(" + sHour + ")" + sFinal);
protected final Pattern reHourMinute = Pattern.compile("(" + sHour + ")" + sSep + "(" + sMinute + ")" + sFinal);
protected final Pattern reHourMinuteSecond = Pattern.compile("(" + sHour + ")" + sSep + "(" + sMinute + ")" + sSep + "("
+ sSecond + ")" + sFinal);
private final Pattern reMatchingChars = Pattern.compile(sMatchingChars);
public Pattern reMatchingChars() {
return reMatchingChars;
}
/**
* Every subclass has its own logger. The important point is that if several threads are accessing the variable at the same
* time, the logger needs to be thread-safe or it will produce rubbish.
*/
// private Logger logger = MaryUtils.getLogger("DurationEP");
public DurationEP() {
super();
}
protected int canDealWith(String s, int type) {
return match(s, type);
}
protected int match(String s, int type) {
switch (type) {
case 0:
if (matchDurationHMS(s))
return 1;
if (matchDurationHM(s))
return 2;
if (matchDurationH(s))
return 3;
break;
case 1:
if (matchDurationHMS(s))
return 1;
break;
case 2:
if (matchDurationHM(s))
return 2;
break;
case 3:
if (matchDurationH(s))
return 3;
break;
}
return -1;
}
protected List<Element> expand(List<Element> tokens, String s, int type) {
if (tokens == null)
throw new NullPointerException("Received null argument");
if (tokens.isEmpty())
throw new IllegalArgumentException("Received empty list");
Document doc = ((Element) tokens.get(0)).getOwnerDocument();
// we expect type to be one of the return values of match():
List<Element> expanded = null;
switch (type) {
case 1:
expanded = expandDurationHMS(doc, s);
break;
case 2:
expanded = expandDurationHM(doc, s);
break;
case 3:
expanded = expandDurationH(doc, s);
break;
}
replaceTokens(tokens, expanded);
return expanded;
}
protected boolean matchDurationHMS(String s) {
return reHourMinuteSecond.matcher(s).matches();
}
protected boolean matchDurationHM(String s) {
return reHourMinute.matcher(s).matches();
}
protected boolean matchDurationH(String s) {
return reHour.matcher(s).matches();
}
protected List<Element> expandDurationHMS(Document doc, String s) {
ArrayList<Element> exp = new ArrayList<Element>();
Matcher reMatcher = reHourMinuteSecond.matcher(s);
if (!reMatcher.find()) {
return null;
}
String hour = reMatcher.group(1); // first bracket pair in reHour: hour
String minute = reMatcher.group(2);
String second = reMatcher.group(3);
if (hour.equals("01") || hour.equals("1")) {
exp.addAll(makeNewTokens(doc, "eine Stunde"));
} else {
exp.addAll(number.expandInteger(doc, hour, false));
exp.addAll(makeNewTokens(doc, "Stunden"));
}
if (!minute.equals("00")) {
if (!second.equals("00")) {
exp.addAll(makeNewTokens(doc, "und"));
}
if (minute.equals("01")) {
exp.addAll(makeNewTokens(doc, "eine Minute"));
} else {
exp.addAll(number.expandInteger(doc, minute, false));
exp.addAll(makeNewTokens(doc, "Minuten"));
}
}
if (!second.equals("00")) {
exp.addAll(makeNewTokens(doc, "und"));
if (second.equals("01")) {
exp.addAll(makeNewTokens(doc, "eine Sekunde"));
} else {
exp.addAll(number.expandInteger(doc, minute, false));
exp.addAll(makeNewTokens(doc, "Sekunden"));
}
}
return exp;
}
protected List<Element> expandDurationHM(Document doc, String s) {
ArrayList<Element> exp = new ArrayList<Element>();
Matcher reMatcher = reHourMinute.matcher(s);
reMatcher.find();
String hour = reMatcher.group(1);
String minute = reMatcher.group(2);
if (hour.equals("01") || hour.equals("1")) {
exp.addAll(makeNewTokens(doc, "eine Stunde"));
} else {
exp.addAll(number.expandInteger(doc, hour, false));
exp.addAll(makeNewTokens(doc, "Stunden"));
}
if (!minute.equals("00")) {
exp.addAll(makeNewTokens(doc, "und"));
if (minute.equals("01")) {
exp.addAll(makeNewTokens(doc, "eine Minute"));
} else {
exp.addAll(number.expandInteger(doc, minute, false));
exp.addAll(makeNewTokens(doc, "Minuten"));
}
}
return exp;
}
protected List<Element> expandDurationH(Document doc, String s) {
ArrayList<Element> exp = new ArrayList<Element>();
Matcher reMatcher = reHour.matcher(s);
reMatcher.find();
String hour = reMatcher.group(1); // first bracket pair in reHour: hour
if (hour.equals("01") || hour.equals("1")) {
exp.addAll(makeNewTokens(doc, "eine Stunde"));
} else {
exp.addAll(number.expandInteger(doc, hour, false));
exp.addAll(makeNewTokens(doc, "Stunden"));
}
return exp;
}
}