| # The Composer Tool

The composer is a command-line tool to compose files or directories by invoking type-specific composition functions on its operands. Some of the composition functions are implemented by other composition tools while others are handled internally by the composer itself. Together, the composition functions encompass several different file types, including `.jak` files, `.properties` files, and directories.

The composer's most important use is to compose directory hierarchies representing entire layers. In this mode, the composer recursively descends the hierarchies, identifying and composing matching files within the hierarchies. This document discusses the use of composer with special attention to the composition of layers.

- composer basics
- composition overview
- composing layers (directory hierarchies)
- basic equation files
- more complex equations files
- composer configuration
- supported file types
- command-line invocation
- programmatic invocation

## Composer Basics

At a minimum, the composer requires one or more source operands listing files or directories to be composed and a target naming the file or directory into which to place the result. The source operands and the target may be specified in one of two ways. First, the target can be specified explicitly using the `--target` option, while the source operands can also be specified explicitly as non-option arguments. Here's an example command line of this type with two source arguments, `base.jak` and `refinement.jak`:

>     composer --target=result.jak base.jak refinement.jak

Alternatively, both the sources and target can be provided in an equation file specified via the `--equation` option. If a file named `result.jak.equation` is defined to contain two whitespace-separated operands, `base.jak` and `refinement.jak` in that order, then the same effect as above can be achieved with the following command line:

>     composer --equation=result.jak

In this command, the value of the `--equation` option specifies the base name of the equation file. The base name is also used as the default target name and the `--target` option can be used to override this default. More information can be found in the equation files section.

Now, what does the composer do when invoked with the above command? If `base.jak` and `refinement.jak` are readable files, the composer uses the file extension `.jak` to recognize that the source file types are those of Jak source files. In general, there may be multiple source types which will be resolved into a common type, if possible. Then, the common type is used to select a composition method. In this case, since `base.jak` and `refinement.jak` are both of type `.jak`, the common type is also `.jak` and, by default, the composer is configured to invoke m ixin to compose `.jak` files. In this example, the resulting output would be written into the target, `result.jak`.

There are some important points to note. First, the source arguments are listed in a specific order. The left-most source argument is the base of a composition and successive source arguments are refinements applied in order from left to right. Second, the source arguments may be of different types as long as they can be resolved to a common type. Third, the type of the target argument is not used in determining the common type of the source operands. In particular, it's perfectly valid to place the result of a composition into a file of a completely different type than that of the sources.

Of course, the composer has other command-line options and it can be configured for several different compositions. Arguably, though, the most important composition handled by the composer is the composition of directory hierarchies that represent layers.

## Composition Overview

In the example above, the composition of `.jak` files is handled by an external tool instead of an internal composition function. In the default composer configuration, `.jak` files are primitive operands as are all source files handled by external tools. More generally, though, the composer operates on units which may be directories, files or portions of files. Units are divided into two types: primitives, which are treated by the composer as opaque objects, and collectives, which are collections of named units.

All compositions, whether of primitives or collectives, are determined via the method suggested in the previous section. Given a list of source units, a common type is determined if possible. The common type is used to select a composition function via a configuration file. The source units are passed to the function for evaluation and the result is written to a target unit. If the source units are collectives, the composition function is a generalization of inheritance as implemented in object-oriented languages.

Here's how collective composition works. Suppose there are two collectives, the `Base` and the `Refinement`, each containing uniquely named units called members. For example, the `Base` could contain members named `alpha` and `beta`, while the `Refinement` could contain members named `alpha`, `delta` and `gamma`. Conventionally, the member names are called signatures and the collection of signatures for a collective is called the signature set. In our example, the signature set for `Base` is {`alpha`, `beta`} while the signature set for `Refinement` is {`alpha`, `delta`, `gamma`}.

Further, each member of a collective has an assigned value. For example, in object `Base`, suppose the member `alpha` has value 120.0 while member `beta` has value 2718. It's conventional to use dot notation to refer to a member within a collective. For example, `Base.beta` refers to member `beta` within collective `Base`.

Of course, the members of `Refinement` also have assigned values. In the table below, the collectives `Base` and `Refinement` are depicted with their members where the possible signatures are listed in the last four rows while the assigned values for the members of `Base` and `Refinement` are shown in the second and third columns, respectively. The intersection of a signature's row and a collective's column is blank if the collective has no member with that signature. For example, `Refinement` has no member with signature `beta`, so the cell at the third column of the row for `beta` is left blank.

> Collectives `Base` and `Refinement`
> Signatures | Assigned Values
> --- | ---
> `Base` | `Refinement`
> alpha | 120.0 | 123
> beta | 2718 |
> delta |  | 0.005
> gamma |  | "label"

The composition of two collectives (the sources) is another collective (the target) which also contains uniquely named members. The target's signature set is the union of the signature sets of the sources. So, if the sources are `Base` and `Refinement`, the target's signature set is {`alpha`, `beta`, `delta`, `gamma`}. The values assigned to the target's members are calculated by recursively applying composition for each signature in the target's signature set. The operands for each recursive composition are found by taking corresponding members from the sources in the same order as the sources. For example, if collective `Target` is the composition of `Base` and `Refinement`, in that order, then the value of `Target.alpha` is found by composing `Base.alpha` and `Refinement.alpha` in that order. The composition function to use in the recursive invocation is again determined as described above and the procedure repeats until no further compositions of collectives remain.

Here's a table showing the recursive compositions formed when composing `Base` and `Refinement` to yield collective `Target`. Only `Target.alpha` has two operands in the recursive composition since signature `alpha` is the only signature with members in both `Base` and `Refinement`.

> Composing `Base` and `Refinement` into `Target`
> Signatures | Assigned Values
> --- | ---
> `Base` | `Refinement` | `Target`
> alpha | 120.0 | 123 | compose (120.0, 123)
> beta | 2718 |  | compose (2718)
> delta |  | 0.005 | compose (0.005)
> gamma |  | "label" | compose ("label")

So far, the composition of numbers and strings has been left undefined. To complete the example, let's suppose that strings are composed by concatenation and that numbers are composed by subtraction. Then, strings and numbers will be primitives and the final result of composing `Base` and `Refinement`, in that order, is shown in the table below.

> Composing `Base` and `Refinement` into `Target`
> Signatures | Assigned Values
> --- | ---
> `Base` | `Refinement` | `Target`
> alpha | 120.0 | 123 | -3.0
> beta | 2718 |  | 2718
> delta |  | 0.005 | 0.005
> gamma |  | "label" | "label"

It's important to note that composition is not usually commutative. For example, if the order of the above composition were reversed, the value of `Target.alpha` would be +3.0 instead of -3.0.

Using the model path. Source operands are often part of a model, a collection of related components used to define a product line. The `composer` supports the model viewpoint by providing a search path, called the model path, for source operands and other related files. This is a list of directories separated by the system-dependent path separator character. On Unix systems, the path separator character is "`:`" and, on Windows systems, it is "`;`".

A model path can be specified with the `--model` command-line parameter. For example, on a Unix system, the `composer` could be run as follows:

>     composer --model=myGUIComponents:/opt/components/GUI baseFrame editor

In this example, the `composer` would search for each of the two operands, `baseFrame` and `editor`, by first looking in the `myGUIComponents` directory, then in the `/opt/components/GUI` directory. Each search is done independently, so that `baseFrame` could be found in `/opt/components/GUI` while `editor` could be found in `myGUIComponents`. It's also possible to specify the model path by defining the property `composer.model.path` in a properties file.

Details of the model path search. The model path search is called resolution and it is similar to other path searches, such as the resolution of Java class files against the `CLASSPATH` environment variable. For example, only relative filenames are resolved against the model search path; an absolute filename is always used exactly as given. On the other hand, model path resolution differs from other path searches in two important ways. First, any relative filename, even those specifying a directory path, will be resolved against the model path. For example, the filename `dsl/bali/Data.jak`, which contains the directory path `dsl/bali`, will be resolved against the model path. Second, a source operand may be specified as a `file` URI. This means is that a "/" can always be used as the file separator character in source operands, even on Windows systems where the file separator character is normally "\".

## Composing Layers (Directory Hierarchies)

In the composer, layers are implemented as directory hierarchies and directories are particular types of collectives. The members of a directory collective are the files within the directory and the signature of each file member is the name of the file. Composition of directories, then, is implemented as described in the previous section. To ensure that this is clear, this section contains a fully described example.

Suppose that the following composer command is issued where `base`, `refinement` and `packages` are all directories:

>     composer --target=project base refinement packages

Let's suppose that the directory `base` contains files `alf.jak` and `bet.jak` while directory `refinement` contains files `bet.jak` and `gam.jak`. Further, let's suppose that both `base` and `refinement` contain subdirectories named `network` each with a single file named `network.properties`. Finally, let's suppose that the directory `packages` contains one subdirectory named `network` with Java files named `Control.java` and `Link.java`.

Viewing `base`, `refinement` and `packages` simply as collectives with member signatures determined by filenames results in the following tabular representation:

> Collectives `base`, `refinement` and `packages`
> Signatures | Assigned Values
> --- | ---
> `base` | `refinement` | `packages`
> alf.jak | a `.jak` file |  |
> bet.jak | a `.jak` file | a `.jak` file |
> gam.jak |  | a `.jak` file |
> network | a directory | a directory | a directory

Since the sources are all directories, the target, `project`, will be instantiated as a directory and its members will be computed by recursively applying composition across members of sources with the same signatures. This results in the following sequence of events initiated by the composer, including several recursive invocations of the composer:

- create directory `project` if it doesn't already exist;
- `composer --target=project/alf.jak base/alf.jak`
- `composer --target=project/bet.jak base/bet.jak refinement/beta.jak`
- `composer --target=project/gam.jak refinement/gam.jak`
- `composer --target=project/network base/network refinement/network packages/network`

The first three recursive invocations of composer act on `.jak` files which are primitives. However, the fourth invocation is on sub-directories of the original source directories. Since directories are collectives, the composer again applies composition of collectives to create the target sub-directory `project/network`. Here's a tabular representation of that composition:

> Collectives `base/network`, `refinement/network` and `packages/network`
> Signatures | Assigned Values
> --- | ---
> `base/network` | `refinement/network` | `packages/network`
> network.properties | a `.properties` file | a `.properties` file |
> Control.java |  |  | a `.java` file
> Link.java |  |  | a `.java` file

This results in the following sequence of events with three recursive invocations of the composer:

- create directory `project/network` if it doesn't already exist;
- `composer --target=project/network/network.properties beta/network/network.properties refinement/network/network.properties`
- `composer --target=project/network/Control.java packages/network/Control.java`
- `composer --target=project/network/Link.java packages/network/Link.java`

At this point, all compositions are for primitives, so there are no further recursive invocations of the composer and no more compositions are performed. However, for top-level compositions of directories, the composer performs one final step. If (and only if) the target directory contains an Ant build file named `build.xml` and if there were no errors in composition, then the composer will start the build tool, Ant, with a command line such as the following:

>     ant -buildfile <target-directory>/build.xml

For the example above, the top-level target directory is `project`, so the command issued is:

>     ant -buildfile project/build.xml

For sophisticated builds, a `build.xml` file can be created as the result of a recursive composition performed while the target directory is being composed. Even though the `build.xml` file is generated by the composition itself, it will still be invoked in the final step as described above. A particularly useful method for generating a `build.xml` file is as the result of composing `build.xml.vm` files in the source directories. With the default file type configuration, `.vm` files are composed using Velocity as described below.

## Basic Equation Files

When composing large numbers of files, it's inconvenient to enter the operand names on the command line each time the composition is run. It's much easier, in this case, to enter the operand names just once into an equation file. Then, the composer can be invoked so as to read the operand names from the equation file. This section describes basic equation files which, in the default file type configuration, are files with the `.equation` extension. A alternative format for more complex equations files is described in the next section.

Consider the example from the previous section. There, three directory operands (`base`, `refinement` and `packages`) were being composed into target directory `project`. Now, suppose we create an equation file, `project.equation`, that contains the following lines:

>     base
>     refinement
>     packages

Then, the composer can be invoked with the following command line:

>     composer --equation=project

This command line specifies several pieces of information. First, the base name of the equation file is `project`, as given by the value of the `--equation` argument. If desired, it's also valid to specify both the base name, `project`, and the extension, `.equation`, as shown below:

>     composer --equation=project.equation

Either way, the base name of the equation file is also used to supply the second piece of information, the default target name. So the above command will place the result of the composition into a directory named `project`. The default can be overridden by supplying an additional `--target` argument. For example,

>     composer --equation=project --target=george

specifies that the composition result will be named `george` instead of `project`.

Finally, the third set of information, the source operands, is read from the equation file. In this example, there are three source operands, one per line, in the equation file `project.equation`. Therefore, in this example, the following two command lines are equivalent:

>     composer --equation=project
>     composer --target=project base refinement packages

Note: Comment lines can also be placed into equation files. If the first non-blank character on a line is a `#`, the line will be treated as a comment.

Composing equation files. So far, the examples have shown how equation files can be used to save typing. That's a bit boring, though useful. However, equation files themselves can be composed, which makes life much more interesting. This allows equation files to specify components that can be used in later compositions. Further, equation files implement a form of inheritance, allowing the same set of equation files to be composed in different ways to build different components.

Here's how inheritance works. There's a keyword, `super`, that can be used as the name of an operand within an equation file. The `super` keyword specifies that a base list of operands be inserted into the operand list. To make this clear, suppose there are two equation files as shown in the table below:

> Files `base.equation` and `packages.equation`
> File: | `base.equation` | `packages.equation`
> --- | --- | ---
> Contents: |
> `base`
> `refinement`
> `super`
> `filesystem`

These two equation files can be composed. Here's an example command line for such a composition:

>     composer --target=result.equation base.equation packages.equation

The composition works from left-to-right. The contents of the first file, `base.equation`, provides the base to substitute for the `super` keyword in the second file, `packages.equation`. The result will be the following three lines

>     base
>     refinement
>     filesystem

which are written into the target file, `result.equation`. It's also possible to compose more than two equation files. For example, suppose there's another equation file, `network.equation`, with the following contents:

>     ip-v4
>     tcp
>     super
>     ftp

In this file, the keyword `super` occupies the third line (in general, `super` can be at any position in an equation file). Now, to continue our example, suppose we compose these three equation files with the following command:

>     composer --target=result.equation base.equation packages.equation network.equation

The composition of the first two files, `base.equation` and `packages.equation`, is used as the base for substitution into the third file, `network.equation`. The result, written into file `result.equation`, will be the following lines:

>     ip-v4
>     tcp
>     base
>     refinement
>     filesystem
>     ftp

The order of composition is important! Suppose we modified the above command line to reverse the last two operands, as shown below:

>     composer --target=result.equation base.equation network.equation packages.equation

Then, the lines written into the target file will be in a different order:

>     ip-v4
>     tcp
>     base
>     refinement
>     ftp
>     filesystem

The operand order must be arranged so that the result is in the desired order. Assuming that the order is correct, the result is another equation file that can be used in a following composition. For example, the target of the previous composition could be used to specify another composition as follows:

>     composer --equation=result

The simple examples above give just a flavor of the possibilities. It's left to the reader to develop more sophisticated applications!

## More Complex Equations Files

It's often the case that compositional designs are hierarchical, with applications being composed from sub-components which are themselves composed from smaller sub-components. Such designs can be represented with `.equation` files as described above. Sometimes, though, more compact representations are desired. These can be achieved with `.equations` (note the plural!) files as described in this section. The format for these files is the same as that specified `load` method for Java properties files. In particular, a comment line can be included by beginning the line with a "#".

For example, consider an application that is designed to run on a variety of different operating systems. Typically, such tools are composed of a portable component and a non-portable components that varies according to operating system. A design can insulate the portable component by providing an adapter to convert tool functions to O/S-dependent functions. It's natural to define an O/S adapter as a separate component, varying according to operating sytem, that is composed with the portable component to build a complete instance of the application. However, an O/S adapter is likely to be composed of several smaller components, as is the portable component. Here's a `.equations` file, `testVersion.equations`, that shows an example hierarchical design:

>     # Base version with test stubs for the O/S adapter:
>     #
>     this = osAdapter portable
>     osAdapter = os/test/adapter
>     portable = support interface/command

Other than comments, an `.equations` file contains a set of unordered assignment statements where each assignment specifies a composition. In the example above, the left-hand side (the key) of each assignment defines a component to be the composition specified on the right-hand side (the value). The three components defined are `this`, `osAdapter` and `portable`. The keyword `this` designates the root assignment while the other assignments define sub-components to be combined into the root composition. Pictorially, the composition of `this` is hierarchical as shown below:

The image above shows a tree with a single root named `this`; three `leaves` named `os/test/adapter`, `support` and `interface/command`; and two `internal nodes` named `osAdapter` and `portable`. The evaluation of `this` is the composition of all leaves reachable from `this`, in order from left to right. The composer performs this composition with the following command:

>     composer --equation=testVersion

The leaves are interpreted as URI names relative to the model path. As with basic equation files, the target name, `testVersion` is taken from the base name of the `.equations` file and the `--target` option can be used to override this default.

Composing `.equations` files. Additional power becomes available when `.equations` files are composed. Extending the above example, suppose there's another `.equations` file, `win2kFeatures.equations`, with the following content:

>     osAdapter = os/windows/common os/win2k/adapter

Refining `testVersion.equations` with `win2kFeatures.equations` can be done with the following command:

>     composer --target=win2kVersion.equations testVersion.equations win2kFeatures.equations

The result is a file, `win2kVersion.equations`, with content similar to that shown below:

>     # Generated from [testVersion.equations, win2kFeatures.equations]
>     #
>     this = osAdapter portable
>     osAdapter = os/windows/common os/win2k/adapter
>     portable = support interface/command

Composition of `.equations` files is done by inheriting assignments where an assignment's signature is its key. In the above example, the last value assigned to key `osAdapter` was that defined in `win2kFeatures.equations`, so that is the value used in the result. The hierarchical structure of the resulting composition is shown in the following graph:

Another keyword, `super`, can be used to modify this type of composition. If an operand on the right-hand side of an assignment has the form `super.key`, then the previous value assigned to `key` to substituted at that point. Similarly, if `super` appears as an operand, then the previous value of `this` is substituted. As an example of the use of `super`, consider the files, `one.equations` and `two.equations`, shown below:

> Files `one.equations` and `two.equations`
> File: | `one.equations` | `two.equations`
> --- | --- | ---
> Contents: |
> `a = alpha`
> `b = beta`
> `g = gamma`
> `this = a b g`
> `a = aleph`
> `b = super.a baffle`
> `this = before super after`

In file `two.equations`, there are two instances of `super`. The first is `super.a` in the value of `b` and the second is simply `super` in the value of `t`. Composing these two files yields the following set of assignments:

>     a = aleph
>     b = alpha baffle
>     g = gamma
>     this = before a b g after

Again, it's left to the reader to develop more sophisticated applications!

## Composer Configuration

There are two parts to configuring the composer. First, it's recommended that it be installed so that it has access to Ant and Java tools. Second, any non-standard properties, including file type preferences, should be placed into a composer properties file. This section describes these two layers of configuration.

Configuring `composer` for Ant and Java tools. Strictly speaking, it's not necessary to configure composer for Ant unless Ant is to be used in compositions. However, the standard distribution of the composer is defined to invoke Ant for top-level directory compositions as described previously. The invocation is done via the java.lang.Runtime.exec method which finds and executes Ant in a system-dependent fashion. In general, it is recommended that Ant be installed in a directory in a standard system directory. If this is not possible, the location of Ant's executable can be specified via the `tool.ant` property in a `composer.properties` file or on the composer command line.

Similarly, Ant may execute tasks that invoke Java tools such as `javac` and `java`. In order for this to be correctly done, the Java tools must be installed so that Ant can find and execute them. For recent versions of Java, Standard Edition, this is automatic except for Ant's external invocations of `java`, the Java virtual machine. Again, this is done via a java.lang.Runtime.exec method and it is recommended that `java` be installed in a system directory. If this is not possible, the location of a `java` executable can be specified in Ant build files with the `jvm` attribute of the `Java` task.

Configuring `composer` properties. The composer uses several properties to control the details of its operation. Most properties specify file types as described in the next section, but additional properties, as listed below, are used as well:

- `composer.directory.ignore` specifies sub-directories that should be ignored during recursive invocations of composer. The property value is a pattern as described in the Java API documentation for the `Pattern` class. Sub-directories whose names match this pattern will be ignored by composer during recursive invocations only. A matching directory operand will not be ignored if it is explicitly named on the command line or within an equation file.

- `composer.file.ignore` specifies files that should be ignored during recursive invocations of composer. The property value is a pattern as per `Pattern` and it will be used only to match the names of non-directories. However, matching operands will be ignored by composer during recursive invocations only. Those on the command line or within an equation file will not be ignored.

- `composer.layer.base` specifies the base package path for `.jak` file compositions. If `composer.layer.base` is defined, the generated package name used in a target `.jak` file is the concatenation of the base path, a period and the relative path to the target file (after replacing file separators with periods). For example, if `composer.layer.base` is defined to be `math.special` and the target `.jak` file is `matrix/Eigenvalue.jak`, the generated package name would be `math.special.matrix`. On the other hand, if `composer.layer.base` were not defined, the generated package name would be `matrix`.

- `composer.model.path` specifies a search path for special files associated with a model. In the absence of an explicit definition, the search path is defined to be the working directory. Currently, this definition affects the search for property definitions and source operands. It also affects Velocity template compositions, which optionally include `.prefix` and `.suffix` files from the model path in their compositions.

- `tool.ant` specifies the location of the Ant executable. This is resolved by the java.lang.Runtime.exec method. Typically, a fully-qualified path will specify the exact location of Ant, while an unqualified name will be resolved via a search in a system search path. The default value for `tool.ant` is the unqualified name `ant`.

- `user.home` specifies the location of user configuration files (see below). On Unix systems, this refers to the user's home directory. On Windows systems, unfortunately, the situation is more complicated since different versions of Windows place configuration files in different locations. One way that a user can discover the definition of `user.home` on a particular version of Windows is to compile and run the following Java program:

  >     public class Home {

  >         public static void main (String[] args) {
  >     	System.out.println (System.getProperty ("user.home")) ;
  >         }

  >     }

All of the above properties, as well as file type properties, are resolved by taking the first definition in the following list:

- Property definitions on the command line.
- Property definitions in a `composer.properties` file found in the model search path specified via property `composer.model.path`.
- Property definitions in a file named `.composer.properties` in the directory specified by property `user.home`
- Property definitions internal to the composer. These are stored in a resource named `composer.properties` packaged with the composer distribution.

If a property is not found in the above list, it is undefined. The property files and resources referenced above, as well as embedded comments, must satisfy the format described in java.util.Properties.load. As an example, here are the default composer definitions for non-filetype properties:

>     composer.directory.ignore : CVS
>     composer.file.ignore      : .*~|#.*#|%.*%|[.]#.*|core

>     tool.ant : ant

These are the only non-filetype defaults provided by the composer itself, though several other properties are defined by the Java platform. In particular, the default value for user.home is provided by the Java platform. File type properties are described below, along with their defaults as defined by the composer.

## Supported File Types

Each unit processed by the composer is assigned a type as defined by properties in the properties search described in the previous section. In detail, the unit's type is found via the following multi-stage search through the properties:

- First, each unit is assigned a base key. If the unit is a directory, the base key is `unit.directory` and, if the unit is a normal file, the base key is `unit.file`. Currently, the only units are either directories or files so these are the only base keys possible.

- Next, if the unit has an extension as part of its name, a property name is formed by appending the extension to the base key. For example, a file named `main.java` yields property name `unit.file.java` while a directory named `main.java` yields property `unit.directory.java`. If this property name has a value, the search terminates.

- Otherwise, the base key is used as a property name. If this property name has a value, the search terminates.

- Otherwise, the composer uses the value `FileUnit`.

The value found by the above search may be either a fully-qualified class name containing periods or an unqualified class name. An unqualified class name is converted to a fully-qualified name by prepending the package name `composer.unit`, which is a package distributed with the composer. In principle, a user could configure the composer to use file types other than those in `composer.unit`, but this is not currently recommended since the interfaces have not been finalized. However, the user is free to use any file type defined in `composer.unit`. Their descriptions follow:

- An `AdjoinFileUnit` can be any regular file. Files of this type are composed by concatenating their contents in the same order as listed in the composition. A related file type is `ReverseAdjoinFileUnit`, described below.

- A `DirectoryCollective` can be any directory. Directories of this type are composed as described in Composing Layers (Directory Hierarchies).

- An `EquationFileUnit` can be any regular file containing an equation definition.

- A `FileUnit` can be any directory or regular file. Units of this type, when composed, are specifically defined to produce an error. This is the default type, so errors will occur for all units with extensions that are not explicitly assigned another type.

- An `IgnoreFileUnit` can be any directory or regular file. Units of this type, when composed, are specifically defined to be ignored and no output will be produced. Appropriate assignments of this file type, along with definitions of composer.directory.ignore and composer.file.ignore, allow a precise specification of operands during recursive invocations of the composer.

- A `JamPackFileUnit` can be any regular file containing Jak source code. Files of this type are composed using the JamPack tool. A related file type is `MixinFileUnit`, described below.

- A `LastFileUnit` can be any regular file. Files of this type are composed by copying only the contents of the last file in the composition sources. All the other sources are ignored. This can be useful when composing configuration files from multiple layers since only the most refined configuration file will be copied.

- A `MixinFileUnit` can be any regular file containing Jak source code. Files of this type are composed using the Mixin tool. Refer also to `JamPackFileUnit`, described above.

- A `PropertiesFileUnit` can be any regular file containing property definitions as per java.util.Properties.load. Property files are composed by, for each property in the source files, taking the last property definition in the source list. In other words, later property definitions override earlier ones.

- A `ReverseAdjoinFileUnit` can be any regular file. It is similar to the `AdjoinFileUnit` type, but files of this type are composed by concatenation in reverse order.

- A `SingletonFileUnit` can be any regular file. Compositions of these types are valid only if there is just one source file. In this case, the singleton file will be copied to the target. Compositions involving more than one source will cause an error.

- A `VelocityFileUnit` can be any regular file containing Velocity directives. Files of this type are composed in two stages to produce the target file and a derived file. In the first stage, the sources are concatenated as per `AdjoinFileUnit` and the result is written into the target. In the second stage, a Velocity template is formed by concatenating a prefix file, the target file from the first stage, and a suffix file. The prefix and suffix files are found by appending `.prefix` and `.suffix`, respectively, to the target's filename and searching for them in the model path. Velocity is used to evaluate the template and the output is written to a file named with the base name of the first-stage target.

  For example, if the target file is named `build.xml.vm`, the model path is searched for a file named `build.xml.vm.prefix` and, if found, it will form the first part of the Velocity template. Similarly, a file named `build.xml.vm.suffix` is sought to form the last part of the Velocity template. Finally, when Velocity expands the template, the output will be written to a file named `build.xml` in the same directory as the original target.

Any one of the above file types may be assigned to a `unit` property as described in the beginning of this section. For example, if the user wants directories named with an extension `.tmp` to be ignored, it would be appropriate to assign file type `FileUnit` to property `unit.directory.tmp`. The standard distribution of the composer has the following set of default type definitions:

>     unit.directory          : DirectoryCollective

>     unit.file               : FileUnit

>     unit.file.b             : BaliComposerFileUnit
>     unit.file.bak           : IgnoreFileUnit
>     unit.file.BAK           : IgnoreFileUnit
>     unit.file.drc           : DRCFileUnit
>     unit.file.equation      : EquationFileUnit
>     unit.file.equations     : EquationsFileUnit
>     unit.file.jak           : MixinFileUnit
>     unit.file.jar           : SingletonFileUnit
>     unit.file.java          : SingletonFileUnit
>     unit.file.prefix        : AdjoinFileUnit
>     unit.file.properties    : PropertiesFileUnit
>     unit.file.pyc           : IgnoreFileUnit
>     unit.file.pyo           : IgnoreFileUnit
>     unit.file.suffix        : ReverseAdjoinFileUnit
>     unit.file.swp           : IgnoreFileUnit
>     unit.file.timestamp     : IgnoreFileUnit
>     unit.file.txt           : LastFileUnit
>     unit.file.vm            : VelocityFileUnit

Any or all of the above definitions can be overridden as described in the configuration section.

## Command-Line Invocation

The standard distribution of the composer includes an executable Jar file and a convenience script for `bash` shells under Linux or Cygwin. This section describes the command-line use of the convenience script.

In the standard distribution of the Jakarta Tool Suite (JTS), the `composer` script is created in the `bin` sub-directory of the JTS base directory. For ease of reference, the user may include this sub-directory in the executables search path for his or her system and, in the remainder of this section, this is assumed to be the case. Then, the basic form for the `composer` command is:

>     composer [<option> ...] <source-file-or-directory> ...

The `--target` option (see below) and at least one source argument must be given on the command line, but there can be as many additional source arguments as desired up to system limits. Each source argument will be resolved as described in Supported File Types. In general , a multiple source types will be resolved to a common type by finding the least common ancestor of their individual types in an inheritance hierarchy of file types. The common type will be used to select a composition function as described earlier. Currently, however, the inheritance hierarchy has not been completely specified, so the wise user will ensure that all sources have the same type! It has been specified, however, that type `FileUnit` is the ancestor of all file and directory types while `DirectoryCollective` is an ancestor of all directory types.

In addition to the source arguments, there may be options on the command line as well. These options are of two kinds. There are Java options for the Java virtual machine and there are composer options for the composer itself. The `composer` script separates the two kinds of options, passing the Java options to the virtual machine and the composer options to the composer. Here's a summary of the available options:

Java Options:

> `-classpath` <system-dependent-classpath>
>   This may be used to specify alternative locations for composer classes and the tools used by the composer. The default, which is to use the class path defined in the composer Jar file, is usually the recommended choice. The shortcut form `-cp` may also be used
> `-D`<property>`=`<value>
>   This is one way to specify property definitions on the command line. As described in the Composer Configuration section, properties defined on the command line override all other property definitions.
> `-X`<JVM-option>
>   Specifies a non-standard configuration option to the Java virtual machine. These are system-dependent options and the user should consult the Java documentation for his or her platform.

> Some other Java options are available, but these are primarily for debugging and the casual user should avoid their use. The ultimate documentation for these is the `composer` script itself and the platform-specific documentation for the user's Java virtual machine.

`composer` Options:

> `--ant=`<ant-executable>
>   This is an alternate method for defining the `tool.ant` property that specifies the location of the Ant executable.
> `--equation=`<equation-file>
>   Specifies an equation file from which the target and source operands can be derived. The base name of the file is all that needs to be provided; the extension ".equation" will added. The file contents may include comments and character escape sequences as per properties files. After comment and escape processing, the source operands are listed in the file separated by whitespace and/or newlines. If no `--target` option is provided, the base name of the equation file is used as the target.
> `--help`
>   This causes the composer to print a helpful message about the composer command-line parameters. Immediately after processing the `--help` option, the composer will exit without processing other command-line arguments.
> `--ignore=`<pattern>
>   This specifies an overriding value for the composer.file.ignore property, thus allowing a short-hand way to specify which files to be ignored during recursive invocations of composer. For now, this option is not recommended since its definition is not finalized.
> `--layer=`<base-layer-name>
>   This is an alternate method for defining the `composer.layer.base` property that specifies the base package name for `.jak` compositions. See the section on Composer Configuration for more details.
> `--logging=`<logging-level>
>   This selects how much detail to report during execution. The logging level may be one of `all` (prints every logging message), `fine` (prints all progress messages plus some debugging messages), `info` (prints messages about files created and destroyed), `warning` (prints messages about risky but not fatal situations), `severe` (prints messages only about fatal errors) or `off` (prints no logging messages). There are other levels possible (see java.util.Logging.Level), but they aren't useful in the composer.
> `--model=`<model-search-path>
>   This is an alternate method for defining the `composer.model.path` property that specifies the search path used to find model files. See the section on Composer Configuration for details.
> `--target=`<target-file-or-directory>
>   A target is required by the composer and this option is one way to specify the destination of the composition. If this option is not present, but an equation file is specified via the `--equation`, then the composition target will be taken from the base name of the equation file. Regardless of how the target is determined, if the source operands are files the target will be a file and, if the operands are directories, the target will be a directory. If it already exists, its contents will be overwritten and, if it doesn't yet exist, it will be created.

Note that all Java options described above begin with one dash while the composer options described above begin with two dashes and follow POSIX conventions to specify values using an `=` symbol. Alternate forms are valid, but not recommended.

## Programmatic Invocation

The current version of composer is intended as a stand-alone program started via the `main` method in class `composer.Main`. This is because composer is evolving conceptually and internal packages, classes and methods are subject to frequent change. Therefore, the recommended method for invoking the composer programmatically is as an external program via the `java.lang.Runtime` class.

ATS Home Page

Copyright © Software Systems Generator Research Group. All rights reserved.
Revised: April 17, 2003.

Last modified: Thu Jan 30 09:22:07 CST 2003