/**
 * Portions Copyright 2001 Sun Microsystems, Inc.
 * Portions Copyright 1999-2001 Language Technologies Institute, 
 * Carnegie Mellon University.
 * All Rights Reserved.  Use is subject to license terms.
 * 
 * See the file "license.terms" for information on usage and
 * redistribution of this file, and for a DISCLAIMER OF ALL 
 * WARRANTIES.
 */
package com.sun.speech.freetts.en;

import com.sun.speech.freetts.UtteranceProcessor;
import com.sun.speech.freetts.Voice;
import com.sun.speech.freetts.Utterance;
import com.sun.speech.freetts.Item;
import com.sun.speech.freetts.Relation;
import com.sun.speech.freetts.ProcessException;
import com.sun.speech.freetts.PathExtractorImpl;
import com.sun.speech.freetts.PathExtractor;


/**
 * Annotates the utterance with post lexical information.
 */
public class PostLexicalAnalyzer implements UtteranceProcessor {
    private static final PathExtractor wordPath =
	new PathExtractorImpl("R:SylStructure.parent.parent.name", true);
    private static final PathExtractor P_PH_VC =
	new PathExtractorImpl("p.ph_vc", true);
    private static final PathExtractor N_PH_VC =
	new PathExtractorImpl("n.ph_vc", true);

    /**
     * Constructs a PostLexicalAnalyzer
     */
     public PostLexicalAnalyzer () {
     }

    /**
     * Performs the post lexical processing.
     *
     * @param  utterance  the utterance to process
     *
     * @throws ProcessException if an error occurs while
     *         processing of the utterance
     */
    public void processUtterance(Utterance utterance) throws ProcessException {
	fixApostrophe(utterance);
 	fixTheIy(utterance);
    }

    /**
     * Fixes apostrophe s segments.
     *
     * @param utterance the utterance to fix
     */
    private void fixApostrophe(Utterance utterance) {
	Voice voice = utterance.getVoice();
	for (Item item = utterance.getRelation(Relation.SEGMENT).getHead();
		item != null;
		item = item.getNext()) {
	    String word = wordPath.findFeature(item).toString();

	    if (word.equals("'s")) {

		String pname = item.getPrevious().toString();

		if (("fa".indexOf(
			    voice.getPhoneFeature(pname,"ctype")) != -1) &&
		    ("dbg".indexOf(
			    voice.getPhoneFeature(pname, "cplace")) == -1)) {
		    prependSchwa(item);
		} else  if (voice.getPhoneFeature(pname, "cvox").equals("-")) {
		    item.getFeatures().setString("name", "s");
		}
	    } else if (word.equals("'ve") ||
		       word.equals("'ll") || word.equals("'d")) {
		if ("-".equals(P_PH_VC.findFeature(item))) {
		    prependSchwa(item);
		}
	    }
	}
    }


    /**
     * Prepends a schwa to the given item
     * 
     * @param item the item to prepend the schwa to.
     */
    private static void prependSchwa(Item item) {
	Item schwa = item.prependItem(null);
	schwa.getFeatures().setString("name", "ax");
	item.getItemAs(
	    Relation.SYLLABLE_STRUCTURE).prependItem(schwa);
    }


    /**
     * Changes the pronunciation of "the" from 'd ax'  to 'd iy' if
     * the following word starts with a vowel. "The every" is a good
     * example.
     *
     * @param  utterance  the utterance to process
     */
    private void fixTheIy(Utterance utterance) {
	Voice voice = utterance.getVoice();
	for (Item item = utterance.getRelation(Relation.SEGMENT).getHead();
		item != null; item = item.getNext()) {

	    if ("ax".equals(item.toString())) {
		String word = wordPath.findFeature(item).toString();
		if ("the".equals(word) &&
			("+".equals(N_PH_VC.findFeature(item)))) {
		    item.getFeatures().setString("name", "iy");
		}
	    }
	}
    }

    /**
     * Returns the string representation of the object
     *
     * @return the string representation of the object
     */
    public String toString() {
        return "PostLexicalAnalyzer";
    }
}

