Step 03: Database Access - Ariadne Spoken Dialogue System

advertisement
Step 04: Java Databases
The dialogue manager needs to be told which referring expressions can be resolved by
database lookup. In step 3, we showed how this can be done using an MS Access
database. This step illustrates how the concepts in the ontology can be mapped onto java
classes. This technique allows you to instantiate a set of objects in Java and to refer to
them using natural language.
The difference between representing objects in the domain in databases and in java
classes lies in the fact that it is easier to represent and change state in Java classes than it
is in databases.
To get an idea, open the file <ariadne dir>/data/tutorial/step04/step04.adl
and take a look at the constructs that start with the database keyword. Also, take a
look at edu.cmu.cs.is.step04.Step04.java
Database Conversion Rules
When comparing the adl file from this step to the one from the last step, you will see a lot
more database conversion rules. The structure of the additional database conversion rules
is the same, except that the query protocol and the query language both are called ‘jpkg’
(short for Java Package) instead of ‘dao’ and ‘sql’, respectively. This means that the
internal java protocol and the internal query language should be used to retrieve objects.
In other words, the fact that java objects are queried instead of Sql databases is
transparent to the dialogue manager.
Note to C++ programmers: You can always program your own query protocol and
query language to access databases. How this is done can be learned from the arditf_jpkg,
arditf_dao and arditf_sql packages.
Java Implementation
Java provides generic mechanisms to query and set properties of objects. Called
JavaBeans, this technique requires each compliant object to support two methods for
each property of type T, namely
public T getProperty() ;
public void setProperty(T t);
Another mechanism, called reflection, allows classes to determine at runtime which
methods are defined for an object. These two techniques are at the heart of the database
access to java objects. The idea is to consider a class definition of a JavaBean as a
database definition with one table (representing the objects). The table contains the fields
that can be accessed by the JavaBeans methods. For example, if we have a class
definition along the lines of
public class Lamp {
public void
public void
public void
setOnOff(bool);
setBrightness(int);
setName(String);
public bool
getOnOff();
public int
getBrightness();
public String getName();
};
we consider this equivalent to a SQL database definition named ‘Lamp’ which contains
one table, also called ‘lamp’, which in turn contains the four fields OnOff, Brightness
and Name, of types bool, int and string, respectively. The
DialoguePackageAdapter class provides generic mechanisms to query the objects, you
just need to tell the query method where your objects are stored and how they can be
accessed. This is what the method declaration
abstract Object[] getObjects(String databaseName,String tableName);
is for. It ensures that for each database and table in that database, the objects are returned.
In the example implementation in Step04Package, the start() method will create all the
objects for each database and store them in an array. The getObjects() method will then
simply return the array of objects for the requested database and requested table.
Another consideration is the declaration of the properties that should be accessible
through database access. Let’s say our class Lamp from above has an additional method
getInternalName() which returns some internal name of the lamp for bookkeeping
purposes. This property should not be exposed to the dialogue system or data access from
outside. In order to allow such data hiding, you will have to declare all the databases,
tables and fields that can be accessed from outside and pass these declarations to the
constructor of the DialoguePackageAdapter. This is similar in principle to the way in
which methods are declared (see step02). Let’s say we have two databases, obe storing
lamps, and one storing media players such as TVs and radios. In our example, to allow
the dialogue manager to access the three properties in class Lamp, you could do
something along the lines of
private static final String[]
{ "Lamps",”Players” };
databaseNames_ =
private static final String[][] entryNames_ = {
{ "Name","OnOff","Brightness" },
{ "Name","OnOff","Volume", "Treble", "Bass }
};
private static final String[][] entryTypes_ = {
{ "string","boolean","int" },
{ "string","boolean","int","int","int","int" }
};
This declares the availability of two databases called Lamps and Players, each with one
table, also called Lamps and Players. The table Lamps has the three fields OnOff, Name
and Brightness of types bool, string and int. The table players has the additional fields
Volume, Treble and Bass of type int. You can then construct the
DialoguePackageAdapter class as follows.
public Step04Package() {
super(databaseNames_,entryNames_,entryTypes_,methods_,undos_);
}
How to make your life easier
Of course, you can always use the import statement introduced in the last step to generate
lexical grammar rules from databases. Again, it is transparent if the database accessed is
SQL or Java or even your own database format and protocol, provided you implement the
necessary stub classes. See step04.adl for the usage of the import statement.
Download