ClarityPrintHelper
protocol ClarityPrintHelper
A protocol that groups print logic helper methods for use by ClarityPrintLogic in its single method that calculates, formats and prints messages to the console.
Default versions of the helper methods are implemented in a protocol extension.
-
goForPrintFromSettings(_:
Extension method_: _: functionNumber: _: _: ) A method that calculates whether a print number should have its associated message printed to the console according to given parameters.
The function returns the Bool
goForPrint
as an inout parameter.There are four main task phases to the method:
- Initialise the default value for
goForPrint
totrue
. - Initialise and set Bool values from derived specifications used for the verification calculations.
- Verify in the negative a sequence of print scenarios that have increasing priority. If any scenario is verified as invalid or ‘no go’ set
goForPrint
to false. - Evaluate the master override print scenarios from
settings
. If an evaluation succeeds resetgoForPrint
to the given override value.
- settings: A SettingsManagerService instance. The argument to the parameter is not optional: the instance will have already been guarded against being nil and unwrapped for this method to be called.
- entityCode: A String representing the EntityCode value of the EntityLog containing
printNumber
. - printNumber: An Int representing a unique number used as a key to access a specific associated message from a dictionary containing all message data.
- functionNumber: An Int representing the function number value as specified for the key
function_number
in the EntityLog JSON file corresponding to the print number. - nodeType: The NodeType case of the Message associated with
printNumber
. goForPrint: An
inout
parameter that returns whether a print number should have its associated message printed to the console according to specifications calculated from the other given parameters.
Note
The parameter
functionNumber
is given a default value to allow its omission in unit tests where not required.Declaration
Swift
func goForPrintFromSettings(_ settings: SettingsManagerService, _ entityCode: String, _ printNumber: Int, functionNumber: Int = 0, _ nodeType: NodeType, _ goForPrint: inout Bool)
- Initialise the default value for
-
compileSequentialComposite(_:
Extension method_: _: _: _: _: _: ) A method that assigns specific values to specific indexes of a String array according to given parameters before returning the array.
The Swift print API does not provide grid references for printing strings to specific positions in the console. Clarity requires the ability to correctly align related elements in specific columns for multiple message types – strings that consist of different elements.
Clarity solves this problem by compiling a master composite array of strings that are assembled in the sequential order that they appear across the different message types. Required strings can then be concatenated from specified indexes in the array.
Each element that can have a different value is allocated a dedicated ‘slot’ represented by an index in the array. If an element is not included in a message type it is either omitted or replaced by a spacer depending on the circumstances.
Slot positions themselves do not necessarily always align across the different message types once different groups of elements have been removed. The aim is to ensure related elements are placed in specific columns that align vertically.
This approach is effective and performant.
Important
The method is agnostic about how the array should be used for concatenating the message string. A component value is assigned to every slot position represented in the array whether or not the slot is used in the message string for the print number. It is only important that the correct values are assigned to the components for the context of the message to print.The size of the array should remain optimum for the sake of performance. Testing a large array with empty indexes as placeholders had a small but noticeable impact on the speed of unit tests run in total.
Note
The ‘slot’ index numbers are named and stored in a constant file to ensure a single value of truth. This allows the composite to be easily amended in future releases.The string character count of certain spacers are calculated from components with strings of variable character count. This includes calculations that ensure some number columns remain right aligned and other component columns remain left aligned.
There are three main task phases to the method:
- Resolve values for the message variable components.
- Resolve all spacer component values.
- Assign components to the composite array from the resolved values and constants stored in PrintConstants.
Declaration
Swift
func compileSequentialComposite(_ printNumber: Int, _ messageToPrint: EntityLog.Message, _ nodeType: NodeType, _ settings: SettingsManagerService, _ formatting: FormattingManagerService, _ functionName: String? = nil, _ values: Any? = nil) -> [String]
Parameters
printNumber
An Int representing a unique number used as a key to access a specific associated message from a dictionary containing all message data.
messageToPrint
An EntityLog.Message instance representing the message associated with
printNumber
.settings
A SettingsManagerService instance.
formatting
A FormattingManagerService instance.
functionName
An optional String representing the function name derived from a
#function
macro argument provided to the relevant public Clarity print overloads.values
An optional parameter for the inclusion of variable values to be printed as part of the message. The parameter can be a single value of any type, a
Collection
of any type or an instance conforming to theError
protocol.Return Value
An array of String components that include the composite elements that can be concatenated into a print message for a given print number.
-
resolveNodeTypeGroup(_:
Extension method_: _: ) A method that resolves the NodeType of a message from the given parameters and returns the NodeType case.
This method divides NodeTypes into three distinct categories: control nodes, function name or values depending on the presence of particular arguments.
If a print statement contains an argument for either the
functionName
orvalues
parameter any control node NodeType set for the print number will be overridden. The message will then be formatted as a function name or a value reporter depending on the argument regardless of the messagenodeType
property derived from JSON.This method checks for the existence of an argument for either the
functionName
orvalues
parameter of the print statement and resolves the NodeType accordingly.There are two main task phases to the method:
- Evaluate
functionName
: if the argument is nil or a blank string set the node type case to the value of the messagenodeType
property derived from JSON. Otherwise set the node type case to.functionName
. - Evaluate
values
: if the argument is not nil and it conforms to theError
protocol overwrite the node type case to.errorReporter
otherwise overwrite the node type case to.valueReporter
.Note
ThefunctionName
andvalues
parameters will never both have arguments in the same call.
Declaration
Parameters
messageToPrint
An EntityLog.Message instance representing the message associated with a print number.
functionName
An optional String representing the function name derived from a
#function
macro argument provided to the relevant public Clarity print overloads.values
An optional parameter for the inclusion of variable values to be printed as part of the message. The parameter can be a single value of any type, a
Collection
of any type or an instance conforming to theError
protocol.Return Value
The NodeType case of
messageToPrint
. - Evaluate
-
symbolsFromFormatting(_:
Extension method_: _: _: _: ) A method that returns as inout parameters the control flow node symbols and function type symbols to include in a message string according to the given parameters.
The method switches on the incoming NodeType and FunctionType case parameter arguments and assigns symbol values derived from the Formatting JSON data to the
inout
parameters.Note
This method divides NodeTypes into three distinct categories: control flow nodes, outcome types or function types depending on the column the symbol is placed.If the
nodeType
parameter is afunctionName
case the two Switch statements onnodeType
will default and theinout
parameters will remain unchanged as empty strings. The Switch statement onfunctionType
will assign a value tofunctionTypeSymbol
on all calls (all Message instances have a FunctionType if not a function type symbol). If thenodeType
parameter is not afunctionName
case the value will be ignored by the method that concatenates message strings.Declaration
Swift
func symbolsFromFormatting(_ nodeType: NodeType, _ functionType: FunctionType, _ controlFlowNodeSymbol: inout String, _ outcomeTypeSymbol: inout String, _ functionTypeSymbol: inout String)
Parameters
nodeType
A
NodeType
case.functionType
A
FunctionType
case.controlFlowNodeSymbol
A String
inout
parameter that returns the control flow node symbol that represents the incomingnodeType
argument.outcomeTypeSymbol
A String
inout
parameter that returns the ‘semantic outcome’ symbol that represents the incomingnodeType
argument.functionTypeSymbol
A String
inout
parameter that returns the function ‘type’ symbol that represents the incomingfunctionType
argument. -
totalPlaces(from:
Extension method) A method that takes an Int value and returns its total number of digit places as an Int.
There are two main task phases to the method:
- If the value of integer is 0 return the value 1. Zero is not a valid argument for calculating log 10 but zero is a possible value of an integer.
- Calculate the number of digit places in the number using the
log10(_:)
function. This requires convertinginteger
into aDouble
and adding 1 to the result ( the log 10 of a single digit equates to 0). - Convert the
Double
back into anInt
for the return.
Note
This method is a candidate for converting into an extension method on Int.
Declaration
Swift
func totalPlaces(from integer: Int) -> Int
Parameters
integer
An Int representing the number that requires its number of digit places calculated.
Return Value
An Int value that is the total number of digit places in the
integer
parameter . -
spacerFromInversePlaces(_:
Extension method_: ) A method that calculates the inverse number of digit places in a number based on a maximum of 5 digit places and a minimum of 1 digit place. It then returns a blank spacer string of the calculated length as an inout parameter.
The inverse number is assigned to the parameter
count
of the String initialiserinit(repeating: count:)
with a single space String assigned to the parameterrepeating
to create a blank spacer string of the specified length.Note
The returned spacer is used to compile strings containing column elements that are correctly justified based on the variable content of other elements adjacent to them in the string.The basis of a maximum of 5 digit places is predicated on the notion that a client project using Clarity would never require the use of a maximum function number or print number exceeding 99,999.
A future release could add a
max
parameter to this method allowing for an unlimited number of function and print numbers usable in Clarity (although this would be an improbable requirement).Declaration
Swift
func spacerFromInversePlaces(_ integer: Int?, _ inverseDigitPlacesSpacer: inout String)
Parameters
integer
An Int representing a number that requires the inverse number of digit places calculated.
inverseDigitPlacesSpacer
A String
inout
parameter for the return of a blank spacer that has a character count equal to the total inverse number of digit places in theinteger
parameter based on a maximum of 5 digit places. -
calculateEntityCodeDifferentialSpacer(_:
Extension method_: _: ) A method that calculates the difference between the maximum character count of all EntityLog EntityCodes and a given EntityCode count. It then returns a blank spacer string of the calculated length as an inout parameter.
Note
The returned differential spacer is applied to all message string types in the composite slot position following the slot for the
EntityCode
value. All following components in the message will be moved forward by the count of the differential spacer and thereby align with messages containing anEntityCode
with a different character count. If a message belongs to anEntityLog
with anEntityCode
that is equal to the maximum count the differential spacer will have the value of an empty string (and not be offset forward).Declaration
Swift
func calculateEntityCodeDifferentialSpacer(_ characterCount: Int, _ maxEntityCodeCharacterCount: Int, _ entityCodeDifferentialSpacer: inout String)
Parameters
characterCount
An Int representing the character count of a message
EntityCode
.maxEntityCodeCharacterCount
An Int representing the maximum character count of all EntityLog Entity Codes in a client application.
entityCodeDifferentialSpacer
A String
inout
parameter for the return of a blank spacer that has a character count equal to the difference betweenmaxEntityCodeCharacterCount
andcharacterCount
. -
readoutSpacer(fromComposite:
Extension method_: ) A method that returns an empty spacer that has a character count equal to the length of a message string up to the beginning of the slot position for a message event description (the readout).
The method takes a message component composite array as an argument for use to calculate the readout character count.
The returned empty spacer is used to ensure correct alignment between the message event description readout and subsequent readouts on following lines in the console (the effect description and/or value reports).
Important
Apple symbols return a character count value of 1 but use the space of two characters in the console. A client application can specify custom values for symbols: these could be set as ordinary String characters or Apple symbols therefore this method uses the extension methodsymbolSpaceCount()
to calculate the correct value from the JSON Formatting data.There are six main task phases to the method:
- Copy the incoming composite argument to two internal variables: this is required for the calculation of the symbol character count. The array extension method `arrayFromIndexes(_:) is a mutating function that changes the indexes of components in the array as a result of removing non-used elements: calling it twice on the same array would return the wrong components and / or produce an ‘out of bounds’ error.
- Get the state of the Bool
displayNodePrintNumberWhenUsingRelativeNumbering
: this is required for the conditional inclusion of some component indexes. - Create a union of the IndexSet constants containing all required component indexes.
- Use the IndexSets to filter both composite string array local variables to contain only the required component indexes using the array extension
arrayFromIndexes(_:)
. - Calculate the total string character count for all strings in both composite arrays.
- Return a blank spacer string with a character count equal to the combined total.
Note
functionTypeSymbol
is accounted for by the constantIndexSet
defaultReadoutSpacers
via its character count included inspacer_RJustifyAdjusterFromFunctionElements
.Declaration
Swift
func readoutSpacer(fromComposite composite: [String], _ settings: SettingsManagerService) -> String
Parameters
composite
An array of Strings that include composite elements that can be concatenated into message strings for a single print number.
settings
A SettingsManagerService instance.
Return Value
An empty String that has a character count equal to the length of a main message string up to the beginning of the slot position for a message event description readout.
-
compileStringsFromComposite(_:
Extension method_: _: _: _: _: _: _: ) A method that takes a String array of message elements for a single print number and concatenates a select composite within the array into message strings for printing to the console according to the given parameters. It then returns the message strings as
inout
parameters.The method also returns a Bool as an
inout
parameter that signifies whether there is a printable value for the effect description readout message string.The method sets relevant parameters required by the method
compileStringForPrintType(_:withComposite:)
that handles the task of concatenating the message string from selected composites.There are four main task phases to the method:
- Set the message
PrintType
according to a combination of itsNodeType
and relevant user settings. If theNodeType
case is.valueReporter
or.errorReporter
but has no value thePrintType
is set to the appropriate reporter case: this case occurs when the client application has set the print numbernode_type
JSON key to 11 or 12 but not supplied avalues
argument to the print statement with the intention of reporting a comment. - If the
NodeType
is equal to the case.valueReporter
set the messagePrintValueType
according to a combination of its value type and relevant user settings passing the value as an associated value. If theNodeType
case is.errorReporter
and the parametervalues
is anError
thePrintValueType
is set to.singleValue(single:)
with the result of callinglocalizedDescription
on the error passed as the associated value. - For all conditional node cases (non function name or value cases) set
printEffectString
to true and setcompiledStringForEffectPrint
by making an additional call tocompileStringForPrintType(_:withComposite:)
passing in the appropriate effectPrintType
case along with thecomposite
parameter argument. - Set
compiledStringForPrint
by callingcompileStringForPrintType(_:withComposite:)
passing in thePrintType
case along with thecomposite
parameter argument.
Declaration
Swift
func compileStringsFromComposite(_ composite: [String], _ nodeType: NodeType, _ settings: SettingsManagerService, _ values: Any?, _ printValueType: inout PrintValueType, _ compiledStringForPrint: inout String, _ printEffectString: inout Bool, _ compiledStringForEffectPrint: inout String)
Parameters
composite
An array of Strings that includes the composite elements that can be concatenated into a print message for a single print number.
nodeType
A
NodeType
case.settings
A SettingsManagerService instance.
values
An optional parameter for the inclusion of variable values to be printed as part of the message. The parameter can be a single value of any type, a
Collection
of any type or an instance conforming to theError
protocol.printValueType
A
PrintValueType
case.compiledStringForPrint
An
inout
String for the return of the main message line compiled from selected elements incomposite
.printEffectString
An
inout
Bool that signifies whethercompiledStringForEffectPrint
holds a value that should be printed to the console.compiledStringForEffectPrint
An
inout
String for the return of a secondary message line for effect readouts compiled from selected elements incomposite
. - Set the message
-
compileStringForPrintType(_:
Extension methodwithComposite: ) A method that takes a String array of message elements for a single print number and returns a select composite within the array concatenated into a single message string according to the given
PrintType
.There are four main task phases to the method:
- Get
IndexSet
constants of specific component indexes that have been sorted into related groups. - Create unions between specific
IndexSet
constants in a first phase of building the required indexes for eachPrintType
. - Switch on
printType
: create additional unions between relevant index sets and use them as arguments to filter the composite string array so that it only contains the required components for eachPrintType
case. - Concatenate and return the filtered array.
Note
The
IndexSet
for the effect message only includes component slots for readout values: the spacer is calculated separately by another method.Declaration
Swift
func compileStringForPrintType(_ printType: PrintType, withComposite initialComposite: [String]) -> String
Parameters
printType
A PrintType case.
initialComposite
An array of Strings that includes composite elements that can be concatenated into print messages for a single print number.
Return Value
A single String concatenated from a select composite of string elements that represent a message for the associated print number.
- Get
-
printCollectionValues(_:
Extension methodwithReadOutSpacer: ) A method that takes a generic collection of value items and a blank spacer string. It uses arguments to these parameters to print value messages to the console.
The inclusion of the given readout spacer ensures that the value strings are always aligned with other message readouts.
Collection values are printed as a list: dictionaries list each key-value pair, arrays list values by index, sets list values in random order.
There are three main task phases to the method:
- The collection is evaluated to identify its type.
- The collection is iterated according to its type so that the relevant string can be built and printed to the console.
- Each message is appended into a String array for the return value.
Note
The value messages are appended into a String array that is returned for testing purposes only.Declaration
Swift
@discardableResult func printCollectionValues<T>(_ collection: T, withReadOutSpacer readOutSpacer: String) -> [String] where T : Sequence
Parameters
collection
A generic collection that conforms to
Sequence
that contains values to be printed to the console.readOutSpacer
An empty String that has a character count equal to the length of a main message string up to the beginning of the slot position where a values message should begin.
Return Value
An array of value message instances: one element for each value in the collection.
-
printValue(_:
Extension methodwithReadOutSpacer: ) A method that takes a single value of any type and a blank spacer string. It uses arguments to these parameters to print a value message to the console.
The inclusion of the given readout spacer ensures that the value string is always aligned with other message readouts.
Note
The value message is returned for testing purposes only.
Declaration
Swift
@discardableResult func printValue(_ singleValue: Any, withReadOutSpacer readOutSpacer: String) -> String
Parameters
singleValue
A single value of type
Any
to be printed to the console.readOutSpacer
An empty String that has a character count equal to the length of a main message string up to the beginning of the slot position where a value message should begin.
Return Value
A String value message.
-
printAlertForDetectedOrphanPrintNumber(_:
Extension method) A method that prints an alert and advice message when a Clarity statement is called in a client application that passes a print number argument not listed in any EntityLog JSON file.
This alert will only be printed if the client application user setting
alertOrphanedPrintNumbersDetected
is set to true.Declaration
Swift
func printAlertForDetectedOrphanPrintNumber(_ printNumber: Int)
Parameters
printNumber
An Int representing the print number that has no associated EntityLog JSON file.