To understand transformations, it is worth dwelling for a moment on how Structure101 Studio creates the viewing hierarchy for a C/C++ code-base. The first part of the process is to create a tree where each top-level node corresponds to a source file, with the code-level items defined in that file (plus any other files that have been merged in) logically arranged as children. The final step is then to infer the directory nodes based on the fully qualified file names, and interject these into the tree as ancestor nodes.
This latter step is fully automatic - you don't have any control over how this is done. However, transformations provide a simple mechanism to manipulate the result of this step.
Conceptually, a transformation boils down to a (virtual) rename of the fully qualified name of a file. By default, a file called "a/b/c/d.cpp" will end up as a child of a directory node called "a/b/c". However, if its fully qualified name is transformed to "x/y/z/d.cpp", it will instead end up as a child of a directory node called "x/y/z".
In this way, transformations give you almost unlimited control over the structure of your model - you can specify a number of expressions that modify the fully-qualified names of the files in your project - in effect moving them to locations other than their actual locations in the code-base.
When would you want to do this? Basically any time that you think you'd like to see code with a different hierarchy. For example:
- If you have lots of test classes co-located with your application code and would like to move them out to a parallel "test" package hierarchy.
- If you have physically split your code-base into an "API" and "Implementation" hierarchy for easy shipment to customers, and you would prefer to see the "real" logical model where the modules are merged into single corresponding locations.
- If your understanding of the "architecture" is different to the physical directory structure - you may want to merge some folders, or split other folders, so as to reflect what you consider to be the architectural components.
You define a Transformation using menu Model/ Transformations and then specifying a number of "Match" and "Output" pairs. The syntax uses "*" to match one or more tokens or characters, and "?" to match exactly one token or character (a token being an element of a path, e.g. A and B and C in A/B/C). If you want to change the sequence of wildcards in the Match expression, you can use "{1}", "{2}" etc. in the Output expression.
Examples:
| Match pattern | Output pattern | Result |
| */Test* | test.*/Test* | Moves any file whose local name starts with "Test" to a parallel hierarchy called "test" |
| src/foo/public/* src/foo/private/* |
src/foo/components/* src/foo/components/* |
Merges src/foo/public/X and com/foo/private/X into src/foo/components/X and src/foo/public/Y and com.foo/private/Y into src/foo/components/Y |
| com/foo/* | * | Removes com/foo from all names |
| */? | {2}/{1} | Changes a/b/C to C/a/b |
| ?/?/* | {2}/{1}/{3} | Changes a/b/C to b/a/C |
The number of transformed items in a model is displayed on the right of the application status bar. Where greater than zero, the value is hyperlinked to a dialog showing a complete list of all the transformed items.
Note:
- Transformations are intended primarily as pattern-based operations. If you have a lot of specific (no wildcards) renames to perform, use a name map instead.
Tip:
- You can import a transformation from a comma-separated text file. This can be useful if you need a lot of expressions and would prefer to use an editor rather than the simple GUI provided by Structure101 Studio. Also, you may find it convenient to automate the creation of the transformation using scripts and/or data from other tools.
- Don't be afraid to experiment with transformations - they are transient and you cannot break anything.