| 
 | 1 | +# Generator  | 
 | 2 | + | 
 | 3 | +The code generator provides the runtime environment for various components. These can be interconnected via a   | 
 | 4 | +configuration. Thus, individual operational sequences can be provided and combined. By this modular structure the code   | 
 | 5 | +generator can be individually extended and configured by developers.  | 
 | 6 | + | 
 | 7 | +The library consists of four subpackages. These define the runtime environment for the code generation.   | 
 | 8 | +The subpackage `Workflow` is responsible for processing the individual workflows. The configuration of the runtime environment  | 
 | 9 | +takes over the subpackage `Config`. The configuration is read from the subpackage `Console` via a command line interface.   | 
 | 10 | +The `Code` subpackage contains classes for file and namespace resolution.  | 
 | 11 | + | 
 | 12 | +## Workflow  | 
 | 13 | + | 
 | 14 | +The figure beneath shows the classes from the `Workflow` package. The class `WorkflowEngine` processes a list of   | 
 | 15 | +classes in a specified order which implement the `Description` interface. The processing is started by the `run()` method.   | 
 | 16 | +The first parameter `workflowContext` is of type `WorkflowContext`. The second parameter `componentDescriptions` is a list   | 
 | 17 | +of objects of type `Description`. A standard implementation of the `WorkflowContext` interface is the class   | 
 | 18 | +`WorkflowContextMap`. It allows to manage the input and output data of the individual components. The `get()` method   | 
 | 19 | +provides associative access to the respective slot data. The `slotName` parameter is of type `String` and corresponds   | 
 | 20 | +to the slot name under which the desired slot data can be found. The `put()` method stores the slot data. The first   | 
 | 21 | +parameter `slotName` of type `String` corresponds to the slot name, under which the data can be  retrieved later. The   | 
 | 22 | +second parameter `slotValue` of type `mixed` corresponds to the slot data to be stored. The slot data is stored in the   | 
 | 23 | +`map` attribute under the given slot name. The `getByDescription()` method returns all input data required for calling   | 
 | 24 | +a component from the `WorkflowContext` object. The parameter description is of the type `DescriptionWithInputSlot`. The   | 
 | 25 | +return value is of type `array`.  | 
 | 26 | + | 
 | 27 | +Several interfaces are available for the description of a component. The interface `Description` must be implemented   | 
 | 28 | +by all classes that describe a component for the code generator. The `component()` method returns the component. A   | 
 | 29 | +component can be a function or a class. This is indicated by the pseudo-type `callable`. If a component is defined as a   | 
 | 30 | +class, it must provide a `__invoke()` method. This method is automatically executed when an object is called as a function.   | 
 | 31 | +An interface is not possible here because the components can have different input parameters and otherwise there would   | 
 | 32 | +be no function support. The `DescriptionWithInputSlot` interface is available for the description of required input data.   | 
 | 33 | +The `inputSlots()` method returns a list with slot names for the required input data when the component is called. The   | 
 | 34 | +`DescriptionWithOutputSlot` interface is available for describing the output data. The `outputSlot()` method returns the   | 
 | 35 | +slot name under which the output data of the component is stored. The two interfaces `DescriptionWithInputSlot` and   | 
 | 36 | +`DescriptionWithOutputSlot` can be used to describe components that have only input or only output data. Since components   | 
 | 37 | +usually have both input and output data, there is the class `ComponentDescriptionWithSlot`. The constructor has three   | 
 | 38 | +parameters. The first parameter `component` is of type `callable` and corresponds to the component to be executed. The   | 
 | 39 | +second parameter `outputSlot` is of type `string` and corresponds to the slot name under which the output data is   | 
 | 40 | +stored. The third parameter `inputSlots` is a list of element type `String` and contains the slot names for the required input   | 
 | 41 | +data of the component. The `ComponentDescriptionWithSlot` class inherits from the `DescriptionTrait`, `InputSlotTrait` and   | 
 | 42 | +`OutputSlotTrait` classes. These classes each provide the methods for the implemented interfaces. For components with   | 
 | 43 | +input data only, there is the class `ComponentDescriptionWithInputSlotOnly`. This inherits from the classes   | 
 | 44 | +`DescriptionTrait` and `InputSlotTrait`.  | 
 | 45 | + | 
 | 46 | +  | 
 | 47 | + | 
 | 48 | +## Code  | 
 | 49 | + | 
 | 50 | +The figure beneath shows the classes from the package `Code`. To generate classes it is necessary to know the package,   | 
 | 51 | +the namespace and the file path. The `ClassInfo` interface defines the necessary methods. The `getPackagePrefix()` method   | 
 | 52 | +returns the package prefix. This is prefixed to every class name. The `getSourceFolder()` method returns the path to the   | 
 | 53 | +code directory. The `getClassNamespaceFromPath()` method is used to determine the namespace using the passed path. The   | 
 | 54 | +`getFullyQualifiedClassNameNameFromFilename()` method returns the class name including namespace based on the file name.   | 
 | 55 | +The `getClassNamespace()` method returns the class namespace from FQCN. The `getClassName()` method returns the class   | 
 | 56 | +name from FQCN. The `getPath()` method returns the path which is extracted from class name by using package prefix and   | 
 | 57 | +source folder. The `getFilenameFromPathAndName()` method returns the file name based on the passed path and name. The   | 
 | 58 | +`getPathAndNameFromFilename()` method returns the path and name as a list based on the passed file name. The   | 
 | 59 | +`isValidPath()` method checks whether the passed path or file name belongs to this namespace or package.  | 
 | 60 | + | 
 | 61 | +A standard implementation of the `ClassInfo` interface is provided by the class `Psr4Info`. The constructor   | 
 | 62 | +has four parameters. The first parameter `sourceFolder` is of type String and corresponds to the path of the code directory.   | 
 | 63 | +The second parameter `packagePrefix` is of type String and corresponds to the package prefix. The third parameter   | 
 | 64 | +`filterDirectoryToNamespace` is of type callable and a filter for the conversion of a directory path into a namespace.   | 
 | 65 | +The fourth parameter `filterNamespaceToDirectory` is of type callable and a filter for the conversion of a namespace into   | 
 | 66 | +a directory path. Using the static `fromComposer()` method, an instance of the class `Psr4Info` will be created based   | 
 | 67 | +on the Composer configuration. Composer is a package manager for PHP. The first parameter `classLoader` is of type `ClassLoader`   | 
 | 68 | +from the external package `Composer::Autoload`. The third parameter `filterDirectoryToNamespace` is of type callable   | 
 | 69 | +and a filter for the conversion of a directory path into a namespace. The fourth parameter `filterNamespaceToDirectory`   | 
 | 70 | +is of type callable and a filter for the conversion of a namespace into a directory path. The fourth parameter `exclude`   | 
 | 71 | +is of type String and specifies which path should be ignored. The class `ClassInfoList` stores a list of objects of   | 
 | 72 | +type `ClassInfo` in the attribute `list`. These are passed to the constructor. More can be added using the   | 
 | 73 | +`addClassInfo()` method. The `classInfoForPath()` method returns the appropriate `ClassInfo` object based on the   | 
 | 74 | +provided path. The `classInfoForFilename()` method returns the matching `ClassInfo` object based on the provided filename.  | 
 | 75 | + | 
 | 76 | +  | 
 | 77 | + | 
 | 78 | +## Config  | 
 | 79 | + | 
 | 80 | +The figure beneath shows the classes from the package `Config`. The code generator supports different   | 
 | 81 | +types of configuration via the interface `Config`. The `consoleCommands()` method can return a list of CLI commands for   | 
 | 82 | +the code generator CLI. The `WorkflowConfig` interface is available for the configuration of components. It implements the interface   | 
 | 83 | +`Config`. The descriptions of the components can be retrieved using the `componentDescriptions()` method. The return   | 
 | 84 | +value is a list with element type `Description` from the package `Workflow`. A standard implementation of the   | 
 | 85 | +`WorkflowConfig` interface is realized by the class `Workflow`. The constructor expects a list with element type   | 
 | 86 | +`Description` from the package `Workflow`. Several workflows can be combined via the `WorkflowCollection` interface.   | 
 | 87 | +It implements the interfaces `Config` and `Iterator`. The interface `Iterator` allows the iteration via individual   | 
 | 88 | +component descriptions. A standard implementation of the interface `WorkflowCollection` is realized by the class   | 
 | 89 | +`WorkflowList`. The constructor expects a list with element type `WorkflowConfig`.  | 
 | 90 | + | 
 | 91 | +To be able to read the configuration from different sources, the interface `Resolver` exists. This interface defines the   | 
 | 92 | +`resolve()` method with a parameter. The parameter `workflowContext` is of type `WorkflowContext` from the package   | 
 | 93 | +`Workflow`. The input parameter `workflowContext` can be used by the respective configuration to provide necessary data   | 
 | 94 | +for starting the code generation. The return value is of type `Config`. A standard implementation of the `Resolver`   | 
 | 95 | +interface is realized by the class `FilePhpResolver`. The path to the configuration file is passed to the constructor   | 
 | 96 | +and stored in the `file` attribute. When the `resolve()` method is called, this file is read in and the corresponding   | 
 | 97 | +configuration is returned to the caller.  | 
 | 98 | + | 
 | 99 | +  | 
 | 100 | + | 
 | 101 | +## Console  | 
 | 102 | + | 
 | 103 | +To execute the code generator, a command line interface is available in the package `Console`. The figure beneath shows the  | 
 | 104 | +procedure for starting the code generator. You can see a `workflowCommand` object of the type `WorkflowCommand`. First,   | 
 | 105 | +the `loadWorkflowContext()` method of the `workflowCommand` object is called. This returns an object of type   | 
 | 106 | +`WorkflowContext` from the package  `Workflow` back. The return value is stored in the local attribute   | 
 | 107 | +`workflowContext`. Next, the `loadConfig()` method of the `workflowCommand` object is called. As argument the local   | 
 | 108 | +attribute `workflowContext` is passed to it. The return value of this method is an object of type `Config` from the   | 
 | 109 | +package `Config`. This is stored in the local attribute `config`.  | 
 | 110 | + | 
 | 111 | +The following checks what type of configuration the local config attribute is. If this is the type `WorkflowConfig`   | 
 | 112 | +from the package `Config`, the `executeWorkflow()` method of the `workflowCommand` object is called. The local   | 
 | 113 | +attributes `config` and `workflowContext` are passed to it in the listed order. This method is described in detail in the   | 
 | 114 | +interaction reference *Execute Workflow*. If the local attribute `config` is of type `WorkflowCollection` from the package   | 
 | 115 | +`Config`, iteration is first performed over this attribute. At the beginning of each loop pass, the current object is   | 
 | 116 | +fetched from the list and stored in the local attribute `workflowConfig`. Next, the `executeWorkflow()` method of the   | 
 | 117 | +`workflowCommand` object is called. This will call the local attribute `workflowConfig` of the current loop pass and the   | 
 | 118 | +local attribute `workflowContext` in the listed order. At the end of each iteration the internal pointer is set to the   | 
 | 119 | +next element in the list. The iteration is done until there is no next element in the list. If the local attribute   | 
 | 120 | +`config` is neither of type `WorkflowConfig` nor `WorkflowCollection`, an exception is raised via the `RuntimeException` class.  | 
 | 121 | + | 
 | 122 | +  | 
 | 123 | + | 
 | 124 | +How to start the workflows is shown in the figure beneath. The `executeWorkflow()` method of the `workflowCommand` object   | 
 | 125 | +first calls the `componentDescriptions()` method of the `config` object. The return value is a list of objects of type   | 
 | 126 | +`Description` from the package `Workflow` and is stored in the local attribute `descriptions`. Next, a   | 
 | 127 | +`workflowEngine` object of type `WorkflowEngine` from the package `Workflow` is created. Afterwards, the `workflowCommand`   | 
 | 128 | +object calls its `run()` method. The `workflowContext` object and the local attribute `descriptions` are passed to this   | 
 | 129 | +method in the listed order. This method is described in detail in the interaction reference *Run workflow engine*.  | 
 | 130 | + | 
 | 131 | +  | 
 | 132 | + | 
 | 133 | +The figure beneath shows the processing of the working steps. First, the list of the input parameter `descriptions` is   | 
 | 134 | +iterated. At the beginning of each loop pass, the current description object is fetched from the list and stored in the   | 
 | 135 | +local attribute `description`. The `workflowEngine` object next calls for each `description` object its `component()` method.   | 
 | 136 | +The result is a `component` object, which is stored in the local attribute `component` and called later. Afterwards, it is   | 
 | 137 | +checked whether the `description` object is of the `DescriptionWithInputSlot` type. This is described in more detail in   | 
 | 138 | +the interaction reference *Instance of DescriptionWithInputSlot*. The next step is to check whether the description   | 
 | 139 | +object is of type `DescriptionWithOutputSlot`. This is described in detail in the interaction reference   | 
 | 140 | +*Instance of DescriptionWithOutputSlot*. At the end of each iteration the internal pointer is set to the next element   | 
 | 141 | +in the list. The iteration is done until there is no next element in the list.  | 
 | 142 | + | 
 | 143 | +  | 
 | 144 | + | 
 | 145 | +The figure beneath shows the process if the description object is of type `DescriptionWithInputSlot` from the package   | 
 | 146 | +`Workflow`. In this case, input parameters are required when calling the local attribute `component`. Therefore, the   | 
 | 147 | +`workflowEngine` object calls the `getByDescription()` method of the `workflowContext` object. The local attribute   | 
 | 148 | +`description` is passed as argument to this method. Based on this, a list with the necessary input data is returned   | 
 | 149 | +from the `workflowContext` object and stored in the local attribute `inputData`. Next, the local attribute `component` is   | 
 | 150 | +called. The UML stereotype *<<invoke>>* indicates that the local attribute `component` is called like a function. Each   | 
 | 151 | +element in the list of the local attribute `inputData` is passed as one argument. This allows, despite the dynamic call,   | 
 | 152 | +the definition of parameters with corresponding types for the `__invoke()` method in the respective class or for a   | 
 | 153 | +function. The return value is stored in the local attribute `slotValue`. If the description object is not of type   | 
 | 154 | +`DescriptionWithInputSlot`, the local attribute `component` is called without any arguments. The return value is stored   | 
 | 155 | +in the local attribute `slotValue`.  | 
 | 156 | + | 
 | 157 | +  | 
 | 158 | + | 
 | 159 | +The figure beneath shows the process, if the description object is of type `DescriptionWithOutputSlot` from   | 
 | 160 | +the package `Workflow`. The `outputSlot()` method of the `description` object is called here. The return value is the slot   | 
 | 161 | +name under which the data is stored in the `workflowContext` object. This is stored in the local attribute `slotName`.   | 
 | 162 | +Next, the `put()` method of the `workflowContext` object is called. The local attributes `slotName` and `slotValue` are   | 
 | 163 | +passed to it in the listed order.  | 
 | 164 | + | 
 | 165 | +  | 
0 commit comments