The figure below shows the subsystems of the CADEMIA engineering platform. The Model subsystem represents the structured object sets of a specific engineering application. The user's input is handled by the Command subsystem. The model is visually represented by the View subsystem that is embedded into the Graphical User Interface (GUI).

start -> cmdList
cmdList -> (cmd ";")*
cmd -> <TEXT> argList
argList -> (arg)*
arg -> <TEXT>|<LITERAL>
A command argument consists of a simple text or a string literal with double quotes as bracket delimiters. When a command is prompting for arguments the user can enter one of the symbols described in table below:
| Syntax | Semantics |
|---|---|
| #menu(m) | item m of current menu |
| #window(w) | window w |
| #digitize(x, y, w) | digitize at (x, y) in window w |
| #cancel() | cancel command |
| #interrupt(l) | interrupt command by command list l |
| <TEXT>|<LITERAL> | text or string literal |
Macros must be formatted on the basis of this command language. Macros are to be stored in the file system, preferably with the extension cademia_macro. At runtime, they are dynamically loaded and executed via the CADEMIA command play.
For mouse strokes also the rules of the command language apply. It is possible to refer to the coordinates of the currently issued mouse stroke.
| Syntax | Semantics |
|---|---|
| #strokestart<N> | Start point of stroke <N>, e.g. #strokestart0 for the first part stroke |
| #strokeent<N> | End point of stroke <N>, e.g. #strokeend2 for the 3rd part stroke |
| #strokewin<N> | Window name where stroke <N> was entered, e.g. #strokewin1 for the 2nd part stroke |
Command language extensions have their limitations, both in complexity and in execution speed. For extensions of a certain complexity in the next section extensions in Java should be considered.
interface Cmd {
void doCmd(Object context) throws CmdAbortedException;
void undoCmd(Object context);
void redoCmd(Object context);
boolean changesState();
boolean isUndoable();
}
The doCmd() method is responsible for the initial execution of the command. It is invoked exactly once in the lifetime of the object and has the user interaction code. The object set is transformed from state m to m'.

The undoCmd() method is responsible for undoing the changes applied to the object set by the doCmd() method. No user interaction code must be contained in this method. The model instance is transformed from state m' to state m. It should be noted that the object set must be exactly in state m' when undoCmd() is invoked.
The redoCmd() method redoes the command without any user interaction. Analogous to the doCmd() method the object set is transformed from state m to m'. Again, the model instance must be exactly in state m when redoCmd() is invoked.
The changesState() method indicates whether the object set was changed as a result of the doCmd() method. If this method returns false then the command object should not be added to the sequence of executed commands. An example is an aborted command or a command that translates objects by a null vector.
The isUndoable() method should return false in the rare case where a command cannot be reversed. An example for an irreversible command is the loading of a document, since normally it cannot be guaranteed that the state of the document hasn't changed at the time of a later redoCmd().
The commands are managed by an instance of class CmdMgr (see figure above). The command manager stores the sequence of command objects in a list and has a cursor that identifies the actual command object.
| User action | Object and invoked method | Command sequence |
|---|---|---|
| Do command a | a.doCmd() | (a) |
| Do command b | b.doCmd() | (a, b) |
| Do command c | c.doCmd() | (a, b, c) |
| Undo | c.undoCmd() | (a, b, c) |
| Undo | b.undoCmd() | (a, b, c) |
| Redo | b.redoCmd() | (a, b, c) |
| Do command d | d.doCmd() | (a, b, d) |
This is exemplified in the table above where for a given user action in column 1 the appropriate command object and method are indicated in column 2. Column 3 contains the sequence of command objects with the actual command printed in bold face. It should be noted that the doCmd() method results in a change of the list structure and the actual element whereas the undoCmd() and redoCmd() methods only change the actual element.
The model cannot be strictly separated from the other subsystems. For instance, the view subsystem should reflect changes of the model subsystem. On the other hand the model components should not be dependent of the view subsystem. Thus, a generic notification mechanism is of particular importance.
interface ObservableObject {
static interface Listener {
void wasChanged(ObservableObject o);
void wasCloned(ObservableObject src,
ObservableObject dest);
}
void addListener(Listener l);
void removeListener(Listener l);
}
Objects implementing the ObservableObject interface must notify their observers when they are changed or cloned. The set of listeners is controlled by the addListener() and removeListener() methods. Components have to implement the Component interface shown in the next figure. The Serializable and Cloneable interfaces are well known from the Java platform.

Components contain lists of attributed shapes and texts. The border of a shape consists of an arbitrary number of 3rd order Bezier curves. Attributes describe items like the boundary and the interior of a shape or the font, the height and the subscripting even of a arbitrary subranges of a text.
Components are modified via controls. This is illustrated in figure 6 for a 3rd order Bezier curve. Components have a set of features with clear semantics for the user. For instance, the features of the curve shown in figure 6 could be the Length and the Color.

interface ObservableSet extends Set {
static interface Listener {
void wasAdded(ObservableObject o);
void wasChanged(ObservableObject o);
void wasRemoved(ObservableObject o);
void wasCloned(ObservableObject src,
ObservableObject dest);
}
void addListener(Listener l);
void removeListener(Listener l);
}
An instance of ObservableSet contains ObservableObjects. ObservableSet.Listener objects are added by the addListener() method. Via the Listener methods the client is informed about changes of the set (wasAdded() and wasRemoved()) and events caused by the contained objects (wasChanged() and wasCloned()).

The implementation of an ObservableSet is shown in the figure above. ObservableSetImpl implements the ObservableSet interface that extends the Set interface. A private Set implemented by a HashSet contains the ObservableObjects. This Set is privately used by ObservableSetImpl for its implementation and cannot be seen from outside.
Changes of the set are easily observed because the only way of adding and removing objects is via the ObservableSet or its base interface Set. To observe object events the ObservableSetImpl class adds an ObservableObject.Listener to each ObservableObject contained in the set.
A completely modular graphical user interface (GUI) is defined for all CAD functionality with synchronization of input by keyboard, mouse, menus and icons. The next figure illustrates the concept of an InputDevice that allows arbitrary input devices to be plugged to the user interface.

Since input handling is strictly text based the communication between user interface and input device is straightforward.
interface InputDevice {
static interface Listener {
void gotInput(String str);
void wasChanged(ObservableObject o);
}
void addInputListener(Listener l);
void removeInputListener(Listener l);
void setEnabled(boolean enabled);
boolean isEnabled();
}
The synchronization of the windowing system and the model is shown in the figure below. The GUI contains an arbitrary number of GeometryPanels. Each GeometryPanel has a projection that maps model to view coordinates. Each model component is visualized by a ViewController that in turn is composed of an arbitrary number of Views. The synchronization of model and view is based upon the ObservableSet already introduced.

The file plugin.cademia_macro is a CADEMIA macro that is executed after the plugin has been loaded. The macro should execute commands to dynamically add the commands to the command table. This is done via the putcmd/ command.
The plugin.ini file defines the Plugin's properties Name, Version and Info. The Plugin is stored under this name. The Plugin-name must be unique. It is not possible to have two Plugins with the same name loaded.
The Java classpath is extended by the CADEMIA-Plugin.
See the Development Tutorial on how to develop a CADEMIA-Plugin.