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.

  • 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:

    1. Initialise the default value for goForPrint to true.
    2. Initialise and set Bool values from derived specifications used for the verification calculations.
    3. 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.
    4. Evaluate the master override print scenarios from settings. If an evaluation succeeds reset goForPrint 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)
  • 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:

    1. Resolve values for the message variable components.
    2. Resolve all spacer component values.
    3. 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 the Error 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.

🦮🦮🦮 Composite helpers

  • 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 or values 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 message nodeType property derived from JSON.

    This method checks for the existence of an argument for either the functionName or values parameter of the print statement and resolves the NodeType accordingly.

    There are two main task phases to the method:

    1. Evaluate functionName: if the argument is nil or a blank string set the node type case to the value of the message nodeType property derived from JSON. Otherwise set the node type case to .functionName.
    2. Evaluate values: if the argument is not nil and it conforms to the Error protocol overwrite the node type case to .errorReporter otherwise overwrite the node type case to .valueReporter.

      Note

      The functionName and values parameters will never both have arguments in the same call.

    Declaration

    Swift

    func resolveNodeTypeGroup(_ messageToPrint: EntityLog.Message, _ functionName: String?, _ values: Any?) -> NodeType

    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 the Error protocol.

    Return Value

    The NodeType case of messageToPrint.

  • 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 a functionName case the two Switch statements on nodeType will default and the inout parameters will remain unchanged as empty strings. The Switch statement on functionType will assign a value to functionTypeSymbol on all calls (all Message instances have a FunctionType if not a function type symbol). If the nodeType parameter is not a functionName 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 incoming nodeType argument.

    outcomeTypeSymbol

    A String inout parameter that returns the ‘semantic outcome’ symbol that represents the incoming nodeType argument.

    functionTypeSymbol

    A String inout parameter that returns the function ‘type’ symbol that represents the incoming functionType 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:

    1. 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.
    2. Calculate the number of digit places in the number using the log10(_:) function. This requires converting integer into a Double and adding 1 to the result ( the log 10 of a single digit equates to 0).
    3. Convert the Double back into an Int 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 .

  • 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 initialiser init(repeating: count:) with a single space String assigned to the parameter repeating 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 the integer parameter based on a maximum of 5 digit places.

  • 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 an EntityCode with a different character count. If a message belongs to an EntityLog with an EntityCode 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 between maxEntityCodeCharacterCount and characterCount.

  • 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 method symbolSpaceCount() to calculate the correct value from the JSON Formatting data.

    There are six main task phases to the method:

    1. 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.
    2. Get the state of the Bool displayNodePrintNumberWhenUsingRelativeNumbering: this is required for the conditional inclusion of some component indexes.
    3. Create a union of the IndexSet constants containing all required component indexes.
    4. Use the IndexSets to filter both composite string array local variables to contain only the required component indexes using the array extension arrayFromIndexes(_:).
    5. Calculate the total string character count for all strings in both composite arrays.
    6. Return a blank spacer string with a character count equal to the combined total.

    Note

    functionTypeSymbol is accounted for by the constant IndexSet defaultReadoutSpacers via its character count included in spacer_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.

🎁 Compilation

  • 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:

    1. Set the message PrintType according to a combination of its NodeType and relevant user settings. If the NodeType case is .valueReporter or .errorReporter but has no value the PrintType is set to the appropriate reporter case: this case occurs when the client application has set the print number node_type JSON key to 11 or 12 but not supplied a values argument to the print statement with the intention of reporting a comment.
    2. If the NodeType is equal to the case .valueReporter set the message PrintValueType according to a combination of its value type and relevant user settings passing the value as an associated value. If the NodeType case is .errorReporter and the parameter values is an Error the PrintValueType is set to .singleValue(single:) with the result of calling localizedDescription on the error passed as the associated value.
    3. For all conditional node cases (non function name or value cases) set printEffectString to true and set compiledStringForEffectPrint by making an additional call to compileStringForPrintType(_:withComposite:) passing in the appropriate effect PrintType case along with the composite parameter argument.
    4. Set compiledStringForPrint by calling compileStringForPrintType(_:withComposite:) passing in the PrintType case along with the composite 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 the Error protocol.

    printValueType

    A PrintValueType case.

    compiledStringForPrint

    An inout String for the return of the main message line compiled from selected elements in composite.

    printEffectString

    An inout Bool that signifies whether compiledStringForEffectPrint 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 in composite.

  • 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:

    1. Get IndexSet constants of specific component indexes that have been sorted into related groups.
    2. Create unions between specific IndexSet constants in a first phase of building the required indexes for each PrintType.
    3. 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 each PrintType case.
    4. 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.

🖨 Print string(s) and values

  • 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:

    1. The collection is evaluated to identify its type.
    2. The collection is iterated according to its type so that the relevant string can be built and printed to the console.
    3. 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.

  • 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.

  • 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.