Source code: org/alicebot/server/core/parser/TemplateParser.java
1 /*
2 Alicebot Program D
3 Copyright (C) 1995-2001, A.L.I.C.E. AI Foundation
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 You should have received a copy of the GNU General Public License
11 along with this program; if not, write to the Free Software
12 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
13 USA.
14 */
15
16 /*
17 Code cleanup (4.1.3 [00] - October 2001, Noel Bush)
18 - formatting cleanup
19 - general grammar fixes
20 - complete javadoc
21 - made all imports explicit
22 - replaced String literals with constants (except for 0.9 bot predicates)
23 - removed unused depth, length and interpreter fields and deprecated constructors using them
24 - removed extraneous "extends Object" :-)
25 - removed use of IdProcessor and DateProcessor (although they might return later)
26 - renamed variables with more descriptive names
27 - removed unused global fields (globals, classifier, graphmaster, bot)
28 - changed tests like if(someVariable == true) to if(someVariable)
29 - removed non-AIML1.0.1 support for <get></get> (only atomic form is supported)
30 - inserted commented-out support for AIML 1.0.1 <gender/>
31 - changed name of virtualtag() to shortcutTag()
32 - changed formattag() to formatTag()
33 - inlined some unnecessary variables that were created only for debugging
34 - changed to use of ActiveMultiplexor
35 - added getValid2dIndex method
36 - added getValid1dIndex method
37 - changed method names "countnode" to "nodeCount", "getnode" to "getNode"
38 - made INPUT_STAR(S), THAT_STAR(S) and TOPIC_STAR(S) private and created get methods
39 */
40
41 /*
42 Further optimization (4.1.3 [01] - November 2001, Noel Bush
43 - introduced pluggable processor usage
44 - removed constructor that took Interpreter argument
45 - moved processListItem to ConditionProcessor
46 - moved processing of deprecated tags to DeprecatedAIMLParser and made optional
47 (via setting in Globals)
48 - changed to extend GenericParser and moved the following methods there:
49 - getArg (renamed to getAttributeValue)
50 - formatTag
51 - nodeCount
52 - getNode
53 - processTag
54 - processResponse
55 - entirely removed constructor that takes depth as a parameter
56 */
57
58 package org.alicebot.server.core.parser;
59
60 import java.util.ArrayList;
61 import java.util.Stack;
62
63 import org.alicebot.server.core.Globals;
64 import org.alicebot.server.core.logging.Log;
65 import org.alicebot.server.core.processor.AIMLProcessorException;
66 import org.alicebot.server.core.processor.AIMLProcessorRegistry;
67 import org.alicebot.server.core.processor.ProcessorException;
68 import org.alicebot.server.core.util.Trace;
69
70
71 /**
72 * <code>TemplateParser</code> is still a primitive class, implementing not a
73 * "real" XML parser, but just enough (hopefully) to get the job done.
74 */
75 public class TemplateParser extends GenericParser
76 {
77 /** The stack of inputStars Vector that will allow correct use of <srai> */
78 private Stack stackStar = new Stack();
79
80 /** The values captured from the input by wildcards in the <code>pattern</code>. */
81 private ArrayList inputStars = new ArrayList();
82
83 /** The values captured from the input path by wildcards in the <code>that</code>. */
84 private ArrayList thatStars = new ArrayList();
85
86 /** The values captured from the input path by wildcards in the <code>topic</code>. */
87 private ArrayList topicStars = new ArrayList();
88
89 /** The input that matched the <code>pattern</code> associated with this template (helps to avoid endless loops). */
90 private ArrayList inputs = new ArrayList();
91
92 /** The userid for which this parser is used. */
93 private String userid;
94
95 /** The botid on whose behalf this parser is working. */
96 private String botid;
97
98
99 /**
100 * Initializes an <code>TemplateParser</code>.
101 * The <code>input</code> is a required parameter!
102 *
103 * @param input the input that matched the <code>pattern</code>
104 * associated with this template (helps to avoid endless loops)
105 *
106 * @throws TemplateParserException if the <code>input</code> is null
107 */
108 public TemplateParser(String input, String userid, String botid) throws TemplateParserException
109 {
110 if (input == null)
111 {
112 throw new TemplateParserException("No input supplied for TemplateParser!");
113 }
114 this.inputs.add(input);
115 this.userid = userid;
116 this.botid = botid;
117 super.processorRegistry = AIMLProcessorRegistry.getSelf();
118 }
119
120
121 /**
122 * Processes the AIML within and including a given AIML element.
123 *
124 * @param level the current level in the XML trie
125 * @param tag the tag being evaluated
126 *
127 * @return the result of processing the tag
128 *
129 * @throws AIMLProcessorException if the AIML cannot be processed
130 */
131 public String processTag(int level, XMLNode tag) throws ProcessorException
132 {
133 try
134 {
135 return super.processTag(level, tag);
136 }
137 // A ProcessorException at this point can mean several things.
138 catch (ProcessorException e0)
139 {
140 // It could be a deprecated tag.
141 if (Globals.supportDeprecatedTags())
142 {
143 try
144 {
145 return DeprecatedAIMLParser.processTag(level, userid, tag, this);
146 }
147 catch (UnknownDeprecatedAIMLException e1)
148 {
149 // For now, do nothing (drop down to next).
150 }
151 }
152 // It could also be a non-AIML tag.
153 if (Globals.nonAIMLRequireNamespaceQualification())
154 {
155 // If namespace qualification is required, check for a colon.
156 if (tag.XMLData.indexOf(COLON) == -1)
157 {
158 throw new AIMLProcessorException("Unknown element \"" + tag.XMLData + "\"");
159 }
160 }
161 // But if namespace qualification is not required, don't care.
162 return formatTag(level, tag);
163 }
164 catch (StackOverflowError e)
165 {
166 Log.userinfo("Stack overflow error processing " + tag.XMLData + " tag.", Log.ERROR);
167 return EMPTY_STRING;
168 }
169 }
170
171
172 /**
173 * Adds an input to the inputs list (for avoiding infinite loops).
174 *
175 * @param input the input to add
176 */
177 public void addInput(String input)
178 {
179 this.inputs.add(input);
180 }
181
182
183 /**
184 * Returns the input that matched the <code>pattern</code> associated with this template.
185 *
186 * @return the input that matched the <code>pattern</code> associated with this template
187 */
188 public ArrayList getInputs()
189 {
190 return this.inputs;
191 }
192
193
194 /**
195 * Returns the values captured from the input path by wildcards in the <code>pattern</code>.
196 *
197 * @return the values captured from the input path by wildcards in the <code>pattern</code>
198 */
199 public ArrayList getInputStars()
200 {
201 return this.inputStars;
202 }
203
204
205 /**
206 * Returns the the values captured from the input path by wildcards in the <code>that</code>.
207 *
208 * @return the values captured from the input path by wildcards in the <code>that</code>
209 */
210 public ArrayList getThatStars()
211 {
212 return this.thatStars;
213 }
214
215
216 /**
217 * Returns the values captured from the input path by wildcards in the <code>topic name</code>.
218 *
219 * @return the values captured from the input path by wildcards in the <code>topic name</code>
220 */
221 public ArrayList getTopicStars()
222 {
223 return this.topicStars;
224 }
225
226
227 /**
228 * Sets the <code>inputStars</code> list.
229 *
230 * @param values captured from the input path by wildcards in the <code>pattern</code>
231 */
232 public void setInputStars(ArrayList stars)
233 {
234 this.inputStars = stars;
235 }
236
237 /**
238 * Push <code>inputStars</code> Vector
239 *
240 */
241 public void push()
242 {
243 this.stackStar.push(this.inputStars);
244 }
245
246 /**
247 * Pop <code>inputStars</code> Vector
248 *
249 */
250 public void pop()
251 {
252 setInputStars((ArrayList) this.stackStar.pop());
253 }
254
255 /**
256 * Sets the <code>thatStars</code> list.
257 *
258 * @param values captured from the input path by wildcards in the <code>that</code>
259 */
260 public void setThatStars(ArrayList stars)
261 {
262 this.thatStars = stars;
263 }
264
265
266 /**
267 * Sets the <code>topicStars</code> Vector.
268 *
269 * @param values captured from the input path by wildcards in the <code>topic name</code>
270 */
271 public void setTopicStars(ArrayList stars)
272 {
273 this.topicStars = stars;
274 }
275
276
277 /**
278 * Returns the userid.
279 *
280 * @return the userid
281 */
282 public String getUserID()
283 {
284 return this.userid;
285 }
286
287
288 /**
289 * Returns the botid.
290 *
291 * @return the botid
292 */
293 public String getBotID()
294 {
295 return this.botid;
296 }
297 }