Context Toolkit: Tutorial: Context Interpreters
Context interpreters are responsible for interpreting or converting context
from one form to another. They maintain no state (although they could)
but simply take context in and output new context information. This can
be as simple as taking in a name and returning the corresponding email
address. It could be more complex and take in the number of people in a
room, the relative gaze directions, the audio level, and the time of day,
and return whether or not a meeting was occurring. I will first discuss
the features of context interpreters and then talk about how to actually
use them. Also take a look at the source
code documentation for the Interpreter class.
Features
A context interpreter is responsible for converting between types of context.
Context interpreters inherit from BaseObject,
so inherit the generic
communications functionality from it. In addition, context interpreters
have the following features: descriptions and interpretations.
Description
All context interpreteters can provide descriptions of themselves to inquiring
components. The description includes the types of context that can be input
to the interpreter and the types of context the interpreter outputs.
Interpretation
The point of context interpreters is to interpret incoming context. Other
components can send context information to an interpreter and (synchronously)
receive an interpretation of that context.
How to Use It
In this section, I'll discuss how to use existing interpreters and then
how to create new interpreters.
Using Existing Interpreters
To use the existing context interpreters in the context.arch.interpreter
package, execute the interpreter: "java context.arch.interpreter.I???"
with no parameters. The parameter list for the interpreter should be printed
out.
In general, the minimum parameter will be a port number for the
interpreter to receive communications on (although the interpreter will
likely have a default). For example, the IButton2Name interpreter, which
converts between an iButton id and a name, has the following parameter
list: [port] . The [...] means the parameter is optional.
An application or context component can communicate with the context
interpreter using the BaseObject class. It can only ask the interpreter
to interpret some context.
When talking to an interpreter, or any context component, you
must have the hostname, port number, and id of the interpreter. The id
for an interpreter is the classname without the preceding 'I'. For example,
to communicate with an instance of IIButton2Name, the id is "IButton2Name".
Asking for Interpretation
The askInterpreter
method has the following prototype:
public DataObject askInterpreter(String remoteHost,
int remotePort,
String remoteId,
AttributeNameValues data)
The data parameter contains the context data to be interpreted. Example
code showing how to use the IIButton2Name interpreter running on the localhost
on port 8888:
AttributeNameValues data = new AttributeNameValues();
data.addAttributeNameValue(IIButton2Name.IBUTTONID, "ABCDEF");
DataObject interpreted = askInterpreter("localhost",8888,IIButton2Name.CLASSNAME,data);
AttributeNameValues newData = new AttributeNameValues(interpreted);
System.out.println("new data is: "+newData);
Creating New Interpreters
The easiest way to create a new interpreter, is to use an existing interpreter
from the context.arch.interpreter
package as a starting point. You can also look at the basic Interpreter
class documentation.
When you want to create a new interpreter, there are a set of
steps that you must take:
-
set the CLASSNAME constant
-
create the interpreter's constructor
-
specify the interpreter's incoming attributes
-
specify the interpreter's outgoing attributes
-
implement the actual interpretation
The IIButton2Name class code will be referred to throughout this subsection.
The code is available here.
Setting the CLASSNAME constant
The id of an interpreter is set to the type of interpreter. Specifically,
it is set to CLASSNAME. It allows other components to easily identify the
interpreter. Example code for the SUser class follows:
/**
* Name of interpreter
*/
public static final String CLASSNAME = "IButton2Name";
Creating the Interpreter's Constructor
The constructor must call the Interpreter class' constructor, usually using
this
constructor that specifies the interpreter port number. The constructor
should set the id using BaseObject's
setId
method. Finally, it should do any setup for performing interpretation.
Example code from the IIButton2Name class follows:
/**
* Constructor that creates the interpreter at the given port. It sets
* the id of the this interpreter to CLASSNAME.
*/
public IIButton2Name(int port) {
super(port); // call constructor
setId(CLASSNAME); // set id
hash.put("16AC850600000044", ANIND); // set up for interpretation
hash.put("166F3C060000003E", SALBER);
hash.put("16F78206000000C3", ABOWD);
hash.put("161B4206000000B5", KHAI);
hash.put("1681400600000048", BROTHERT);
hash.put("16A640060000007B", JMANKOFF);
hash.put("16C78708000000E9", RJO);
hash.put("16D78C08000000C2", DNGUYEN);
hash.put("16748D080000000A", MGP);
hash.put("165D8E0800000064", FUTAKAWA);
hash.put("16148B0800000055", ISHIGURO);
hash.put("16A58E08000000B7", BAS);
hash.put("16CF8F0800000076",KENT);
hash.put("16ED870800000090",VISHAL);
}
Specifying the Interpreter's Incoming Attributes
The incoming attributes of the interpreter must be specified using the
Interpreter class' setInAttributes
method. An interpreter must implement this method by simply returning an
Attributes object that contains the incoming attributes of the interpreter.
Example code from the IIButton2Name class follows:
/**
* Sets the incoming attributes for the interpreter. It has only
* one: IBUTTONID.
*
* @return the incoming attributes for this interpreter
*/
protected Attributes setInAttributes() {
Attributes atts = new Attributes();
atts.addAttribute(IBUTTONID);
return atts;
}
Specifying the Interpreter's Outgoing Attributes
The outgoing attributes of the interpreter must be specified using the
Interpreter class' setOutAttributes
method. An interpreter must implement this method by simply returning an
Attributes object that contains the outgoing attributes of the interpreter.
Example code from the IIButton2Name class follows:
/**
* Sets the outgoing attributes for the interpreter. It has only
* one: USERNAME.
*
* @return the outgoing attributes for this interpreter
*/
protected Attributes setOutAttributes() {
Attributes atts = new Attributes();
atts.addAttribute(USERNAME);
return atts;
}
Implementing the Interpreter's Interpretation
Not much that I can say here. Each interpreter designer can choose their
own method for doing the interpretation. It must do the interpretation
using the Interpreter class'
interpretData
method. The context to interpret is received in an AttributeNameValues
object and the method outputs the interpreted context is an AttributeNameValues
object. The IIButton2Name class created a hashtable to store a lookup table
of iButton ids and user names. When an iButton id comes in, it returns
the corresponding user name. Example code from the IIButton2Name class
follows:
/**
* This method performs the actual interpretation of this component.
* It takes an iButton id and returns a user name.
*
* @param data AttributeNameValues containing data to be interpreted
* @return AttributeNameValues object containing the interpreted data
*/
protected AttributeNameValues interpretData(AttributeNameValues data) {
String buttonid = (String)data.getAttributeNameValue(IBUTTONID).getValue();
String name = (String)hash.get(buttonid);
if (name == null) {
return null;
}
AttributeNameValues atts = new AttributeNameValues();
atts.addAttributeNameValue(USERNAME,name);
return atts;
}
Back to the Table
of Contents.
Back to the Context
Servers section.
Forward to the Helper
Classes section.
Up to the Context
Components section.
Context Toolkit
Home
Last Modified: Feburary 11, 2000
Comments to: anind@cc.gatech.edu