2 * Portions Copyright 2001 Sun Microsystems, Inc.
3 * Portions Copyright 1999-2001 Language Technologies Institute,
4 * Carnegie Mellon University.
5 * All Rights Reserved. Use is subject to license terms.
7 * See the file "license.terms" for information on usage and
8 * redistribution of this file, and for a DISCLAIMER OF ALL
11 package com.sun.speech.freetts;
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.List;
17 import java.util.StringTokenizer;
18 import java.util.logging.Level;
19 import java.util.logging.Logger;
21 import com.sun.speech.freetts.util.Utilities;
25 * Interface that Manages a feature or item path. Allows navigation
26 * to the corresponding feature or item.
27 * This class in controlled by the following system properties:
30 * com.sun.speech.freetts.interpretCartPaths - default false
31 * com.sun.speech.freetts.lazyCartCompile - default true
33 * com.sun.speech.freetts.interpretCartPaths
35 * Instances of this class will optionally pre-compile the paths.
36 * Pre-compiling paths reduces the processing time and objects needed
37 * to extract a feature or an item based upon a path.
39 public class PathExtractorImpl implements PathExtractor {
40 /** Logger instance. */
41 private static final Logger LOGGER =
42 Logger.getLogger(PathExtractorImpl.class.getName());
45 * If this system property is set to true, paths will
48 public final static String INTERPRET_PATHS_PROPERTY =
49 "com.sun.speech.freetts.interpretCartPaths";
52 * If this system property is set to true, CART feature/item
53 * paths will only be compiled as needed.
55 public final static String LAZY_COMPILE_PROPERTY =
56 "com.sun.speech.freetts.lazyCartCompile";
58 private final static boolean INTERPRET_PATHS =
59 Utilities.getProperty(INTERPRET_PATHS_PROPERTY, "false").equals("true");
60 private final static boolean LAZY_COMPILE =
61 Utilities.getProperty(LAZY_COMPILE_PROPERTY, "true").equals("true");
63 private String pathAndFeature;
65 private String feature;
66 private Object[] compiledPath;
67 private boolean wantFeature = false;
70 * Creates a path for the given feature.
72 public PathExtractorImpl(String pathAndFeature, boolean wantFeature) {
73 this.pathAndFeature = pathAndFeature;
74 if (INTERPRET_PATHS) {
75 path = pathAndFeature;
80 int lastDot = pathAndFeature.lastIndexOf(".");
81 // string can be of the form "p.feature" or just "feature"
84 feature = pathAndFeature;
87 feature = pathAndFeature.substring(lastDot + 1);
88 path = pathAndFeature.substring(0, lastDot);
90 this.wantFeature = wantFeature;
92 this.path = pathAndFeature;
96 compiledPath = compile(path);
101 * Finds the item associated with this Path.
102 * @param item the item to start at
103 * @return the item associated with the path or null
105 public Item findItem(Item item) {
107 if (INTERPRET_PATHS) {
108 return item.findItem(path);
111 if (compiledPath == null) {
112 compiledPath = compile(path);
117 for (int i = 0; pitem != null && i < compiledPath.length; ) {
118 OpEnum op = (OpEnum) compiledPath[i++];
119 if (op == OpEnum.NEXT) {
120 pitem = pitem.getNext();
121 } else if (op == OpEnum.PREV) {
122 pitem = pitem.getPrevious();
123 } else if (op == OpEnum.NEXT_NEXT) {
124 pitem = pitem.getNext();
126 pitem = pitem.getNext();
128 } else if (op == OpEnum.PREV_PREV) {
129 pitem = pitem.getPrevious();
131 pitem = pitem.getPrevious();
133 } else if (op == OpEnum.PARENT) {
134 pitem = pitem.getParent();
135 } else if (op == OpEnum.DAUGHTER) {
136 pitem = pitem.getDaughter();
137 } else if (op == OpEnum.LAST_DAUGHTER) {
138 pitem = pitem.getLastDaughter();
139 } else if (op == OpEnum.RELATION) {
140 String relationName = (String) compiledPath[i++];
141 pitem = pitem.getSharedContents().getItemRelation(relationName);
143 System.out.println("findItem: bad feature " + op +
152 * Finds the feature associated with this Path.
153 * @param item the item to start at
154 * @return the feature associated or "0" if the
155 * feature was not found.
157 public Object findFeature(Item item) {
159 if (INTERPRET_PATHS) {
160 return item.findFeature(path);
163 Item pitem = findItem(item);
164 Object results = null;
166 if (LOGGER.isLoggable(Level.FINER)) {
167 LOGGER.finer("findFeature: Item [" + pitem + "], feature '"
171 FeatureProcessor fp =
172 pitem.getOwnerRelation().getUtterance().
173 getVoice().getFeatureProcessor(feature);
176 if (LOGGER.isLoggable(Level.FINER)) {
178 "findFeature: There is a feature processor for '"
182 results = fp.process(pitem);
183 } catch (ProcessException pe) {
184 LOGGER.severe("trouble while processing " + fp);
188 results = pitem.getFeatures().getObject(feature);
192 results = (results == null) ? "0" : results;
193 if (LOGGER.isLoggable(Level.FINER)) {
194 LOGGER.finer("findFeature: ...results = '" + results + "'");
201 * Compiles the given path into the compiled form
202 * @param path the path to compile
203 * @return the compiled form which is in the form
204 * of an array path traversal enums and associated strings
206 private Object[] compile(String path) {
207 List list = new ArrayList();
210 return list.toArray();
213 StringTokenizer tok = new StringTokenizer(path, ":.");
215 while (tok.hasMoreTokens()) {
216 String token = tok.nextToken();
217 OpEnum op = OpEnum.getInstance(token);
219 throw new Error("Bad path compiled " + path);
224 if (op == OpEnum.RELATION) {
225 list.add(tok.nextToken());
228 return list.toArray();
231 // inherited for Object
233 public String toString() {
234 return pathAndFeature;
238 // TODO: add these to the interface should we support binary
241 public void writeBinary();
242 public void readBinary();
248 * An enumerated type associated with path operations.
251 static private Map map = new HashMap();
253 public final static OpEnum NEXT = new OpEnum("n");
254 public final static OpEnum PREV = new OpEnum("p");
255 public final static OpEnum NEXT_NEXT = new OpEnum("nn");
256 public final static OpEnum PREV_PREV = new OpEnum("pp");
257 public final static OpEnum PARENT = new OpEnum("parent");
258 public final static OpEnum DAUGHTER = new OpEnum("daughter");
259 public final static OpEnum LAST_DAUGHTER = new OpEnum("daughtern");
260 public final static OpEnum RELATION = new OpEnum("R");
265 * Creates a new OpEnum.. There is a limited
267 * @param name the path name for this Enum
269 private OpEnum(String name) {
275 * gets an OpEnum thats associated with
277 * @param name the name of the OpEnum of interest
279 public static OpEnum getInstance(String name) {
280 return (OpEnum) map.get(name);
283 // inherited from Object
284 public String toString() {