Rat (Release Audit Tool) results

The following document contains the results of Rat (Release Audit Tool).

*****************************************************
Summary
-------
Generated at: 2024-10-03T10:48:45+02:00

Notes: 0
Binaries: 1
Archives: 0
Standards: 61

Apache Licensed: 1
Generated Documents: 0

JavaDocs are generated, thus a license header is optional.
Generated files do not require license headers.

60 Unknown Licenses

*****************************************************

Files with unapproved licenses:

  .eclipse-pmd
  checkstyle-config.xml
  CODE_OF_CONDUCT.md
  CONTRIBUTING.md
  eclipseCleanUp.xml
  eclipseCodeFormatter.xml
  eclipseCodeTemplates.xml
  Jenkinsfile
  PMD.xml
  pom.xml
  README.md
  src/main/java/de/powerstat/phplib/templateengine/HandleUndefined.java
  src/main/java/de/powerstat/phplib/templateengine/intern/BlockManager.java
  src/main/java/de/powerstat/phplib/templateengine/intern/FileManager.java
  src/main/java/de/powerstat/phplib/templateengine/intern/package-info.java
  src/main/java/de/powerstat/phplib/templateengine/intern/VariableManager.java
  src/main/java/de/powerstat/phplib/templateengine/package-info.java
  src/main/java/de/powerstat/phplib/templateengine/TemplateEngine.java
  src/main/java/module-info.java
  src/site/asciidoc/architecture/01_introduction_and_goals.adoc
  src/site/asciidoc/architecture/02_architecture_constraints.adoc
  src/site/asciidoc/architecture/03_system_scope_and_context.adoc
  src/site/asciidoc/architecture/04_solution_strategy.adoc
  src/site/asciidoc/architecture/05_building_block_view.adoc
  src/site/asciidoc/architecture/06_runtime_view.adoc
  src/site/asciidoc/architecture/07_deployment_view.adoc
  src/site/asciidoc/architecture/08_concepts.adoc
  src/site/asciidoc/architecture/09_architecture_decisions.adoc
  src/site/asciidoc/architecture/10_quality_requirements.adoc
  src/site/asciidoc/architecture/11_technical_risks.adoc
  src/site/asciidoc/architecture/12_glossary.adoc
  src/site/asciidoc/architecture/about-arc42.adoc
  src/site/asciidoc/architecture/config.adoc
  src/site/asciidoc/index.adoc
  src/site/asciidoc/TemplateEngine.adoc
  src/test/java/de/powerstat/phplib/templateengine/intern/test/BlockManagerTests.java
  src/test/java/de/powerstat/phplib/templateengine/intern/test/FileManagerTests.java
  src/test/java/de/powerstat/phplib/templateengine/intern/test/package-info.java
  src/test/java/de/powerstat/phplib/templateengine/intern/test/VariableManagerTests.java
  src/test/java/de/powerstat/phplib/templateengine/package-info.java
  src/test/java/de/powerstat/phplib/templateengine/RunCucumberTest.java
  src/test/java/de/powerstat/phplib/templateengine/StepDefinitions.java
  src/test/java/de/powerstat/phplib/templateengine/test/HandleUndefinedTests.java
  src/test/java/de/powerstat/phplib/templateengine/test/package-info.java
  src/test/java/de/powerstat/phplib/templateengine/test/TemplateEngineTests.java
  src/test/java/module-info.java
  src/test/resources/de/powerstat/phplib/templateengine/templateengine.feature
  src/test/resources/junit-platform.properties
  src/test/resources/log4j2.properties
  src/test/resources/template5.tmpl
  src/test/resources/template6.tmpl
  src/test/resources/templates/template1.tmpl
  src/test/resources/templates/template10.tmpl
  src/test/resources/templates/template2.tmpl
  src/test/resources/templates/template3.tmpl
  src/test/resources/templates/template4.tmpl
  src/test/resources/templates/template7.tmpl
  src/test/resources/templates/template8.tmpl
  src/test/resources/templates/template9.tmpl
  src/test/test.iml

*****************************************************

*****************************************************
  Files with Apache License headers will be marked AL
  Binary files (which do not require any license headers) will be marked B
  Compressed archives will be marked A
  Notices, licenses etc. will be marked N
 !????? .eclipse-pmd
 !????? checkstyle-config.xml
 !????? CODE_OF_CONDUCT.md
 !????? CONTRIBUTING.md
 !????? eclipseCleanUp.xml
 !????? eclipseCodeFormatter.xml
 !????? eclipseCodeTemplates.xml
 !????? Jenkinsfile
  AL    LICENSE.md
 !????? PMD.xml
 !????? pom.xml
 !????? README.md
 !????? src/main/java/de/powerstat/phplib/templateengine/HandleUndefined.java
 !????? src/main/java/de/powerstat/phplib/templateengine/intern/BlockManager.java
 !????? src/main/java/de/powerstat/phplib/templateengine/intern/FileManager.java
 !????? src/main/java/de/powerstat/phplib/templateengine/intern/package-info.java
 !????? src/main/java/de/powerstat/phplib/templateengine/intern/VariableManager.java
 !????? src/main/java/de/powerstat/phplib/templateengine/package-info.java
 !????? src/main/java/de/powerstat/phplib/templateengine/TemplateEngine.java
 !????? src/main/java/module-info.java
 !????? src/site/asciidoc/architecture/01_introduction_and_goals.adoc
 !????? src/site/asciidoc/architecture/02_architecture_constraints.adoc
 !????? src/site/asciidoc/architecture/03_system_scope_and_context.adoc
 !????? src/site/asciidoc/architecture/04_solution_strategy.adoc
 !????? src/site/asciidoc/architecture/05_building_block_view.adoc
 !????? src/site/asciidoc/architecture/06_runtime_view.adoc
 !????? src/site/asciidoc/architecture/07_deployment_view.adoc
 !????? src/site/asciidoc/architecture/08_concepts.adoc
 !????? src/site/asciidoc/architecture/09_architecture_decisions.adoc
 !????? src/site/asciidoc/architecture/10_quality_requirements.adoc
 !????? src/site/asciidoc/architecture/11_technical_risks.adoc
 !????? src/site/asciidoc/architecture/12_glossary.adoc
 !????? src/site/asciidoc/architecture/about-arc42.adoc
 !????? src/site/asciidoc/architecture/config.adoc
  B     src/site/asciidoc/architecture/images/arc42-logo.png
 !????? src/site/asciidoc/index.adoc
 !????? src/site/asciidoc/TemplateEngine.adoc
 !????? src/test/java/de/powerstat/phplib/templateengine/intern/test/BlockManagerTests.java
 !????? src/test/java/de/powerstat/phplib/templateengine/intern/test/FileManagerTests.java
 !????? src/test/java/de/powerstat/phplib/templateengine/intern/test/package-info.java
 !????? src/test/java/de/powerstat/phplib/templateengine/intern/test/VariableManagerTests.java
 !????? src/test/java/de/powerstat/phplib/templateengine/package-info.java
 !????? src/test/java/de/powerstat/phplib/templateengine/RunCucumberTest.java
 !????? src/test/java/de/powerstat/phplib/templateengine/StepDefinitions.java
 !????? src/test/java/de/powerstat/phplib/templateengine/test/HandleUndefinedTests.java
 !????? src/test/java/de/powerstat/phplib/templateengine/test/package-info.java
 !????? src/test/java/de/powerstat/phplib/templateengine/test/TemplateEngineTests.java
 !????? src/test/java/module-info.java
 !????? src/test/resources/de/powerstat/phplib/templateengine/templateengine.feature
 !????? src/test/resources/junit-platform.properties
 !????? src/test/resources/log4j2.properties
 !????? src/test/resources/template5.tmpl
 !????? src/test/resources/template6.tmpl
 !????? src/test/resources/templates/template1.tmpl
 !????? src/test/resources/templates/template10.tmpl
 !????? src/test/resources/templates/template2.tmpl
 !????? src/test/resources/templates/template3.tmpl
 !????? src/test/resources/templates/template4.tmpl
 !????? src/test/resources/templates/template7.tmpl
 !????? src/test/resources/templates/template8.tmpl
 !????? src/test/resources/templates/template9.tmpl
 !????? src/test/test.iml
 
*****************************************************

 Printing headers for text files without a valid license header...
 
=====================================================
== File: .eclipse-pmd
=====================================================
<?xml version="1.0" encoding="UTF-8"?>
<eclipse-pmd xmlns="http://acanda.ch/eclipse-pmd/0.8" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://acanda.ch/eclipse-pmd/0.8 http://acanda.ch/eclipse-pmd/eclipse-pmd-0.8.xsd">
  <analysis enabled="true" />
  <rulesets>
    <ruleset name="PowerStat Rules" ref="PMD.xml" refcontext="project" />
  </rulesets>
</eclipse-pmd>

=====================================================
== File: checkstyle-config.xml
=====================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" "https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
  <property name="severity" value="warning"/>

  <module name="TreeWalker">
    <!-- Annotations -->
    <module name="AnnotationLocation">
      <property name="allowSamelineMultipleAnnotations" value="false"/>
      <property name="allowSamelineSingleParameterlessAnnotation" value="true"/>
      <property name="allowSamelineParameterizedAnnotation" value="false"/>
      <property name="tokens" value="CLASS_DEF, INTERFACE_DEF, PACKAGE_DEF, ENUM_CONSTANT_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF, RECORD_DEF, COMPACT_CTOR_DEF"/>
    </module>
    <!--
    <module name="AnnotationOnSameLine">
      <property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF, RECORD_DEF, COMPACT_CTOR_DEF"/>
    </module>
    -->
    <module name="AnnotationUseStyle">
      <property name="closingParens" value="never"/>
      <property name="elementStyle" value="compact"/>
      <property name="trailingArrayComma" value="never"/>
    </module>
    <module name="MissingDeprecated">
      <property name="violateExecutionOnNonTightHtml" value="false"/>
    </module>
    <module name="MissingOverride">
      <property name="javaFiveCompatibility" value="false"/>
    </module>
    <module name="PackageAnnotation">
    </module>
    <module name="SuppressWarnings">
      <property name="format" value="^\s*+$"/>
      <property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF, ENUM_CONSTANT_DEF, PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF, CTOR_DEF, COMPACT_CTOR_DEF, RECORD_DEF"/>
    </module>
    <module name="SuppressWarningsHolder">
      <property name="aliasList" value=""/>
    </module>

    <!-- Block Checks -->
    <module name="AvoidNestedBlocks">
      <property name="severity" value="warning"/>
      <property name="allowInSwitchCase" value="false"/>
    </module>
    <module name="EmptyBlock">
      <property name="severity" value="warning"/>
      <property name="option" value="text"/>
      <property name="tokens" value="LITERAL_WHILE, LITERAL_TRY, LITERAL_FINALLY, LITERAL_DO, LITERAL_IF, LITERAL_ELSE, LITERAL_FOR, INSTANCE_INIT, STATIC_INIT, LITERAL_SWITCH, LITERAL_SYNCHRONIZED"/>
    </module>
    <module name="EmptyCatchBlock">

=====================================================
== File: CODE_OF_CONDUCT.md
=====================================================
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or
  advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
  address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies within all project spaces, and it also applies when
an individual is representing the project or its community in public spaces.
Examples of representing a project or community include using an official

=====================================================
== File: CONTRIBUTING.md
=====================================================
# How to contribute

## Code of Conduct

This project and everyone participating in it is governed by the [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [powerstat@web.de](mailto:powerstat@web.de).

## I don't want to read this whole thing I just have a question!!!

> **Note:** Please don't file an issue to ask a question. You'll get faster results by using the resources below.

* [EMail](mailto:powerstat@web.de)

## How to report bugs or enhancements

### Reporting Bugs

#### Before Submitting A Bug Report

#### How Do I Submit A (Good) Bug Report?

### Suggesting Enhancements

#### Before Submitting An Enhancement Suggestion

#### How Do I Submit A (Good) Enhancement Suggestion?

## Design Decisions

## Styleguides

### Git Commit Messages

### Issue and Pull Request Labels

### Java Styleguide
#### Package Conventions
### PowerStat's TemplateEngine and Packages

### Documentation Styleguide

### Coding conventions

## How to set up your environment and run tests

## Testing

We have JUnit 5 based unittests, please write tests for new code you create.




=====================================================
== File: eclipseCleanUp.xml
=====================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="2">
<profile kind="CleanUpProfile" name="PowerStat" version="2">
<setting id="cleanup.use_autoboxing" value="false"/>
<setting id="cleanup.qualify_static_method_accesses_with_declaring_class" value="false"/>
<setting id="cleanup.always_use_this_for_non_static_method_access" value="false"/>
<setting id="cleanup.organize_imports" value="true"/>
<setting id="cleanup.remove_trailing_whitespaces_ignore_empty" value="false"/>
<setting id="cleanup.use_directly_map_method" value="true"/>
<setting id="cleanup.format_source_code_changes_only" value="false"/>
<setting id="cleanup.qualify_static_field_accesses_with_declaring_class" value="false"/>
<setting id="cleanup.add_generated_serial_version_id" value="false"/>
<setting id="cleanup.remove_redundant_semicolons" value="true"/>
<setting id="cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class" value="true"/>
<setting id="cleanup.remove_redundant_type_arguments" value="true"/>
<setting id="cleanup.remove_unused_imports" value="true"/>
<setting id="cleanup.insert_inferred_type_arguments" value="false"/>
<setting id="cleanup.make_private_fields_final" value="true"/>
<setting id="cleanup.use_lambda" value="true"/>
<setting id="cleanup.simplify_lambda_expression_and_method_ref" value="false"/>
<setting id="cleanup.always_use_blocks" value="true"/>
<setting id="cleanup.use_this_for_non_static_field_access_only_if_necessary" value="false"/>
<setting id="cleanup.sort_members_all" value="false"/>
<setting id="cleanup.remove_trailing_whitespaces_all" value="true"/>
<setting id="cleanup.add_missing_annotations" value="true"/>
<setting id="cleanup.remove_unnecessary_array_creation" value="true"/>
<setting id="cleanup.always_use_this_for_non_static_field_access" value="true"/>
<setting id="cleanup.make_parameters_final" value="true"/>
<setting id="cleanup.sort_members" value="false"/>
<setting id="cleanup.remove_private_constructors" value="true"/>
<setting id="cleanup.always_use_parentheses_in_expressions" value="true"/>
<setting id="cleanup.remove_unused_local_variables" value="false"/>
<setting id="cleanup.convert_to_enhanced_for_loop" value="true"/>
<setting id="cleanup.remove_unused_private_fields" value="true"/>
<setting id="cleanup.remove_redundant_modifiers" value="true"/>
<setting id="cleanup.never_use_blocks" value="false"/>
<setting id="cleanup.number_suffix" value="true"/>
<setting id="cleanup.add_missing_deprecated_annotations" value="true"/>
<setting id="cleanup.use_this_for_non_static_field_access" value="true"/>
<setting id="cleanup.remove_unnecessary_nls_tags" value="true"/>
<setting id="cleanup.qualify_static_member_accesses_through_instances_with_declaring_class" value="true"/>
<setting id="cleanup.add_missing_nls_tags" value="false"/>
<setting id="cleanup.remove_unnecessary_casts" value="true"/>
<setting id="cleanup.use_unboxing" value="false"/>
<setting id="cleanup.use_blocks_only_for_return_and_throw" value="false"/>
<setting id="cleanup.format_source_code" value="false"/>
<setting id="cleanup.convert_functional_interfaces" value="true"/>
<setting id="cleanup.add_default_serial_version_id" value="true"/>
<setting id="cleanup.remove_unused_private_methods" value="true"/>
<setting id="cleanup.remove_trailing_whitespaces" value="true"/>

=====================================================
== File: eclipseCodeFormatter.xml
=====================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="18">
<profile kind="CodeFormatterProfile" name="PowerStat" version="18">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="0"/>

=====================================================
== File: eclipseCodeTemplates.xml
=====================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?><templates><template autoinsert="false" context="catchblock_context" deleted="false" description="Code in new catch blocks" enabled="true" id="org.eclipse.jdt.ui.text.codetemplates.catchblock" name="catchblock"/></templates>

=====================================================
== File: Jenkinsfile
=====================================================
pipeline
 {
  agent any


  tools
   {
    maven 'Maven3'
    jdk 'JDK11'
    git 'GIT'
   }


  options
   {
    buildDiscarder(logRotator(numToKeepStr: '4'))
    skipStagesAfterUnstable()
    disableConcurrentBuilds()
   }


  triggers
   {
    // MINUTE HOUR DOM MONTH DOW
    pollSCM('H 6-18/4 * * 1-5')
   }


  environment
   {
    DISABLE_AUTH = 'true'
    expectedRemoteUrl = "https://github.com/PowerStat/TemplateEngine.git"
   }


  stages
   {
    stage('Clean')
     {
      steps
       {
        script
         {
          if (isUnix())
           {
            sh 'mvn --batch-mode clean'
           }
          else
           {
            bat 'mvn --batch-mode clean'

=====================================================
== File: PMD.xml
=====================================================
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="PowerStat Rules" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
  <description>This ruleset checks the code for discouraged programming constructs.</description>

  <!-- Apex Rules -->
  <!-- not used -->

  <!-- Ecmascript Rules -->
  <!-- Ecmascript best practices -->
  <rule ref="category/ecmascript/bestpractices.xml/AvoidWithStatement" />
  <rule ref="category/ecmascript/bestpractices.xml/ConsistentReturn" />
  <rule ref="category/ecmascript/bestpractices.xml/GlobalVariable" />
  <rule ref="category/ecmascript/bestpractices.xml/ScopeForInVariable" />
  <rule ref="category/ecmascript/bestpractices.xml/UseBaseWithParseInt" />

  <!-- Ecmascript code style -->
  <rule ref="category/ecmascript/codestyle.xml/AssignmentInOperand">
    <properties>
      <property name="allowIf" value="false" />
      <property name="allowFor" value="false" />
      <property name="allowWhile" value="false" />
      <property name="allowTernary" value="false" />
      <property name="allowTernaryResults" value="false" />
      <property name="allowIncrementDecrement" value="false" />
    </properties>
  </rule>
  <rule ref="category/ecmascript/codestyle.xml/ForLoopsMustUseBraces" />
  <rule ref="category/ecmascript/codestyle.xml/IfElseStmtsMustUseBraces" />
  <rule ref="category/ecmascript/codestyle.xml/IfStmtsMustUseBraces" />
  <rule ref="category/ecmascript/codestyle.xml/NoElseReturn" />
  <rule ref="category/ecmascript/codestyle.xml/UnnecessaryBlock" />
  <rule ref="category/ecmascript/codestyle.xml/UnnecessaryParentheses" />
  <rule ref="category/ecmascript/codestyle.xml/UnreachableCode" />
  <rule ref="category/ecmascript/codestyle.xml/WhileLoopsMustUseBraces" />

  <!-- Ecmascript error prone -->
  <rule ref="category/ecmascript/errorprone.xml/AvoidTrailingComma">
    <properties>
      <property name="allowObjectLiteral" value="false" />
      <property name="allowArrayLiteral" value="false" />
    </properties>
  </rule>
  <rule ref="category/ecmascript/errorprone.xml/EqualComparison" />
  <rule ref="category/ecmascript/errorprone.xml/InnaccurateNumericLiteral" />

  <!-- HTML Rules -->
  <!-- HTML best practices -->
  <!-- <rule ref="category/html/bestpractices.xml/AvoidInlineStyles" /> requires 6.45 -->
  <!-- <rule ref="category/html/bestpractices.xml/UnnecessaryTypeAttribute" /> requires 6.45 -->
  <!-- <rule ref="category/html/bestpractices.xml/UseAltAttributeForImages" /> requires 6.45 -->

=====================================================
== File: pom.xml
=====================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>de.powerstat.toolbaseline</groupId>
    <artifactId>tbl-java-parent</artifactId>
    <version>17.2.0</version>
  </parent>

  <groupId>de.powerstat.phplib</groupId>
  <artifactId>templateengine</artifactId>
  <version>2.2.0</version>
  <packaging>jar</packaging>

  <name>PowerStatsTemplateEngine</name>
  <description>Java port of phplib template engine. See https://sourceforge.net/projects/phplib/ or https://pear.php.net/package/HTML_Template_PHPLIB for more.</description>
  <url>https://www.powerstat.de/TemplateEngine.html</url>

  <properties>
    <license.inceptionYear>2015</license.inceptionYear>
    
    <sonarTypeServer>ossrh</sonarTypeServer>
    <sonarTypeHost>oss.sonatype.org</sonarTypeHost>

  </properties>

  <distributionManagement>
    <site>
      <id>powerstat</id>
      <url>sftp://${web.server}/TemplateEngine/</url>
    </site>
  </distributionManagement>

  <scm>
    <connection>scm:git:https://github.com/PowerStat/TemplateEngine.git</connection>
    <developerConnection>scm:git:https://github.com/PowerStat/TemplateEngine.git</developerConnection>
    <url>https://github.com/PowerStat/TemplateEngine</url>
    <tag>V2.2.0</tag>
  </scm>

  <build>
    <plugins>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.4.2</version>
        <configuration>
          <archive>

=====================================================
== File: README.md
=====================================================
# PowerStat's TemplateEngine

This [TemplateEngine](https://www.powerstat.de/TemplateEngine.html) is a Java port with optimizations of the original PHPLib TemplateEngine.

See:

* [PHPLib](https://sourceforge.net/projects/phplib/)
* [PEAR - PHP Extension and Application Repository](https://pear.php.net/package/HTML_Template_PHPLIB)
* [Synopsis Coverity Scan TemplateEngine](https://scan.coverity.com/projects/templateengine?tab=overview)

## Installation

Because this library is only useful for developers the installation depends on your build environment.

For example when using Apache Maven you could add the following dependency to your project:

    <dependency>
      <groupId>de.powerstat.phplib</groupId>
      <artifactId>templateengine</artifactId>
      <version>2.2.0</version>
    </dependency>

Please add the following entry to your maven `settings.xml`:

    <server>
      <id>nvd</id>
      <password>nvd api-key</password>
    </server>

The API-Key could be requested here: [National Vulnerability Database](https://nvd.nist.gov/developers/request-an-api-key)

Other build tools like gradle will work analogous.

Java platform module system:

    module com.example.java.app
     {
      requires de.powerstat.phplib.templateengine;
     }

To compile this project yourself you could use:

    mvn clean install org.pitest:pitest-maven:mutationCoverage site
    
or simply:

     mvn clean install

or for native image creation:


=====================================================
== File: src/main/java/de/powerstat/phplib/templateengine/HandleUndefined.java
=====================================================
/*
 * Copyright (C) 2002-2003,2017-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */
package de.powerstat.phplib.templateengine;


/**
 * Enum for handling of undefined variables.
 */
public enum HandleUndefined
 {
  /**
   * Remove variables.
   */
  REMOVE(0),

  /**
   * Keep variables.
   */
  KEEP(1),

  /**
   * Change to XML comments.
   */
  COMMENT(2);


  /**
   * Action number.
   */
  private final int action;


  /**
   * Ordinal constructor.
   *
   * @param action Action number
   */
  HandleUndefined(final int action)
   {
    this.action = action;
   }


  /**
   * Get action number.
   *
   * @return Action number
   */
  public int getAction()

=====================================================
== File: src/main/java/de/powerstat/phplib/templateengine/intern/BlockManager.java
=====================================================
/*
 * Copyright (C) 2002-2003,2017-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */
package de.powerstat.phplib.templateengine.intern;


import java.util.Objects;
import java.util.regex.Pattern;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;


/**
 * Template block manager.
 */
public final class BlockManager
 {
  /* *
   * Logger.
   */
  // private static final Logger LOGGER = LogManager.getLogger(BlockManager.class);

  /**
   * Variable manager reference.
   */
  private final VariableManager variableManager;

  /* *
   * Temporary blocks map.
   */
  // private final Map<String, String> blocks = new ConcurrentHashMap<>();


  /**
   * Copy constructor.
   *
   * @param vManager Variable manager
   * @param bManager Block manager to copy from
   * @throws NullPointerException If vManager or bManager is null
   */
  @SuppressFBWarnings("EI_EXPOSE_REP2")
  public BlockManager(final VariableManager vManager, final BlockManager bManager)
   {
    super();
    Objects.requireNonNull(vManager, "vManager"); //$NON-NLS-1$
    Objects.requireNonNull(bManager, "bManager"); //$NON-NLS-1$
    this.variableManager = vManager;
    /*
    for (final Map.Entry<String, String> entry : bManager.blocks.entrySet())
     {

=====================================================
== File: src/main/java/de/powerstat/phplib/templateengine/intern/FileManager.java
=====================================================
/*
 * Copyright (C) 2002-2003,2017-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */
package de.powerstat.phplib.templateengine.intern;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;


/**
 * Template file manager.
 */
public final class FileManager
 {
  /**
   * Logger.
   */
  private static final Logger LOGGER = LogManager.getLogger(FileManager.class);

  /**
   * Maximum template size.
   */
  private static final int MAX_TEMPLATE_SIZE = 1048576;

  /**
   * File path separator.
   */
  private static final String FILEPATH_SEPARATOR = "/"; //$NON-NLS-1$

  /**
   * Variable manager reference.
   */
  private final VariableManager variableManager;


=====================================================
== File: src/main/java/de/powerstat/phplib/templateengine/intern/package-info.java
=====================================================
/*
 * Copyright (C) 2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */


/**
 * Internal implementations.
 */
package de.powerstat.phplib.templateengine.intern;

=====================================================
== File: src/main/java/de/powerstat/phplib/templateengine/intern/VariableManager.java
=====================================================
/*
 * Copyright (C) 2002-2003,2017-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */
package de.powerstat.phplib.templateengine.intern;


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


/**
 * Template variable manager.
 */
public final class VariableManager
 {
  /**
   * Logger.
   */
  private static final Logger LOGGER = LogManager.getLogger(VariableManager.class);

  /**
   * Template matcher regexp pattern.
   */
  private static final Pattern TEMPLATE_MATCHER_REGEXP = Pattern.compile("\\{([^{^}\n\r\t :]+)\\}"); //$NON-NLS-1$

  /**
   * Block matcher regexp.
   */
  private static final Pattern BLOCK_MATCHER_REGEXP = Pattern.compile("\\{([^ \\t\\r\\n}]+)\\}"); //$NON-NLS-1$

  /**
   * Temporary variables map.
   */
  private final Map<String, String> vars = new ConcurrentHashMap<>();


  /**
   * Copy constructor.
   *

=====================================================
== File: src/main/java/de/powerstat/phplib/templateengine/package-info.java
=====================================================
/*
 * Copyright (C) 2002-2003,2017-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */


/**
 * PHPLib like template engine.
 */
package de.powerstat.phplib.templateengine;

=====================================================
== File: src/main/java/de/powerstat/phplib/templateengine/TemplateEngine.java
=====================================================
/*
 * Copyright (C) 2002-2003,2017-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */
package de.powerstat.phplib.templateengine;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;

import de.powerstat.phplib.templateengine.intern.BlockManager;
import de.powerstat.phplib.templateengine.intern.FileManager;
import de.powerstat.phplib.templateengine.intern.VariableManager;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;


/**
 * PHPLib compatible template engine.
 *
 * Unconditionally thread safe.
 * Not serializable, because serialization is dangerous, use Protocol Buffers or JSON instead!
 *
 * @author Kai Hofmann
 * @see <a href="https://sourceforge.net/projects/phplib/">https://sourceforge.net/projects/phplib/</a>
 * @see <a href="https://pear.php.net/package/HTML_Template_PHPLIB">https://pear.php.net/package/HTML_Template_PHPLIB</a>
 */
public final class TemplateEngine
 {
  /* *
   * Logger.
   */
  // private static final Logger LOGGER = LogManager.getLogger(TemplateEngine.class);

  /**
   * Template name constant.
   */
  private static final String TEMPLATE = "template"; //$NON-NLS-1$

  /**
   * Template is empty message.
   */
  private static final String TEMPLATE_IS_EMPTY = "template is empty"; //$NON-NLS-1$

=====================================================
== File: src/main/java/module-info.java
=====================================================
/*
 * Copyright (C) 2019-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */


/**
 * Module for PowerStat's PHPLib like TemplateEngine.
 */
module de.powerstat.phplib.templateengine
 {
  exports de.powerstat.phplib.templateengine;

  // requires java.io;
  // requires java.nio;
  // requires java.util;

  requires org.apache.logging.log4j;
  requires com.github.spotbugs.annotations;

 }

=====================================================
== File: src/site/asciidoc/architecture/01_introduction_and_goals.adoc
=====================================================
[[section-introduction-and-goals]]
== Introduction and Goals

Far in the past there was the phplib template engine which was simple and easy to use. During working with this engine over some years I have optimized it and ported it to the java programming language.
During the time the template engine has been made more safe and secure by using static analysis tools.
Usage of this template engine is for webpages as well as for code generators and everything else you could imagine.

=== Requirements Overview

Functional requirements are:

* Has templates
* Can read templates from files
* Can replace variables within content
* Can append content to variables
* Can cut out blocks from templates/blocks and replace them with a variable
* Can have blocks within blocks

It is a small and fast template engine that divides cleanly between the designer and the software engineer.

.Further Information

* https://sourceforge.net/projects/phplib/[PHPLib]
* https://pear.php.net/package/HTML_Template_PHPLIB[PEAR - PHP Extension and Application Repository]

=== Quality Goals

The top quality goals are:

* Compatibility with phplib template engine
* Performace efficience
* Low memory usage
* Security/Safety
* Usability
* Transferability

=== Stakeholders

The first stakeholder is the developer itself for his other projects. Second stakeholders are all other java or jvm language developers around the world, because it's an open source project.

[options="header",cols="1,2,2"]
|===
|Role/Name|Contact|Expectations
|Kai Hofmann|powerstat@web.de|Stable api, secure, fast, simple
|Every developer|unknown|Stable api, secure, fast, simple
|===

=====================================================
== File: src/site/asciidoc/architecture/02_architecture_constraints.adoc
=====================================================
[[section-architecture-constraints]]
== Architecture Constraints

Architecture constraints are as follows:

* Open source
* Compatible in api and template format with the original phplib template engine
* Given configurations for CheckStyle, PMD, SpotBugs, SonarQube have to be used
* For documentation uml, javadoc and asciidoc have to be used

=====================================================
== File: src/site/asciidoc/architecture/03_system_scope_and_context.adoc
=====================================================
[[section-system-scope-and-context]]
== System Scope and Context

The System context is related to every Java programm or other languages that run on the jvm/graalvm.
Communication could happen via Strings, Files or Streams.


=== Business Context

The template engine is a library that could be used by other developers within the java / jvm context.


=== Technical Context

Technical interfaces in Java are:

* String (in/out)
* File (in)
* InputStream (in)

=====================================================
== File: src/site/asciidoc/architecture/04_solution_strategy.adoc
=====================================================
[[section-solution-strategy]]
== Solution Strategy

Java has been choosen as programming language, because it is widely used.

The template engine has been ported 1:1 in a first step and then improved over time.

To archive key quality goals free available static analysis tools have been introduced and the ruleset (if possible) have been self made for high quality. Also unit tests have been applied with using mutation testing (pitest) and high code coverage (jacoco).
Also Eclipse configurations to reach high quality have been made.

=====================================================
== File: src/site/asciidoc/architecture/05_building_block_view.adoc
=====================================================
[[section-building-block-view]]


== Building Block View

[plantuml, target=building-block, format=png]   
....
package de.powerstat.phplib.templateengine
{
  class TemplateEngine
  enum HandleUndefined
}

package java.io
{
}

package java.nio
{
}

package java.util
{
}

package org.apache.logging.log4j
{
}

java.io <-- de.powerstat.phplib.templateengine
java.nio <-- de.powerstat.phplib.templateengine
java.util <-- de.powerstat.phplib.templateengine
org.apache.logging.log4j <-- de.powerstat.phplib.templateengine
....


=== Whitebox Overall System

[plantuml, target=whitebox-diagram, format=png]   
....
package de.powerstat.phplib.templateengine
{
  enum HandleUndefined
   {
   }
  
  class TemplateEngine 
   {
    +{static} newInstance(engine : TemplateEngine) : TemplateEngine
    +{static} newInstance(file : File) : TemplateEngine

=====================================================
== File: src/site/asciidoc/architecture/06_runtime_view.adoc
=====================================================
[[section-runtime-view]]
== Runtime View

=== <Runtime Scenario 1>

[plantuml, target=activity-diagram1, format=png]   
....
(*) --> "newInstance(File)"
--> "setVar(varname, value)"
--> "finish(template)"
"finish(template)" --> (*)
....

=== <Runtime Scenario 2>

[plantuml, target=activity-diagram2, format=png]   
....
(*) --> "newInstance(InputStream)"
--> "setBlock(parent, varname, name)"
--> "setVar(varname, value)"
--> "parse(target, varname, append=false)"
--> "finish(template)"
"finish(template)" --> (*)
....

=== <Runtime Scenario 3>

[plantuml, target=activity-diagram3, format=png]   
....
(*) --> "newInstance(String)"
--> "setBlock(parent, varname, name)"
--> "setVar(varname, value1)"
--> "parse(target, varname, append=true)"
--> "setVar(varname, value2)"
--> "parse(target, varname, append=false)"
--> "finish(template)"
"finish(template)" --> (*)
....

=== <Runtime Scenario 4>

[plantuml, target=activity-diagram4, format=png]   
....
(*) --> "TemplateEngine(HandleUndefined)"
--> "setFile(newVarname, newFile)"
--> "setVar(varname, value)"
--> "finish(template)"
"finish(template)" --> (*)
....


=====================================================
== File: src/site/asciidoc/architecture/07_deployment_view.adoc
=====================================================
[[section-deployment-view]]


== Deployment View


=== Infrastructure Level 1

[plantuml, target=component-diagram, format=png]   
....
node "JVM/GraalVM" {
  [TemplateEngine.jar]
}
....

=====================================================
== File: src/site/asciidoc/architecture/08_concepts.adoc
=====================================================
[[section-concepts]]
== Cross-cutting Concepts

=== Domain concepts

To be done

=== Safety and security concepts

See development concepts

=== Architecture and design patterns

To be done.

=== Development concepts

* Java
* Maven
* CheckStyle with own rules
* PMD with own rules
* SpotBugs with plugins
* SonarQube
* Unit-Tests with pitest and jacoco

=====================================================
== File: src/site/asciidoc/architecture/09_architecture_decisions.adoc
=====================================================
[[section-design-decisions]]
== Architecture Decisions

* PHPLib template engine - because of it' simplenest
* Java - because its a better language than C++ and wide spread
* Block loop logic is still within the code and not in the template
* Template syntax is XML compatible but could also be used for code templates
* Clean Code
* Domain Driven Design

=====================================================
== File: src/site/asciidoc/architecture/10_quality_requirements.adoc
=====================================================
[[section-quality-scenarios]]
== Quality Requirements

=== Quality Tree

[plantuml, target=quality-tree, format=png]   
....
@startmindmap
* Quality tree
** Compatibility with phplib template engine
** Performace efficience
** Low memory usage
** Security/Safety
*** DDD Value/Entity objects
*** Static code analysis
*** Unit tests
** Usability
*** Simple api
*** Developer documentation
** Transferability
*** Java virtual machine
@endmindmap
....

=== Quality Scenarios

[plantuml, target=use-case, format=png]   
....
:Developer: --> (Generate output with variable content)
....

=====================================================
== File: src/site/asciidoc/architecture/11_technical_risks.adoc
=====================================================
[[section-technical-risks]]
== Risks and Technical Debts

The following risks exists at the moment:

* Unknown memory consumption
* Unknown performance issues
* Unknown security problems

=====================================================
== File: src/site/asciidoc/architecture/12_glossary.adoc
=====================================================
[[section-glossary]]
== Glossary

[cols="e,2e" options="header"]
|===
|Term |Definition

|Block
|Area that can be cut out from a template to replace it one or multiple times with new content

|GraalVM
|Graal virtual machine, successor of JVM

|Java
|The java programming language

|JVM
|Java virtual machine

|Template
|UTF-8 string with replaceable elements

|TemplateEngine
|A program that allows to replace variables and blocks within a template

|Variable
|A replaceable variable within a template
|===

=====================================================
== File: src/site/asciidoc/architecture/about-arc42.adoc
=====================================================
:homepage: https://arc42.org

:keywords: software-architecture, documentation, template, arc42

:numbered!:
**About arc42**

[role="lead"]
arc42, the template for documentation of software and system architecture.

Template Version {revnumber}. {revremark}, {revdate}

Created, maintained and (C) by Dr. Peter Hruschka, Dr. Gernot Starke and contributors.
See https://arc42.org.


=====================================================
== File: src/site/asciidoc/architecture/config.adoc
=====================================================
// asciidoc settings for EN (English)
// ==================================
:toc-title: table of contents

// enable table-of-contents
:toc:

// where are images located?
:imagesdir: ./images

=====================================================
== File: src/site/asciidoc/index.adoc
=====================================================
// header file for arc42-template,
// including all help texts
//
// ====================================

// configure EN settings for asciidoc
include::architecture/config.adoc[]

= image:architecture/arc42-logo.png[arc42] Template
:revnumber: 8.1 EN
:revdate: May 2022
:revremark: (based upon AsciiDoc version)
// toc-title definition MUST follow document title without blank line!
:toc-title: Table of Contents

//additional style for arc42 help callouts
ifdef::backend-html5[]
++++
<style>
.arc42help {font-size:small; width: 14px; height: 16px; overflow: hidden; position: absolute; right: 0; padding: 2px 0 3px 2px;}
.arc42help::before {content: "?";}
.arc42help:hover {width:auto; height: auto; z-index: 100; padding: 10px;}
.arc42help:hover::before {content: "";}
@media print {
	.arc42help {display:none;}
}
</style>
++++
endif::backend-html5[]


include::architecture/about-arc42.adoc[]

// horizontal line
***




// numbering from here on
:numbered:

<<<<
// 1. Introduction and Goals
include::architecture/01_introduction_and_goals.adoc[]

<<<<
// 2. Architecture Constraints
include::architecture/02_architecture_constraints.adoc[]


=====================================================
== File: src/site/asciidoc/TemplateEngine.adoc
=====================================================
= PHPLib template engine =
Kai Hofmann <powersta@web.de>
05.11.2022

== Background ==

This TemplateEngine is a Java port with optimizations of the original PHPLib TemplateEngine.

See:

https://sourceforge.net/projects/phplib/[PHPLIB]

https://pear.php.net/package/HTML_Template_PHPLIB[Pear\:\:HTML_Template_PHPLIB]

== Improvements ==

- unsetVar() has been added to allow to remove template variables.
- JUnit 5 tests have been added and improved with pitest.

== Optimizations ==

- The handling of unkown template variables has been changed to an enum instead of a string.
- The substitution algorithm for variables in templates has been changed so that the variables will be first extracted from the template/block and only these will be replaced (instead of always looping over all known variables).

== Usage example ==

include::../../test/java/de/powerstat/phplib/templateengine/test/TemplateEngineTests.java[tags=NonAppendBlock]

== Known problems ==

=== TemplateEngine replacement order ===

There is a known and not fixable problem with this TemplateEngine.

Assuming the following template file and for test1, test3 a value has been set:

    {test1} 
    <!-- BEGIN test2 --> 
    {test1} {test3}
    <!-- END test2 --> 
    {test3} 

Then after you did:

    engine.setBlock("file3", "test2");
    
and make the final template parse:

    engine.parse("output", "file3", false);
    

=====================================================
== File: src/test/java/de/powerstat/phplib/templateengine/intern/test/BlockManagerTests.java
=====================================================
/*
 * Copyright (C) 2019-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */
package de.powerstat.phplib.templateengine.intern.test;


import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

import de.powerstat.phplib.templateengine.intern.BlockManager;
import de.powerstat.phplib.templateengine.intern.VariableManager;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;


/**
 * Block manager tests.
 */
final class BlockManagerTests
 {
  /**
   * Not constructed constant.
   */
  private static final String NOT_CONSTRUCTED = "Not constructed";

  /**
   * Parent constant.
   */
  private static final String PARENT = "parent";

  /**
   * Block string constant.
   */
  private static final String BLKSTRING = "before<!-- BEGIN blktest -->content<!-- END blktest -->after";

  /**
   * Block test constant.
   */
  private static final String BLKTEST = "blktest";

  /**
   * Block name constant.
   */
  private static final String BLKNAME = "blkname";

=====================================================
== File: src/test/java/de/powerstat/phplib/templateengine/intern/test/FileManagerTests.java
=====================================================
/*
 * Copyright (C) 2019-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */
package de.powerstat.phplib.templateengine.intern.test;


import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.File;
import java.io.IOException;

import org.junit.jupiter.api.Test;

import de.powerstat.phplib.templateengine.intern.FileManager;
import de.powerstat.phplib.templateengine.intern.VariableManager;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;


/**
 * File manager tests.
 */
final class FileManagerTests
 {
  /**
   * Not constructed constant.
   */
  private static final String NOT_CONSTRUCTED = "Not constructed";

  /**
   * Filename1 constant.
   */
  private static final String FILENAME1 = "filename1";

  /**
   * Template 1 file name constant.
   */
  private static final String TEMPLATE1_FILE = "target/test-classes/templates/template1.tmpl";

  /**
   * Add file failed constant.
   */
  private static final String ADD_FILE_FAILED = "addFile failed";

  /**

=====================================================
== File: src/test/java/de/powerstat/phplib/templateengine/intern/test/package-info.java
=====================================================
/*
 * Copyright (C) 2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */


/**
 * UnitTests for PHPLib like template engine internals.
 */
package de.powerstat.phplib.templateengine.intern.test;

=====================================================
== File: src/test/java/de/powerstat/phplib/templateengine/intern/test/VariableManagerTests.java
=====================================================
/*
 * Copyright (C) 2019-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */
package de.powerstat.phplib.templateengine.intern.test;


import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.List;

import org.junit.jupiter.api.Test;

import de.powerstat.phplib.templateengine.intern.VariableManager;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;


/**
 * Variable manager tests.
 */
final class VariableManagerTests
 {
  /**
   * Construction failed constant.
   */
  private static final String CONSTRUCTION_FAILED = "Construction failed";

  /**
   * Testvar constant.
   */
  private static final String TESTVAR = "testvar";

  /**
   * Test constant.
   */
  private static final String TEST = "test";

  /**
   * Variable value not as expected constant.
   */
  private static final String VARIABLE_VALUE_NOT_AS_EXPECTED = "Variable value not as expected";

  /**
   * Null pointer exception constant.

=====================================================
== File: src/test/java/de/powerstat/phplib/templateengine/package-info.java
=====================================================
/*
 * Copyright (C) 2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */


/**
 * PHPLib like template engine.
 */
package de.powerstat.phplib.templateengine;

=====================================================
== File: src/test/java/de/powerstat/phplib/templateengine/RunCucumberTest.java
=====================================================
/*
 * Copyright (C) 2022-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */
package de.powerstat.phplib.templateengine;


import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeEngines;
import org.junit.platform.suite.api.SelectClasspathResource;
import org.junit.platform.suite.api.Suite;

import io.cucumber.junit.platform.engine.Constants;


/**
 * Run cucumber test.
 */
@SuppressWarnings({"java:S2187", "PMD.TestClassWithoutTestCases"})
@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("de/powerstat/phplib/templateengine")
@ConfigurationParameter(key = Constants.PLUGIN_PROPERTY_NAME, value = "pretty")
@ConfigurationParameter(key = Constants.GLUE_PROPERTY_NAME, value = "de.powerstat.phplib.templateengine")
public class RunCucumberTest
 {
  /**
   * Default constructor.
   */
  public RunCucumberTest()
   {
    super();
   }

 }

=====================================================
== File: src/test/java/de/powerstat/phplib/templateengine/StepDefinitions.java
=====================================================
/*
 * Copyright (C) 2022-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */
package de.powerstat.phplib.templateengine;


import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.File;
import java.io.IOException;

import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;


/**
 * Cucumber step definitions.
 */
@SuppressWarnings({"PMD.MethodNamingConventions", "checkstyle:MethodName"})
public class StepDefinitions
 {
  /**
   * Template file 1 path constant.
   */
  private static final String TEMPLATE1_TMPL = "target/test-classes/templates/template1.tmpl"; //$NON-NLS-1$

  /**
   * Template file 2 path constant.
   */
  private static final String TEMPLATE2_TMPL = "target/test-classes/templates/template2.tmpl"; //$NON-NLS-1$

  /**
   * Template block 1 block name constant.
   */
  private static final String BLK1_BLK = "BLK1_BLK"; //$NON-NLS-1$

  /**
   * Template block 1 name constant.
   */
  private static final String BLK1 = "BLK1"; //$NON-NLS-1$

  /**
   * Template name constant.
   */
  private static final String TEMPLATE = "template"; //$NON-NLS-1$

  /**
   * Template variable 1 name constant.
   */

=====================================================
== File: src/test/java/de/powerstat/phplib/templateengine/test/HandleUndefinedTests.java
=====================================================
/*
 * Copyright (C) 2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */
package de.powerstat.phplib.templateengine.test;


import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

import de.powerstat.phplib.templateengine.HandleUndefined;


/**
 * HandleUndefined tests.
 */
final class HandleUndefinedTests
 {
  /**
   * Default constructor.
   */
  /* default */ HandleUndefinedTests()
   {
    super();
   }


  /**
   * Test getAction.
   */
  @Test
  /* default */ void testGetAction()
   {
    assertAll("getAction", //$NON-NLS-1$
      () -> assertEquals(0, HandleUndefined.REMOVE.getAction(), "REMOVE action not as expected"), //$NON-NLS-1$
      () -> assertEquals(1, HandleUndefined.KEEP.getAction(), "KEEP action not as expected"), //$NON-NLS-1$
      () -> assertEquals(2, HandleUndefined.COMMENT.getAction(), "COMMENT action not as expected") //$NON-NLS-1$
    );
   }

 }

=====================================================
== File: src/test/java/de/powerstat/phplib/templateengine/test/package-info.java
=====================================================
/*
 * Copyright (C) 2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */


/**
 * UnitTests for PHPLib like template engine.
 */
package de.powerstat.phplib.templateengine.test;

=====================================================
== File: src/test/java/de/powerstat/phplib/templateengine/test/TemplateEngineTests.java
=====================================================
/*
 * Copyright (C) 2019-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */
package de.powerstat.phplib.templateengine.test;


import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.jupiter.api.Test;

import de.powerstat.phplib.templateengine.HandleUndefined;
import de.powerstat.phplib.templateengine.TemplateEngine;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;


/**
 * TemplateEngine tests.
 */
@SuppressFBWarnings({"CE_CLASS_ENVY", "EC_NULL_ARG"})
@SuppressWarnings({"PMD.LinguisticNaming", "PMD.ExcessiveClassLength", "PMD.LongVariable", "PMD.ExcessivePublicCount"})
final class TemplateEngineTests
 {
  /**
   * Logger.
   */
  private static final Logger LOGGER = LogManager.getLogger(TemplateEngineTests.class);

  /**
   * Template file 1 path constant.
   */
  private static final String TEMPLATE1_TMPL = "target/test-classes/templates/template1.tmpl"; //$NON-NLS-1$

  /**

=====================================================
== File: src/test/java/module-info.java
=====================================================
/*
 * Copyright (C) 2019-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
 */


/**
 * Module for PowerStat's PHPLib like TemplateEngine.
 */
open module de.powerstat.phplib.templateengine
 {
  exports de.powerstat.phplib.templateengine;

  // requires java.io;
  // requires java.nio;
  // requires java.util;

  requires org.apache.logging.log4j;
  requires com.github.spotbugs.annotations;

  requires org.junit.jupiter.api;
  requires org.junit.platform.launcher;
  requires org.junit.platform.suite.api;
  requires io.cucumber.java;
  requires io.cucumber.junit.platform.engine;
  // requires nl.jqno.equalsverifier;

 }

=====================================================
== File: src/test/resources/de/powerstat/phplib/templateengine/templateengine.feature
=====================================================
Feature: TemplateEngine
  PHPLIB Template Engine

  Scenario: A template with a variable to replace with content
    Given A template with a variable
    When The template is processed to replace the variable
    Then The variable is replaced with the value hello world

  Scenario: A template with a block to replace with content
    Given A template with a block
    When The template is processed to replace the block
    Then The block is replaced with the value hello world

=====================================================
== File: src/test/resources/junit-platform.properties
=====================================================
cucumber.publish.quiet=true

=====================================================
== File: src/test/resources/log4j2.properties
=====================================================
status = error
dest = err
name = PropertiesConfig
 
property.filename = target/logs/templateEngine.log
 
filter.threshold.type = ThresholdFilter
filter.threshold.level = debug
 
appender.console.type = Console
appender.console.name = console
appender.console.layout.type = PatternLayout
appender.console.layout.charset = UTF-8
appender.console.layout.pattern = [%level] %date{ISO8601} %processId/%threadId %logger %encode{%message}{CRLF}%n
appender.console.filter.threshold.type = ThresholdFilter
appender.console.filter.threshold.level = debug
 
appender.rolling.type = RollingFile
appender.rolling.name = rfile
appender.rolling.fileName = ${filename}
appender.rolling.filePattern = target/logs/templateEngine-%d{yyyy-MM-dd}-%i.log.gz
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.charset = UTF-8
appender.rolling.layout.pattern = [%level] %date{ISO8601} %processId/%threadId %logger %encode{%message}{CRLF}%n
appender.rolling.policies.type = Policies
appender.rolling.policies.startup.type = OnStartupTriggeringPolicy
appender.rolling.policies.startup.minSize = 1
appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
appender.rolling.policies.size.size=10MB
appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.strategy.max = 5
  
rootLogger.level = warn
rootLogger.appenderRef.console.ref = console
 
logger.powerstat.name = de.powerstat
logger.powerstat.level = debug
logger.powerstat.additivity = false
logger.powerstat.appenderRef.console.ref = console
logger.powerstat.appenderRef.rolling.ref = rfile

=====================================================
== File: src/test/resources/template5.tmpl
=====================================================
123
{variable1}
456

=====================================================
== File: src/test/resources/template6.tmpl
=====================================================

=====================================================
== File: src/test/resources/templates/template1.tmpl
=====================================================
123
{variable1}
456

=====================================================
== File: src/test/resources/templates/template10.tmpl
=====================================================
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890

=====================================================
== File: src/test/resources/templates/template2.tmpl
=====================================================
123
{variable1}
456
<!-- BEGIN BLK1 -->
789
{variable2}
abc
<!-- END BLK1 -->
def
{variable3}
ghi

=====================================================
== File: src/test/resources/templates/template3.tmpl
=====================================================
{test0} 
{test1} 
<!-- BEGIN test2 --> 
abc {test1} def {test3} ghi 
<!-- END test2 --> 
{test3} 
{test0} 

=====================================================
== File: src/test/resources/templates/template4.tmpl
=====================================================

=====================================================
== File: src/test/resources/templates/template7.tmpl
=====================================================
123
{{variable1}
456

=====================================================
== File: src/test/resources/templates/template8.tmpl
=====================================================
123
{1234567890123456789012345678901234567890123456789012345678901234}
456

=====================================================
== File: src/test/resources/templates/template9.tmpl
=====================================================
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890

=====================================================
== File: src/test/test.iml
=====================================================
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
  <component name="NewModuleRootManager" inherit-compiler-output="true">
    <exclude-output />
    <content url="file://$MODULE_DIR$">
      <sourceFolder url="file://$MODULE_DIR$/java" isTestSource="true" />
    </content>
    <orderEntry type="inheritedJdk" />
    <orderEntry type="sourceFolder" forTests="false" />
    <orderEntry type="library" name="templateengine" level="project" />
  </component>
</module>