Macneil Shonle
Ankit Shah
Version 1.1
12 March
2003
Committee ClassDictionary provides the structure of the committee, while Log implements a typical Log. These 2 have been made as independent as possible. The Committee is Good-for-nothing while the log may be used as a Travel Log too.
What we want to do is use these 2 different class hierarchies together in the following fashion.
We want every committee and / or its sub-committee to have a log of activities. This log will be populated by members from that particular committee only.
The committee is first populated and then the logs of various people are parsed in. Then it prints out the committee structure, diaries for each committee and money matters of each committee. These amply demonstrate the traversals and the visitors used in the example.
As can be seen, there are links from committee's to person's and from person's to committee's too. However, manual double coding of this is avoided using an aspect. The aspect, updates the person object by setting its belongs to reference to the committee object for the committee he belongs to.
Also, at the time of creating the committee, an empty log is added to each committee object generated.
When a log is parsed in, we only input the name of the person making an entry in the log. Another aspect will use the internal linking and ensure that the activity is added to right committee's log.
At the end of all the parsing, we wish to traverse the input data and print out the logs and the net expenses by each of the committees.
MyCommittee.java
// Structure of a Committee
// author: Ankit Shah
import java.util.*;
import java.io.*;
aspect(ClassDictionary) Committee{
Committee = "Committee: " String
"Chair: " Person
["Vice Chair: " Person]
"Responsibility:" String
["Reports to:" Committee]
["Sub-Committees: " "(" List(Committee)")"]
"Members: ""["List(Person)"]"
"Budget: "Double.
Person = "Name: "String
"Age: "Integer
["Member of: "Committee]";".
List(S)~ { S }.
}
aspect(AspectJ) CommitteeLogging {
// CommitteeLogging Aspect.....
// Adds Logging capability to Committees...........
// author: Ankit Shah
// Temporary variables to retain data between pointcuts
Log tmpLog;
Committee topCommittee;
// Make every committee have a list of Logs
public Diary Committee.diary = new Diary();
// Methods to add and access logs
public void Committee.addLog (Log l) {
if (diary.logs == null) // If diary has not been initiated, initiate it!!!
diary.logs = new Log_List();
diary.logs.add(l);
}
public Iterator Committee.getLogs () {
return diary.logs.iterator();
}
// Pointcuts
pointcut newCommittee(File f) : call(* Committee.parse(..)) && args(f);
pointcut newLog(File f) : call(* Log.parse(..)) && args(f);
pointcut topCommittee(File f) : newCommittee(f) && withincode(* Main.main (..));
// We get the top-most Committee handle here
Committee around(File f) : topCommittee(f) {
Committee comm = proceed(f);
topCommittee = comm;
topCommittee.linkPpltoComm();
return comm;
}
// A new Log has been created. Visit all persons to try and find the person responsible for the log
// Once the person is found, go to the committee he belongs to and attach the log to that committee.
Log around (File f): newLog(f) {
tmpLog = proceed(f);
Person p = topCommittee.gotoPersons(tmpLog.name);
if (p == null) {
System.out.println("Bad Name: " + tmpLog.name + ". Log: " + tmpLog.id + " Discarded");
return null;
}
p.belongsto.addLog(tmpLog);
return tmpLog;
}
}
MyLog.java
// Log.cd
// author: Ankit Shah
// Any general Diary.....
// Wanna use it during your trip to Miami Beach ???
// The Diary has been added last after an attempt to inter-type declare an ArrayList of
// Logs into Committee failed to be supported by the traversals
aspect(ClassDictionary) MyLog {
Diary = "^" List(Log).
Log = "Log" "ID" String
"by" String
"(" List(Activities) ")"
["Approved by: "OfficialTag].
Activities = "Date: "Date
"Desc:"String
["$"Integer]
["(""$"Integer")"]
["Notes: "String]"#".
// Before ppl grumble..... on Miami beach, strolling may not cost neither get you money !!! Though I very much doubt the former
Date = Integer "/"
Integer "/"
Integer.
OfficialTag= "Name: "String
"Dsg: "String
"on: "Date.
// I believe on compiling simultaneously List from other file definition may be used here. If not then..... well I'll come here and add it.
// I believed wrong !! Here is the List.
List(S)~ { S }.
}
// DateToString Aspect....
// author: Ankit Shah
// Adds methods to the date class to print it out in a nice string format
aspect(AspectJ) DateToString
{
// Formatting the date
public String Date.toString () {
return ("" + month + "/" + date + "/" + year);
}
}
CommitteeTraversals.java
// CommitteeTraversals - Repository of all traversals used in the example
// author: Ankit Shah
aspect(Traversal) CommitteeTraversals
{
// Specialized Strategies USED in this example
declare strategy:
allPersons: "intersect(fromCommittee, toPersons, down)";
declare strategy:
allActivities: "intersect(fromCommittee, toActivities, noBelongsto, noReportsto)";
declare strategy:
allCommittees: "intersect(fromCommittee, toCommittee, down)";
declare strategy:
allDiary: "intersect(fromCommittee, toDiary, noBelongsto, noReportsto)";
// Highly Generic Strategies
declare strategy:
noBelongsto: "from * bypassing -> *, belongsto, * to *";
declare strategy:
noReportsto: "from * bypassing -> *, reporstto, * to *";
declare strategy:
nothrudiary: "from * bypassing -> *, diary, * to *";
declare strategy:
down: "intersect(noBelongsto, nothrudiary, noReportsto)";
declare strategy:
fromCommittee: "from Committee to *";
declare strategy:
toPersons: "from * to Person";
declare strategy:
toActivities: "from * to Activities";
declare strategy:
toCommittee: "from * to Committee";
declare strategy:
toDiary: "from * to Diary";
declare strategy:
toExpend: "from * through -> *, expense, * to *";
declare strategy:
toIncome: "from * through -> *, income, * to *";
// Calculate net expense for the committee and its sub-committees
declare traversal:
Integer netExpense() : allActivities(NetSummingVisitor);
// Calculate gross expense for the committee and its sub-committees
declare traversal:
Integer totalExpenses() : allActivities(SummingVisitor);
// Find a particular person whose name is provided
declare traversal:
Person gotoPersons(String name) : allPersons(FindVisitor);
// Visits all committees and prints them out
declare traversal:
void gotoAll() : allCommittees(PrintVisitor);
// Traverses to all Committees and for every person there,
// set its belongsto link to the appropriate committee
declare traversal:
void linkPpltoComm() : allCommittees(LinkPplToCommVisitor);
// Visits all diaries and prints them out.
declare traversal:
void allDiaries() : allDiary(PrintVisitor);
}
Visitor.java
// SummingVisitor
// author: Ankit Shah
import java.util.Iterator;
import edu.neu.ccs.demeter.dj.*;
aspect(TraversalAdvice) NetSummingVisitor
{
int sum = 0;
// Sum up all the expenses and deduct income
void before (Activities a) {
int expense, income;
expense = income = 0;
if (a.expense != null)
expense = a.expense.intValue();
if (a.income != null)
income = a.income.intValue();
sum += expense - income;
}
// Return result
public Object getReturnValue () {
return new Integer(sum);
}
}
aspect(TraversalAdvice) SummingVisitor
{
int sum;
// Sum up all the expenses
void before (Activities a) {
int expense = 0;
if (a.expense != null)
expense = a.expense.intValue();
sum += expense;
}
// return result
public Object getReturnValue () {
return new Integer(sum);
}
}
// PrintVisitor
// This PrintVisitor is really hardcoded to print the Committee and Log dictionaries.
// Ideally this should be generated by DAJ since print is the opposite function of parse
aspect(TraversalAdvice) PrintVisitor
{
void before (Committee c) {
System.out.println("Committee Name: " +c.name);
System.out.println("\tChair: " + c.chair.name);
if (c.vicechair != null) System.out.println("\tViceChair: " +c.vicechair.name);
System.out.println("\tResponsibility: " + c.responsibility);
if (c.reportsto != null) System.out.println("\tReports to: " + c.reportsto.name);
if (c.subcommittees != null) {
Iterator it = c.subcommittees.iterator();
System.out.println("\tSub - Committees: ");
while (it.hasNext())
System.out.println("\t\t" + ((Committee)it.next()).name);
}
if (c.consists != null) {
Iterator it = c.consists.iterator();
System.out.println("\tMembers: ");
while (it.hasNext())
System.out.println("\t\t" + ((Person)it.next()).name);
}
System.out.println("\tbudget: " + c.budget);
}
void before (Diary d) {
if ((d.logs != null) && (d.logs.size() != 0)) {
System.out.println("Diary: ");
Iterator itr = d.logs.iterator();
while (itr.hasNext()) {
Log l = (Log)itr.next();
System.out.println("Log:\tID = " +l.id + "\tBy: " + l.name);
System.out.println("\tActivities: ");
Iterator it = l.log.iterator();
while (it.hasNext()) {
Activities activity = (Activities)it.next();
System.out.println("\t\t" + activity.date + "\t" + activity.activity);
if (activity.expense != null)
System.out.println("\t\t\t\tExpense = $" + activity.expense);
if (activity.income != null)
System.out.println("\t\t\t\tIncome = ($" + activity.income + ")");
if (activity.comments != null) System.out.println("\t\t\t\tNotes: " + activity.comments);
}
if (l.approvedby != null) System.out.println("\tApproved by: " + l.approvedby.name);
}
}
}
}
// FindVisitor
aspect(TraversalAdvice) FindVisitor
{
// Variables
String target;
Person foundTarget;
// Constructor is Parameterized to receive object to be searched
FindVisitor (String name) {
target = name;
foundTarget = null;
}
// Actual Visitor function
void before(Person host) {
if (host.name == null)
return;
if (host.name.equalsIgnoreCase(target))
foundTarget = host;
}
// Return it
public Object getReturnValue () {
return foundTarget;
}
}
// FindVisitor
// author: Ankit Shah
aspect(TraversalAdvice) LinkPplToCommVisitor
{
// For every committee, get a list of ppl belonging to it and
// set the corresponding persons belongsto member to point to
// its committee object
void before(Committee committee) {
committee.chair.belongsto = committee;
if (committee.vicechair != null)
committee.vicechair.belongsto = committee;
java.util.Iterator itr = committee.consists.iterator();
while (itr.hasNext())
((Person)itr.next()).belongsto = committee;
}
}
// CompareVisitor
// author: Ankit Shah
aspect(TraversalAdvice) CompareVisitor
{
// Compare Visitor calls SummingVisitor's net Expense calculator and then compares it with the committees budget
// to flag whether they've exceeded the budget or not.
void before (Committee c) {
double spent = c.netExpense().doubleValue();
if (spent > c.budget.doubleValue())
System.out.println(c.name + " has exceeded the budget by $" + (spent - c.budget.doubleValue()));
}
}
Main.java
// Main.java
// author: Ankit Shah
// Here I admit.. I'm taking help from Prof. Lieberherr's Main.java in the OS example
import java.io.*;
class Main {
public static void main(String[] args) {
try {
// Read in the files and parse them.
// Remember we read in independent logs and not the whole diary !!!
Committee com = Committee.parse(new File(args[0]));
Log logs[];
if (args.length > 1) {
logs = new Log[args.length - 1];
for (int i = 1; i < args.length; i++)
logs[i - 1] = Log.parse(new File(args[i]));
}
// Various visitors called to demonstrate ease of work
// Printing out all committees
System.out.println("Invoking Print Visitor to list all Committee and their Sub-Committees");
System.out.println("=====================================================================");
com.gotoAll();
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
// Printing out all committees and their diaries
System.out.println("Printing Committee-wise Logs");
System.out.println("============================");
com.allDiaries();
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
// Net Expenses so far
System.out.println("\n\n\nInvoking Net Expense Calculator to calculate Net Expenditure by the Committee and their Sub-Committees");
System.out.println("------------------------------------------------------------------------------------------------------");
System.out.println("Net Expense of "+ com.name + " = $" + com.netExpense().toString());
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
// Gross expenses only by sub-committees
System.out.println("Invoking Gross Expense Visitor on each of the sub-committees of " + com.name);
java.util.Iterator it = com.subcommittees.iterator();
while (it.hasNext()) {
Committee sc = (Committee)it.next();
System.out.println("Sub-Committee: " + sc.name + "\tGross Expense = $" + sc.totalExpenses().toString());
}
} catch (Exception e) {
System.err.println("Hi... its me, Ankit"); System.err.println(e);
}
}
}
committee/ - This folder has all the .java files committee/input/ - This folder has all the .input files committee/cls/ - Here all the generated .class files will be placed
committee.input
Committee: "Event Organizing Committee" Chair: Name: "Roger Morris" Age: 49; Vice Chair: Name: "Adrianna Harrison" Age: 37; Responsibility: "Overall Organization of the Event" Sub-Committees: ( Committee: "Finance Sub-Committee" Chair: Name: "Peter Rhodes" Age: 51; Vice Chair: Name: "Alec Martin" Age: 33; Responsibility: "Finance Management" Members: [ Name: "Julianna Castle" Age: 35; Name: "John Grenada" Age: 30; Name: "Heidi McDermott" Age: 25; ] Budget: 15000.00 Committee: "Logistics Sub-Committee" Chair: Name: "Sean Lambert" Age: 26; Responsibility: "Logistic Support" Members: [ Name: "Larry Hopkins" Age: 20; Name: "Harry Blacksmith" Age: 19; Name: "Mark Mills" Age: 22; ] Budget: 48000.00 ) Members: [ Name: "Greame Hick" Age: 32; Name: "Laura Smith" Age: 40; ] Budget: 63000.00
log1.input
Log ID "MM001" by "Mark Mills" ( Date: 2/15/2003 Desc: "Light System" $ 1500 Notes: "To be Setup by Next Weekend" # Date: 2/15/2003 Desc: "Projector Setup" $ 700 # ) Approved by: Name: "Sean Lambert" Dsg: "Chair, Logisitics Sub-Committee" on: 2/17/2003
log2.input
Log ID "HB001" by "Harry Blacksmith" ( Date: 2/14/2003 Desc: "Leasing out Banner Space" ($ 2000) Notes: "3 Banner Spaces to Coca Cola" # ) Approved by: Name: "Sean Lambert" Dsg: "Chair, Logisitics Sub-Committee" on: 2/17/2003
log3.input
Log ID "SL001" by "Sean Lambert" ( Date: 2/17/2003 Desc: "Progress Report Sent to Chair" Notes: "Copies of MM and HB's Logs enclosed" # Date: 2/15/2003 Desc: "Finance Report Sent to Finance Sub-Committee" # ) Approved by: Name: "Greame Hick" Dsg: "Member, Event Organizing Committee" on: 2/18/2003
log4.input
Log ID "JC001" by "Julianna Castle" ( Date: 2/17/2003 Desc: "Re-imbursed Logistics Sub-Committee" Notes: "Amt is $200.00" # Date: 2/17/2003 Desc: "Payroll" $ 3000 # ) Approved by: Name: "Alec Martin" Dsg: "Vice Chair, Finance Sub-Committee" on: 2/18/2003
$ pwd committee/ $ xajc -d cls/ MyCommittee.java MyLog.java CommitteeTraversals.java Visitors.java Main.java Initiating XAspects Compiler... XAspects used: 11 From 5 source files Initializing Compilation Environment... Aspects being sent to appropriate plugins Generating AspectJ code - Pass 1 --- WARNING!!! --- MyCommittee.java: Package Name / Imports / Modifiers / Inheritence info have no meaning for ClassDictionary Type Aspect. Will be ignored Compiling AspectJ code - Pass 1 Generating AspectJ code - Pass 2 Compiling AspectJ code - Pass 2 Writing Output files XAJC Completed with 0 Errors; 1 Warnings. --- Alternatively if you do not use the xajc script --- $ java edu.neu.ccs.xaspects.XAJC -d cls/ MyCommittee.java MyLog.java CommitteeTraversals.java Visitors.java Main.java should give you same comments as above. $ cd cls $ java Main ../input/committee.input ../input/log1.input ../input/log2.input ../input/log3.input ../input/log4.input
Invoking Print Visitor to list all Committee and their Sub-Committees ===================================================================== Committee Name: Event Organizing Committee Chair: Roger Morris ViceChair: Adrianna Harrison Responsibility: Overall Organization of the Event Sub - Committees: Finance Sub-Committee Logistics Sub-Committee Members: Greame Hick Laura Smith budget: 63000.0 Committee Name: Finance Sub-Committee Chair: Peter Rhodes ViceChair: Alec Martin Responsibility: Finance Management Members: Julianna Castle John Grenada Heidi McDermott budget: 15000.0 Committee Name: Logistics Sub-Committee Chair: Sean Lambert Responsibility: Logistic Support Members: Larry Hopkins Harry Blacksmith Mark Mills budget: 48000.0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Printing Committee-wise Logs ============================ Committee Name: Event Organizing Committee Chair: Roger Morris ViceChair: Adrianna Harrison Responsibility: Overall Organization of the Event Sub - Committees: Finance Sub-Committee Logistics Sub-Committee Members: Greame Hick Laura Smith budget: 63000.0 Committee Name: Finance Sub-Committee Chair: Peter Rhodes ViceChair: Alec Martin Responsibility: Finance Management Members: Julianna Castle John Grenada Heidi McDermott budget: 15000.0 Diary: Log: ID = JC001 By: Julianna Castle Activities: 2/17/2003 Re-imbursed Logistics Sub-Committee Notes: Amt is $200.00 2/17/2003 Payroll Expense = $3000 Approved by: Alec Martin Committee Name: Logistics Sub-Committee Chair: Sean Lambert Responsibility: Logistic Support Members: Larry Hopkins Harry Blacksmith Mark Mills budget: 48000.0 Diary: Log: ID = MM001 By: Mark Mills Activities: 2/15/2003 Light System Expense = $1500 Notes: To be Setup by Next Weekend 2/15/2003 Projector Setup Expense = $700 Approved by: Sean Lambert Log: ID = HB001 By: Harry Blacksmith Activities: 2/14/2003 Leasing out Banner Space Income = ($2000) Notes: 3 Banner Spaces to Coca Cola Approved by: Sean Lambert Log: ID = SL001 By: Sean Lambert Activities: 2/17/2003 Progress Report Sent to Chair Notes: Copies of MM and HB's Logs enclosed 2/15/2003 Finance Report Sent to Finance Sub-Committee Approved by: Greame Hick ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Invoking Net Expense Calculator to calculate Net Expenditure by the Committee and their Sub-Committees ------------------------------------------------------------------------------------------------------ Net Expense of Event Organizing Committee = $3200 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Invoking Gross Expense Visitor on each of the sub-committees of Event Organizing Committee Sub-Committee: Finance Sub-Committee Gross Expense = $3000 Sub-Committee: Logistics Sub-Committee Gross Expense = $2200
XAspects Project Home Page, <http://www.ccs.neu.edu/research/demeter/xaspects>.
|
Author: Ankit Shah. Copyright © 2003. All rights reserved. |