001/**
002 * Portions Copyright 2001 Sun Microsystems, Inc.
003 * Portions Copyright 1999-2001 Language Technologies Institute, 
004 * Carnegie Mellon University.
005 * All Rights Reserved.  Use is subject to license terms.
006 * 
007 * See the file "license.terms" for information on usage and
008 * redistribution of this file, and for a DISCLAIMER OF ALL 
009 * WARRANTIES.
010 */
011package com.sun.speech.freetts;
012
013import java.io.BufferedReader;
014import java.io.IOException;
015import java.io.InputStreamReader;
016import java.net.URL;
017import java.util.HashMap;
018import java.util.Map;
019import java.util.NoSuchElementException;
020import java.util.StringTokenizer;
021
022/**
023 * Implementation of a <code>PhoneSet</code> that reads the info from
024 * a file.  The format of the file is as follows:
025 *
026 * <pre>
027 * phone feature value
028 * phone feature value
029 * phone feature value
030 * ...
031 * </pre>
032 *
033 * Where <code>phone</code> is the phone name, <code>feature</code> is
034 * the phone feature such as "vc," "vlng," "vheight," and so on, and
035 * "value" is the value of the feature.  There can be multiple lines
036 * for the same phone to describe various features of that phone.
037 */
038public class PhoneSetImpl implements PhoneSet {
039    /**
040     * Used for informational purposes if there's a bad line in the
041     * file.
042     */ 
043    private int lineCount = 0;
044
045    /**
046     * The set of phone features indexed by phone.
047     */    
048    private Map phonesetMap;
049
050    /**
051     * Create a new <code>PhoneSetImpl</code> by reading from the
052     * given URL.
053     *
054     * @param url the input source
055     *
056     * @throws IOException if an error occurs
057     */ 
058    public PhoneSetImpl(URL url) throws IOException {
059        BufferedReader reader;
060        String line;
061
062        phonesetMap = new HashMap();
063        reader = new BufferedReader(new
064                InputStreamReader(url.openStream()));
065        line = reader.readLine();
066        lineCount++;
067        while (line != null) {
068            if (!line.startsWith("***")) {
069                parseAndAdd(line);
070            }
071            line = reader.readLine();
072        }
073        reader.close();
074    }
075    
076    /**
077     * Creates a word from the given input line and add it to the map.
078     *
079     * @param line the input line
080     */
081    private void parseAndAdd(String line) {
082        StringTokenizer tokenizer = new StringTokenizer(line," ");
083        try {
084            String phoneme = tokenizer.nextToken();
085            String feature = tokenizer.nextToken();        
086            String value = tokenizer.nextToken();        
087            phonesetMap.put(getKey(phoneme, feature), value);
088        } catch (NoSuchElementException nse) {
089            throw new Error("part of speech data in bad format at line " 
090            + lineCount);
091        }
092    }
093
094    /**
095     * Given a phoneme and a feature, returns the key that
096     * will obtain the value.
097     *
098     * @param phoneme the phoneme
099     * @param feature the name of the feature
100     *
101     * @return the key used to obtain the value
102     */
103    private String getKey(String phoneme, String feature) {
104        return phoneme + feature;
105    }
106
107    /**
108     * Given a phoneme and a feature name, returns the feature.
109     *
110     * @param phone the phoneme of interest
111     * @param featureName the name of the feature of interest
112     *
113     * @return the feature with the given name
114     */
115    public String getPhoneFeature(String phone, String featureName) {
116        return (String) phonesetMap.get(getKey(phone, featureName));
117    }
118}