AFunctor Documentation

Installation

Follow these instructions.

Overview

AFunctor (for lack of a better name) is a translator of boolean Aocl expressions.  It starts with two class diagrams, Top and Bottom, that are related by a refactoring R such that Bottom=R(Top) and Top=R-1(Bottom).  If K1 is an Aocl constraint of Top, its corresponding constraint for Bottom is R(K1); and if K2 is an Aocl constraint of Bottom, its corresponding constraint for Top is R-1(K2).   AFunctor performs these refactorings/translations.

AFunctor takes 4 inputs:
Each file is discussed in turn.  After that, I'll briefly explain:

Union of Class Diagrams

Suppose Top and Bottom are the diagrams in figures (a) and (b) below, taken from Gheyi et al 2006.  Create the union of Top and Bottom; such a union is shown in (c).  Remember: if the same class exists in Top and Bottom, it must be given the same name!  This also applies for names of class attributes and names of associations!  To the right of (c) is a CDSpec declaration of the union.  Note that unique names are given to associations and classes, and fields of each class must have unique names.  This example doesn't use inheritance, but  subclassing relationships can exist. Note that the ID field of tuples is not specified in CDSpec declarations, although an ID field is added when a cdspec file is translated to a database schema.  Further, documentation on writing CDSpecs is found here.






classDiagram GheyiSplit.


table(Bank,[name,vfield]).
table(Account,[accNum:int]).
table(Vector,[vfield]).

assoc(bv,Bank,bank,BLACK_DIAMOND,Vector,b,BLACK_DIAMOND).
assoc(av,Vector,a,BLACK_DIAMOND,Account,account,BLACK_DIAMOND).
assoc(ba,Bank,of,BLACK_DIAMOND,Account,acc,NONE).




CSV Diagram Difference Table

A CSV file, GheyiSplit.diff.csv, declares how to convert the union diagram back into Top and Bottom.  The contents of this file is shown in HTML below, in normal text form and prettyprinted, where the columns are:
Each row of the table declares a virtual class, a virtual association, or a virtual field in the designated diagram (TorB).  For example, the first 3 rows below indicate that the virtual elements of Top are the Vector class and the vb and av associations.  The last two rows indicate that the ba association is virtual in Bottom, and so is the vfield of Bank.  The order in which rows are defined in this table is not important.  Also if a class is declared virtual, that means that the value for every non-virtual field must be computed.  A virtual class can have virtual attributes (whose values are computed from existing computed attribute values).

TorB
CorA
name
field
'Notes'
T
C
Vector

Vector table is computed in top
T
A
vb

association bv is computed in top
T
A
av

association av is computed in top
B
A
ab

association ab is computed in bottom
B
C
Bank
field
bottom Bank has virtual field vfield


The Program AFunctor.First

The contents of GheyiSplit.cdspec.pl and GheyiSplit.diff.csv files are produced by hand.  Place them in a directory, GhehiSplit, whose sole contents are GheyiSplit/GheyiSplit.cdspec.pl  and  GheyiSplit/GheyiSplit.diff.csv.  And then run:
> ls GheyiSplit
GheyiSplit.diff.csv GheyiSplit.cdspec.pl
 
>java AFunctor.First GheyiSplit

AFunctor.First produces files GheyiSplit.extra.csv and GheyiSplit.update.csv, for you to use/complete in the next steps, provided of course that no errors were found.  It also generates PNG files, Top.class.png, Bottom.class.png, and their union,  GheyiSplit.class.png***.  See if the generated figures are what you expect.  If errors are reported, follow their leads to correct errors. 

Normally, .extra.csv will have linkA operations, where A is the name of an association or its dual (A_) for each BLACK_DIAMOND link.  The association that connects Bank to Vector will have two such links:
Initial csv files look like below.  The next sections explain both.

GheyiSplit.update.csv
GheyiSplit.extra.csv
TorB,fname,input,output,set,Notes
T,vfield,Bank,Str,xxx,
T,vfield,$Bank,$Str,xxx,
T,ab,Account,$Bank,xxx,
T,ab,$Account,$Bank,xxx,
T,linkab,Account,Bank,xxx,
T,ab_,Bank,$Account,xxx,
T,ab_,$Bank,$Account,xxx,
B,$Vector,Void,$Vector,xxx,
B,vfield,Vector,Str,xxx,
B,vfield,$Vector,$Str,xxx,
B,vb,Vector,$Bank,xxx,
B,vb,$Vector,$Bank,xxx,
B,linkvb,Vector,Bank,xxx,
B,vb_,Bank,$Vector,xxx,
B,vb_,$Bank,$Vector,xxx,
B,linkvb_,Bank,Vector,xxx,
B,av,Account,$Vector,xxx,
B,av,$Account,$Vector,xxx,
B,linkav,Account,Vector,xxx,
B,av_,Vector,$Account,xxx,
B,av_,$Vector,$Account,xxx,

TorBorTB,fName,input,output,arrowtype,Notes
T,linkab,Account,Bank,noargs,
B,linkvb,Vector,Bank,noargs,
B,linkvb_,Bank,Vector,noargs,
B,linkav,Account,Vector,noargs,

***Generally, PNG files are not generated.  To enable PNG generation, create a file PngOn in the directory in which you run AFunctor.First.  When you want to turn PNG generation off, delete the PngOn file or simply rename it to PngOff.

An Allegory Category for this example is shown below.  There is a domain for each type of tuple (Bank,Vector,Account) and a domain for each type of table ($Bank,$Vector,$Account).  Some of the arrows between domains are shown; most operations on tables are not depicted (like field getters and setters).  The Aocl package for this cdspec is created by Meta4, yet another tool.




CVS Update Table

Here's how AFunctor translation works.  For any given Aocl expression, each operation on Top is translated to the corresponding operation (single or compound) on Bottom, and vice versa.  A select on a table in Top is translated to a select on the corresponding table in Bottom, and vice versa; a traversal of an association in Top is translated to a traversal of the corresponding association in Bottom, and so on. Only when a concrete class in Top translates to a virtual class in Bottom, when a traversal of a concrete association in Top translates to a virtual association in Bottom, and accessing a concrete field in Top translates to an access of a virtual field in Bottom, and vice versa, do to you have to specify a translation. All .update.csv tables have these columns:
When you run AFunctor.First, an initial .update.csv table is produced, in this case the table below:

GheyiSplit.update.csv
TorB,fname,input,output,set,Notes
T,vfield,Bank,Str,xxx,
T,vfield,$Bank,$Str,xxx,
T,ab,Account,$Bank,xxx,
T,ab,$Account,$Bank,xxx,
T,linkab,Account,Bank,xxx,
T,ab_,Bank,$Account,xxx,
T,ab_,$Bank,$Account,xxx,
B,$Vector,Void,$Vector,xxx,
B,vfield,Vector,Str,xxx,
B,vfield,$Vector,$Str,xxx,
B,vb,Vector,$Bank,xxx,
B,vb,$Vector,$Bank,xxx,
B,linkvb,Vector,Bank,xxx,
B,vb_,Bank,$Vector,xxx,
B,vb_,$Bank,$Vector,xxx,
B,linkvb_,Bank,Vector,xxx,
B,av,Account,$Vector,xxx,
B,av,$Account,$Vector,xxx,
B,linkav,Account,Vector,xxx,
B,av_,Vector,$Account,xxx,
B,av_,$Vector,$Account,xxx,

Each row with xxx is to be replaced with the String replacement of the designated function.  I'll show and explain a few translations below -- you must do the rest.  (This example has been fully worked out -- see me for details).  The first row (T,vfield,Bank,str) saysTop vfield:Bank->Str is a function that translates a Bank tuple to a vfield value, a string.  The notes in red says replace a Top vfield reference with "linkvb_().vfield"  to produce the corresponding expression in Bottom.


GheyiSplit.update.csv

TorB,fname,input,output,set,Notes
T,vfield,Bank,Str,linkvb_().vfield,
T,vfield,$Bank,$Str,vb_().vfield(),
T,ab,Account,$Bank,av().vb(),
T,ab,$Account,$Bank,av().vb(),
...
B,$Vector,Void,$Vector,$Bank.to$Vector(),
start with the Bottom Bank tuple and follow it to is Vector tuple to get value of vfield
start with a table of Bottom Bank tuples, follow vb_() to a table of Vector tuples, and apply vfield() to produce a $Str table
start with a Bottom Account tuple, follow av() association then vb() association to produce a table of Bottom Bank tuples.
same reasoning as above
Take any table of Bottom Bank tuples and apply a to$Vector function to produce the corresponding $Vector tuples


The only "odd" part in this translation is in the last row.  Remember: Bank tuples are in 1:1 correspondence with Vector tuples.  As the $Vector table is computed in Top, the expression that computes it is $Bank.to$Vector().  That is start with any table of Bank tuples and apply the function to$Vector:$Bank->$Vector to convert the input $Bank table to its corresponding $Vector table.  This function, to$Vector, is an operation that you need to add to the Top universe.  Given a Top $Bank table, to$Vector literally computes the virtual $Vector table***.   And not surprising, there is a corresponding function, namely to$Bank: $Vector->$Bank, which takes the $Vector table and right-semijoins it with the full $Bank table.    The theorems associated with this table are identities:

for each $Bank subtable $b:    $b = $toBank( to$Vector( $b ))     and  for each $Vector subtable $v:    $v = $toVector( to$Bank( $v ))

So as you progressively remove "xxx" translations from the .update.csv file, make a note of the new operations that you need to add to Top and Bottom.  The signatures of these operations are defined in the .extra.cvs operations table, discussed next.

Here is something I noticed.  I followed the above process when creating my solutions.  What I eventually realized is that instead of inventing new operations, I simply use the existing operations (in Top and Bottom) to express the translations.  So instead of translating Top $Vector to $Bank.to$Vector (requiring me to add a to$Vector operation to Top), I henceforth simply used $Bank.b(), as b() is an operation that exists in Top now (because of the Union diagram).  In this way, very few NEW operations need to be added.  Only the virtual operations (and virtual tables) have to be implemented on each side.  If you don't immediately see this, you will.  Trust me.


CSV Extra Operation Table DON FROM HERE

Normally each concrete class of (a) maps to a concrete class of (b); the same for concrete fields and associations, and vice versa.  Only when a concrete element maps to a virtual/computed element must an expression be defined to compute the virtual element (class, field, or association) that is missing.   This may introduce new operations. The signature of each new operation must be defined in the .extra.csv table whose columns are:
Things you should know:
TorBorTB
operation
input
output
arrowType
Notes
T
makeVector
Void
$Vector
noargs
this operation computes the Vector table from existing Top data
T
vb_
$Bank
$Vector
noargsgiven a table of Bank tuples, compute the right semijoin with the $Vector table
T
vb_
Bank
$Vector
noargs
given a single Bank tuple, compute its associated table of Vector tuples
T
toBank
Vector
Bank
noargsgiven a Vector tuple, compute its corresponding Bank tuple
T
vb
Vector
$Bank
noargs
given a single Vector tuple, compute its associated table of Bank tuples
T
vb
$Vector
$Bank
noargs
given a table of Vector tuples, compute its corresponding table of Bank tuples
T
av
$Account
$Vector
noargs
given a table of Account tuples, compute the right semijoin with the $Vector table
T
av
Account
$Vector
noargsgiven a single Account tuple, its associated table of Vector tuple
T
av_
$Vector
$Account
noargsgiven a table of Vector tuples, compute the right semijoin with the $Account table
T
av_
Vector
$Account
noargsgiven a table of Vector tuples, compute the right semijoin with the $Account table
T
toVector
Account
Vector
noargs
given a single Account tuple, compute its corresponding Vector tuple
B
ab
$Account
$Bank
noargs
given a table of Account tuples, compute the right semijoin with the $Bank table
B
ab
Account
$Bank
noargs
given a single Account tuple, its associated table of Bank tuples
B
ab_
$Bank
$Account
noargs
given a table of Bank tuples, compute the right semijoin with the $Account table
B
ab_
Bank
$Account
noargs
given a single Bank tuple, its associated table of Account tuples
B
linktoB
Bank
Account
noargs
given a single Bank tuple, follow the 'b' association to its corresponding Account tuple

You may have noticed that every association has 2 roles, like in Top, "of" and "accs".


In the above table, each role corresponds to two functions in Aocl:
So this is a total of 4 functions per association that need to be defined (2 for one direction, another 2 for the dual).

What AFunctor Produces

Given the above file inputs (union class diagram, CSV diagram difference table, CSV extra operation table, and CSV Update table), AFunctor generates Java packages.  Two are source code (named Top and Bottom), and another two packages are test packages (named Top and Bottom).  Any class diagram element that you declare to be computed, you must define an expression using existing (like select, count, traverse an existing association) operations or extra operations (as defined in the above table), to compute the value/relationships of that element.  AFunctor produces a set of files that you need to complete to enter these expressions.  At which point, you can run the generated test files for parsing, one-way-translation, and round-tripping to see how well your translators (aka functor) works.

How to Run AFunctor

Let R be the name of a refactoring.  Create a directory R with the following 4 files:
Make sure that AFunctor.jar is on your classpath and from the command line type:
> java AFunctor.Main R
Which tells AFunctor that the CDSpec file is R/R.cdspec.pl, the difference table is R/R.diff.csv, and so on. In the directory that you ran AFunctor, you'll find an AAOutput directory is created that contains all of the generated source described above

How to Build Your Translator

You need to:
  1. Create a NetBeans project that is NOT under version control -- this is important!  NetBeans goes crazy when you perform the next steps when the project is under version control,
  2. Add to this project the AFunctor.jar and MDELite9.1.jar,
  3. The newly created project has a src directory -- you can delete the subdirectories under this directory so that src/ is empty,
  4. Copy the contents of AAOutput/src to src (that is AAOutput/src becomes the src directory of the new project),
  5. Copy the contenst of AAOutput/test to src (that is AAOutput/test becomes the test directory of the new project),
  6. By now, NetBeans will have automatically have compiled all src/ and test/ files.  There should be no compilation errors (otherwise AFunctor did something wrong).  Report this to me immediately.

How to Run Your Translator

Now manually run the generated test files.  There are only three for Top and Bottom:

A RoundTripTest output
Output Meaning
THEOREM (last058):
$Person.last().exists();
=
$Person.combine().last().exists();
details:
$Person.last().exists(); =>
$Person.both().last().exists(); =>
$Person.combine().last().exists();
Conjectured theorem: id()  ==  combine().

means E = E" must be a Bottom identity:

$Person.last().exists() == $Person.combine().last().exists()

details:
Bottom E => (translates to)
Top E' => (translates to)
Bottom E"
Conjectured theorem is bogus, but looking closer it means:
last() = combine().last()


For this particular case,
Make sure that all Top and Bottom round trip tests are correct.  If so, you have translated all operations correctly.  There are an infinite number of Aocl expressions, but you know how all operations now are translated, and if there are any theorems to prove, you will have exposed them.

Warning: this translation is NOT easy.  But doing it gave me an insight on what WOULD be easy.