We are taking an incremental approach to adaptive software development in this
course: In hw 1 you read and analyzed Java programs, in
hw 2 you filled in missing information in Java programs that use DJ,
in hw 3 you modified programs that use class dictionaries
(similar to XML schemas) and a tiny bit of DemeterJ (the weaving feature
offered by Class1 { {{ ... }} } Class2 { {{ ... }} } ... ).
Now in hw 4 you write a simple Java program using DJ and a
tiny bit of DemeterJ (the weaving feature) from scratch but
you are given the class dictionary.
This homework has two parts: The first part is the Laboratory Guide
and the second part is a simple UNIX shell. The Laboratory Guide
introduces you to DemeterJ (formerly called Demeter/Java) but most
of what you learn will help you to write Java Programs with DJ
and a tiny bit of DemeterJ. So when you go through the Laboratory Guide,
focus on class dictionaries and how you would express the
adaptive programs you encounter directly using DJ without using the
adaptive programming language of DemeterJ.
Name substitution throughout Laboratory Guide and other documents:
Demeter/Java -> DemeterJ
demjava -> demeterj
THEMES:
Laboratory Guide:
An interesting example of adaptive programming in Java
(Lab Guide).
Simple Unix shell in DJ
with weaving and code generation from class dictionary by DemeterJ.
This second part is significantly more challenging than the
the previous homeworks. If you cannot do it completely,
apply the Growth Plan Pattern and
turn in the last phase you could complete.
PURPOSE: See DemeterJ in action. Study an application of the concepts
covered so far in the context of a Java application.
Tasks to be done:
Read and work through the Laboratory Guide using DemeterJ
and hand in all
files modified.
Browse through the DemeterJ User's Guide available from the
DemeterJ and AP-Studio Resources page
http://www.ccs.neu.edu/research/demeter/DemeterJava/.
Focus on class dictionaries and pnly a little bit on the adaptive programming language of DemeterJ.
Browsing the User's Guide
will help you to better understand the Laboratory Guide available
from the same resource page.
The purpose of this laboratory exercise is to see adaptive
programming in operation in the Java world.
Corrections to the Laboratory Guide:
None at the moment.
Please send mail to
lieber@ccs.neu.edu johan@ccs.neu.edu
if you find something not clear in the Laboratory Guide.
From a happy user of the Demeter/C++ lab guide. The DemeterJ
Laboratory Guide is a translation of the Demeter/C++ Lab Guide.
Hi Crista:
I just finished working through the Demeter Lab Guide and already feel
a lot more comfortable with Demeter. The Lab Guide is concise, clear
and written with a great deal of empathy for the user. Congratulations
for doing such an excellent job with the Lab Guide!
...
PART 2:
We simulate a few Operating System file management commands
by building our own data structures that represent what the commands do.
You are not allowed to use Runtime and Process
objects in this homework. Your program should be able to handle
inputs like:
mkdir a
mkdir b
cd a
mkdir c
mkdir d
cd d
mkdir x
cd ..
cp -r d e
cd ..
echo "before du"
du
find . -name x -print
and produce the same output as UNIX, except that the disk usage
command du prints
only the file structure and no sizes.
More precisely, your program should be able to execute a list
of commands as defined by the Extended Backus-Naur-Form (EBNF) grammar below
(in Demeter class dictionary notation):
It is recommended that you start with primitive commands like
CreateEmptyFile, MakeDirectory, ChangeDirectoryUp, ChangeDirectoryDown.
Hint: Try to use the CopyVisitor of DemeterJ to do the copying:
CompoundFile{
traversal toAll(UniversalVisitor) { to *;}
public CompoundFile copy() {{
CopyVisitor cv = new CopyVisitor(CompoundFile.class);
this.toAll(cv);
return (CompoundFile) cv.get_return_val();
}}
}
For example, for the input:
mkdir a
mkdir b
cd a
mkdir c
mkdir d
cd ..
du
your program should produce the output:
./a/c
./a/d
./a
./b
But you should write your program in such a way that it would be
easy to add the rest of the commands.
Note that
RecursiveCopy,
DiskUsage and
Find
have significant common behavior that you should factor out.
You should focus your efforts on correct inputs as described by the above
grammar. It is not important that you give a good error message
in case of a syntax error. But your program needs to handle correct inputs
correctly.
To represent your file system you may want to use
Java classes similar to the ones described below.
Solution approach:
Use the data-binding approach of DemeterJ to generate
Java class definitions and parser and pretty printer from
a schema (class dictionary).
Start with the DemeterJ program in
$SD/hw/4/os
and add more behavior files to the program.
For illustration purposes, I constructed a FileSystem-object
manually and I printed it out with the display method.
Use DemeterJ in the limited way as shown in the previous
homework:
(e.g. in $SD/hw/3/onlyDJ-average-default-list).
Write your schema in a os.cd file. Define all your visitor classes
in your .cd file and make them inherit from class Visitor.
Put "import edu.neu.ccs.demeter.dj.*;" as the first line in
your .cd file. Define the parts of your visitors in the
.beh file or in the
.cd file. Use the DemeterJ User Manual
http://www.ccs.neu.edu/research/demeter/DemeterJava/UserManual/node2.html
to learn to write class dictionaries for DemeterJ. Specifically, the LL(1)
section
"How to Make a Class Dictionary LL(1)"
is important.
Write your behavior files using the pattern:
A {
{{
// in plain Java:
// any additional instance variables
// any additional methods
}}
}
B {
{{
// in plain Java:
// any additional instance variables
// any additional methods
}}
}
// etc.
In the Java methods you use DJ to program adaptively.
Note that if a method needs additional instance
variables, you may introduce them in your behavior file
as shown above. This does not allow you to parse or print
those variables. If you need that capability (which is rare), you need
to introduce your instance variables in your .cd file.
Practice good separation of concerns. Each requirement of the form:
"Implement Behavior X" should be ideally implemented in one behavior file.
When the requirement changes, we should ideally only have to change
the corresponding behavior file.
DemeterJ generates several Visitor classes from the class dictionary.
If you want to use those visitors you need to know a little bit
of DemeterJ behavior file syntax. If you want to have a print method
for class "Commands", create a file print.beh:
Commands {
void print() to * (PrintVisitor);
}
and add print.beh to the list of behavior files in your *.prj file.
The meaning of the above method is: traverse to all objects reachable
from the current Commands-object and use the PrintVisitor as visitor.
The directory
$SD/hw/4/visitor-usage
contains examples how to use the various visitors.
The detailed documentation is in the DemeterJ user manual.