Computer Assisted Medical Intervention Tool Kit  version 6.0
Loading...
Searching...
No Matches
/build/camitk-9Ht7pk/camitk-6.0.0/sdk/libraries/extensiongenerator/TransformEngine.h

Utility class to transform strings depending on json object values.

Utility class to transform strings depending on json object values This is inspired by inja but is much much much more basic.

The template string can contains loops, conditions and variable fields.

Example

Example using templateStr

// code for $name$ (class $upperCamelCase(name)$) or $upperSnakeCase(name)$
// generated on $date()$ $time()$
@for@ $param$ in $parameters$
param = addParameter(new Property("$param.name$", $param.defaultValue$, tr("$param.description$"), "$param.unit$"));
@if@ $param.readOnly$
param->setReadOnly(true);
@else@
// param is not read only
@endif@
@subfor@ $ev$ in $param.enumValues$
// value: $ev$
@endsubfor@
@endfor@
@if@ $name$
// given name: $name$
@else@
// no given name
@endif@
@if@ $option$
// option: $option$
@else@
// no option
@endif@
@if@ $optionList$
// optionList is given
@for@ $o$ in $optionList$
// option: $o$
@endfor@
@else@
// no optionlist
@endif@

and data the given json data:

{
"name": "test data",
"optionList": [
"option1",
"option2",
false,
-5,
0
],
"parameters": [
{
"defaultValue": 100,
"description": "Testing double",
"name": "testDouble",
"readOnly": false,
"type": "double",
"unit": ""
},
{
"defaultValue": "QVector3D(0.0, 0.0, 0.0)",
"description": "test 3D vector",
"name": "testVector3D",
"readOnly": true,
"type": "QVector3D",
"unit": "mm"
},
{
"defaultValue": 1,
"description": "test enum",
"enumValues": [
"V1",
"V2",
"V3"
],
"name": "testenum",
"readOnly": false,
"type": "enum",
"unit": "mm"
}
]
}

then calling:

transformToString(templateStr, data)

will produce:

// code for test data (class TestData) or TEST_DATA
// generated on 2024-05-16 18:25:08
param = addParameter(new Property("testDouble", 100.0, tr("Testing double"), ""));
// param is not read only
param = addParameter(new Property("testVector3D", QVector3D(0.0, 0.0, 0.0), tr("test 3D vector"), "mm"));
param->setReadOnly(true);
param = addParameter(new Property("testenum", 1.0, tr("test enum"), "mm"));
// param is not read only
// value: V1
// value: V2
// value: V3
// given name: test data
// no option
// optionList is given
// option: option1
// option: option2
// option: false
// option: -5.0
// option: 0.0

Functions

The following utility functions can be used in the template file (see example table below):

  • $date()$ → generation date as YYYY-MM-DD
  • $year()$, $month()$, $day()$ → respectively current year (as YYYY), month (1 to 12) and day (1 to 31)
  • $time()$ → generation time as HH:MM:SS
  • $index(p)$ → index of the current p in a loop (-1 if the template engine is outside a loop)
  • $title(var)$ → clean var (remove everything that is not space nor letters) and capitalize the first letter of every words
  • $lowerCamelCase(var)$ → same as titleCase but remove non-alphanumeric characters except underscores, first letter is lowercase and all space between words are removed
  • $upperCamelCase(var)$ → same as camelCase but first letter is uppercase
  • $lowerSnakeCase(var)$ → same as titleCase but remove non-alphanumeric characters except underscores, all space between words are replaced by an underscore and all letters are lowercase
  • $upperSnakeCase(var)$ → same as lowerSnakeCase but all letters are uppercase
  • $kebabCase(var)$ → same as lowerCamelCase but all letters are lowercase and words are separated by "-"
  • $joinKebabCase(var)$ → same as kebabCase but all words are joined (no separator)
Input Function Output
"my class name! 123 (test)" title "My Class Name! 123 (test)"
"my class name! 123 (test)" lowerCamelCase "myClassName123Test"
"my class name! 123 (test)" upperCamelCase "MyClassName123Test"
"my class name! 123 (test)" lowerSnakeCase "my_class_name_123_test"
"my class name! 123 (test)" upperSnakeCase "MY_CLASS_NAME_123_TEST"
"my class name! 123 (test)" kebabCase "my-class-name-123-test"
"my class name! 123 (test)" joinKebabCase "myclassname123test"

for statement

Used for array to loop over each value

@for@ $i$ in $array$
... // here $i takes the value of a[i]
... // $i.j$ corresponds to a[i].j
@endfor@

Loop inside loop are supported using @subfor@..@endsubfor@

if statement

In if statement you can use the contains and equals as well (this can also be used in loops):

  • @if@ contains($field$) ... @endif@ → check if data contains field
  • @if@ contains($object.field$) ... @endif@ → check if data contains object that contains field
  • @if@ equals($a$,"yes") yes @else@ no @endif@ → check if the value of data a is equals to "yes"
  • @for@ $i$ in $a$ @if@ equals($i.b$,"foo") $index(i)$ has b==foo ($i.b$), @else@ $index(i)$ does not have b==foo, @endif@ @endfor@ → check if each value of i in a are equals to "foo"
  • @if@ $parameter$ ...@endif@ → check if parameter can be evaluated to true, i.e.:
    • parameter is present in the data
    • and it is not null nor of undefined value
    • and is either
      • a boolean and equals to true
      • a string but not empty, nor null nor equals to "false"
      • a double but not equals to 0.0
      • an int but not equals to 0
      • an array, a map or an object but not empty

Algorithm

The main algorithm has three steps

  1. replace loop 1.1 replace functions inside loop 1.2 replace loop inside loop 1.3 replace conditions inside loop 1.4 replace variables inside loop
  2. replace conditions
  3. replace variables
  4. replace functions
/*****************************************************************************
* $CAMITK_LICENCE_BEGIN$
*
* CamiTK - Computer Assisted Medical Intervention ToolKit
* (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
*
* Visit http://camitk.imag.fr for more information
*
* This file is part of CamiTK.
*
* CamiTK is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* CamiTK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with CamiTK. If not, see <http://www.gnu.org/licenses/>.
*
* $CAMITK_LICENCE_END$
****************************************************************************/
#ifndef __TRANSFORM_ENGINE__
#define __TRANSFORM_ENGINE__
#include <QJsonObject>
public:
TransformEngine(QDate currentDate, QTime currentTime);
bool setTemplateString(QString templateString);
// or a function (e.g. "/tmp/$upperCamelCase(name)$.h" will use upperCamelCase(data[name]) to determine the actual filename)
bool transformToFile(const QJsonObject& data, const QString& filename, bool overwrite = true);
QString transformToString(const QString& templateString, const QJsonObject& data);
private:
QString templateString;
QDate currentDate;
QTime currentTime;
int indexInLoop;
int indexInSubLoop;
QString transformLoop(const QString& textToTransform, const QJsonObject& data);
QString transformCondition(const QString& textToTransform, const QJsonObject& data);
QString transformVariable(const QString& textToTransform, const QJsonObject& data);
QString transformFunctions(const QString& textToTransform, const QJsonObject& data);
QString transformConditionInLoop(const QString& loopContent, const QJsonObject& loopContentData, const QString& variableName);
QString transformVariableInLoop(const QString& loopContent, const QJsonObject& loopContentData, const QString& variableName);
QString transformFunctionsInLoop(const QString& loopContent, const QJsonObject& loopContentData, const QString& variableName);
QString transformLoopInLoop(const QString& loopContent, const QJsonObject& loopContentData, const QString& variableName);
QString genericTransform(const QString& textToTransform, const QString& regularExpression, const std::function<QString(const QStringList&)>& matchFunction, bool withoutTrailingSpace = false);
QString substring(const QString& str, int startIndex, int endIndex = -1);
QString extractLeadingSpaces(const QString& str);
QString removeTrailingSpaces(const QString& str);
QString titleCase(const QString& str, const QString& separator = "");
QString clean(const QString& str);
QString camelCase(const QString& str, const QString& separator = "");
QVariant valueOf(const QJsonObject& data, const QString& key, const QString& subkey = QString());
QString append(QStringList& result, const QString& str, int startIndex = -1, int endIndex = -1, bool removeTrailingSpace = false);
QString appendWithoutTrailingSpace(QStringList& result, const QString& str, int startIndex = -1, int endIndex = -1);
bool saveToFile(const QString& content, const QString& filename, bool overwrite = true);
QString evaluateFunction(const QString& functionName, const QJsonObject& data, const QString& parameter, const QString& parameterField);
};
#endif // __TRANSFORM_ENGINE__
Definition TransformEngine.h:221
bool transformToFile(const QJsonObject &data, const QString &filename, bool overwrite=true)
transform the current template string using the given data and save it to filename
Definition TransformEngine.cpp:75
bool setTemplateString(QString templateString)
set the current template string
Definition TransformEngine.cpp:67
QString transformToString(const QString &templateString, const QJsonObject &data)
transform the given template using the given data to a string.
Definition TransformEngine.cpp:102
TransformEngine()
Constructor set up the date and time.
Definition TransformEngine.cpp:55