Repository: raydac/java-comment-preprocessor Branch: master Commit: 74a11a047782 Files: 717 Total size: 2.6 MB Directory structure: gitextract_jyzsnnek/ ├── .gitattributes ├── .github/ │ ├── dependabot.yml │ └── workflows/ │ └── run-maven-tests.yml ├── .gitignore ├── .projectKnowledge/ │ ├── JCPreprocessor.mmd │ └── documap.mmd ├── LICENSE ├── README.md ├── changelog.txt ├── jcp/ │ ├── pom.xml │ └── src/ │ ├── assemble/ │ │ └── bundle.xml │ ├── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── igormaznitsa/ │ │ │ └── jcp/ │ │ │ ├── InfoHelper.java │ │ │ ├── JcpPreprocessor.java │ │ │ ├── ant/ │ │ │ │ └── PreprocessTask.java │ │ │ ├── cmdline/ │ │ │ │ ├── ActionPreprocessorExtensionHandler.java │ │ │ │ ├── AllowMergeBlockLineHandler.java │ │ │ │ ├── AllowWhitespaceDirectiveHandler.java │ │ │ │ ├── CareForLastEolHandler.java │ │ │ │ ├── ClearTargetHandler.java │ │ │ │ ├── CommandLineHandler.java │ │ │ │ ├── DestinationDirectoryHandler.java │ │ │ │ ├── DontOverwriteSameContentHandler.java │ │ │ │ ├── ExcludeFoldersHandler.java │ │ │ │ ├── ExcludedFileExtensionsHandler.java │ │ │ │ ├── FileExtensionsHandler.java │ │ │ │ ├── GlobalVariableDefiningFileHandler.java │ │ │ │ ├── GlobalVariableHandler.java │ │ │ │ ├── HelpHandler.java │ │ │ │ ├── InCharsetHandler.java │ │ │ │ ├── KeepAttributesHandler.java │ │ │ │ ├── KeepCommentsHandler.java │ │ │ │ ├── KeepLineHandler.java │ │ │ │ ├── OutCharsetHandler.java │ │ │ │ ├── PreserveIndentDirectiveHandler.java │ │ │ │ ├── RemoveCommentsHandler.java │ │ │ │ ├── SourceDirectoryHandler.java │ │ │ │ ├── UnknownAsFalseHandler.java │ │ │ │ └── VerboseHandler.java │ │ │ ├── containers/ │ │ │ │ ├── FileInfoContainer.java │ │ │ │ ├── PreprocessingFlag.java │ │ │ │ └── TextFileDataContainer.java │ │ │ ├── context/ │ │ │ │ ├── CommentRemoverType.java │ │ │ │ ├── CommentTextProcessor.java │ │ │ │ ├── EnvironmentVariableProcessor.java │ │ │ │ ├── ExecutionAllowable.java │ │ │ │ ├── JCPSpecialVariableProcessor.java │ │ │ │ ├── PreprocessingState.java │ │ │ │ ├── PreprocessorContext.java │ │ │ │ ├── PreprocessorContextAware.java │ │ │ │ └── SpecialVariableProcessor.java │ │ │ ├── directives/ │ │ │ │ ├── AbortDirectiveHandler.java │ │ │ │ ├── AbstractDirectiveHandler.java │ │ │ │ ├── ActionDirectiveHandler.java │ │ │ │ ├── AfterDirectiveProcessingBehaviour.java │ │ │ │ ├── BreakDirectiveHandler.java │ │ │ │ ├── CommentNextLineDirectiveHandler.java │ │ │ │ ├── ContinueDirectiveHandler.java │ │ │ │ ├── DefineDirectiveHandler.java │ │ │ │ ├── DefinelDirectiveHandler.java │ │ │ │ ├── DirectiveArgumentType.java │ │ │ │ ├── EchoDirectiveHandler.java │ │ │ │ ├── ElseDirectiveHandler.java │ │ │ │ ├── EndDirectiveHandler.java │ │ │ │ ├── EndIfDirectiveHandler.java │ │ │ │ ├── ErrorDirectiveHandler.java │ │ │ │ ├── ExcludeIfDirectiveHandler.java │ │ │ │ ├── ExitDirectiveHandler.java │ │ │ │ ├── ExitIfDirectiveHandler.java │ │ │ │ ├── FlushDirectiveHandler.java │ │ │ │ ├── GlobalDirectiveHandler.java │ │ │ │ ├── GlobalElseDirectiveHandler.java │ │ │ │ ├── GlobalEndIfDirectiveHandler.java │ │ │ │ ├── GlobalIfDirectiveHandler.java │ │ │ │ ├── IfDefDirectiveHandler.java │ │ │ │ ├── IfDefinedDirectiveHandler.java │ │ │ │ ├── IfDirectiveHandler.java │ │ │ │ ├── IfNDefDirectiveHandler.java │ │ │ │ ├── IncludeDirectiveHandler.java │ │ │ │ ├── LocalDirectiveHandler.java │ │ │ │ ├── MsgDirectiveHandler.java │ │ │ │ ├── NoAutoFlushHandler.java │ │ │ │ ├── OutDisabledDirectiveHandler.java │ │ │ │ ├── OutEnabledDirectiveHandler.java │ │ │ │ ├── OutNameDirectiveHandler.java │ │ │ │ ├── OutdirDirectiveHandler.java │ │ │ │ ├── PostfixDirectiveHandler.java │ │ │ │ ├── PrefixDirectiveHandler.java │ │ │ │ ├── UndefDirectiveHandler.java │ │ │ │ ├── WarningDirectiveHandler.java │ │ │ │ └── WhileDirectiveHandler.java │ │ │ ├── exceptions/ │ │ │ │ ├── FilePositionInfo.java │ │ │ │ └── PreprocessorException.java │ │ │ ├── expression/ │ │ │ │ ├── Expression.java │ │ │ │ ├── ExpressionItem.java │ │ │ │ ├── ExpressionItemPriority.java │ │ │ │ ├── ExpressionItemType.java │ │ │ │ ├── ExpressionParser.java │ │ │ │ ├── ExpressionTree.java │ │ │ │ ├── ExpressionTreeElement.java │ │ │ │ ├── Value.java │ │ │ │ ├── ValueType.java │ │ │ │ ├── Variable.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── AbstractFunction.java │ │ │ │ │ ├── AbstractStrConverter.java │ │ │ │ │ ├── FunctionABS.java │ │ │ │ │ ├── FunctionBINFILE.java │ │ │ │ │ ├── FunctionDefinedByUser.java │ │ │ │ │ ├── FunctionESC.java │ │ │ │ │ ├── FunctionEVALFILE.java │ │ │ │ │ ├── FunctionIS.java │ │ │ │ │ ├── FunctionISSUBSTR.java │ │ │ │ │ ├── FunctionROUND.java │ │ │ │ │ ├── FunctionSTR2CSV.java │ │ │ │ │ ├── FunctionSTR2GO.java │ │ │ │ │ ├── FunctionSTR2INT.java │ │ │ │ │ ├── FunctionSTR2JAVA.java │ │ │ │ │ ├── FunctionSTR2JS.java │ │ │ │ │ ├── FunctionSTR2JSON.java │ │ │ │ │ ├── FunctionSTR2WEB.java │ │ │ │ │ ├── FunctionSTR2XML.java │ │ │ │ │ ├── FunctionSTRLEN.java │ │ │ │ │ ├── FunctionTRIMLINES.java │ │ │ │ │ └── xml/ │ │ │ │ │ ├── AbstractXMLFunction.java │ │ │ │ │ ├── FunctionXML_ATTR.java │ │ │ │ │ ├── FunctionXML_GET.java │ │ │ │ │ ├── FunctionXML_LIST.java │ │ │ │ │ ├── FunctionXML_NAME.java │ │ │ │ │ ├── FunctionXML_OPEN.java │ │ │ │ │ ├── FunctionXML_ROOT.java │ │ │ │ │ ├── FunctionXML_SIZE.java │ │ │ │ │ ├── FunctionXML_TEXT.java │ │ │ │ │ ├── FunctionXML_XELEMENT.java │ │ │ │ │ ├── FunctionXML_XLIST.java │ │ │ │ │ └── NodeContainer.java │ │ │ │ └── operators/ │ │ │ │ ├── AbstractOperator.java │ │ │ │ ├── OperatorADD.java │ │ │ │ ├── OperatorAND.java │ │ │ │ ├── OperatorDIV.java │ │ │ │ ├── OperatorEQU.java │ │ │ │ ├── OperatorGREAT.java │ │ │ │ ├── OperatorGREATEQU.java │ │ │ │ ├── OperatorLESS.java │ │ │ │ ├── OperatorLESSEQU.java │ │ │ │ ├── OperatorMOD.java │ │ │ │ ├── OperatorMUL.java │ │ │ │ ├── OperatorNOT.java │ │ │ │ ├── OperatorNOTEQU.java │ │ │ │ ├── OperatorOR.java │ │ │ │ ├── OperatorSUB.java │ │ │ │ └── OperatorXOR.java │ │ │ ├── extension/ │ │ │ │ ├── LogPreprocessorExtension.java │ │ │ │ └── PreprocessorExtension.java │ │ │ ├── gradle/ │ │ │ │ ├── JcpGradlePlugin.java │ │ │ │ └── JcpTask.java │ │ │ ├── logger/ │ │ │ │ ├── PreprocessorLogger.java │ │ │ │ └── SystemOutLogger.java │ │ │ ├── maven/ │ │ │ │ ├── MavenPropertiesImporter.java │ │ │ │ └── PreprocessMojo.java │ │ │ ├── removers/ │ │ │ │ ├── AbstractCommentRemover.java │ │ │ │ ├── CStyleCommentRemover.java │ │ │ │ ├── JcpCommentLineRemover.java │ │ │ │ └── JustCopyRemover.java │ │ │ └── utils/ │ │ │ ├── AntPathMatcher.java │ │ │ ├── ArrayUtils.java │ │ │ ├── GetUtils.java │ │ │ ├── IOUtils.java │ │ │ ├── PreprocessorUtils.java │ │ │ └── ResettablePrinter.java │ │ └── resources/ │ │ ├── META-INF/ │ │ │ └── gradle-plugins/ │ │ │ └── com.igormaznitsa.jcp.properties │ │ ├── com/ │ │ │ └── igormaznitsa/ │ │ │ └── jcp/ │ │ │ └── ant/ │ │ │ ├── antlib.xml │ │ │ └── tasks.properties │ │ └── jcpversion.properties │ ├── site/ │ │ ├── markdown/ │ │ │ ├── examples/ │ │ │ │ └── hello-world.md │ │ │ ├── index.md │ │ │ └── usage.md │ │ └── site.xml │ └── test/ │ ├── java/ │ │ └── com/ │ │ └── igormaznitsa/ │ │ └── jcp/ │ │ ├── AbstractMockPreprocessorContextTest.java │ │ ├── AbstractSpyPreprocessorContextTest.java │ │ ├── JCPreprocessorTest.java │ │ ├── TestUtils.java │ │ ├── ant/ │ │ │ └── PreprocessTaskTest.java │ │ ├── cmdline/ │ │ │ ├── AbstractCommandLineHandlerTest.java │ │ │ ├── ActionPreprocessorExtensionHandlerTest.java │ │ │ ├── AllowMergeBlockLineHandlerTest.java │ │ │ ├── AllowWhitespaceDirectiveHandlerTest.java │ │ │ ├── CareForLastEolHandlerTest.java │ │ │ ├── ClearTargetFolderHandlerTest.java │ │ │ ├── CommentRemoverTypeHandlerTest.java │ │ │ ├── DestinationDirectoryHandlerTest.java │ │ │ ├── DontOverwriteSameContentHandlerTest.java │ │ │ ├── ExcludeFoldersHandlerTest.java │ │ │ ├── ExcludedFileExtensionsHandlerTest.java │ │ │ ├── FileExtensionsHandlerTest.java │ │ │ ├── GlobalVariableDefiningFileHandlerTest.java │ │ │ ├── GlobalVariableHandlerTest.java │ │ │ ├── HelpHandlerTest.java │ │ │ ├── InCharsetHandlerTest.java │ │ │ ├── KeepLineHandlerTest.java │ │ │ ├── OutCharsetHandlerTest.java │ │ │ ├── PreserveIndentDirectiveHandlerTest.java │ │ │ ├── RemoveCommentsHandlerTest.java │ │ │ ├── SourceDirectoryHandlerTest.java │ │ │ ├── UnknownAsFalseHandlerTest.java │ │ │ └── VerboseHandlerTest.java │ │ ├── context/ │ │ │ ├── EnvironmentVariableProcessorTest.java │ │ │ ├── JCPSpecialVariableProcessorTest.java │ │ │ ├── PreprocessorContextTest.java │ │ │ └── ProcessContentWithSpacesAndWithoutTest.java │ │ ├── directives/ │ │ │ ├── AbortDirectiveHandlerTest.java │ │ │ ├── AbstractDirectiveHandlerAcceptanceTest.java │ │ │ ├── AbstractDirectiveHandlerTest.java │ │ │ ├── ActionDirectiveHandlerTest.java │ │ │ ├── CommentNextLineDirectiveHandlerTest.java │ │ │ ├── DefineDirectiveHandlerTest.java │ │ │ ├── DefinelDirectiveHandlerTest.java │ │ │ ├── EchoDirectiveHandlerTest.java │ │ │ ├── ErrorDirectiveHandlerTest.java │ │ │ ├── ExcludeIfDirectiveHandlerTest.java │ │ │ ├── ExitDirectiveHandlerTest.java │ │ │ ├── ExitIfDirectiveHandlerTest.java │ │ │ ├── FlushDirectiveHandlerTest.java │ │ │ ├── GlobalDirectiveHandlerTest.java │ │ │ ├── GlobalIfElseEndifTest.java │ │ │ ├── IfDefDirectiveHandlerTest.java │ │ │ ├── IfDefinedDirectiveHandlerTest.java │ │ │ ├── IfElseEndifDirectiveHandlerTest.java │ │ │ ├── IfElseEndifDirectiveWithKeepLinesHandlerTest.java │ │ │ ├── IfNDefDirectiveHandlerTest.java │ │ │ ├── IncludeDirectiveHandlerTest.java │ │ │ ├── LinesNotMatchException.java │ │ │ ├── LocalDirectiveHandlerTest.java │ │ │ ├── MsgDirectiveHandlerTest.java │ │ │ ├── NoAutoFlushDirectiveHandlerTest.java │ │ │ ├── OnlySpacesTest.java │ │ │ ├── OutDisabledDirectiveHandlerTest.java │ │ │ ├── OutEnabledDirectiveHandlerTest.java │ │ │ ├── OutNameDirectiveHandlerTest.java │ │ │ ├── OutdirDirectiveHandlerTest.java │ │ │ ├── PrefixPostfixDirectiveHandlerTest.java │ │ │ ├── SpecVarsROTest.java │ │ │ ├── SpecialDirectivesBlockTest.java │ │ │ ├── SpecialDirectivesTest.java │ │ │ ├── UndefDirectiveHandlerTest.java │ │ │ ├── VariablePair.java │ │ │ ├── WarningDirectiveHandlerTest.java │ │ │ └── WhileContinueBreakEndDirectiveHandlerTest.java │ │ ├── exceptions/ │ │ │ └── PreprocessorExceptionTest.java │ │ ├── expression/ │ │ │ ├── ExpressionParserTest.java │ │ │ ├── ExpressionTest.java │ │ │ ├── ExpressionTreeTest.java │ │ │ ├── functions/ │ │ │ │ ├── AbstractFunctionTest.java │ │ │ │ ├── FunctionABSTest.java │ │ │ │ ├── FunctionBINFILETest.java │ │ │ │ ├── FunctionDefinedByUserTest.java │ │ │ │ ├── FunctionESCTest.java │ │ │ │ ├── FunctionEVALFILETest.java │ │ │ │ ├── FunctionISSUBSTRTest.java │ │ │ │ ├── FunctionISTest.java │ │ │ │ ├── FunctionROUNDTest.java │ │ │ │ ├── FunctionSTR2CSVTest.java │ │ │ │ ├── FunctionSTR2GOTest.java │ │ │ │ ├── FunctionSTR2INTTest.java │ │ │ │ ├── FunctionSTR2JAVATest.java │ │ │ │ ├── FunctionSTR2JSONTest.java │ │ │ │ ├── FunctionSTR2JSTest.java │ │ │ │ ├── FunctionSTR2WEBTest.java │ │ │ │ ├── FunctionSTR2XMLTest.java │ │ │ │ ├── FunctionSTRLENTest.java │ │ │ │ ├── FunctionTRIMLINESTest.java │ │ │ │ └── xml/ │ │ │ │ ├── AbstractFunctionXMLTest.java │ │ │ │ ├── FunctionXML_ATTRTest.java │ │ │ │ ├── FunctionXML_GETTest.java │ │ │ │ ├── FunctionXML_LISTTest.java │ │ │ │ ├── FunctionXML_NAMETest.java │ │ │ │ ├── FunctionXML_OPENTest.java │ │ │ │ ├── FunctionXML_ROOTTest.java │ │ │ │ ├── FunctionXML_SIZETest.java │ │ │ │ ├── FunctionXML_TEXTTest.java │ │ │ │ ├── FunctionXML_XELEMENTTest.java │ │ │ │ └── FunctionXML_XLISTTest.java │ │ │ └── operators/ │ │ │ ├── AbstractOperatorTest.java │ │ │ ├── OperatorADDTest.java │ │ │ ├── OperatorANDTest.java │ │ │ ├── OperatorDIVTest.java │ │ │ ├── OperatorEQUTest.java │ │ │ ├── OperatorGREATEQUTest.java │ │ │ ├── OperatorGREATTest.java │ │ │ ├── OperatorLESSEQUTest.java │ │ │ ├── OperatorLESSTest.java │ │ │ ├── OperatorMODTest.java │ │ │ ├── OperatorMULTest.java │ │ │ ├── OperatorNOTEQUTest.java │ │ │ ├── OperatorNOTTest.java │ │ │ ├── OperatorORTest.java │ │ │ ├── OperatorSUBTest.java │ │ │ └── OperatorXORTest.java │ │ ├── maven/ │ │ │ ├── MavenPropertiesImporterTest.java │ │ │ └── PreprocessMojoTest.java │ │ ├── removers/ │ │ │ ├── AbstractCommentRemoverTest.java │ │ │ ├── CStyleCommentsRemoverTest.java │ │ │ ├── JcpCommentLineRemoverTest.java │ │ │ └── JustCopyCommentsRemoverTest.java │ │ ├── usecases/ │ │ │ ├── AbortTest.java │ │ │ ├── AbstractUseCaseTest.java │ │ │ ├── BinFileTest.java │ │ │ ├── DefUndefTest.java │ │ │ ├── EvalFileTest.java │ │ │ ├── ExternalGlobalDefFileTest.java │ │ │ ├── GenerationTest.java │ │ │ ├── IncludeAndExitTest.java │ │ │ ├── InsidePreprocessingTest.java │ │ │ ├── PrefixPostfixTest.java │ │ │ ├── PreserveIndentOffTest.java │ │ │ ├── PreserveIndentOnTest.java │ │ │ ├── SimpleTest.java │ │ │ ├── SpacesBeforeDirectivesNotAllowedTest.java │ │ │ ├── SpacesBeforeDirectivesTest.java │ │ │ ├── StaticSiteTest.java │ │ │ ├── Str2JavaTest.java │ │ │ ├── StringDirectiveTest.java │ │ │ ├── TextBufferVariablesTest.java │ │ │ ├── UnknownVarAsFalseTest.java │ │ │ ├── UsePrefixAsMultilineTest.java │ │ │ └── UserFunctionTest.java │ │ └── utils/ │ │ ├── PreprocessorUtilsTest.java │ │ └── antpathmatcher/ │ │ └── AntPathMatcherTest.java │ └── resources/ │ └── com/ │ └── igormaznitsa/ │ └── jcp/ │ ├── cmdline/ │ │ └── global_variable_def.txt │ ├── context/ │ │ ├── spacedFile.txt │ │ └── standardFile.txt │ ├── directives/ │ │ ├── directive_abort.txt │ │ ├── directive_action.txt │ │ ├── directive_comment_next_line.txt │ │ ├── directive_define.txt │ │ ├── directive_definel.txt │ │ ├── directive_echo.txt │ │ ├── directive_error.txt │ │ ├── directive_excludeif.txt │ │ ├── directive_exit.txt │ │ ├── directive_exitif.txt │ │ ├── directive_global.txt │ │ ├── directive_globalifelseendif.txt │ │ ├── directive_globalifelseendif2.txt │ │ ├── directive_if_else_endif.txt │ │ ├── directive_if_else_endif_with_keptlines.txt │ │ ├── directive_ifdef.txt │ │ ├── directive_ifdefined.txt │ │ ├── directive_ifndef.txt │ │ ├── directive_include.txt │ │ ├── directive_include2.txt │ │ ├── directive_include3.txt │ │ ├── directive_local.txt │ │ ├── directive_msg.txt │ │ ├── directive_outdir.txt │ │ ├── directive_outdisabled.txt │ │ ├── directive_outenabled.txt │ │ ├── directive_outname.txt │ │ ├── directive_prefixpostfix.txt │ │ ├── directive_special.txt │ │ ├── directive_special_block.txt │ │ ├── directive_undef.txt │ │ ├── directive_warning.txt │ │ ├── directive_while_continue_break_end.txt │ │ ├── only_spaces.txt │ │ └── specvars_ro.txt │ ├── exceptions/ │ │ ├── wrong_bracket.txt │ │ ├── wrong_bracket_closing.txt │ │ └── wrong_bracket_include.txt │ ├── expression/ │ │ └── functions/ │ │ ├── eval/ │ │ │ ├── TestBin.txt │ │ │ ├── TestBinLong.txt │ │ │ ├── TestEval.java │ │ │ └── TestEvalWithIncluded.java │ │ └── xml/ │ │ ├── noxml.txt │ │ └── test.xml │ ├── global_error_at.txt │ ├── global_ok.txt │ ├── maven/ │ │ └── test.pom.xml │ ├── removers/ │ │ └── java/ │ │ ├── etalon.etl │ │ └── test_java.ppp │ ├── usecases/ │ │ ├── AbortTest/ │ │ │ ├── etl/ │ │ │ │ └── text.txt │ │ │ └── src/ │ │ │ ├── text.txt │ │ │ ├── text1.txt │ │ │ ├── text2.txt │ │ │ └── text3.txt │ │ ├── BinFileTest/ │ │ │ ├── etl/ │ │ │ │ └── body.txt │ │ │ └── src/ │ │ │ └── body.txt │ │ ├── DefUndefTest/ │ │ │ ├── etl/ │ │ │ │ └── text.txt │ │ │ └── src/ │ │ │ └── text.txt │ │ ├── EvalFileTest/ │ │ │ ├── etl/ │ │ │ │ └── newfolder/ │ │ │ │ ├── file1.txt │ │ │ │ └── file2.txt │ │ │ └── src/ │ │ │ ├── _file1.txt │ │ │ ├── _file2.txt │ │ │ └── text.txt │ │ ├── ExternalGlobalDefFileTest/ │ │ │ ├── etl/ │ │ │ │ └── test.txt │ │ │ ├── list.cfg │ │ │ └── src/ │ │ │ └── test.txt │ │ ├── GenerationTest/ │ │ │ ├── etl/ │ │ │ │ ├── file1.ttt │ │ │ │ ├── file2.ttt │ │ │ │ └── file3.ttt │ │ │ └── src/ │ │ │ └── text.txt │ │ ├── IncludeAndExitTest/ │ │ │ ├── etl/ │ │ │ │ └── text.txt │ │ │ └── src/ │ │ │ ├── text.txt │ │ │ ├── text1.txt │ │ │ └── text2.txt │ │ ├── InsidePreprocessingTest/ │ │ │ ├── etl/ │ │ │ │ └── text.txt │ │ │ └── src/ │ │ │ ├── some.txt │ │ │ └── text.txt │ │ ├── PrefixPostfixTest/ │ │ │ ├── etl/ │ │ │ │ └── text.txt │ │ │ └── src/ │ │ │ └── text.txt │ │ ├── PreserveIndentOffTest/ │ │ │ ├── etl/ │ │ │ │ └── text.txt │ │ │ └── src/ │ │ │ └── text.txt │ │ ├── PreserveIndentOnTest/ │ │ │ ├── etl/ │ │ │ │ └── text.txt │ │ │ └── src/ │ │ │ └── text.txt │ │ ├── SimpleTest/ │ │ │ ├── etl/ │ │ │ │ └── text.txt │ │ │ └── src/ │ │ │ └── text.txt │ │ ├── SpacesBeforeDirectivesNotAllowedTest/ │ │ │ ├── etl/ │ │ │ │ └── body.txt │ │ │ └── src/ │ │ │ └── body.txt │ │ ├── SpacesBeforeDirectivesTest/ │ │ │ ├── etl/ │ │ │ │ └── body.txt │ │ │ └── src/ │ │ │ └── body.txt │ │ ├── StaticSiteTest/ │ │ │ ├── etl/ │ │ │ │ ├── cmn/ │ │ │ │ │ ├── sendfeedback.phtml │ │ │ │ │ ├── styles.css │ │ │ │ │ └── styles2.css │ │ │ │ ├── eng/ │ │ │ │ │ ├── end.txt │ │ │ │ │ ├── gpage_airaggression.htm │ │ │ │ │ ├── gpage_airboil.htm │ │ │ │ │ ├── gpage_aneks_ny2006.htm │ │ │ │ │ ├── gpage_blazinggears.htm │ │ │ │ │ ├── gpage_caspianmonster.htm │ │ │ │ │ ├── gpage_castleassault.htm │ │ │ │ │ ├── gpage_cockroach.htm │ │ │ │ │ ├── gpage_coconutsfall.htm │ │ │ │ │ ├── gpage_conecone.htm │ │ │ │ │ ├── gpage_copterbomber.htm │ │ │ │ │ ├── gpage_drunkman.htm │ │ │ │ │ ├── gpage_firingline.htm │ │ │ │ │ ├── gpage_fisher.htm │ │ │ │ │ ├── gpage_fruitmania.htm │ │ │ │ │ ├── gpage_hardday.htm │ │ │ │ │ ├── gpage_hunt.htm │ │ │ │ │ ├── gpage_icegifts.htm │ │ │ │ │ ├── gpage_ironstream.htm │ │ │ │ │ ├── gpage_kalah.htm │ │ │ │ │ ├── gpage_kickkick.htm │ │ │ │ │ ├── gpage_lifesaver.htm │ │ │ │ │ ├── gpage_livebridge.htm │ │ │ │ │ ├── gpage_mobilechase.htm │ │ │ │ │ ├── gpage_mobilesheriff.htm │ │ │ │ │ ├── gpage_mtvpaparazzo.htm │ │ │ │ │ ├── gpage_mtvpillow.htm │ │ │ │ │ ├── gpage_mtvpuzzle.htm │ │ │ │ │ ├── gpage_mtvstage.htm │ │ │ │ │ ├── gpage_nimble.htm │ │ │ │ │ ├── gpage_opthunderclap.htm │ │ │ │ │ ├── gpage_oysterbank.htm │ │ │ │ │ ├── gpage_papaninsquest.htm │ │ │ │ │ ├── gpage_ravenscheese.htm │ │ │ │ │ ├── gpage_searoad.htm │ │ │ │ │ ├── gpage_searovers.htm │ │ │ │ │ ├── gpage_slider_alpop.htm │ │ │ │ │ ├── gpage_smashingkick.htm │ │ │ │ │ ├── gpage_smscat.htm │ │ │ │ │ ├── gpage_spiders.htm │ │ │ │ │ ├── gpage_starharbor.htm │ │ │ │ │ ├── gpage_strangehunt.htm │ │ │ │ │ ├── gpage_tastydish.htm │ │ │ │ │ ├── gpage_vineyard.htm │ │ │ │ │ ├── gpage_waterway.htm │ │ │ │ │ ├── gpage_wildballs.htm │ │ │ │ │ ├── gpage_wildroad.htm │ │ │ │ │ ├── menu1_about.htm │ │ │ │ │ ├── menu1_contacts.htm │ │ │ │ │ ├── menu1_job.htm │ │ │ │ │ ├── menu1_news.htm │ │ │ │ │ ├── menu1_partnership.htm │ │ │ │ │ ├── menu2_all.htm │ │ │ │ │ ├── menu2_arcade.htm │ │ │ │ │ ├── menu2_clientserver.htm │ │ │ │ │ ├── menu2_erotic.htm │ │ │ │ │ ├── menu2_fighting.htm │ │ │ │ │ ├── menu2_gambling.htm │ │ │ │ │ ├── menu2_logic.htm │ │ │ │ │ ├── menu2_multiplayer.htm │ │ │ │ │ ├── menu2_quest.htm │ │ │ │ │ ├── menu2_racing.htm │ │ │ │ │ ├── menu2_shooter.htm │ │ │ │ │ ├── menu2_sport.htm │ │ │ │ │ ├── menu3_appsall.htm │ │ │ │ │ ├── send_error.html │ │ │ │ │ └── send_ok.html │ │ │ │ ├── games/ │ │ │ │ │ └── games2003_2006.html │ │ │ │ ├── index.htm │ │ │ │ ├── loadpages/ │ │ │ │ │ ├── muzon_AirBoil.htm │ │ │ │ │ └── muzon_StarHarbor.htm │ │ │ │ ├── rus/ │ │ │ │ │ ├── gpage_airaggression.htm │ │ │ │ │ ├── gpage_airboil.htm │ │ │ │ │ ├── gpage_aneks_ny2006.htm │ │ │ │ │ ├── gpage_blazinggears.htm │ │ │ │ │ ├── gpage_caspianmonster.htm │ │ │ │ │ ├── gpage_castleassault.htm │ │ │ │ │ ├── gpage_cockroach.htm │ │ │ │ │ ├── gpage_coconutsfall.htm │ │ │ │ │ ├── gpage_conecone.htm │ │ │ │ │ ├── gpage_copterbomber.htm │ │ │ │ │ ├── gpage_drunkman.htm │ │ │ │ │ ├── gpage_firingline.htm │ │ │ │ │ ├── gpage_fisher.htm │ │ │ │ │ ├── gpage_fruitmania.htm │ │ │ │ │ ├── gpage_hardday.htm │ │ │ │ │ ├── gpage_hunt.htm │ │ │ │ │ ├── gpage_icegifts.htm │ │ │ │ │ ├── gpage_ironstream.htm │ │ │ │ │ ├── gpage_kalah.htm │ │ │ │ │ ├── gpage_kickkick.htm │ │ │ │ │ ├── gpage_lifesaver.htm │ │ │ │ │ ├── gpage_livebridge.htm │ │ │ │ │ ├── gpage_mobilechase.htm │ │ │ │ │ ├── gpage_mobilesheriff.htm │ │ │ │ │ ├── gpage_mtvpaparazzo.htm │ │ │ │ │ ├── gpage_mtvpillow.htm │ │ │ │ │ ├── gpage_mtvpuzzle.htm │ │ │ │ │ ├── gpage_mtvstage.htm │ │ │ │ │ ├── gpage_nimble.htm │ │ │ │ │ ├── gpage_opthunderclap.htm │ │ │ │ │ ├── gpage_oysterbank.htm │ │ │ │ │ ├── gpage_papaninsquest.htm │ │ │ │ │ ├── gpage_ravenscheese.htm │ │ │ │ │ ├── gpage_searoad.htm │ │ │ │ │ ├── gpage_searovers.htm │ │ │ │ │ ├── gpage_slider_alpop.htm │ │ │ │ │ ├── gpage_smashingkick.htm │ │ │ │ │ ├── gpage_smscat.htm │ │ │ │ │ ├── gpage_spiders.htm │ │ │ │ │ ├── gpage_starharbor.htm │ │ │ │ │ ├── gpage_strangehunt.htm │ │ │ │ │ ├── gpage_tastydish.htm │ │ │ │ │ ├── gpage_vineyard.htm │ │ │ │ │ ├── gpage_waterway.htm │ │ │ │ │ ├── gpage_wildballs.htm │ │ │ │ │ ├── gpage_wildroad.htm │ │ │ │ │ ├── menu1_about.htm │ │ │ │ │ ├── menu1_contacts.htm │ │ │ │ │ ├── menu1_job.htm │ │ │ │ │ ├── menu1_news.htm │ │ │ │ │ ├── menu1_partnership.htm │ │ │ │ │ ├── menu2_all.htm │ │ │ │ │ ├── menu2_arcade.htm │ │ │ │ │ ├── menu2_clientserver.htm │ │ │ │ │ ├── menu2_erotic.htm │ │ │ │ │ ├── menu2_fighting.htm │ │ │ │ │ ├── menu2_gambling.htm │ │ │ │ │ ├── menu2_logic.htm │ │ │ │ │ ├── menu2_multiplayer.htm │ │ │ │ │ ├── menu2_quest.htm │ │ │ │ │ ├── menu2_racing.htm │ │ │ │ │ ├── menu2_shooter.htm │ │ │ │ │ ├── menu2_sport.htm │ │ │ │ │ ├── menu3_appsall.htm │ │ │ │ │ ├── send_error.html │ │ │ │ │ └── send_ok.html │ │ │ │ └── wap/ │ │ │ │ ├── index.wml │ │ │ │ └── logo.wbmp │ │ │ └── src/ │ │ │ ├── about.htm │ │ │ ├── channels.xml │ │ │ ├── cmn/ │ │ │ │ ├── sendfeedback.phtml │ │ │ │ ├── styles.css │ │ │ │ └── styles2.css │ │ │ ├── contacts.htm │ │ │ ├── devices.xml │ │ │ ├── eng/ │ │ │ │ ├── send_error.html │ │ │ │ └── send_ok.html │ │ │ ├── gamelist.htm │ │ │ ├── gameref.htm │ │ │ ├── games/ │ │ │ │ └── games2003_2006.html │ │ │ ├── games.htm │ │ │ ├── games.xml │ │ │ ├── hotnews.htm │ │ │ ├── hotnews.xml │ │ │ ├── index.htm │ │ │ ├── job.htm │ │ │ ├── loadpages/ │ │ │ │ ├── muzon_AirBoil.htm │ │ │ │ └── muzon_StarHarbor.htm │ │ │ ├── main.htm │ │ │ ├── news.htm │ │ │ ├── news.xml │ │ │ ├── partnership.htm │ │ │ ├── rus/ │ │ │ │ ├── send_error.html │ │ │ │ └── send_ok.html │ │ │ ├── site.xml │ │ │ └── wap/ │ │ │ ├── index.wml │ │ │ └── logo.wbmp │ │ ├── Str2JavaTest/ │ │ │ ├── etl/ │ │ │ │ └── text.txt │ │ │ └── src/ │ │ │ ├── body.txt │ │ │ ├── str.txt │ │ │ └── text.txt │ │ ├── StringDirectiveTest/ │ │ │ ├── etl/ │ │ │ │ └── text.txt │ │ │ └── src/ │ │ │ └── text.txt │ │ ├── TextBufferVariablesTest/ │ │ │ ├── etl/ │ │ │ │ └── text.txt │ │ │ └── src/ │ │ │ └── text.txt │ │ ├── UnknownVarAsFalseTest/ │ │ │ ├── etl/ │ │ │ │ └── body.txt │ │ │ └── src/ │ │ │ └── body.txt │ │ ├── UsePrefixAsMultilineTest/ │ │ │ ├── etl/ │ │ │ │ └── text.txt │ │ │ └── src/ │ │ │ └── text.txt │ │ └── UserFunctionTest/ │ │ ├── etl/ │ │ │ └── text.txt │ │ └── src/ │ │ └── text.txt │ └── utils/ │ └── somefile.txt ├── jcp-tests/ │ ├── extlibs/ │ │ └── gradle-tooling-api-5.1.jar │ ├── jcp-test-android/ │ │ ├── app/ │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src/ │ │ │ ├── androidTest/ │ │ │ │ └── java/ │ │ │ │ └── android/ │ │ │ │ └── it/ │ │ │ │ └── igormaznitsa/ │ │ │ │ └── com/ │ │ │ │ └── jcpandroid/ │ │ │ │ └── ExampleInstrumentedTest.java │ │ │ ├── main/ │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java/ │ │ │ │ │ └── android/ │ │ │ │ │ └── it/ │ │ │ │ │ └── igormaznitsa/ │ │ │ │ │ └── com/ │ │ │ │ │ └── jcpandroid/ │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── utils/ │ │ │ │ │ └── Utils.java │ │ │ │ └── res/ │ │ │ │ ├── drawable/ │ │ │ │ │ └── ic_launcher_background.xml │ │ │ │ ├── drawable-v24/ │ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ │ ├── layout/ │ │ │ │ │ ├── activity_main.xml │ │ │ │ │ └── content_main.xml │ │ │ │ ├── menu/ │ │ │ │ │ └── menu_main.xml │ │ │ │ ├── mipmap-anydpi-v26/ │ │ │ │ │ ├── ic_launcher.xml │ │ │ │ │ └── ic_launcher_round.xml │ │ │ │ └── values/ │ │ │ │ ├── colors.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ └── test/ │ │ │ └── java/ │ │ │ └── android/ │ │ │ └── it/ │ │ │ └── igormaznitsa/ │ │ │ └── com/ │ │ │ └── jcpandroid/ │ │ │ ├── ExampleUnitTest.java │ │ │ └── utils/ │ │ │ └── UtilsTest.java │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── local.properties │ │ ├── pom.xml │ │ └── settings.gradle │ ├── jcp-test-ant/ │ │ ├── pom.xml │ │ └── src/ │ │ └── test/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── igormaznitsa/ │ │ │ └── jcp/ │ │ │ └── it/ │ │ │ └── ant/ │ │ │ └── TestAntTaskResult.java │ │ └── resources/ │ │ ├── build.xml │ │ ├── config.cfg │ │ └── src/ │ │ └── com/ │ │ └── igormaznitsa/ │ │ └── dummyproject/ │ │ └── main.java │ ├── jcp-test-gradle-6/ │ │ ├── build.gradle │ │ ├── configFile.txt │ │ ├── pom.xml │ │ ├── settings.gradle │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── igormaznitsa/ │ │ │ └── jcp/ │ │ │ └── it/ │ │ │ └── gradle/ │ │ │ ├── Main.java │ │ │ └── Some.java │ │ └── test/ │ │ └── java/ │ │ └── com/ │ │ └── igormaznitsa/ │ │ └── jcp/ │ │ └── it/ │ │ └── gradle/ │ │ └── TestMain.java │ ├── jcp-test-gradle-7/ │ │ ├── build.gradle │ │ ├── configFile.txt │ │ ├── pom.xml │ │ ├── settings.gradle │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── igormaznitsa/ │ │ │ └── jcp/ │ │ │ └── it/ │ │ │ └── gradle/ │ │ │ ├── Main.java │ │ │ └── Some.java │ │ └── test/ │ │ └── java/ │ │ └── com/ │ │ └── igormaznitsa/ │ │ └── jcp/ │ │ └── it/ │ │ └── gradle/ │ │ └── TestMain.java │ ├── jcp-test-gradle-8/ │ │ ├── build.gradle │ │ ├── configFile.txt │ │ ├── pom.xml │ │ ├── settings.gradle │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── igormaznitsa/ │ │ │ └── jcp/ │ │ │ └── it/ │ │ │ └── gradle/ │ │ │ ├── Main.java │ │ │ └── Some.java │ │ └── test/ │ │ └── java/ │ │ └── com/ │ │ └── igormaznitsa/ │ │ └── jcp/ │ │ └── it/ │ │ └── gradle/ │ │ └── TestMain.java │ ├── jcp-test-gradle-9/ │ │ ├── build.gradle │ │ ├── configFile.txt │ │ ├── pom.xml │ │ ├── settings.gradle │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── igormaznitsa/ │ │ │ └── jcp/ │ │ │ └── it/ │ │ │ └── gradle/ │ │ │ ├── Main.java │ │ │ └── Some.java │ │ └── test/ │ │ └── java/ │ │ └── com/ │ │ └── igormaznitsa/ │ │ └── jcp/ │ │ └── it/ │ │ └── gradle/ │ │ └── TestMain.java │ ├── jcp-test-javassist/ │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── igormaznitsa/ │ │ │ └── jcp/ │ │ │ └── it/ │ │ │ └── test/ │ │ │ ├── JavassistMain.java │ │ │ ├── Javassistable.java │ │ │ └── Main.java │ │ └── test/ │ │ └── java/ │ │ └── com/ │ │ └── igormaznitsa/ │ │ └── jcp/ │ │ └── it/ │ │ └── test/ │ │ └── JavassistableTest.java │ ├── jcp-test-jep238/ │ │ ├── pom.jdk9.xml │ │ ├── pom.xml │ │ └── src/ │ │ ├── assembly/ │ │ │ └── assembly.xml │ │ ├── main/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── igormaznitsa/ │ │ │ └── tests/ │ │ │ ├── JDK9APIClass.java │ │ │ ├── Main.java │ │ │ └── OldJavaClass.java │ │ └── test/ │ │ └── java/ │ │ └── com/ │ │ └── igormaznitsa/ │ │ └── tests/ │ │ ├── JDK9APIClassTest.java │ │ └── OldJavaClassTest.java │ ├── jcp-test-maven/ │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── igormaznitsa/ │ │ │ └── jcp/ │ │ │ └── it/ │ │ │ └── maven/ │ │ │ └── Main.java │ │ └── test/ │ │ └── java/ │ │ └── com/ │ │ └── igormaznitsa/ │ │ └── jcp/ │ │ └── it/ │ │ └── maven/ │ │ └── TestMain.java │ ├── jcp-test-maven-action/ │ │ ├── jcp-test-maven-action-action/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ └── main/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── igormaznitsa/ │ │ │ └── jcp/ │ │ │ └── it/ │ │ │ └── CustomPreprocessorExtension.java │ │ ├── jcp-test-maven-action-plugin-call/ │ │ │ ├── pom.xml │ │ │ └── src/ │ │ │ ├── main/ │ │ │ │ └── java/ │ │ │ │ └── com/ │ │ │ │ └── igormaznitsa/ │ │ │ │ └── jcp/ │ │ │ │ └── it/ │ │ │ │ └── Main.java │ │ │ └── test/ │ │ │ └── java/ │ │ │ └── com/ │ │ │ └── igormaznitsa/ │ │ │ └── jcp/ │ │ │ └── it/ │ │ │ └── MainTest.java │ │ └── pom.xml │ ├── jcp-test-static-site/ │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── resources/ │ │ │ ├── about.htm │ │ │ ├── channels.xml │ │ │ ├── cmn/ │ │ │ │ ├── sendfeedback.phtml │ │ │ │ ├── styles.css │ │ │ │ └── styles2.css │ │ │ ├── contacts.htm │ │ │ ├── devices.xml │ │ │ ├── eng/ │ │ │ │ ├── send_error.html │ │ │ │ └── send_ok.html │ │ │ ├── gamelist.htm │ │ │ ├── gameref.htm │ │ │ ├── games/ │ │ │ │ └── games2003_2006.html │ │ │ ├── games.htm │ │ │ ├── games.xml │ │ │ ├── hotnews.htm │ │ │ ├── hotnews.xml │ │ │ ├── index.htm │ │ │ ├── job.htm │ │ │ ├── loadpages/ │ │ │ │ ├── muzon_AirBoil.htm │ │ │ │ └── muzon_StarHarbor.htm │ │ │ ├── main.htm │ │ │ ├── news.htm │ │ │ ├── news.xml │ │ │ ├── partnership.htm │ │ │ ├── rus/ │ │ │ │ ├── send_error.html │ │ │ │ └── send_ok.html │ │ │ ├── site.xml │ │ │ └── wap/ │ │ │ ├── index.wml │ │ │ └── logo.wbmp │ │ └── test/ │ │ └── java/ │ │ └── com/ │ │ └── igormaznitsa/ │ │ └── jcp/ │ │ └── it/ │ │ └── test/ │ │ └── TestSite.java │ └── pom.xml └── pom.xml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ * text=false * -crlf ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: "maven" directory: "/" schedule: interval: "daily" rebase-strategy: "disabled" ================================================ FILE: .github/workflows/run-maven-tests.yml ================================================ name: Run maven tests on: pull_request: branches: - master push: branches: - master jobs: test: name: Run tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' cache: maven - name: Maven test run: mvn test ================================================ FILE: .gitignore ================================================ **/.gradle/ **/build/ **/target/ /nbproject/ **/dependency-reduced-pom.xml *.iml /.idea/ /.idea/libraries /jcp-tests/jcp-test-jep238/build.log /jcp-tests/jcp-test-gradle/.buildProfile/report/ /jcp/.flattened-pom.xml ================================================ FILE: .projectKnowledge/JCPreprocessor.mmd ================================================ Mind Map generated by NB MindMap plugin > __version__=`1.0`,showJumps=`true` --- # Java Comment
preprocessor - LINK
https://github.com/raydac/java-comment-preprocessor
## Current > fillColor=`#FFFF99` ## Issues > fillColor=`#FF9999`,topicLinkUID=`15150167A1AA` - LINK
https://github.com/raydac/java-comment-preprocessor/issues
## Backlog > fillColor=`#99FF99` ## Changelog > leftSide=`true` - FILE
changelog.txt
================================================ FILE: .projectKnowledge/documap.mmd ================================================ [Scia Reto](https://sciareto.org) mind map > __version__=`1.1`,showJumps=`true` --- # Java Comment Preprocessor
v 7\.2\.0 ## > fillColor=`#FFFFFF`,mmd.image=`iVBORw0KGgoAAAANSUhEUgAAAL4AAAAwCAYAAACvzsA1AAAQkElEQVR42u1dB1gVxxZeiS3RGI2xRtm93MstXBBUwK5YUey9xl4TC1gAsYBdH6Im6osleWqKL7EbSWKPiVhATSyxIAjYEH02LBdszJtZBoPXe3dmdheSl7fn+863IDPnzM78c+bMOTMrx2mkkUZUVBVyTci1CGyCXFpFvWUge1HorY3bqJFGqlF/yICBf1dJbwXIOQx6n2tDpZGa9JgR+IhLqqD3LKNOmzZUGqlF78oAPeK6CvX6yNB5XRsujdQik0zgD1Sg0wXyIxk6T2rDpZFa1EIm8D9RoNNfps5F2nBppBYtkgnC3Qp0PpOps7E2XBqpRRdlgvCMTH09ZeoD2lBppCbJBeFtmfruy9SX9lfuxNQoQUPS/xDVVAB8ORY4XIGuHX+1znu4TD/gwceG1MwY/fIbkdVLqi3/yXJeQ2gB0TCFwLcw6rujQNcsFd63GOQ3Ib8FuRR+ot+L40gTE2WtckuxfaoHj5YaQOZCve3OXF2xW4tqKm7k45W5gL+zzMMle6Vu2KOlus0PFrmXUCCyJH7f0viJ3rnon4S5IpBL4DbkjUFx/O/OqCzkcpjRz2/jn/OoHJZFTSsUAn9AIWyi87iNzI72hLwd8j0uN4SajYwp5Kf4iX5HCbwHkM9DHkEr2LZK/xiC/1nWSj14vAyCP0YfqhY6Hn/NudhW6m9mrYKyl+uR7JuMItwgr8SuZRZ+32f4mY374jDkOgqaiQAXCLkt5taQPSTK/wv3sw23IW8MbNgoznZSLwbyC8jHIYdAzsCYQJNGh3+ex9Lw4wrBuIJBl02hrjIMugyQ92Kwy9GFjlHsxFbJCXXmIDAB5EwEzgdL9KduhhvBncnmEkpB/2iVmx+Um43kQs6x/RPKX2wA9xfoq1NUnw75KuP7XoLclLGZIRLyZuQrh1aZAwxteQi5h5O9aDG8MtvwhPGGfAFPbN/C2NiyJpRiFOp5zGCBtqvwXnmMrKLDXeu9OYbG0BLfta3W38tcZLh0M8wIEPDTJ5sa/qRgo5sRrm/3nynuSWhSZYmTys2G3KmHSwzgXrReJ1E1CPIthe/Lkpu5ISFnDS4zRkFb8oO/Mrb4eW4b+vtnkFMgr8e/V6ZtuF4FYNwm+GaIyhNkZFLo2UzxPjpsBYDKjKzLG/bKroe598gIhWCPMGxCz4xJkCeYwPUQ00dyQX99tKlTxkSTOIEer3BLt610u5O1WlxVwMOPoSsV7VbOQTVkAVep+L7LKf100mFCpWNxP5++UZDj8M/olO6vkHvhcqXyuT1UNI6g+AX216TKPKDYJC0myKhKsTQPJ+hgOW+Ug9+N5VRogL3C9BD3/unjzCB9rDkhfYwZXB9tBtc+tIBrIyyfs4A9qbtVfF4dam59daRFlHMj2GiDK0hSRrgx7WaYIRFOhNO3Jrv/7EREcgFM9rGEZrcuAJ2OuBPW9w4eYw5vhN/Ck+89jD+m8Nduji4ze1uiTBbeoUtZYZoOvksoV09Cx1uU+4dovOGrgDusIh5Amrr77ZWmDbf0uTrcAq4Ms8RdGeoBrgz2AJcHQu5vPcBq6RO7Wb3T+lnBlUEe4Oowy91rH5ku3ggxiasIsv6IMyKMtRxYelrXBvXvZQbApRCavLCQgL+9IMJKFwhK/XC5nwjWU2IDyH1B0FEcuxGkDqhCiBRI1T2E3S0pSiPIOPVawqqvRxcE1tQ+1iNpfeGztydI6Qm5myfTXYWLXT0rJnfyzLnU3RPK8nySNsBj7dXhHuLqAVcT0X3KCDNeFP3/qSaW8UOZ9Sbc65eGquLNp5LjIXspV1b0/BRyI2yVK2AvIoz7E0/jPqBMTpH8x1pO5POEei1xueYKEmUkHXco+2IeQc4G+wopPaxNL3X1BMmdPZMh30ru6AWSOniBi+29Np6qUbPpSaO3pMLUuvW4k/UtpS+0qJGTGOQt1k3u4rkqtbcVrhpwBRkCrf8I0fV5cT3Y1T6itYTQ3mkU70yy2lKBiysUY4YmpquEjKYU7uYttUFfgqAwf8w4mFB2qhMdBzm64wcRBPl7Jd6jF2GD5UXZH6SMch/7CqdbelkvBtUAiYE1nie2rrExsZU3uNDCG5ypVSv1N2vtWCllCULuYnrC3Tf+XGMfcL65N0hsWWNFUnuv7EtdvcSVA60mous01H2wbfWg/NVJp2mHqZRQtEns30igz8ShR9IG+QZBTrrawB/M0R9AI3V0nAP5lRh89rWEskMJnTcUJz7G4vAZeg6i6HiWpfsd+wrHmniWOR/gAxBwzzXymXO2kQ846VX73Am9H4AsuiY/iOmEVykqr77O70tU9pR37RNnG9S8fb6Z94kLgd7gYtsaILmTF0CuT0ov6wLGzexpRhxskJD1xEmkpDFFUKQcpf54gqzv1Qb+PoZ4bmVGVwSBMVWi7FG78kcV+Pdq0ACC/mzO7polAPG5Ftvg9wJa93OnfWvO/9Xke/W4mx/IZf9LTl0cj1ZcvJv/+GNu/qgcZN/0M3V8NkHwAzSR0KqR2AauJJ290D1o7nIvD5a2vsn47sskZKEs79sO6iylSIaplUCdoOZAu3DkO7ZNGZe2UnapcqmyJoaM7lMnna8GITfoS4p3u+coji+OmpvfIwTeY4LfZgTkPE4Q/JPieb+GDk1cFf/yCTr/58d0uLzOf+wJg++NE0a/9N/Mvhlw1cg45VX7zCmfmp/JCF12YXh/N0JU6LkTy006xt6boQ2pBFmV1RzwUhTJhddyK4Ty1Sk3PmsY4+9ZnPzDVMVwu+pD7oCTIMjCHWYMqTmN0kDgpuWC1y9FBDLkBMyHq9V6ZYLH8XW5X6tZi8QL/vcThDpiGThhDsE6mcfzrH+umwSg7w9+1tUuneFbh2VfpjYj4Jd1sJrf5tQ5sYtkZRBWWlXpPcJu+oqDOj8SXjYvhEG6Umjv9A6XCzon8XxkxdFhuP+oCICpTjepOv9jGOhpCbo6LyCDeAjqo0KdaxDgW+Mqvbq3juPrhx4R6oll4nn/p7DMpAQ8Yf5wfSDw3Xy7O1A3v5CB/4R7/cSjC16FndU5x+h5PJSQlag28DsQXvgHB3VmEuoE4XJSGdglDuTuJMgNp+zALxkzsSysd6b4KF9nuwhioc5D+PM3R4W6AAH7sFAfHBIaPIRAF4867xYCuAN8E/MvQmMQJzQU/36Er7sE1X1p/XMn0MVjOl/xdCgEv7267EIGfhbOs+Qn0jGXbQw4JOVvdqsN/H8TFDo63tmNUAf5nnsIZRx9fe0Soc77hHcZUsCAeOo8HGLlDgt1J2OQgzi+Qb84oRE4KHJj8LPQBOyqVvdlNGgf3/zYT0JT+O8B8O8NYw8J9RPQJEGTRZwAOnEC3NnP+5Y6IvjYqyuNoyWFCXxHK3+kggicPTXjCv7+xSv0nKCwg4M6/go7cZSTttxX4OMtYGwDOti0Dq8i7SEbITcg1EmSasCB6g28Ech/gSCHFn3BASHgGQL3fqEZ5OZgH99ssOgn8q267BZagb1CC/FvB/iARfmtPwL/Ud5/91FXX+90aytHqmi/OHcD+81yOO+uwm0c3n1Hxub6PQYcrlGQOWamchSd5yi9X1UB6J3dzS3KyT8vQnNzLAWn5o0ScooqXW73i0CHIBea394rtLy1R2gJ9kCQ7xYCwU4hUPwcyg9C2ws7hTZgl9Aa7OZbRMKy93KtfxNxdTgEJ8ARvt4zCTWuhHamctJnptSgYhR7AhYifVdJVSLdsZX6NqVc4A9xIq+HjMRY3gCQDpatpuyPIIKcKJKAPXzLXQjku4TAFzv51pcRwH8UggAEO4jl2y7Z6tqp7XdCRxArtEP/fheWOYjKw0mSa/2h64Os/0G+YZAC4H/IFTxVIbRhH4Os0lwhf1iABDapVPtdGaBPkJC3g1B3ppN6nxDqrWHojzMMGWaHFMu3GYVA/r3QLidWaB8DGewQOgAE9m2uHadtEbr+vk3oDLYLncAO13ZdYdkcNDkQ+NHKsE90f5oeQbIOujZ0poZ0ynV8IQDfqqJPLhBkfa1241dz8s9hr5MBfCk/jZRL8HdQpzgn/0CbHLdPktBysNW1rSsCuQh0vuNABPKtQhewBfLXFQPLbBR6gM1CN/R7HPz79Vzr3x6uCEG5rg9yi6q0JF2iqErw8VfLtODoiMfHOOKGDq2Fcc4vbX+kYvKMdOxhtNrAJ134aCRRty8j6KWWvrcpohTOso1SdQ4w9AXpOmQSraAtfNcjWyC4N/HdEjYJ3c9tgmDfKPS8v0g/Lma90Ddng9ATbHLtNhZaf4AmBgI/WhVi+XZZsdXbVqJQUZbQX6wX0YfLMH6kqJ07g/6FXCFubGn8dKljpGZG4JskZL1PsGDOkhd+MnIQckJpAK9wVPSNa88aCNzfCr0Rb1unGwjWCQOmRxvGg7W6gU/W830Wfyv0yoSTQbT+W+EE2C50vLStekdhBx9Em+V8SGjvfMqcRyQhfFtSJnZYKIUgq6yaoK+rsPFVGJJEpJszpE3leif1OlLoLkoAUEvKdxhH27GRLn2KLDIEX/hC+CDrK/6DpZ/rhtyaawwF840TwRL92Mtf8X2XrBf6gW+E3k/hBHm8ke/WU8b4jaVo8wq8mhbN974oUYQOr7WhGD9fCUMlVe8Ew3u4qBwdIlKwwsaXoUyiPKeYsaQY7gSZFj/vUJmjREoX7BLQTt5Amk6do8udH/Pdx7kucJ8I5ruPj5xtCgczTZPBHGMYmKuf0D/aEJwUYwjeFeM+pk+MMaTPQkPIqWghWC9jDGku5j/DocL7mB9wdBe/pb6RFEioO53hHbxlGj3Z9AWn7AhoUUrgL6VoC+l0aIDEJo/18yCZnLwwbC3ajp2tC6k8xxi6dLYpDMwyhiVHmqfER5ojwAxjBIgyT96GJgH6G1oF5hkn7ZvrNul9mWM4iiuYLG0EQe8kju6aKg31U3GTTEUnCAp1FDIyOPKlZqUxXMBJH0W+yxVOyr46awdHGkI7RZmmPIswT9s41TINTLeE95hunmqLMk8BMyD4Z5nCz841h3ZfYJjyhoJx/FTl96Q58x6rYl+Rrk0a1AZ+NmF5pPlS2QZCo2k+oUc6/nCfIgyp5EAaOrl5VOHke436lx/GTTFObT/ZEpkZboncF2aOTIbPtRGW6cenmaedhKvA/hnmCHT5m5tnDVE6lotVAPw17o9TtSQibaxZPpibwDHedivIiA7tbfZ6HP3NKmdEulw+hkIGsjBZjAOdbeeLkqyYLAq1RLWb6DFzykTLjHERQhQfaplVoYASSj7YlWMxAjkYxJ1VxM4aRllS/+Hf6YLoqGo4jBeAGVmfDnjWs9xP1WM/rAeOkARgN4lWhgsOmwY4YIGj/2ox0tea0JF3cMwYtc/+LAtyN9BhtZ523IaTeetrnDFK/OhRsMfsl/uccPPMIlzBEZL9Lg5RXuOkrwOiLy+U52R8FZrL/QZRW7t+CpTplqAVu52Dfm/IiEON8Ma7Ip5QiCtxhfwZ7DGGKPE50hpdebTn/MjRXvPm/Qn9gCZ3BRwEqFQQboNGGjmkEV7Ri8Wn5z9iRlqii2g9otH/BXX3iBK/8tvFOt2tq+c8l7GGN7RO0ejvTTWNI797ufM0jipjNQzppPWKRn9bcnfPTXrq9f0b5P93k3HQRq13NPpbEwT5J+76AcWrVfvjAwkm98HekN/Veqfw6L8MpcrkyHZvbQAAAABJRU5ErkJggg==` ### goals > fillColor=`#FF3700`,textColor=`#DBDBDB` #### preprocess > fillColor=`#FF3700`,textColor=`#DBDBDB` ##### sources > fillColor=`#FFFF00` ###### Source root folders for preprocessing,
if it is empty then project provided folders will be used\. > fillColor=`#49EFB6` ####### \
\$\{basedir\}/src\
\$\{basedir\}/res\
\
> align=`left`,fillColor=`#FFB600` ##### eol > fillColor=`#FFFF00` ###### End of line string to be used in reprocessed results\.
It supports java escaping chars\. > fillColor=`#49EFB6` ####### $\{line\.separator\} ######## \\\r\\n\ > fillColor=`#FFB600` ##### keepAttributes > fillColor=`#FFFF00` ###### Keep attributes for preprocessing file
and copy them to result one\. > fillColor=`#49EFB6` ####### false ######## \true\ > fillColor=`#FFB600` ##### target > fillColor=`#FFFF00` ###### Target folder to place preprocessing result
in regular source processing phase\. > fillColor=`#49EFB6` ####### \$\{project\.build\.directory\}/generated\-sources/preprocessed\ > fillColor=`#FFB600` ##### targetTest > fillColor=`#FFFF00` ###### Target folder to place preprocessing result
in test source processing phase\. > fillColor=`#49EFB6` ####### \$\{project\.build\.directory\}/generated\-test\-sources/preprocessed\ > fillColor=`#FFB600` ##### sourceEncoding > fillColor=`#FFFF00` ###### Encoding for text read operations\. > fillColor=`#49EFB6` ####### UTF\-8 ######## \US\-ASCII\ > fillColor=`#FFB600` ##### targetEncoding > fillColor=`#FFFF00` ###### Encoding for text write operations\. > fillColor=`#49EFB6` ####### UTF\-8 ######## \US\-ASCII\ > fillColor=`#FFB600` ##### ignoreMissingSources > fillColor=`#FFFF00` ###### Flag to ignore missing source folders,
if false then mojo fail for any missing source folder,
if true then missing folder will be ignored\. > fillColor=`#49EFB6` ####### false ######## \true\ > fillColor=`#FFB600` ##### excludeExtensions > fillColor=`#FFFF00` ###### List of file extensions to be excluded from preprocessing\. > fillColor=`#49EFB6` ####### xml ######## \
\png\
\xml\
\txt\
\
> align=`left`,fillColor=`#FFB600` ##### extensions > fillColor=`#FFFF00` ###### List of file extensions to be included into preprocessing\. > fillColor=`#49EFB6` ####### java, txt, htm, html ######## \
\cpp\
\frt\
\
> align=`left`,fillColor=`#FFB600` ##### unknownVarAsFalse > fillColor=`#FFFF00` ###### Recognize a unknown variable as containing boolean FALSE flag\. > fillColor=`#49EFB6` ####### false ######## \true\ > fillColor=`#FFB600` ##### dryRun > fillColor=`#FFFF00` ###### Dry run, making preprocessing but without output > fillColor=`#49EFB6` ####### false ######## \true\ > fillColor=`#FFB600` ##### verbose > fillColor=`#FFFF00` ###### Verbose mode > fillColor=`#49EFB6` ####### false ######## \true\ > fillColor=`#FFB600` ##### clearTarget > fillColor=`#FFFF00` ###### Clear target folder if it exists\. > fillColor=`#49EFB6` ####### false ######## \true\ > fillColor=`#FFB600` ##### baseDir > fillColor=`#FFFF00` ###### Set base directory which will be used for relative source paths\. > fillColor=`#49EFB6` ####### $\{project\.basedir\} ######## \$\{project\.basedir\}/src\ > fillColor=`#FFB600` ##### careForLastEol > fillColor=`#FFFF00` ###### Carefully reproduce last EOL in result files\. > fillColor=`#49EFB6` ####### false ######## \true\ > fillColor=`#FFB600` ##### replaceSources > fillColor=`#FFFF00` ###### Replace source root folders in maven project
after preprocessing for following processing\. > fillColor=`#49EFB6` ####### true ######## \false\ > fillColor=`#FFB600` ##### keepComments > fillColor=`#FFFF00` ###### Keep comments in result files\. > fillColor=`#49EFB6` ####### true ######## \REMOVE\_JCP\_ONLY\ > fillColor=`#FFB600` ##### vars > fillColor=`#FFFF00` ###### List of variables to be registered
in preprocessor as global ones\. > fillColor=`#49EFB6` ####### \
\SOME TEXT\
\12345\
\
> align=`left`,fillColor=`#FFB600` ##### excludeFolders > fillColor=`#FFFF00` ###### List of patterns of folder paths to be excluded from preprocessing,
It uses ANT path pattern format\. > fillColor=`#49EFB6` ####### \
\\*\*/folder1\
\/some/\*\*/folder2\
\ > align=`left`,fillColor=`#FFB600` ##### configFiles > fillColor=`#FFFF00` ###### List of external files containing variable definitions\. > fillColor=`#49EFB6` ####### \
\$\{basedir\}/config1\.txt\
\$\{basedir\}/config2\.txt\
\
> align=`left`,fillColor=`#FFB600` ##### keepLines > fillColor=`#FFFF00` ###### Keep preprocessing directives in result files as commented ones,
it is useful to not break line numeration in result files\. > fillColor=`#49EFB6` ####### true ######## \false\ > fillColor=`#FFB600` ##### allowWhitespaces > fillColor=`#FFFF00` ###### Turn on support of white spaces
in preprocessor directives between '//' and the '\#'\. > fillColor=`#49EFB6` ####### false ######## \true\ > fillColor=`#FFB600` ##### allowBlocks > fillColor=`#FFFF00` ###### Enable merging of text lines for //$""" and //$$""" > fillColor=`#49EFB6` ####### false ######## \true\ > fillColor=`#FFB600` ##### preserveIndents > fillColor=`#FFFF00` ###### Preserve indents in lines marked by '//$' and '//$$' directives\.
Directives will be replaced by white spaces chars\. > fillColor=`#49EFB6` ####### false ######## \true\ > fillColor=`#FFB600` ##### useTestSources > fillColor=`#FFFF00` ###### Turn on test sources root use\. > fillColor=`#49EFB6` ####### false ######## \true\ > fillColor=`#FFB600` ##### skip > fillColor=`#FFFF00` ###### Skip preprocessing\. > fillColor=`#49EFB6` ####### false ######## \true\ > fillColor=`#FFB600` ####### activated by ######## jcp\.preprocess\.skip > fillColor=`#FFB600` ##### dontOverwriteSameContent > fillColor=`#FFFF00` ###### Turn on check of content body compare with existing result file to prevent overwriting,
if content is the same then preprocessor will not be writing new result content\. > fillColor=`#49EFB6` ####### false ######## \true\ > fillColor=`#FFB600` ##### actionPreprocessorExtension > fillColor=`#FFFF00` ###### Provide a class as the preprocessor extension through its full class name\.
The class must have the default constructor\. > fillColor=`#49EFB6` ####### null > fillColor=`#FFFFFF` ######## \com\.igormaznitsa\.jcp\.extension\.LogPreprocessorExtension\ > fillColor=`#FFB600` ## > fillColor=`#FFFFFF`,mmd.image=`iVBORw0KGgoAAAANSUhEUgAAAE4AAAAwCAYAAAC/gkysAAAOyUlEQVR42u1aB1QU1xrGksTEHo2JCqwtKpZYYiwxmjxN4ovJM5pEE9t7JjFGfSemgh17jw2DvYJ0kCYggjRBBGmiCCwgICIIClIFEf73/Xdn1wUWWBHfieWe852ZvXPnzr3f/H1WR+cJauUlZZV+p3vFd7tqG2kesytgms7zprkVpOSozomo8Q0f+eCwJa6Jdt1X0elP9zo9Z0hDyw5JUSftxeseVz4L/MGq0OK1xWTdeRk5GKxNSveKHcbXM/zkzwkDSToT1X4XXstpkWwbOd/78/0kSNNdLoiz77mmxGfK4V3PGdPQbgZdbS8/HLz95MjtZPn6EgVpEmz0jclp0KZoEN2Jx5bm3X12iaooK1dJ3TXXy11idvi5n+izjqw6Lq1EmlLqHHqvzQ2cbWn0TEtXUfodJWlNku0i344wdotlgqw6LatOmiBuOdl2XUmQRj+2gUrCn6l2KzxNSVqzq1bhE4J+tMm17LBYkKORNAlMqkOfdenhS0+K0OTsd8efHUfgN8NMed5Gfij4J+9JBx84gbrATuLN1XTqY1PrZ8p7qjxnep4u7Nl299E7qjmBusBS59h/Q1zC0fOjea7Ms4lPMWkVD0jLOpfUL3LNKRfHtzZodgJaSB2cRJnX5/u3PdWSdjerQHWe4hA1JvQPx4ts5Gt0AtpAz5ich2wJyQpJ7s7zlhWWPl2k5VxMV6rpC/EHz80I+NYiw6qzQmrqTZqkrif6rs/3m3HM8KmzZwgxlOevXtrqs8hrwr5iq47L6vSc2qmrKjRxZyfzVIQm6hvAebcIY/fdbqN3KlSzIUhTSh3so+PAjTeCf7afzs+KXHXq6SAt+8K1YefmWrs4Ddz4aPasFidh12M1uY/ZdYSD6CeWtNKcItV5jInfhKi1nmF+046SbZeVj2zTarN1cBJXLq4/PUbKdZ8wz5ldoKqhxe8PmpvqGJ0S+rsjpbnF0BkEuJyg8yYt31jasMQpQhM6PX7vxidONYFGfF58K7917uWM1fkJWTlx+wLp5Hvb6XbUdYI0CJWy7b6KXEdsFSTWZbuOv7qQLDssqeYQaroH855FQNyX13G/SgX5b0laefE9lROgiopD5XfLSq7aRJDbqB1k3sqQ7sTdpCTLcOEBozd6UarzJUFijaRBIh37raewRS7kNWE/WbRbJAjkuZhMs5aKo7rkikzirQ0lPpMP//Kkec7hgAdQnnAslFze2SLSKPuea6go/Q5l+CYIO5cdmkIIVMkeqqXJ0Fu0X0QnR23HeDnIDiP54fPkOnwreX6yh1KdoinN4wr6gun8Lw7kMvRPOt52oSrzsNFfwS/rRO7lGx3/dqEJVKVaX1ZIysTcmIyIdM9YCoFNO9F/g8KWgTiPMbvo7s0CygpOFlIG20dIvcjBYF011WSEgJDs0FQqSstlg09XTPzFvVnnk0nZKsorCJmIMAGX/jwj5uICAceHeGG3zn5v+Q2vK3ypq2LNutXXbK1LwLL/A2EaHh4816YlNrYAapl6bp4NqwrSIAUJTNpxqJjPV4eoNLeY0txjBHEXDJ3E5p0Hb1KRxqUkxwEbhUQxIdxKc4rp3FwbCvnNUWKrgjS18pIySjS/wAm/kFY2Bx4f/rUHl5pXWX8jYCAwCWhX274eC2k2shU9zdsY7cRbDkl2iIouKyq9XZiaQ1etw8nrX/sEYbwBt/d3ktPATeQ3/Rjdy7tLsaYBUNUVFDzfVmzYHdeZZLZfZyYdoJzodCFJD8SKBImF13KorlZxvxzPjxDks+1zHbEtPtTI+T1p7eOAbcBeYAewAlgDfAmo4j4bPWMdeOeGI0xJGjbZAlgKm5LkMnRLCRN1v/ieapP85vMSsijBLJQy/ORUdD2XskNS6PzPDoK4gG+PC1UKmHUcwlNBpz4yFaQF/WgtbOCjNiYd4Q8kebPwvDARJ5zf3rwY0v8f7KE/0A3QAzoAHYFhwAJgMghrWpd21UvScOwJOGOjpZ4fm1JmQFKNqoMwQHWtKD2PkJ8K4hKOhhB/F/X6dC/dv1tGSRZhINWeim/kacGK9uRl+CVQMjx6quPFqHPzbMf/rNP7xRr29gLQFhgKrAV+B9prY6K0I03PuBMM/REOB/ymHaM8eVYtK6+oRmLJ7SJxnn/1FlcyKGaHL5WX3hfXmNDaGl9nZ1OTet7L13x/wrEQYSq8Jx2Yo4mAKudNgTbAEGAr4AOsf2R1hb1iG1HGKldyq7DWjTKp6adjEW6UVLt2xfQshS93UxFZVysvu0/hy1yFh2YTUInQghK6tMWbv+pTXnz1F5lsH8XfJMht9E67NNfL+jWFJlUIbAK0BEYDvkAcMKZepG3SmfAKFm6MfFNISZ2bhRRFb/Im36+PVJPM4J/sKdM/UUiKNiqXdvKyCITZ6/rPNKeKsvJK1xOPXxBB8aXNZ6rdfysijTzH7SanwZsKfKcenSQEoJWhVs4P542BV4AfgFxgltZBbdRaRWnmhk98F7xtr/J75VpJCQesToM2wbMtoszAJNF3YaEzFSImY+K1IU0RihSJoBeejrwnHqCLyDbuxGZWGlOSXUhx+4JAYGi1+9nL+880I0vEdrCpJuhq/bDRgySB7FQ2P1QmkO4V1yMzIPHM3cx8rTbLG/H95qiQAg4JWC3LISUhv5+g+APnHnhgTYRDegQxMJGcMVza5ks3g65SGe5hstkLI+wRzxASp5Q+9FcKYaRWkHxbhEGcVSCTSAqcbSU+6GSHX3tYp8ixX9NaB5eXPkiKsejhsGkJ3p8foLKCEq2Ii1zpTojxRNrEWQMHohzZZ19IpcjVHiJOUzqDwmu5lOpyCaRUCHvo0HMtxe0/p3AiidmV5uVYLmyhi5gbaidIZOMfhICbVVJTY2l3H2Misgn+jHhm0sGFD1urq9ObIr1Rl7im1z2vTDz7nUU+vy02vtqEC5z22GGB6oVKzgbOfHGQ7t0ppsA51hSx0gPnCuLu3swX8ZwIXTgY/sBE3M+hC6u1sJelZUL1HQzWink5G+Hc9Fb4NWE/ObjmJJ9VOmKFG2WeTRJOg9vtyOvi2bwGvg8xXVDYYpf+DZagR284/eD3/YrmybaRC7gawerGhpn/9JLhn1AjYSwNnEIp62xVk3ZOuYL/a0tKdRcqBom5vN1XZBG3II2snpxxeEG6YR4IOa+I8TzH76lcUuLvC7gnVApPYnb4QRWNRL+ixrdEIfGwi1xVSfeKJx84Kf7N1Wekfv/WZJLqXdXgBpVqJz983kT930FcHOSANWqdpypuUtqTYkgMqxZSG7LosLjOuhrX5Lgex3aH5xTekjcMhC1xFc6gHPOzJHI4w47Ef7qZyquql5t4jXfiMhGiZGNezR+yrUCiE9Kv4AX2dHGDF3mM/Ytfjn38/iARmlza7P3wpIEAdQIbpXvGymJ2+nlwhaHqh2FeKFcoWBXZ/XOFgnNHqDKZtzbU+huCslIi5u9c5StVt5WiTARVEuc8lu0fP4ftZKVye2eF7WRPLQLdI+fJGuM1FkW5RAUbx4WHZLsIit0beC9wjtU/6yVpRTfuqJPWBAt8O2KFe5xS3GvaNHtJ9/dNKMXhIoLSk1DBhQ34sWW52KCQHIlUliR2GtGbvav9n4TJ55CHSWNHwvU5z3Gm1SvFEjgf9pl8mNK945AqJu6AELSVtKxeqtos5UTUZ/BM+XX90YUXyolz7O6zCDa9ReWjIT/vaYINbBnbQc5UOAOo+lL5t3kbI3IGgVwDvGoboSpoCkeiPr6zgrwbPnL2ttfxMobVS+ruFZS2RtA4n72ORfvFWn0EYSmLRoojnMZj+lJVVQo5r+XYLsbEX/GyNIxjr8lmg52KN5waV53Z7rLHVai5YpxZK0MRS/K4RPPQ31Kdol8SZquiQjvS0txiOl3ZFbDTbdTOGkVbHRwKhPx6Qhh25dt87KSp/WXVf4YZ5cXdFAVQjc/GS2RPykIQtz9IFEKvn4ol2GzxvYM9rXpoFAfyQo2co7y/OGjwUNIG1pfB29yAPZFjwpoQL456xhl4WCq8ajykTG7VcVlt9zQ88Ew4i3gk80kIYHOx5ljN45bLQYzcvLURYCi377VG7jF2lxxOQQ6yVeN4z8i75a4jtl4/Nc703Yci7oDOfAPEPv0wUU3oA/QFPgVmm7X8Y6ypzqzeCDT7Westr+2+xwJoRd89OrOHQlVXQgKHo8+grntg6/odfenXfrBrWLNxpWsgt69ZS8MB2FdrnYZuUl1qqovu2lZ/lw9EkZ33trLRNX6vIee0012pY1WfjzXdZV0aKc/bytq/MFI2yOCwrtFMG93lFra6K4Zwfw9Z154Yx2irdt+LQGegtfRb2d8K6AO8ATSW+poBekATqb+t8rk46kpzGyjnqtp6ybo30pV1btFP1rO7pe6y3iBvEPc37vJyc6ytkzRvB6ClNCfP3wt4E+gGtKhh7/UirAfwFW9I+t2ki0x/9ACZgf8SvZlBkLSpEmn9cc0O+BNYyMRI44cAlsAstTnbAL8Be4D1QHepvzewu5tM1h5HY+BrJl66xmM3A0ZAX00bk17St7jf8h/67wxw1F39lYXu0vEj9QdN7irTP4R1f4jr84CPpPHDgMOANbCGSZT6RwGfAO3qRR4GTwfspUV3kfpaSA+7gIXYqY0dAxQDwUAQIJP6maA8YJ8aQRMBf2kT89QW/C5wTSKTj6uBl6VrqcApYDtLSA3EtQOiAD+Qt4reyG8O4n6doj/2KPqov6xXGPr55X4vjWepNgHCgflKTcHxS8AKOAb0q4+0GUqL5ePrahJ4k6Wrm2Jz+lL/B8AdaSFTpL6ugC0QDwQCM9QW5gFMBqYqicBxOJAImErErVAjTi7NYVlV4qTrjaWXd1+SIPEPxXV6c5uM0x+xrpesW+FgWV8mNJkFQu2+KZJwDFTrG8GSD3jyeb2MIm58S5Ka3tLieLOXpT53YI40brQkaerizeLuJhHAi1gn9b8qLewCEMKSJvW/I0ksS/Vx4A814kIBb8Ac+FjDOptJEsrPWyLNM5yv6cl0p/GLgrqOxDFM+WKl+3g/ZsBgtT42Td8Dr9VHVf8HIjGNJEgJIG8AAAAASUVORK5CYII=` ### tasks > fillColor=`#FF00FF` #### preprocess > fillColor=`#FF00FF` ##### sources > fillColor=`#FFFF00` ###### paths ####### path ######## \
\\./src\
\
> align=`left`,fillColor=`#FFB600` ##### eol > fillColor=`#FFFF00` ###### eol="\\r\\n" > fillColor=`#FFB600` ##### keepAttributes > fillColor=`#FFFF00` ###### keepAttributes="true" > fillColor=`#FFB600` ##### target > fillColor=`#FFFF00` ###### target="$\{jcp\.target\.folder\}" > fillColor=`#FFB600` ##### sourceEncoding > fillColor=`#FFFF00` ###### sourceEncoding="UTF\-8" > fillColor=`#FFB600` ##### targetEncoding > fillColor=`#FFFF00` ###### targetEncoding="UTF\-8" > fillColor=`#FFB600` ##### ignoreMissingSources > fillColor=`#FFFF00` ###### ignoreMissingSources="false" > fillColor=`#FFB600` ##### excludeExtensions > fillColor=`#FFFF00` ###### extension > fillColor=`#FFDB00` ####### \
\cpp\
\xml\
\
> align=`left`,fillColor=`#FFB600` ##### extensions > fillColor=`#FFFF00` ###### extension > fillColor=`#FFDB00` ####### \
\java\
\
> align=`left`,fillColor=`#FFB600` ##### unknownVarAsFalse > fillColor=`#FFFF00` ###### unknownVarAsFalse="true" > fillColor=`#FFB600` ##### dryRun > fillColor=`#FFFF00` ###### dryRun="false" > fillColor=`#FFB600` ##### verbose > fillColor=`#FFFF00` ###### verbose="true" > fillColor=`#FFB600` ##### clearTarget > fillColor=`#FFFF00` ###### clearTarget="true" > fillColor=`#FFB600` ##### careForLastEol > fillColor=`#FFFF00` ###### careForLastEol="true" > fillColor=`#FFB600` ##### keepComments > fillColor=`#FFFF00` ###### keepComments="REMOVE\_JCP\_ONLY" > fillColor=`#FFB600` ##### vars > fillColor=`#FFFF00` ###### var ####### \
\antdefined\
\
> align=`left`,fillColor=`#FFB600` ##### excludeFolders > fillColor=`#FFFF00` ###### folder ####### \
\\*\*/excluded1\
\\*\*/excluded2\
\
> align=`left`,fillColor=`#FFB600` ##### configFiles > fillColor=`#FFFF00` ###### paths ####### path ######## \
\\./config\.cfg\
\
> align=`left`,fillColor=`#FFB600` ##### keepLines > fillColor=`#FFFF00` ###### keepLines="true" > fillColor=`#FFB600` ##### allowWhitespaces > fillColor=`#FFFF00` ###### allowWhiteSpaces="true" > fillColor=`#FFB600` ##### allowBlocks > fillColor=`#FFFF00` ###### allowBlocks="true" > fillColor=`#FFB600` ##### preserveIndents > fillColor=`#FFFF00` ###### preserveIndents="true" > fillColor=`#FFB600` ##### dontOverwriteSameContent > fillColor=`#FFFF00` ###### dontOverwriteSameContent="true" > fillColor=`#FFB600` ##### actionPreprocessorExtension > fillColor=`#FFFF00` ###### actionPreprocessorExtension="com\.igormaznitsa\.jcp\.extension\.LogPreprocessorExtension" > fillColor=`#FFB600` ## > fillColor=`#FFFFFF`,mmd.image=`iVBORw0KGgoAAAANSUhEUgAAAKwAAAAwCAYAAACMlZHgAAAL2klEQVR42u2dCZAWxRXH9yAuYXddYCFAEOQQDUmQc48Zli1RCWUOAaMRE9AyGMTdnYHlDtFSUSHImooXIlki0SRUzFGxkiorIEVhtEyElMGgQU0CiBhEFANIybl5r6fnm+Pra47v4yPpqfrXbrE9Pd3Tv37z+vWboago7mGb7s8uoAGgBlAraB1oI2gbaCvoZdDToBWga0FDQT2K9KGPvB+2eR9oB+gIqCOC9oA2gKZmTQB96COHwE6KCCpLH4GuAZXpG3pWxrAE1BXU3afqItsoDZSzSLnqUDlU6bnSUffnhhSg7aCWeqq2tnkfx96gndRwuDoNwF4aAnYg/PuZULn3QcMKqj+zXry4GCXo8HjQyZSgRT2embUa3HwA2we0L3scjJEhYAczxuo4aEShgOr+XAaaJOn0b1IEtoMu1AZqaPNmYfee08D6YH0E1AF6BdTF/XeGW4A6kTK07xOfSUOrgVWE1oXV1VQ/zAxom1MGFnUINFhTpYGVWdaFIVhRx4ULMNvsDBoFqokgjA4cVViMlWsrq4HlwTqSAaurp3Jww36pYGmf0mRpYFnQop96RADsx6ChWW5Bsht2nqJ70Krp0sBmrCvVKgGsrh5L8Wa5P29SAHY/qFdqroGlUM+smGPRUs/va6z7ZKTXjnMBWMtQArYrtaAiWE+Crkp5hrv+7w4FaJckHvxmuBmtY53fbyPW/XpQG+hJUDtoMfHF3WNOY5K+TaI5FPez/z7OXxZzMe4A/Rj0E9D3nfPdv0Ob7fp4g26btaDvgtbSfmLdV9O/VeUNWP+42eZo0CLa31+AHgPdAu2uEoLr810fVrCuf4rUqCjWxTa/oegaFKdg0XFL8VEFi341cVlU+tDa4K97Waiuf7LbYeBEvVkhF+MuUIVSO9xBdlytr9HwoKjuVaD3cgqsd98/RSfxu5I2PQ396M8FF0CsVIAVNVAZVNv8NKhnJHBt8w8KwC6NCWsx/XkL3VZUDa09D+qvCMk09q6R+RajPcNB2yO0Awf5y8L76LbDMi6AMn9MFlJMCVgP1r6glyK04WPuWAOI8xVgXSqJw6K60Rl7PHTxP4OuDJRldw6t0yeSjrwD6hQT2rkxB3AfQNCb6U96lnU63Wvv4ALr9tsCGOT95OkGoQ9uGXgPjyWPgacArFXn3psBCdqyGnzxEj+sJaDnJbC+S31ckU/SpnBxBPdSjkV2rKBt/kBh5o2K7MfiQDvnn4l547ZzF0O2WSc591++dpTTSRd3AE+SGDarLc6E353Kpo1l1iUGdnYDTiB80r6RsD0zM4wAhJ8BvS0Bdr4Ehm0RG9AgqKvCyRYSnj8t4qKujPOodoXXe436raLrrsmuvxb9ssOS8zb52rNFIVd4p2RivcqZ9PdK6sbF1d8VgTUSAduSmcz3SJ6Wi0mWnm0+JBn3fq6FHQI6LYD1LYlvsizGjHmb5GDy6/ym5Py1arDWu/XN59Szi1wr2Ia+dMXKKv8B6IKAW8DfkkY/+dZMn2bjKt+sF0yY5cRCZga8DvNPZ7EXRETXBaMfZM3Au18Pk/BVsJ/owhzIGbDOORWc+o8z4+p2fRl9Y4V1znoX2AkS63oJ03d1On1+AjO/UhBVQNdgImgKQ9eQgY/mDpzgLGL6B2KWrQ3+cxZw2j3FV6aUu1C0fDkQ2Ees3wlxseqcEXiMBge9huOThiMPSzh1NwUWZf7JZhk9uJY8DWD5a4bbGRET/3lrOMalB4LYIoD1V6BS7s6WbT6YyDdJY9NBXm445/qLFSIKrzDO+5EzgLVu6OgQo8ycrIWRA/dmRtnNmTgrvz2PM87DHIzP+sqw/MR/kDay4pleZOPGHAL7LOfef52GDFnCsNdXGYtSfApdgsDeKwB2kMQdOJLQmU53E0K82AoPSLXCuQuYubreI4z1yDvGzDDDyAZ7QTTRsfBjRDtdfRnnfZJZfF03qJguRtlPMW69xE0ZxJx0iX1Y0t9tRelm712BwK7mwHon1xXwgsBJG7AgD8DOimXdyeOT+HnZjyavTD/OhkMfDrAHGeW/KN2KdM4Pn4duzuV04pRz3IabFertxd7pCi2MowLrxOG3pwqsBcZHAOwECbCdUmjE/DwAO41z7QqFc2czznvDtxJmxRf/LQCWBcZ4hZyA7hxYnH3jpjGlHGCXKkzK/uzFlzGcEd9lhdiu5DwV0KD9JWULe73IJTgaY9ZH1fQ8AFsrjO21hKxbMyyOVk13z31OaGGjAYtQvcAo/3Np0ott3i0E1imzhzu5RNvl6Jax7k8zAKc23isE19jIKH8KnggjoG81EQXjWF+FwFoCH/Y+iQ+7KSGwPZNkmEWA9jQTPMuo4GZD2eZt3FBYLGAN9DN/yKnz2uyNmAysgzhxXgfY5tFuueVsOKhRYC3qnE2M/cyk+bkN3mRuzoQHf8tph7MrNrcxXP8iTn+/lSS18HIBsAdA1YKw1qgEsG5izUxfMs400P0MrQTdqtS5pszW4Ep+kN7o41i/+mL6jn4ZxxVg+bB9lIF12jGBQsTyR6eQdYFllDhhvbHQJmOwIFaKoFzmcxsqBW2eAf0rceomE6cTWRjyN0ruZvrVuOjhX2MyjZqU+gxaV05ZXKx/AfpYnD2pjXLhtw7oxsEpAbTrJDkEz8aAFW/25wWZY0MkseE1Ed2CKk74ydVzNLXwpwo7Qbt8N7hXJGCdtmwV1P1Xmv63libdiNrhLbq8ENUqQfmdtH/t9Ml4WrD1eyHH38XPUr0uuMZrNIZa6eNjuaD8r0EWDWfdSFMNj1FLzn5rmm7N7pUAMk4wABfGeGP2TlEsFa63S9KeG2KkFM5NyfH3A9tbGVgrk/hSybGyUeUB6/UVs7Q+TJj08h3J/RwjqWN35m1nb3NJlktwhtO/LzkJRuOKwskvWySAvAwqE1jZoWR/W+0mL5K4KDMkbTlK3zuLswBbnQdg3wsE9NnB+okpQJsNrFP3uATx8TZnt80UT36LJL2fUgLWg/yDmG26vaiptjgMyUKF9MKJCsm5LYJHzYbAVijDd6WT4k1JO97BSRYJVA+UEsFCIC1gD5B8BLnFH8ZIw0wG7Oyxbt0Xc2K+Isvq7PzNGy9+NcjKtP8yJWDXT3fP60Hdkih9/BuM3fksq9ZFAdiDkk8W+X83Qd+myR+TSZ6sYEtV8no5My831uGB20i3SUV5o/gYezEGsIeEwAahRffgCUkm2UES+mInzFyRvdCs8b9x8Agn3OXf3t1ALCAvWiJsP9npaw9dY1/W51Sbab33jHVDdLJ1ws7Ak9i/AIz4ikx7rvb+cRtY5a2HxHHZjBUyOtHvSuHe9QMkG8iBZx61flV00mXvz3vAVtJMqJU+3UXOlU6ewARH62PQd7qepIAuo98t60nLvEAXuK5+R/Ik5MajG9mNcp4s62g/2+hCpy95MkbJzQiH3Zxzq0mesxMKXETCZeI24X27iJZvp33B1/2/R9taFUhKYlk4UDfQMQkwh0GfSzOuT6+NH5z7vQKwSyLHYFUsLn+SseKmWwKpi6lsbhjiFMk543PXx1QGMeKLs5bk3jXVKEGDelABmp+lCo1T1wjQGcl194N6pvpNBFHi8cxRJZyEkhVF+iiMg/qyhxWgHZ3ydXcoXLMlZx1vHhO2Sp1pTJTlXzVqUgoDVvfnSAV4doM6p2HtFBdaa3N+A6y6Urq6tkFv8t+UQL+1TgNTKNBSLZQ8ovFvM6lFLk+gAaB9ElhfpWVz23nbGKIQZrlJU1K48LZJQDoB+jChZO7HXm4SefrAXiSB9SFSbk6DhqOA3YMHFD+wkQshrJVpL/BiAvsMSRjJx4pbH4mhveMswPoSugt5g5UP7CHhu1/6KFh4axVitGkJQ2vn5RXWbB/2P2QP2zLK8xrP1EeqlrY7aD1+iTtHoGJoa3LeQfWA7UL25sPf0dKgntPQovrh5kGKoOKGwFcwTHbWYGW9sapB/d8Bl/7ej/7HHa+DPooAKH5jdg9oo2tRzxqo+vi/hBg3EAaDGkHzQE+ANoG2Upg3g56h/9/XFNAw3GLVd04f+tCHPvShj0I6/gtjopxeR4k2EgAAAABJRU5ErkJggg==` ### plug\-in > fillColor=`#12ED12` #### com\.igormaznitsa\.jcp > fillColor=`#12ED12` ##### task > fillColor=`#12ED12` ###### preprocess ####### sources > fillColor=`#FFFF00` ######## sources = \['src/main/java'\] > fillColor=`#FFC800` ####### eol > fillColor=`#FFFF00` ######## eol = '\\r\\n' > fillColor=`#FFC800` ####### keepAttributes > fillColor=`#FFFF00` ######## keepAttributes=true > fillColor=`#FFC800` ####### target > fillColor=`#FFFF00` ######## target = file\('build/preprocessed/java'\) > fillColor=`#FFC800` ####### sourceEncoding > fillColor=`#FFFF00` ######## sourceEncoding='UTF\-8' > fillColor=`#FFC800` ####### targetEncoding > fillColor=`#FFFF00` ######## targetEncoding='UTF\-8' > fillColor=`#FFC800` ####### ignoreMissingSources > fillColor=`#FFFF00` ######## ignoreMissingSources=false > fillColor=`#FFC800` ####### excludeExtensions > fillColor=`#FFFF00` ######## excludeExtensions=\['txt','xml'\] > fillColor=`#FFC800` ####### extensions > fillColor=`#FFFF00` ######## extensions=\['java'\] > fillColor=`#FFC800` ####### unknownVarAsFalse > fillColor=`#FFFF00` ######## unknownVarAsFalse=false > fillColor=`#FFC800` ####### dryRun > fillColor=`#FFFF00` ######## dryRun=false > fillColor=`#FFC800` ####### verbose > fillColor=`#FFFF00` ######## verbose=true > fillColor=`#FFC800` ####### clearTarget > fillColor=`#FFFF00` ######## clearTarget=true > fillColor=`#FFC800` ####### baseDir > fillColor=`#FFFF00` ######## baseDir = file\('build/someBase'\) > fillColor=`#FFC800` ####### careForLastEol > fillColor=`#FFFF00` ######## careForLastEol=true > fillColor=`#FFC800` ####### keepComments > fillColor=`#FFFF00` ######## keepComments='keep\_all' > fillColor=`#FFC800` ####### vars > fillColor=`#FFFF00` ######## vars = \['someVar': 'Some Test Value'\] > fillColor=`#FFC800` ####### excludeFolders > fillColor=`#FFFF00` ######## excludeFolders=\['\*\*/some1','\*\*/some2'\] > fillColor=`#FFC800` ####### configFiles > fillColor=`#FFFF00` ######## configFiles=\['\./configFile\.txt'\] > fillColor=`#FFC800` ####### keepLines > fillColor=`#FFFF00` ######## keepLines=true > fillColor=`#FFC800` ####### allowWhitespaces > fillColor=`#FFFF00` ######## allowWhitespaces=true > fillColor=`#FFC800` ####### allowBlocks > fillColor=`#FFFF00` ######## allowBlocks=true > fillColor=`#FFB600` ####### preserveIndents > fillColor=`#FFFF00` ######## preserveIndents=true > fillColor=`#FFC800` ####### skip > fillColor=`#FFFF00` ######## skip=true > fillColor=`#FFC800` ####### dontOverwriteSameContent > fillColor=`#FFFF00` ######## dontOverwriteSameContent=false > fillColor=`#FFC800` ####### actionPreprocessorExtension > fillColor=`#FFFF00` ######## actionPreprocessorExtension="com\.igormaznitsa\.jcp\.extension\.LogPreprocessorExtension" > fillColor=`#FFB600` ####### outcomingFiles > fillColor=`#00A4FF` ######## read only > fillColor=`#FF71CC` ######### set of files touched during preprocessing > fillColor=`#FFFF00` ####### incomingFiles > fillColor=`#00A4FF` ######## read only > fillColor=`#FF71CC` ######### set of generated result files > fillColor=`#FFFF00` ## External config files > fillColor=`#00B6FF` ### multi\-line text files > fillColor=`#00B6FF` #### line starts with > fillColor=`#00B6FF` ##### / ###### can contain CLi key > fillColor=`#49EFB6` ####### /V ##### \# > leftSide=`true` ###### recognized as comment > fillColor=`#49EFB6` ####### \# some ignored comment ##### @ ###### throws preprocessor error > fillColor=`#49EFB6` ####### @ error string ##### any other non\-empty ###### interpret as global variable definition > fillColor=`#49EFB6` ####### \=\ ######## globalVar="Hello world" > fillColor=`#FFC800` #### empty line > fillColor=`#00B6FF` ##### ignored > fillColor=`#49EFB6` ## Command Line > fillColor=`#00DBFF`,leftSide=`true` ### /H,/h,/?,\-H\.\-? > fillColor=`#00DBFF` #### print help information > fillColor=`#49EFB6` ### /T: > fillColor=`#00DBFF`,leftSide=`true` #### set input encoding > fillColor=`#49EFB6` ##### /T:UTF\-8 > fillColor=`#FFC800` ### /TT: > fillColor=`#00DBFF` #### set output encoding > fillColor=`#49EFB6` ##### /TT:UTF\-8 > fillColor=`#FFC800` ### /C > fillColor=`#00DBFF`,leftSide=`true` #### clear target folder before preprocessing > fillColor=`#49EFB6` ### /I: > fillColor=`#00DBFF`,leftSide=`true` #### define source folder for preprocessing > fillColor=`#49EFB6` ##### /I:\./src > fillColor=`#FFC800` ### /O: > fillColor=`#00DBFF`,leftSide=`true` #### define result folder > fillColor=`#49EFB6` ##### /O:\./preprocess > fillColor=`#FFC800` ### /F: > fillColor=`#00DBFF`,leftSide=`true` #### comma separated list of preprocessed extensions > fillColor=`#49EFB6` ##### /F:java,txt,html > fillColor=`#FFC800` ### /EF: > fillColor=`#00DBFF`,leftSide=`true` #### comma separated list of excluded extensions > fillColor=`#49EFB6` ##### /EF:xml,png > fillColor=`#FFC800` ### /EA: > fillColor=`#00DBFF`,leftSide=`true` #### preprocessor extension class name > fillColor=`#49EFB6` ##### /EA:com\.igormaznitsa\.jcp\.extension\.LogPreprocessorExtension > fillColor=`#FFB600` ### /ES > fillColor=`#00DBFF`,leftSide=`true` #### turn on support of white spaces betwee // and \# in directives > fillColor=`#49EFB6` ### /R > fillColor=`#00DBFF`,leftSide=`true` #### remove all Java like comments from result files > fillColor=`#49EFB6` ### /K > fillColor=`#00DBFF`,leftSide=`true` #### prevent line numeration in result files > fillColor=`#49EFB6` ### /Z > fillColor=`#00DBFF`,leftSide=`true` #### disable override result file if exists and has same content > fillColor=`#49EFB6` ### /V > fillColor=`#00DBFF`,leftSide=`true` #### turn on verbose mode > fillColor=`#49EFB6` ### @\ > fillColor=`#00DBFF`,leftSide=`true` #### read global variables from a file > fillColor=`#49EFB6` ### @@\ > fillColor=`#00DBFF`,leftSide=`true` #### read global variables from file which path defined by expression > fillColor=`#49EFB6` ### /P: > fillColor=`#00DBFF`,leftSide=`true` #### define global variable value > fillColor=`#49EFB6` ##### /P:DEBUG=true > fillColor=`#FFC800` ### /N > fillColor=`#00DBFF`,leftSide=`true` #### carefully reproduce last EOL in result file > fillColor=`#49EFB6` ### /PI > fillColor=`#00DBFF`,leftSide=`true` #### turn on indent preserving for //$ and //$$ directives > fillColor=`#49EFB6` ### /ED: > fillColor=`#00DBFF`,leftSide=`true` #### folders to be excluded from preprocessing
ANT matcher is allowed, system path separator as delimiter > fillColor=`#49EFB6` ##### /ED:/\*\*/test:/\*\*/test\*/some > fillColor=`#FFC800` ### /A > fillColor=`#00DBFF`,leftSide=`true` #### keep original source attributes for result files > fillColor=`#49EFB6` ### /U > fillColor=`#00DBFF`,leftSide=`true` #### turn on FALSE as unknown variable value > fillColor=`#49EFB6` ### /B > fillColor=`#00DBFF`,leftSide=`true` #### Enable sulpport of multiline merging for //$ and //$$ > fillColor=`#49EFB6` ### /M: > fillColor=`#00DBFF`,leftSide=`true` #### allows select keep comment processor
to remove selected kind of commented lines > fillColor=`#49EFB6` ##### /M:remove\_jcp\_only > fillColor=`#FFC800` ##### allowed values > fillColor=`#FFCC71` ###### true > fillColor=`#FFCC71` ####### same as keep\_all > fillColor=`#49EFB6`,topicLinkUID=`18C52A4D054A` - TOPIC
18C52A4EDD2A
###### false > fillColor=`#FFCC71` ####### same as remove\_c\_style > fillColor=`#49EFB6` - TOPIC
18C52A5933DA
###### keep\_all > fillColor=`#FFCC71`,topicLinkUID=`18C52A4EDD2A` ####### to not remove comments > fillColor=`#49EFB6` ###### remove\_c\_style > fillColor=`#FFCC71`,topicLinkUID=`18C52A5933DA` ####### remove all comments in C style > fillColor=`#49EFB6` ###### remove\_jcp\_only > fillColor=`#FFCC71` ####### remove only comment lines related to JCP > fillColor=`#49EFB6` ## DSL > leftSide=`true` ### Directives > fillColor=`#00FFFF` #### //\#local \=\ > fillColor=`#00FFFF` ##### define local variable > fillColor=`#49EFB6` ###### //\#local somevar="Hello world" > fillColor=`#FFC800` #### //\#if \\.\.//\#else\.\.//\#endif > fillColor=`#00FFFF` ##### conditional execution
needs boolean expression > fillColor=`#49EFB6` ###### //\#if boovar
\.\.\.
//\#else
\.\.\.
//\#endif > align=`left`,fillColor=`#FFC800` #### //\#ifdefined \\.\.\.//\#else\.\.//\#endif > fillColor=`#00FFFF`,leftSide=`true` ##### conditional execution
checks that a variable is defined > fillColor=`#49EFB6` ###### //\#ifdefined
\.\.\.
//\#else
\.\.\.
//\#endif > align=`left`,fillColor=`#FFC800` ##### //\#ifdef\.\.\.//\#else\.\.\.//\#endif > fillColor=`#FFDB00` #### //\#ifndef \\.\.//\#else\.\.//\#endif > fillColor=`#00FFFF`,leftSide=`true` ##### conditional execution
checks that a variable is not defined > fillColor=`#49EFB6` ###### //\#ifndef svar
\.\.\.
//\#else
\.\.\.
//\#endif > align=`left`,fillColor=`#FFC800` #### //\#while \\.\.//\#break\.\.//\#continue\.\.//\#end > fillColor=`#00FFFF`,leftSide=`true` ##### conditional execution
while expression result is TRUE > fillColor=`#49EFB6` ###### //\#while a\>0
\.\.\.
//\#break
\.\.\.
//\#continue
\.\.\.
//\#end > align=`left`,fillColor=`#FFC800` #### //\#exitif \ > fillColor=`#00FFFF`,leftSide=`true` ##### conditional end of current file preprocessing
return to calling file if presented > fillColor=`#49EFB6` ###### //\#exitif avar="hello" > fillColor=`#FFC800` #### //\#exit > fillColor=`#00FFFF`,leftSide=`true` ##### end of current file preprocessing
return to calling file if presented > fillColor=`#49EFB6` #### //\#outdir \ > fillColor=`#00FFFF`,leftSide=`true` ##### set output directory for preprocessing file > fillColor=`#49EFB6` ###### //\#outdir "some/folder" > fillColor=`#FFC800` #### //\#\[\+|\-\] > fillColor=`#00FFFF`,leftSide=`true` ##### turn on \(\+\) and turn off \(\-\) preprocessing > fillColor=`#49EFB6` ###### preprocessed
//\#\-
non preprocessed
//\#\+
preprocessed > align=`left`,fillColor=`#FFC800` #### //\#outname \ > fillColor=`#00FFFF`,leftSide=`true` ##### set result name for preprocessing file > fillColor=`#49EFB6` ###### //\#outname "some\.java" > fillColor=`#FFC800` #### //\#// > fillColor=`#00FFFF`,leftSide=`true` ##### comment next line > fillColor=`#49EFB6` ###### //\#//
line to be commented > align=`left`,fillColor=`#FFC800` #### //\#definel \ > fillColor=`#00FFFF`,leftSide=`true` ##### define a local boolean variable as TRUE > fillColor=`#49EFB6` ###### //\#definel newvar > fillColor=`#FFC800` #### //\#define \ > fillColor=`#00FFFF`,leftSide=`true` ##### define a global boolean variable as TRUE > fillColor=`#49EFB6` ###### //\#define newglobal > fillColor=`#FFC800` #### //\#undef \ > fillColor=`#00FFFF`,leftSide=`true` ##### remove variable if exists > fillColor=`#49EFB6` ###### //\#undef newvar > fillColor=`#FFC800` #### //\#flush > fillColor=`#00FFFF`,leftSide=`true` ##### force flushing of current buffer states to disk
and clear internal buffers > fillColor=`#49EFB6` #### //\#include \ > fillColor=`#00FFFF`,leftSide=`true` ##### include preprocess result of defined file into position > fillColor=`#49EFB6` ###### //\#include "some\.java" > fillColor=`#FFC800` #### //\#action > fillColor=`#00FFFF`,leftSide=`true` ##### make call to user extension
with comma separated arguments\.
Its logic can be tuned through a preprocessor extennsion class > fillColor=`#49EFB6` ###### //\#action 1000,"hello",123 > fillColor=`#FFC800` ####### It requires a preprocessor extension > fillColor=`#FF3700`,mmd.emoticon=`error`,textColor=`#FFFFFF` #### //\#postfix\[\+|\-\] > fillColor=`#00FFFF`,leftSide=`true` ##### turn on \(\+\) or turn off \(\-\) output into postfix section > fillColor=`#49EFB6` ###### some text
//\#postfix\+
it will be in the end
//\#postfix\-
other text > align=`left`,fillColor=`#FFC800` #### //\#prefix\[\+|\-\] > fillColor=`#00FFFF`,leftSide=`true` ##### turn on \(\+\) or turn off \(\-\) output into prefix section > fillColor=`#49EFB6` ###### some text
//\#prefix\+
it will be in the beginning
//\#prefix\-
other text > align=`left`,fillColor=`#FFC800` #### //\#global \=\ > fillColor=`#00FFFF`,leftSide=`true` ##### define a global variable value > fillColor=`#49EFB6` ###### //\#global debug=true > fillColor=`#FFC800` #### //\#\_if\.\.//\#\_else\.\.//\#\_endif > fillColor=`#00FFFF`,leftSide=`true` ##### special condition to be checked during 1st preprocessing pass
works with global variables > fillColor=`#49EFB6` ###### //\#\_if debug
\.\.\.
//\#\_else
\.\.\.
//\#\_endif > align=`left`,fillColor=`#FFC800` #### //\#excludeif \ > fillColor=`#00FFFF`,leftSide=`true` ##### exclude file from preprocessing
if boolean expression returns true > fillColor=`#49EFB6` ###### //\#excludeif debug > fillColor=`#FFC800` #### //\#error \ > fillColor=`#00FFFF`,leftSide=`true` ##### stop work and generate exception with notification
macroses allowed > fillColor=`#49EFB6` ###### //\#error unexpected value /\*$var1$\*/ > fillColor=`#FFC800` #### //\#warning \ > fillColor=`#00FFFF`,leftSide=`true` ##### log text as warning
macroses allowed > fillColor=`#49EFB6` ###### //\#warning be careful with /\*$var4$\*/ > fillColor=`#FFC800` #### //\#echo \ > fillColor=`#00FFFF`,leftSide=`true` ##### log text as info
macroses allowed > fillColor=`#49EFB6` ###### //\#echo the line /\*$\_\_line\_\_$\*/ > fillColor=`#FFC800` #### //\#msg \ > fillColor=`#00FFFF`,leftSide=`true` ##### log text as info
macroses allowed, if verbose mode then stack will be printed > fillColor=`#49EFB6` ###### //\#msg some info > fillColor=`#FFC800` #### //\#noautoflush > fillColor=`#00FFFF`,leftSide=`true` ##### turn off autoflush for EOF > fillColor=`#49EFB6` #### //\#abort \ > fillColor=`#00FFFF`,leftSide=`true` ##### abort preprocessing and show message
macroses allowed > fillColor=`#49EFB6` ###### //\#abort thats all\! > fillColor=`#FFC800` #### //$ > fillColor=`#00FFFF`,leftSide=`true` ##### remove comment and print result with macross processing > fillColor=`#49EFB6` ###### //$ some line with /\*$var$\*/ > fillColor=`#FFC800` ####### Special case //$""" means merging of text lines
before providing them to an external processor > fillColor=`#FFC800` #### //$$ > fillColor=`#00FFFF`,leftSide=`true` ##### remove comment and print result, macroses ignored > fillColor=`#49EFB6` ###### //$$ some line with /\*$nonprocessed macroses$\*/ > fillColor=`#FFC800` ####### Special case //$$""" means merging of text lines
before providing them to an external processor > fillColor=`#FFC800` #### /\*\-\*/ > fillColor=`#00FFFF`,leftSide=`true` ##### drop tail of line > fillColor=`#49EFB6` ###### some line/\*\-\*/dropped part > fillColor=`#FFC800` ### Data types > fillColor=`#FFC800`,leftSide=`true` #### boolean > fillColor=`#FFC800` ##### true > fillColor=`#FFC800` ##### false > fillColor=`#FFC800`,leftSide=`true` #### integer > fillColor=`#FFC800`,leftSide=`true` ##### signed 64 bit ###### 234567, 0x56FE > fillColor=`#FFC800` #### float > fillColor=`#FFC800`,leftSide=`true` ##### signed 32 bit ###### 0\.745 > fillColor=`#FFC800` #### string > fillColor=`#FFC800`,leftSide=`true` ##### "hello world" > fillColor=`#FFC800` ### Operators > fillColor=`#FFFF00`,leftSide=`true` #### ==, \>, \>=, \<, \<=, \!= > fillColor=`#FFFF00` #### \+,\-,\*,/,% > fillColor=`#FFFF00`,leftSide=`true` #### \!, &&, ||, ^ > fillColor=`#FFFF00`,leftSide=`true` ### Functions > fillColor=`#FFC67D`,leftSide=`true` #### INT|FLOAT abs\(INT|FLOAT\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` #### INT round\(INT|FLOAT\) > fillColor=`#00B6FF`,leftSide=`true`,textColor=`#FFFFFF` #### BOOL is\(STR,ANY\) > fillColor=`#00B6FF`,leftSide=`true`,textColor=`#FFFFFF` #### STR evalfile\(STR\) > fillColor=`#00B6FF`,leftSide=`true`,textColor=`#FFFFFF` #### STR binfile\(STR, STR\) > fillColor=`#00B6FF`,leftSide=`true`,textColor=`#FFFFFF` #### string processing > fillColor=`#FFCC71` ##### BOOL issubstr\(STR,STR\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` ##### INT strlen\(STR\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` ##### STR trimlines\(STR\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` ##### STR esc\(STR\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` ##### INT str2int\(STR\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` ##### STR str2web\(STR\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` ##### STR str2csv\(STR\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` ##### STR str2js\(STR\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` ##### STR str2json\(STR\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` ##### STR str2xml\(STR\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` ##### STR str2java\(STR\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` ##### STR str2go\(STR\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` #### xml functions > fillColor=`#FFCC71`,leftSide=`true` ##### STR xml\_get\(STR, INT\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` ##### INT xml\_size\(STR\) > fillColor=`#00B6FF`,leftSide=`true`,textColor=`#FFFFFF` ##### STR xml\_attr\(STR, STR\) > fillColor=`#00B6FF`,leftSide=`true`,textColor=`#FFFFFF` ##### STR xml\_root\(STR\) > fillColor=`#00B6FF`,leftSide=`true`,textColor=`#FFFFFF` ##### STR xml\_name\(STR\) > fillColor=`#00B6FF`,leftSide=`true`,textColor=`#FFFFFF` ##### STR xml\_list\(STR, STR\) > fillColor=`#00B6FF`,leftSide=`true`,textColor=`#FFFFFF` ##### STR xml\_text\(STR\) > fillColor=`#00B6FF`,leftSide=`true`,textColor=`#FFFFFF` ##### STR xml\_open\(STR\) > fillColor=`#00B6FF`,leftSide=`true`,textColor=`#FFFFFF` ##### STR xml\_xlist\(STR, STR\) > fillColor=`#00B6FF`,leftSide=`true`,textColor=`#FFFFFF` ##### STR xml\_xelement\(STR, STR\) > fillColor=`#00B6FF`,leftSide=`true`,textColor=`#FFFFFF` #### User defined functions > fillColor=`#FFC67D`,leftSide=`true` ##### $\\(\.\.\.\) > fillColor=`#00B6FF`,textColor=`#FFFFFF` ###### It requires a preprocessor extension > fillColor=`#FF3700`,mmd.emoticon=`error`,textColor=`#FFFFFF` ### special variables > fillColor=`#5BEBA4`,leftSide=`true` #### jcp\.version > fillColor=`#5BEBA4` ##### preprocessor version ##### read only > fillColor=`#FF0000`,textColor=`#FFFFFF` #### jcp\.src\.path > fillColor=`#5BEBA4`,leftSide=`true` ##### full path to preprocessing source file ##### \_\_file\_\_ ##### read only > fillColor=`#FF0000`,leftSide=`true`,textColor=`#FFFFFF` #### jcp\.src\.dir > fillColor=`#5BEBA4`,leftSide=`true` ##### Preprocessing file folder ##### \_\_filefolder\_\_ ##### read only > fillColor=`#FF0000`,textColor=`#FFFFFF` #### jcp\.src\.name > fillColor=`#5BEBA4`,leftSide=`true` ##### Preprocessing file name ##### \_\_filename\_\_ ##### read only > fillColor=`#FF0000`,leftSide=`true`,textColor=`#FFFFFF` #### \_\_line\_\_ > fillColor=`#5BEBA4`,leftSide=`true` ##### number of preprocessing line ##### read only > fillColor=`#FF0000`,leftSide=`true`,textColor=`#FFFFFF` #### jcp\.dst\.path > fillColor=`#5BEBA4`,leftSide=`true` ##### destination file path ##### read only > fillColor=`#FF0000`,leftSide=`true`,textColor=`#FFFFFF` #### jcp\.dst\.dir > fillColor=`#5BEBA4`,leftSide=`true` ##### destination folder #### jcp\.dst\.name > fillColor=`#5BEBA4`,leftSide=`true` ##### destination file name #### \_\_time\_\_ > fillColor=`#5BEBA4`,leftSide=`true` ##### current time
HH:mm:ss #### \_\_date\_\_ > fillColor=`#5BEBA4`,leftSide=`true` ##### current date
MMM dd yyyy #### \_\_timestamp\_\_ > fillColor=`#5BEBA4`,leftSide=`true` ##### source file timestamp
EEE MMM dd HH:mm:ss yyyy ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ ![Logo](assets/banner.png) [![License Apache 2.0](https://img.shields.io/badge/license-Apache%20License%202.0-green.svg)](http://www.apache.org/licenses/LICENSE-2.0) [![Maven central](https://img.shields.io/badge/maven%20central-7.3.0-green.svg)](https://search.maven.org/#artifactdetails|com.igormaznitsa|jcp|7.3.0|jar) [![Java 11+](https://img.shields.io/badge/java-11%2b-green.svg)](http://www.oracle.com/technetwork/java/javase/downloads/index.html) [![Maven 3.0+](https://img.shields.io/badge/maven-3.0%2b-green.svg)](https://maven.apache.org/) [![Gradle 6.0+](https://img.shields.io/badge/gradle-6.0%2b-green.svg)](https://gradle.org/) [![Ant 1.8.2+](https://img.shields.io/badge/ant-1.8.2%2b-green.svg)](http://ant.apache.org/) [![Arthur's acres sanctuary donation](assets/arthur_sanctuary_banner.png)](https://www.arthursacresanimalsanctuary.org/donate) # Changelog __7.3.0 (11-okt-2025)__ - added way to manipulate current JCP text buffers as string variables: `jcp.text.buffer.all`,`jcp.text.buffer.middle`, `jcp.text.buffer.prefix` and `jcp.text.buffer.postfix` - added way to find `PreprocessorExtension` and `SpecialVariableProcessor` among Java services - refactoring of API for `SpecialVariableProcessor` and `CommentTextProcessor` - replaced single string property `actionPreprocessorExtension` by string list `actionPreprocessorExtensions` to provide way for many preprocessor extensions. - internal refactoring mainly to provide way for multiple external services implementing extensions __7.2.1 (21-jul-2025)__ - refactoring of CommentTextProcessor call - refactoring [Full changelog](https://github.com/raydac/java-comment-preprocessor/blob/master/changelog.txt) # Introduction Originally developed in 2002, the preprocessor tool emerged from the need to manage diverse sources for J2ME devices efficiently. It aimed to streamline altering specific calls' positions across different devices, optimizing the development process. With Java as the primary technology, the tool was fine-tuned for C/Java family languages, capitalizing on their import sections and C-comment style. Initially a closed project, it transitioned to an open-source initiative in 2011. Today, it stands out as a potent two-pass Java preprocessor, adept at understanding document structure (prefix, body, and postfix), incorporating loops, and utilizing XML files as data sources. Its capabilities extend to generating static websites. The preprocessor now exists as a comprehensive uber-jar bundled with interface code for Maven, ANT, and Gradle, seamlessly integrating with these tools. It requires a minimum JDK of version 1.8. Moreover, various Linux repositories offer the preprocessor as a package, commonly named `libcomment-preprocessor-java`, simplifying its accessibility for users. # Mind map with all options ![Mind map of preprocessor options](assets/documap.png) # How to use The Preprocessor can work as: - CLI tool - Java JAR-library - [Maven goal](jcp-tests/jcp-test-maven) [_(generated Maven mojo site)_](https://raydac.github.io/jcp-maven-plugin-site/index.html) - [ANT task](jcp-tests/jcp-test-ant) - [Gradle task](jcp-tests/jcp-test-gradle) The preprocessor has been published in [the Maven Central](https://search.maven.org/artifact/com.igormaznitsa/jcp). ``` ... com.igormaznitsa jcp 7.3.0 preprocessSources generate-sources preprocess ... ``` # How to use from command line The uber-jar can be started directly under Java through CLI interface. Let's take a look at short example below how to start it in command line under Linux: ``` java -jar jcp-7.3.0.jar --i:./test --o:./result ``` The example above just preprocessing files from ./test folder (which extensions allowed to be preprocessed by default), and placing result files into ./result folder. Keep in your mind that the preprocessor processing not all files, for instance XML files will not be preprocessed by default. Files which extension not marked for preprocessing will be just copied (of course if the extensions is not in the excluded extension list) More complex example: ``` java -jar jcp-7.3.0.jar --c --r --v --f:java,xml --ef:none --i:./test --o:./result '--p:HelloWorld=$Hello world$' ``` - --c clear the destination folder before work - --r remove all Java-style comments from preprocessed result files - --v show verbose log about preprocessing process - --f include .java and .xml files into preprocessing (by default the preprocessor doesn't preprocess XNL files and the extension should to be defined explicitly) - --ef don't exclude any extension from preprocessing - --i use ./test as source folder - --o use ./result as destination folder - --p define named global variable HelloWorld? with the 'Hello world' content - --z turn on checking of file content before replacement, if the same content then preprocessor will not replace the file - --es allow whitespace between comment and directive (by default it is turned off) # Some examples - [Prepare sources for Javassist](jcp-tests/jcp-test-javassist) - [Make multi-versioned JAR for JEP-238](jcp-tests/jcp-test-jep238) - [Generate static file from XML sources](jcp-tests/jcp-test-static-site) - [Simple Android Gradle-based project](jcp-tests/jcp-test-android) # Example of Java sources with directives In Java the only allowed way to inject directives and to not break work of tools and compilers - is to use commented space, so that the preprocessor uses it. ```Java //#local TESTVAR="TEST LOCAL VARIABLE" //#echo TESTVAR=/*$TESTVAR$*/ //#include "./test/_MainProcedure.java" public static final void testproc() { System.out.println(/*$VARHELLO$*/); System.out.println("// Hello commentaries"); //#local counter=10 //#while counter!=0 System.out.println("Number /*$counter$*/"); //#local counter=counter-1 //#end System.out.println("Current file name is /*$SRV_CUR_FILE$*/"); System.out.println("Output dir is /*$SRV_OUT_DIR$*/"); //#if issubstr("Hello","Hello world") System.out.println("Substring found"); //#endif } ``` # Multi-sectioned documents In opposite a regular document, a Java document has as minimum two sections - prefix (where situated import and special information) and body. For access to such sections there are special preprocessing directives `//#prefix[-|+]`, `//#postfix[-|+]`. They allow turning on or off output into prefix and postfix sections. ```Java //#prefix+ import java.lang.*; //#prefix- public class Main { //#prefix+ import java.util.*; //#prefix- public static void main(String ... args){} } ``` # How to remove all comments from sources Sometimes it is very useful to remove totally all comments from sources, such possibility included into JCP and can be activated with either a special flag or command line switcher. The example below shows how to remove all comments with CLI use: ``` java -jar ./jcp-7.3.0.jar --i:/sourceFolder --o:/resultFolder -ef:none --r ``` ================================================ FILE: changelog.txt ================================================ __7.3.0 (11-okt-2025)__ - added way to manipulate current JCP text buffers as string variables: `jcp.text.buffer.all`,`jcp.text.buffer.middle`,`jcp.text.buffer.prefix` and `jcp.text.buffer.postfix` - added way to find `PreprocessorExtension` and `SpecialVariableProcessor` among Java services - refactoring of API for `SpecialVariableProcessor` and `CommentTextProcessor` - replaced single string property `actionPreprocessorExtension` by string list `actionPreprocessorExtensions` to provide way for many preprocessor extensions. - internal refactoring mainly to provide way for multiple external services implementing extensions __7.2.1 (21-jul-2025)__ - refactoring of CommentTextProcessor call - refactoring __7.2.0 (13-jul-2025)__ - minimum JDK version 11 - added support for external processors calls during uncommenting actions `//$` and `//$$`, processors can be provided as services - removed support of Gradle 5 - updated dependencies __7.1.2 (08-jun-2024)__ - added way to define a preprocessor extension class through CLI (as `/EA:`) and in plugins (as `actionPreprocessorExtension`). The class should be provided in the clas path.[#48](https://github.com/raydac/java-comment-preprocessor/issues/48) - updated some dependencies __7.1.1 (13-jan-2024)__ - fixed NPE for empty or null global variable value in Maven and Gradle [#47](https://github.com/raydac/java-comment-preprocessor/issues/47) - updated dependencies __7.1.0 (10-dec-2023)__ - refactoring of internal API - updated dependencies - improved keep comments processing, added `/M:` CLI option [#46](https://github.com/raydac/java-comment-preprocessor/issues/46) __7.0.5 (11-dec-2021)__ - fixed compatibility with Gradle 7.x - added support of build under JDK 16 - updated dependencies 7.0.4 (26-sep-2020) - fixed default flag state `keep comments` for start in CLI mode [#24](https://github.com/raydac/java-comment-preprocessor/issues/24) - fixed working directory detection in CLI mode 7.0.3 (13-sep-2020) - added way to get info about all input and produced files from preprocessor context - reworked Gradle plug-in, removed extension and now properties should be directly provided for task [#21](https://github.com/raydac/java-comment-preprocessor/issues/21) - refactoring, removed some auxiliary plugins from build process and extra code 7.0.2 (15-jul-2019) - fixed leaks of system scoped dependencies in generated pom.xml 7.0.1 (19-apr-2019) - minor refactoring 7.0.0 (31-mar-2019) - reworked some parameters for Maven and ANT plug-ins - added embedded Gradle plugin `com.igormaznitsa.jcp` - removed maven `clear` goal - removed maven `preprocessTest` goal (use flag `useTestSources` instead) - added function `STR esc(STR)` - fixed build under JDK 9+ - XML functions work through embedded [Apache Xalan](https://xalan.apache.org/) and [Apache Xerces](http://xerces.apache.org/) - minimal needed Java version changed to 1.8 - refactoring 6.1.4 (16-jun-2018) - removed dependencies to meta packages (their sources moved into project) #19 6.1.3 (29-apr-2018) - added automatic module name `igormaznitsa.jcp` - CORE: added `/U` key to turn on mode to interpret unknown variables as FALSE (in Maven and ANT `unknownVarAsFalse`), [#17](https://github.com/raydac/java-comment-preprocessor/issues/17) 6.1.2 (02-apr-2017) - CORE: added STR TRIMLINES(STR) function to trim lines represented as string and removing empty lines - CORE: added `/A` command line option (`copyFileAttributes` in Maven and ANT) to copy file attributes - CORE: added `/ED:` command line option to exclude sub-folders from preprocessing (`excludedFolders` in Maven and ANT) with ANT pattern support. - CORE: added `/PI` command line flag (`preserveIndent` in Maven and ANT), turn on mode to preserve indent when removing `//$` and `//$$`, thanks to @jamuir - CORE: comma in split lines in BINFILE function moved from the start of line to the end of the previous line (to increase compatibility with Go) 6.1.1 (11-feb-2017) - MAVEN: information about imported maven properties will be shown only in either verbose mode or debug mode - MAVEN: added auxiliary goal `preprocessTests` which provides flag `useTestSources` as true and activated by default in GENERATE_TEST_SOURCES phase #14 - MAVEN: added 'ignoreMissingSources' boolean parameter, allows to skip preprocessing if source folders not found or not provided #12 - MAVEN: added 'skip'boolean parameter, it allows to skip execution, also it is possible to use `-Djcp.preprocess.skip=true` #13 - CORE: added function `BOOL is(STR,ANY)` to check existence of variable for its name and compare its value with etalon (through string conversion, it will ensure true for `true` and `"true"` case), #10 - CORE: added `STR str2go(STR)` function to escape strings to be represented in Golang sources - CORE: improved the BINFILE function, it allows `base64|byte[]|uint8[]|int8` and modifiers `s|d|ds|sd` where s - means splitting to lines and d - means deflate compression 6.1.0 (03-jul-2016) - implemented request #9, added support of whitespace between directive and comment, in command line it is `--es` option and in MAVEN and ANT it is boolean parameter `allowWhitespace`, by default it is turned off - added function STR binfile(STR,STR) to load a bin file as encoded base64 or java byte array string - changes in Preprocessor API, removed usage of null instead of PreprocessorContext or PreprocessingState as argument for many methods, improved tests - fixed #8 issue, fixed work with absolute paths in //#include and evalfile(), added tests - refactoring 6.0.1 - improved the MAVEN plugin to hide content of potentially sensitive properties from printing into Maven log (issue #2) - added --z option ('compareDestination' in MAVEN and ANT) to check content of existing result file and to not replace it if content equals (issue #1), by default turned off because makes some overhead - fixed --c argument usage in CLI, now by default the preprocessor started in CLI doesn't clear its output folder, use --c to turn it on - improved tests - minor bug-fixing 6.0.0 - bugfixing and log improvement - RENAMED DIRECTIVE! //#assert renamed to appropriate name //#echo - RENAMED FUNCTIONS! renamed XML functions to more appropriate and short names - xml_getRoot to xml_root - xml_elementAt to xml_get - xml_elementsNumber to xml_size - xml_getAttribute to xml_attr - xml_getElementName to xml_name - xml_getElementsForName to xml_list - xml_getElementText to xml_text - fixed //#exit and //#exitif behavior to prevent total exit and return level up in include stack - added //#abort directive to provide possibility to stop preprocessing immediately without errors - added function 'STR evalfile(STR)' for local preprocessing of a file body and return it as a string - added predefined variables 'line','filename','filefolder' and 'file' which allow to get name and path parameters for the current preprocessing file path - added predefined variables 'time','date' and 'timestamp' which work similar C++ predefined macroses - added function 'STR str2java(STR,BOOL)' to escape and split string to be presented as java sources - added functions 'STR str2js(STR)', 'STR str2json(STR)','STR str2xml(STR)' and 'STR str2csv(STR)' - added functions 'STR xml_xlist(STR,STR)' and 'STR xml_xelement(STR,STR)' which allow to use xpath to get element lists an elements - apache common-io and common-lang libraries have been packed into the jar and hidden - added the short variant '//#ifdef BOOL' for '//#ifdefined BOOL' - added '//#ifndef BOOL' to check that a variable is undefined - added '//#definel NAME' and '//#define NAME' to define local and global variables, they can use not only the default TRUE value for defined variables, but also result of expression (example: //#define ten 2*5) - added '//#undef NAME' to remove a variable definition from context - added '//#error EXPR' and '//#warning EXPR' directives to throw exception and log warnings - added support of custom line separator through the 'jcp.line.separator' system property - added '//#noautoflush' to prevent auto saving text buffers after file preprocessing 5.3.4 - added support of test source folder preprocessing for maven projects - added the "clear" maven goal to clear created preprocessing folders or any defined folders and files - by default the maven plugin trying to keep numeration of lines in preprocessed files (the 'keepLines' is true by default) 5.3.3 - fixed the bug in the comment removing (multiple stars before closing slash) - fixed the exception if there is not any organization tag in a project pom.xml - added support for '-' and '--' prefixes in CLI arguments - improved CLI argument error messaging - the license has been changed to Apache 2.0 5.3.2 - very minor refactoring. - fixed issue (ID 5) "Removing strings contain only spaces" - the first version published in the maven central 5.3.1 - very minor bug-fixing, added the main-class attribute in the preprocessor JAR Manifest 5.3 - Added feature to keep non-executing lines as commented ones (/k command line key), all non-executing lines will be saved in the output as commented ones 5.2 - Fixed issue (ID 3). The default charset was used to read text files. 5.1 - Fixed issue (ID 1). Inaccessible functionality both "load a file with global variables" and "define global variable" through a command line call. 5.0 - The initial published version of totally reworked preprocessor ================================================ FILE: jcp/pom.xml ================================================ 4.0.0 com.igormaznitsa jcp-pom 7.3.0 jcp maven-plugin Java Comment Preprocessor Powerful multi-pass preprocessor to process directives situated in C-styled commentaries gradle-releases-repository https://repo.gradle.org/gradle/libs-releases-local/ 6.0 site ${project.basedir}/../mojo-doc-site org.apache.maven.plugins maven-plugin-report-plugin org.apache.maven.plugins maven-clean-plugin delete-project-site clean clean true true ${mojo.site.dir} org.apache.maven.plugins maven-site-plugin generate-project-site site verify ${mojo.site.dir} publish org.apache.maven.plugins maven-assembly-plugin make-bundle install single src/assemble/bundle.xml org.apache.maven.plugins maven-javadoc-plugin generate-javadoc package jar ${maven.compiler.release} true false **/HelpMojo.java org.apache.maven.plugins maven-source-plugin generate-sources package jar org.apache.maven.plugins maven-gpg-plugin sign-artifacts verify sign net.nicoulaj.maven.plugins checksum-maven-plugin 1.11 verify files ${project.build.directory} *.jar *.pom SHA-1 MD5 org.apache.ant ant 1.10.15 provided org.apache.maven.plugin-tools maven-plugin-annotations ${min.maven.api} provided org.apache.maven maven-plugin-api ${min.maven.api} provided org.apache.maven maven-core ${min.maven.api} provided org.apache.maven.shared file-management 3.2.0 provided commons-io commons-io commons-io commons-io 2.19.0 org.apache.commons commons-text 1.14.0 commons-codec commons-codec 1.19.0 xerces xercesImpl 2.12.2 xalan xalan 2.7.3 org.projectlombok lombok 1.18.38 provided org.junit.vintage junit-vintage-engine ${junit.version} test org.apache.maven maven-compat ${min.maven.api} test org.apache.maven maven-artifact ${min.maven.api} provided org.apache.maven maven-artifact-manager 2.2.1 provided org.apache.maven.plugin-testing maven-plugin-testing-harness 2.1 test org.powermock powermock-module-junit4 2.0.9 test org.powermock powermock-api-mockito2 2.0.9 test org.gradle gradle-core ${gradle.api.version} provided org.gradle gradle-core-api ${gradle.api.version} provided org.gradle gradle-model-core ${gradle.api.version} provided org.gradle gradle-logging ${gradle.api.version} provided org.gradle gradle-base-services ${gradle.api.version} provided org.gradle gradle-base-services-groovy ${gradle.api.version} provided org.gradle gradle-plugins ${gradle.api.version} provided org.gradle gradle-tooling-api ${gradle.api.version} provided org.codehaus.groovy groovy 2.5.14 provided src/main/resources false /jcpversion.properties src/main/resources true **/jcpversion.properties org.apache.maven.plugins maven-enforcer-plugin jcp-check-enforce-rules ${maven.compiler.release} test provided test provided true [${maven.compiler.release},) [${min.maven.api},) compile true true enforce org.codehaus.mojo extra-enforcer-rules 1.10.0 com.igormaznitsa uber-pom 1.0.3 *
parent
modules
profiles/profile/modules
true
package upom true
org.projectlombok lombok-maven-plugin 1.18.20.0 generate-sources delombok org.apache.maven.plugins maven-plugin-plugin true mojo-descriptor descriptor help-goal helpmojo org.apache.maven.plugins maven-shade-plugin package shade javax.xml hidden.jcp.javax.xml org.apache.commons hidden.jcp.org.apache.commons license hidden.jcp.license org.xml hidden.jcp.org.xml org.apache.xpath hidden.jcp.org.apache.xpath org.apache.xml hidden.jcp.org.apache.xml org.apache.wml hidden.jcp.org.apache.wml org.apache.regexp hidden.jcp.org.apache.regexp org.apache.html hidden.jcp.org.apache.html org.apache.bcel hidden.jcp.org.apache.bcel org.apache.xerces hidden.jcp.org.apache.xerces org.apache.xalan hidden.jcp.org.apache.xalan org.w3c hidden.jcp.org.w3c java_cup hidden.jcp.java_cup trax hidden.jcp.trax org.springframework hidden.jcp.org.springframework org.springframework:* commons-io:* commons-codec:* commons-text:* org.apache.commons:* xerces:* xalan:* com.igormaznitsa:* xml-apis:* *:* META-INF/LICENSE.txt META-INF/NOTICE.txt META-INF/MANIFEST.MF META-INF/MANIFEST.txt META-INF/*.SF META-INF/*.DSA META-INF/*.RSA META-INF/services/javax.xml.* META-INF/services/org.apache.* META-INF/services/org.w3c.* META-INF/services/org.xml.* META-INF/versions/9/module-info.class com.igormaznitsa.jcp.JcpPreprocessor org.apache.maven.plugins maven-jar-plugin com.igormaznitsa.jcp.JcpPreprocessor igormaznitsa.jcp org.apache.maven.plugins maven-compiler-plugin -Xlint:all true true ${maven.compiler.release} **${file.separator}JCPreprocessor${file.separator}src${file.separator}test${file.separator}resources${file.separator}com${file.separator}igormaznitsa${file.separator}jcp${file.separator}it${file.separator}maven${file.separator}dummy_maven_project${file.separator}**${file.separator}*.java org.apache.maven.plugins maven-surefire-plugin ${project.build.testOutputDirectory}
================================================ FILE: jcp/src/assemble/bundle.xml ================================================ bundle false false tar.gz ${project.build.directory} /com/igormaznitsa/${project.artifactId}/${project.version} *.jar *.jar.asc *.jar.sha1 *.jar.md5 *.pom *.pom.asc *.pom.sha1 *.pom.md5 original*.* *.zip ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/InfoHelper.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp; import static com.igormaznitsa.jcp.context.JCPSpecialVariableProcessor.getReference; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toList; import com.igormaznitsa.jcp.cmdline.CommandLineHandler; import com.igormaznitsa.jcp.context.JCPSpecialVariableProcessor; import com.igormaznitsa.jcp.directives.AbstractDirectiveHandler; import com.igormaznitsa.jcp.expression.ValueType; import com.igormaznitsa.jcp.expression.functions.AbstractFunction; import com.igormaznitsa.jcp.expression.operators.AbstractOperator; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Properties; public final class InfoHelper { public static final String DELIMITER = "-------------------------------------------------"; public static final String SHORT_DELIMITER = "----------------------"; public static final String VERSION; public static final String URL; public static final int YEAR; static { final String path = "/jcpversion.properties"; try (final InputStream stream = InfoHelper.class.getResourceAsStream(path)) { final Properties props = new Properties(); props.load(stream); VERSION = requireNonNull(props.getProperty("version")); URL = requireNonNull(props.getProperty("url")); YEAR = Integer.parseInt(requireNonNull(props.getProperty("year")).trim()); } catch (IOException ex) { throw new IllegalStateException("Can't read resource: " + path, ex); } } private InfoHelper() { } public static String getVersion() { return "v" + VERSION; } public static String getCopyright() { return "Copyright (C) 2002-" + YEAR + " Igor A. Maznitsa (https://www.igormaznitsa.com)"; } public static String getSite() { return "Project page: " + URL; } public static String getProductName() { return "Java Comment Preprocessor"; } public static List makeTextForHelpInfo() { final List result = new ArrayList<>(); result.add(JcpPreprocessor.class.getCanonicalName() + " [@cfgFile] [cliCommands]"); result.add(""); result.add("Command line"); result.add(SHORT_DELIMITER); result.add("allowed '/','-' and '--' prefixes, '--' doesn't support multiple commands at once"); result.add(makeColumns("@cfgFile", "file contains global definition list", 14)); result.addAll(JcpPreprocessor.getCommandLineHandlers().stream() .map(InfoHelper::makeCommandLineKeyReference).collect(toList())); result.add(DELIMITER); result.add("Directives"); result.add(SHORT_DELIMITER); for (final AbstractDirectiveHandler handler : AbstractDirectiveHandler.findAllDirectives()) { result.add(makeDirectiveReference(handler)); } result.add(DELIMITER); result.add("Special directives"); result.add(SHORT_DELIMITER); result .add(makeSpecialDirectiveReference("//$", "uncomment and process all following macroses")); result.add(makeSpecialDirectiveReference("//$$", "like //$ but macroses ignored")); result.add(makeSpecialDirectiveReference("/*-*/", "truncate line")); result.add("Operators"); result.add(SHORT_DELIMITER); for (final AbstractOperator handler : AbstractOperator.getAllOperators()) { result.add(makeOperatorReference(handler)); } result.add(DELIMITER); result.add("Functions"); result.add(SHORT_DELIMITER); for (final AbstractFunction handler : AbstractFunction.findAllFunctions()) { result.add(makeFunctionReference(handler)); } result.add(DELIMITER); result.add("Allowed types"); result.add(SHORT_DELIMITER); result.add(" BOOL: true,false"); result.add(" INT: 2374,0x56FE (signed 64 bit)"); result.add(" STR: \"Hello World!\" (or $Hello World!$ if in CLI)"); result.add("FLOAT: 0.745 (signed 32 bit)"); result.add(DELIMITER); result.add("Special variables"); result.add(SHORT_DELIMITER); result.addAll( getReference().stream().map(InfoHelper::makeSpecialVariableReference).collect(toList())); return result; } private static String makeSpecialVariableReference( final JCPSpecialVariableProcessor.NameReferencePair p) { final String name = p.getName(); final String ref = p.getReference(); return makeColumns(name, ref, 24); } private static String makeCommandLineKeyReference(final CommandLineHandler handler) { return makeColumns(handler.getKeyName(), handler.getDescription(), 14); } private static String makeDirectiveReference(final AbstractDirectiveHandler directive) { final StringBuilder activityPasses = new StringBuilder(); int i = 0; if (directive.isGlobalPhaseAllowed()) { i++; activityPasses.append("1st"); } if (directive.isPreprocessingPhaseAllowed()) { if (i > 0) { activityPasses.append(','); } activityPasses.append("2th"); i++; } activityPasses.append(i > 1 ? "passes" : " pass"); final String directiveName = directive.getFullName(); final String descr = (directive.isDeprecated() ? "{DEPRECATED} " : "") + directive.getReference() + " (" + activityPasses + ')'; return makeColumns(directiveName, descr, 16); } private static String makeSpecialDirectiveReference(final String name, final String reference) { return makeColumns(name, reference, 14); } private static String makeOperatorReference(final AbstractOperator operator) { return makeColumns(operator.getKeyword(), operator.getReference(), 14); } private static String makeFunctionReference(final AbstractFunction func) { final String funcName = func.getName(); final String description = func.getReference(); final StringBuilder variants = new StringBuilder(" ["); final String result = func.getResultType().getSignature().toUpperCase(Locale.ROOT); int variantIndex = 0; for (final List signature : func.getAllowedArgumentTypes()) { if (variantIndex > 0) { variants.append(" | "); } variants.append(result).append(' ').append(funcName).append(" ("); for (int i = 0; i < signature.size(); i++) { if (i > 0) { variants.append(','); } variants.append(signature.get(i).getSignature().toUpperCase(Locale.ROOT)); } variants.append(')'); variantIndex++; } variants.append(']'); return makeColumns(funcName, description, 24) + variants; } private static String makeColumns(final String name, final String reference, final int firstColumnWidth) { final int spaces = firstColumnWidth - name.length(); final StringBuilder result = new StringBuilder(name); result.append(" ".repeat(Math.max(0, spaces))); result.append(reference); return result.toString(); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/JcpPreprocessor.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp; import static com.igormaznitsa.jcp.InfoHelper.makeTextForHelpInfo; import static com.igormaznitsa.jcp.utils.PreprocessorUtils.fillContextByFoundServices; import static com.igormaznitsa.jcp.utils.PreprocessorUtils.readWholeTextFileIntoArray; import static com.igormaznitsa.jcp.utils.PreprocessorUtils.throwPreprocessorException; import com.igormaznitsa.jcp.cmdline.ActionPreprocessorExtensionHandler; import com.igormaznitsa.jcp.cmdline.AllowMergeBlockLineHandler; import com.igormaznitsa.jcp.cmdline.AllowWhitespaceDirectiveHandler; import com.igormaznitsa.jcp.cmdline.CareForLastEolHandler; import com.igormaznitsa.jcp.cmdline.ClearTargetHandler; import com.igormaznitsa.jcp.cmdline.CommandLineHandler; import com.igormaznitsa.jcp.cmdline.DestinationDirectoryHandler; import com.igormaznitsa.jcp.cmdline.DontOverwriteSameContentHandler; import com.igormaznitsa.jcp.cmdline.ExcludeFoldersHandler; import com.igormaznitsa.jcp.cmdline.ExcludedFileExtensionsHandler; import com.igormaznitsa.jcp.cmdline.FileExtensionsHandler; import com.igormaznitsa.jcp.cmdline.GlobalVariableDefiningFileHandler; import com.igormaznitsa.jcp.cmdline.GlobalVariableHandler; import com.igormaznitsa.jcp.cmdline.HelpHandler; import com.igormaznitsa.jcp.cmdline.InCharsetHandler; import com.igormaznitsa.jcp.cmdline.KeepAttributesHandler; import com.igormaznitsa.jcp.cmdline.KeepCommentsHandler; import com.igormaznitsa.jcp.cmdline.KeepLineHandler; import com.igormaznitsa.jcp.cmdline.OutCharsetHandler; import com.igormaznitsa.jcp.cmdline.PreserveIndentDirectiveHandler; import com.igormaznitsa.jcp.cmdline.RemoveCommentsHandler; import com.igormaznitsa.jcp.cmdline.SourceDirectoryHandler; import com.igormaznitsa.jcp.cmdline.UnknownAsFalseHandler; import com.igormaznitsa.jcp.cmdline.VerboseHandler; import com.igormaznitsa.jcp.containers.FileInfoContainer; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.context.PreprocessorContextAware; import com.igormaznitsa.jcp.directives.ExcludeIfDirectiveHandler; import com.igormaznitsa.jcp.exceptions.FilePositionInfo; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import com.igormaznitsa.jcp.utils.AntPathMatcher; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.Set; import lombok.Data; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; /** * The main class implements the Java Comment Preprocessor, it has the main * method and can be started from a command string * Base directory for preprocessing can be provided through System property 'jcp.base.dir' * if it is not provided then current work directory will be recognized as base one. */ public final class JcpPreprocessor { static final CommandLineHandler[] COMMAND_LINE_HANDLERS = new CommandLineHandler[] { new HelpHandler(), new InCharsetHandler(), new OutCharsetHandler(), new ClearTargetHandler(), new SourceDirectoryHandler(), new DestinationDirectoryHandler(), new FileExtensionsHandler(), new ExcludedFileExtensionsHandler(), new AllowWhitespaceDirectiveHandler(), new RemoveCommentsHandler(), new KeepCommentsHandler(), new KeepLineHandler(), new DontOverwriteSameContentHandler(), new VerboseHandler(), new GlobalVariableDefiningFileHandler(), new GlobalVariableHandler(), new CareForLastEolHandler(), new PreserveIndentDirectiveHandler(), new ExcludeFoldersHandler(), new KeepAttributesHandler(), new ActionPreprocessorExtensionHandler(), new AllowMergeBlockLineHandler(), new UnknownAsFalseHandler() }; private static final String PROPERTY_JCP_BASE_DIR = "jcp.base.dir"; private final PreprocessorContext context; public JcpPreprocessor(final PreprocessorContext context) { Objects.requireNonNull(context, "Configurator is null"); this.context = context; } public static List getCommandLineHandlers() { return Arrays.asList(COMMAND_LINE_HANDLERS); } public static void main(final String... args) { printHeader(); final String[] normalizedStrings = PreprocessorUtils .replaceStringPrefix(new String[] {"--", "-"}, "/", PreprocessorUtils.replaceChar(args, '$', '\"')); PreprocessorContext preprocessorContext = null; final File baseDir = getBaseDir(); System.out.println("Base directory: " + baseDir); try { preprocessorContext = processCommandLine(baseDir, args, normalizedStrings); } catch (Exception ex) { System.err.println("Error during CLI processing: " + ex.getMessage()); System.exit(1); } final JcpPreprocessor preprocessor = new JcpPreprocessor(preprocessorContext); try { preprocessor.execute(); } catch (Exception unexpected) { System.err.println(PreprocessorException.referenceAsString(' ', unexpected)); System.exit(1); } System.exit(0); } private static File getBaseDir() { final String baseDirInProperties = System .getProperty(PROPERTY_JCP_BASE_DIR, System.getProperty("user.dir", new File("").getAbsolutePath()) ); return new File(baseDirInProperties); } private static PreprocessorContext processCommandLine(final File baseDir, final String[] originalStrings, final String[] normalizedStrings) { final PreprocessorContext result = new PreprocessorContext(baseDir); for (int i = 0; i < normalizedStrings.length; i++) { final String arg = normalizedStrings[i]; boolean processed = false; for (final CommandLineHandler processor : getCommandLineHandlers()) { if (processor.processCommandLineKey(arg, result)) { processed = true; if (processor instanceof HelpHandler) { help(); System.exit(2); } break; } } if (!processed) { System.err.println("Can't process CLI argument, see manual: " + originalStrings[i]); System.out.println(); help(); System.exit(1); } } fillContextByFoundServices(result); return result; } private static void printHeader() { System.out.println(InfoHelper.getProductName() + ' ' + InfoHelper.getVersion()); System.out.println(InfoHelper.getSite()); System.out.println(InfoHelper.getCopyright()); } private static void help() { System.out.println(); makeTextForHelpInfo().forEach(System.out::println); } public PreprocessorContext getContext() { return this.context; } public Statistics execute() throws IOException { final long timeStart = System.currentTimeMillis(); this.context.getActivatedConfigFiles().addAll(processConfigFiles()); this.context.logInfo(String .format("File extensions: %s excluded %s", this.context.getExtensions(), this.context.getExcludeExtensions())); final List srcFolders = this.context.getSources(); this.context.logDebug("Source folders: " + srcFolders); if (srcFolders.isEmpty()) { this.context.logWarning("Source folder list is empty!"); } final Collection filesToBePreprocessed = collectFilesToPreprocess(srcFolders, this.context.getExcludeFolders()); this.context.addAllPreprocessedResources(filesToBePreprocessed); final List excludedIf = processGlobalDirectives(filesToBePreprocessed); processFileExclusion(excludedIf); if (!this.context.isDryRun()) { createTargetFolder(); } else { this.context.logInfo("Dry run mode is ON"); } final Statistics stat = this.preprocessFiles(filesToBePreprocessed, true); final long elapsedTime = System.currentTimeMillis() - timeStart; this.context.logInfo("-----------------------------------------------------------------"); this.context.logInfo(String .format("Preprocessed %d files, copied %d files, ignored %d files, elapsed time %d ms", stat.getPreprocessed(), stat.getCopied(), stat.getExcluded(), elapsedTime)); return stat; } private void processFileExclusion(final List foundExcludeIf) { final String DIRECTIVE_NAME = new ExcludeIfDirectiveHandler().getFullName(); for (final PreprocessingState.ExcludeIfInfo item : foundExcludeIf) { final String condition = item.getCondition(); final File file = item.getFileInfoContainer().getSourceFile(); Value val; if (context.isVerbose()) { context.logForVerbose(String .format("Processing condition '%s' for file '%s'", condition, file.getAbsolutePath())); } try { val = Expression.evalExpression(condition, this.context); } catch (PreprocessorException ex) { throw new PreprocessorException( ex.getMessage(), condition, new FilePositionInfo[] {new FilePositionInfo(file, item.getStringIndex())}, ex.getCause() ); } catch (IllegalArgumentException ex) { throw new PreprocessorException("Wrong expression at " + DIRECTIVE_NAME, condition, new FilePositionInfo[] {new FilePositionInfo(file, item.getStringIndex())}, ex); } if (val.getType() != ValueType.BOOLEAN) { throw new PreprocessorException("Expression at " + DIRECTIVE_NAME + " is not a boolean one", condition, new FilePositionInfo[] {new FilePositionInfo(file, item.getStringIndex())}, null); } if (val.asBoolean()) { item.getFileInfoContainer().setExcluded(true); if (context.isVerbose()) { context.logForVerbose(String .format("File '%s' excluded for active '%s' condition", file.getAbsolutePath(), condition)); } } } } private List processGlobalDirectives( final Collection files) throws IOException { final List result = new ArrayList<>(); for (final FileInfoContainer fileRef : files) { if (!(fileRef.isExcludedFromPreprocessing() || fileRef.isCopyOnly())) { final long startTime = System.currentTimeMillis(); result.addAll(fileRef.processGlobalDirectives(context, null)); final long elapsedTime = System.currentTimeMillis() - startTime; if (context.isVerbose()) { context.logForVerbose(String .format("Global phase completed for file '%s', elapsed time %d ms ", PreprocessorUtils.getFilePath(fileRef.getSourceFile()), elapsedTime)); } } } return result; } private Statistics preprocessFiles(final Collection files, final boolean notifyProcessors) throws IOException { if (notifyProcessors) { final List successfullyNotified = new ArrayList<>(); try { context.fireNotificationStart(successfullyNotified); } catch (final Exception ex) { context.logError("Error during init of context aware processors: " + ex.getMessage()); successfullyNotified.forEach(x -> { try { x.onContextStopped(context, ex); } catch (Exception err) { context.logError("Error: " + err.getMessage()); } }); throw new IllegalStateException("Exception during notification of context aware listeners", ex); } } int preprocessedCounter = 0; int copiedCounter = 0; int excludedCounter = 0; Throwable error = null; try { for (final FileInfoContainer fileRef : files) { if (fileRef.isExcludedFromPreprocessing()) { excludedCounter++; } else if (fileRef.isCopyOnly()) { if (!context.isDryRun()) { final File destinationFile = this.context.createDestinationFileForPath(fileRef.makeTargetFilePathAsString()); boolean doCopy = true; if (this.context.isDontOverwriteSameContent() && PreprocessorUtils.isFileContentEquals(fileRef.getSourceFile(), destinationFile)) { doCopy = false; if (this.context.isVerbose()) { this.context.logForVerbose(String .format("Copy skipped because same content: %s -> {dst} %s", PreprocessorUtils.getFilePath(fileRef.getSourceFile()), fileRef.makeTargetFilePathAsString())); } } if (doCopy) { if (this.context.isVerbose()) { this.context.logForVerbose(String.format("Copy file %s -> {dst} %s", PreprocessorUtils.getFilePath(fileRef.getSourceFile()), fileRef.makeTargetFilePathAsString())); } PreprocessorUtils.copyFile(fileRef.getSourceFile(), destinationFile, this.context.isKeepAttributes()); fileRef.getGeneratedResources().add(destinationFile); copiedCounter++; } } } else { final long startTime = System.currentTimeMillis(); fileRef.preprocessFileWithNotification(this.context, null, false); final long elapsedTime = System.currentTimeMillis() - startTime; if (this.context.isVerbose()) { this.context.logForVerbose(String .format("File preprocessing completed '%s', elapsed time %d ms", PreprocessorUtils.getFilePath(fileRef.getSourceFile()), elapsedTime)); } preprocessedCounter++; } } } catch (Throwable err) { error = err; if (error instanceof IOException) { throw (IOException) error; } if (error instanceof RuntimeException) { throw (RuntimeException) error; } if (error instanceof Error) { throw (Error) error; } } finally { context.fireNotificationStop(error); } return new Statistics( preprocessedCounter, copiedCounter, excludedCounter ); } private void createTargetFolder() throws IOException { final File target = context.getTarget(); final boolean targetExists = target.isDirectory(); if (context.isClearTarget() && targetExists) { this.context.logForVerbose("Cleaning target folder: " + target); try { FileUtils.cleanDirectory(target); } catch (IOException ex) { throw new IOException("Can't clean folder: " + PreprocessorUtils.getFilePath(target), ex); } } if (!targetExists && !target.mkdirs()) { throw new IOException("Can't make folder: " + PreprocessorUtils.getFilePath(target)); } this.context.logForVerbose("Target folder has been prepared: " + target); } private Collection collectFilesToPreprocess( final List sources, final List excluded) throws IOException { final Collection result = new ArrayList<>(); final AntPathMatcher antPathMatcher = new AntPathMatcher(); for (final PreprocessorContext.SourceFolder sourceFolder : sources) { String canonicalSourcePath = sourceFolder.getAsFile().getCanonicalPath(); this.context.logDebug("Processing folder: " + sourceFolder); if (!canonicalSourcePath.endsWith(File.separator)) { canonicalSourcePath += File.separator; } for (final File file : findAllFiles(canonicalSourcePath, sourceFolder.getAsFile(), antPathMatcher, excluded)) { if (this.context.isFileExcludedByExtension(file)) { this.context .logForVerbose(String.format("File '%s' excluded by its extension", file.getPath())); } else { final String canonicalFilePath = file.getCanonicalPath(); final String canonicalRelativePath = canonicalFilePath.substring(canonicalSourcePath.length()); final FileInfoContainer reference = new FileInfoContainer(file, canonicalRelativePath, !this.context.isFileAllowedForPreprocessing(file)); result.add(reference); this.context.logDebug("File added to preprocess list: " + reference); } } } return result; } private Set findAllFiles( final String sourceCanonicalPath, final File dir, final AntPathMatcher antPathMatcher, final List excludedFolderPatterns ) throws IOException { final Set result = new HashSet<>(); this.context.logDebug("Looking for files in folder: " + dir); final File[] allowedFiles = dir.listFiles(); if (allowedFiles == null) { this.context.logWarning("Can't find files in folder: " + dir); } else { final String normalizedBasePath = FilenameUtils.normalize(sourceCanonicalPath, true); for (final File file : allowedFiles) { if (file.isDirectory()) { final String folderPath = file.getCanonicalPath(); String excludedFolderPattern = null; if (!excludedFolderPatterns.isEmpty()) { final String subPathInBase = folderPath.substring(normalizedBasePath.length()); for (final String pattern : excludedFolderPatterns) { if (antPathMatcher.match(pattern, subPathInBase)) { excludedFolderPattern = pattern; break; } } } if (excludedFolderPattern == null) { result.addAll( findAllFiles(sourceCanonicalPath, file, antPathMatcher, excludedFolderPatterns)); } else { this.context.logForVerbose( String.format("Folder '%s' excluded by '%s'", folderPath, excludedFolderPattern)); } } else { result.add(file); } } } return result; } List processConfigFiles() throws IOException { final List processedConfigFileList = new ArrayList<>(); for (final File file : context.getConfigFiles()) { processedConfigFileList.add(file); final String[] lines = readWholeTextFileIntoArray(file, StandardCharsets.UTF_8, null); int readStringIndex = -1; for (final String curString : lines) { final String trimmed = curString.trim(); readStringIndex++; if (trimmed.isEmpty() || trimmed.charAt(0) == '#') { // do nothing } else if (trimmed.charAt(0) == '@') { throwPreprocessorException("Config file doesn't allow have lines started with '@'", trimmed, file, readStringIndex, null); } else if (trimmed.charAt(0) == '/') { // a command line argument boolean processed = false; try { for (CommandLineHandler handler : getCommandLineHandlers()) { if (context.isVerbose()) { context.logForVerbose(String .format("Processing сonfig file key '%s' at %s:%d", trimmed, file.getName(), readStringIndex + 1)); } if (handler.processCommandLineKey(trimmed, context)) { processed = true; break; } } } catch (Exception unexpected) { throwPreprocessorException("Exception during directive processing", trimmed, file, readStringIndex, unexpected); } if (!processed) { throwPreprocessorException("Unsupported or disallowed directive", trimmed, file, readStringIndex, null); } } else { // a global variable final String[] split = PreprocessorUtils.splitForEqualChar(trimmed); if (split.length != 2) { throwPreprocessorException("Wrong variable definition", trimmed, file, readStringIndex, null); } final String name = split[0].trim().toLowerCase(Locale.ROOT); final String expression = split[1].trim(); if (name.isEmpty()) { throwPreprocessorException("Empty variable name detected", trimmed, file, readStringIndex, null); } try { final Value result = Expression.evalExpression(expression, this.context); this.context.setGlobalVariable(name, result); if (this.context.isVerbose()) { this.context.logForVerbose(String .format("Registering global variable '%s' = '%s' (%s:%d)", name, result, file.getName(), readStringIndex + 1)); } } catch (Exception unexpected) { throwPreprocessorException("Can't process the global variable definition", trimmed, file, readStringIndex, unexpected); } } } } return processedConfigFileList; } @Data public static final class Statistics { private final int preprocessed; private final int copied; private final int excluded; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/ant/PreprocessTask.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.ant; import static com.igormaznitsa.jcp.utils.PreprocessorUtils.fillContextByFoundServices; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.CommentRemoverType; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.context.SpecialVariableProcessor; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.logger.PreprocessorLogger; import com.igormaznitsa.jcp.utils.GetUtils; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.io.File; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.function.Supplier; import java.util.stream.Collectors; import lombok.Data; import lombok.EqualsAndHashCode; import org.apache.commons.text.StringEscapeUtils; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; /** * The class implements an ANT task to allow calls for preprocessing from ANT build scripts. Also it allows to out messages from preprocessor directives into the ANT log and read * ANT properties as global variables (with the "ant." prefix) * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ @Data @EqualsAndHashCode(callSuper = false) public class PreprocessTask extends Task implements PreprocessorLogger, SpecialVariableProcessor { private Sources sources = null; private String eol = null; private boolean keepAttributes = false; private String target = null; private String sourceEncoding = null; private String targetEncoding = null; private boolean ignoreMissingSources = false; private ExcludeExtensions excludeExtensions = null; private Extensions extensions = null; private boolean unknownVarAsFalse = false; private boolean dryRun = false; private boolean allowBlocks = false; private boolean verbose = false; private boolean clearTarget = false; private boolean careForLastEol = false; private String keepComments = CommentRemoverType.REMOVE_C_STYLE.name(); private Vars vars = null; private ExcludeFolders excludeFolders = null; private ConfigFiles configFiles = null; private boolean keepLines = true; private boolean allowWhitespaces = false; private boolean preserveIndents = false; private boolean dontOverwriteSameContent = false; private String actionPreprocessorExtensions = ""; private Map antVariables = new HashMap<>(); private void registerConfigFiles(final PreprocessorContext context) { if (this.getConfigFiles() != null) { for (final Sources.Path f : this.getConfigFiles().getPaths()) { log("Registering config file: " + f.getValue()); context.registerConfigFile( new File(Objects.requireNonNull(f, "File must not be null").getValue().trim())); } } } private void fillGlobalVars(final PreprocessorContext context) { if (this.getVars() != null) { for (final Vars.Var g : this.getVars().getListVars()) { context.setGlobalVariable(Objects.requireNonNull(g.getName(), "Name must not be null"), Value.recognizeRawString( Objects.requireNonNull(g.getValue(), "Value must not be null"))); } } } PreprocessorContext makePreprocessorContext() { fillAntVariables(); final PreprocessorContext context = new PreprocessorContext(getProject().getBaseDir()); context.setPreprocessorLogger(this); context.registerSpecialVariableProcessor(this); if (this.getTarget() != null) { context.setTarget(new File(this.getTarget())); } if (this.getSources() != null) { context.setSources(this.getSources().getPaths() .stream() .map(Sources.Path::getValue) .collect(Collectors.toList()) ); } if (this.getExcludeExtensions() != null) { context.setExcludeExtensions(this.getExcludeExtensions().listExtensions .stream() .map(x -> x.name.trim()) .filter(x -> !x.isEmpty()) .collect(Collectors.toList()) ); } if (this.getExtensions() != null) { context.setExtensions(this.getExtensions().listExtensions .stream() .map(x -> x.name.trim()) .filter(x -> !x.isEmpty()) .collect(Collectors.toList()) ); } if (this.getSourceEncoding() != null) { context.setSourceEncoding(Charset.forName(this.getSourceEncoding())); } if (this.getTargetEncoding() != null) { context.setTargetEncoding(Charset.forName(this.getTargetEncoding())); } context.setDontOverwriteSameContent(this.isDontOverwriteSameContent()); context.setClearTarget(this.isClearTarget()); context.setDryRun(this.isDryRun()); context.setAllowsBlocks(this.isAllowBlocks()); context.setKeepComments(PreprocessorUtils.findCommentRemoverForId(this.getKeepComments())); context.setVerbose(this.isVerbose()); context.setKeepLines(this.isKeepLines()); context.setCareForLastEol(this.isCareForLastEol()); context.setAllowWhitespaces(this.isAllowWhitespaces()); context.setPreserveIndents(this.isPreserveIndents()); context.setKeepAttributes(this.isKeepAttributes()); context.setUnknownVariableAsFalse(this.isUnknownVarAsFalse()); if (this.getEol() != null) { context.setEol(StringEscapeUtils.unescapeJava(this.getEol())); } if (this.getExcludeFolders() != null) { context.setExcludeFolders( this.getExcludeFolders().getFolders() .stream() .map(ExcludeFolders.Folder::getPath) .collect(Collectors.toList()) ); } if (!this.getActionPreprocessorExtensions().isEmpty()) { info("Instantiating action preprocessor extensions: " + this.getActionPreprocessorExtensions()); Arrays.stream(this.getActionPreprocessorExtensions().split(",")) .filter(x -> !x.trim().isEmpty()) .forEach(x -> context.addPreprocessorExtension( PreprocessorUtils.findAndInstantiatePreprocessorExtensionForClassName( x.trim()))); } this.registerConfigFiles(context); this.fillGlobalVars(context); fillContextByFoundServices(context); return context; } @Override public void execute() throws BuildException { PreprocessorContext context; JcpPreprocessor preprocessor; this.antVariables.clear(); this.antVariables.putAll(fillAntVariables()); try { context = makePreprocessorContext(); } catch (Exception unexpected) { final PreprocessorException pp = PreprocessorException.extractPreprocessorException(unexpected); throw new BuildException(pp == null ? unexpected.getMessage() : pp.toString(), pp == null ? unexpected : pp); } preprocessor = new JcpPreprocessor(context); try { preprocessor.execute(); } catch (Exception unexpected) { final PreprocessorException pp = PreprocessorException.extractPreprocessorException(unexpected); throw new BuildException(pp == null ? unexpected.getMessage() : pp.toString(), pp == null ? unexpected : pp); } } @Override public void error(final String message) { log(message, Project.MSG_ERR); } @Override public void info(final String message) { log(message, Project.MSG_INFO); } @Override public void debug(final String message) { log(message, Project.MSG_DEBUG); } @Override public void debug(final Supplier supplier) { if (supplier != null) { final String text = supplier.get(); if (text != null) { log(text, Project.MSG_DEBUG); } } } @Override public void warning(final String message) { log(message, Project.MSG_WARN); } private Map fillAntVariables() { final Project theProject = getProject(); final Map result; if (theProject == null) { result = Collections.emptyMap(); } else { result = new HashMap<>(); for (final Object key : getProject().getProperties().keySet()) { final String keyStr = key.toString(); final String value = theProject.getProperty(keyStr); if (value != null) { result.put("ant." + keyStr.toLowerCase(Locale.ROOT), Value.valueOf(value)); } } } return result; } @Override public Set getVariableNames() { final Set result; if (this.antVariables == null) { result = Set.of(); } else { result = this.antVariables.keySet(); } return result; } @Override public Value getVariable(final String varName, final PreprocessorContext context) { if (antVariables == null) { throw context.makeException("Non-initialized ANT property map detected", null); } final Value result = this.antVariables.get(varName); if (result == null) { throw context.makeException("Request for unsupported Ant property '" + varName + '\'', null); } return result; } @Override public void setVariable(final String varName, final Value value, final PreprocessorContext context) { throw context.makeException( "Request to change ANT property '" + varName + "'. NB! ANT properties are read only!", null); } public Extensions createExtensions() { this.extensions = new Extensions(); return this.extensions; } public ExcludeExtensions createExcludeExtensions() { this.excludeExtensions = new ExcludeExtensions(); return this.excludeExtensions; } public ExcludeFolders createExcludeFolders() { this.excludeFolders = new ExcludeFolders(); return this.excludeFolders; } public Sources createSources() { this.sources = new Sources(); return this.sources; } public ConfigFiles createConfigFiles() { this.configFiles = new ConfigFiles(); return this.configFiles; } public Vars createVars() { this.vars = new Vars(); return this.vars; } @Data @EqualsAndHashCode(callSuper = false) public static class Sources { protected List paths = new ArrayList<>(); public Path createPath() { final Path result = new Path(); paths.add(result); return result; } @Data public static class Path { private String value = ""; public void addText(final String text) { this.value += GetUtils.ensureNonNull(text, ""); } } } @Data @EqualsAndHashCode(callSuper = false) public static class ConfigFiles extends Sources { } @Data @EqualsAndHashCode(callSuper = false) public static class ExcludeFolders { private List folders = new ArrayList<>(); public Folder createFolder() { final Folder result = new Folder(); this.folders.add(result); return result; } @Data public static class Folder { private String path = ""; public void addText(final String text) { this.path = GetUtils.ensureNonNull(text, ""); } } } @Data @EqualsAndHashCode(callSuper = false) public static class ExcludeExtensions extends Extensions { } @Data @EqualsAndHashCode(callSuper = false) public static class Extensions { protected final List listExtensions = new ArrayList<>(); public Extension createExtension() { final Extension result = new Extension(); this.listExtensions.add(result); return result; } @Data public static class Extension { private String name = ""; public void addText(final String text) { this.name += GetUtils.ensureNonNull(text, ""); } } } @Data @EqualsAndHashCode(callSuper = false) public static class Vars { private List listVars = new ArrayList<>(); public Var createVar() { final Var result = new Var(); this.listVars.add(result); return result; } @Data @EqualsAndHashCode(callSuper = false) public static class Var { private String name = ""; private String value = ""; public void addText(final String text) { this.value += text; } } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/ActionPreprocessorExtensionHandler.java ================================================ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.extension.PreprocessorExtension; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.util.Locale; public class ActionPreprocessorExtensionHandler implements CommandLineHandler { private static final String ARG_NAME = "/EA:"; @Override public String getDescription() { return "class for action directives (must be in classpath with default constructor)"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (!key.isEmpty() && key.toUpperCase(Locale.ROOT).startsWith(ARG_NAME)) { final String tail = PreprocessorUtils.extractTrimmedTail(ARG_NAME, key); if (!tail.isEmpty()) { final PreprocessorExtension preprocessorExtension = PreprocessorUtils.findAndInstantiatePreprocessorExtensionForClassName(tail); context.addPreprocessorExtension(preprocessorExtension); } result = true; } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/AllowMergeBlockLineHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * Enable merging of text lines found in //$""" and //$$""" into single text block * for processing by external processors. * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) * @since 7.2.0 */ public class AllowMergeBlockLineHandler implements CommandLineHandler { private static final String ARG_NAME = "/B"; @Override public String getDescription() { return "treat //$\"\"\" and //$$\"\"\" prefixed lines as single text block"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (ARG_NAME.equalsIgnoreCase(key)) { context.setAllowsBlocks(true); result = true; } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/AllowWhitespaceDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * Allow spaces between comment and directive. * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class AllowWhitespaceDirectiveHandler implements CommandLineHandler { private static final String ARG_NAME = "/ES"; @Override public String getDescription() { return "enable whitespace-tolerant mode between // and #"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (ARG_NAME.equalsIgnoreCase(key)) { context.setAllowWhitespaces(true); result = true; } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/CareForLastEolHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; public class CareForLastEolHandler implements CommandLineHandler { private static final String ARG_NAME = "/N"; @Override public String getDescription() { return "preserve last line EOL in output"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (ARG_NAME.equalsIgnoreCase(key)) { context.setCareForLastEol(true); result = true; } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/ClearTargetHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The handler to process the key signals that the preprocessor must clear the * destination directory before preprocessing * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class ClearTargetHandler implements CommandLineHandler { private static final String ARG_NAME = "/C"; @Override public String getDescription() { return "clear target folder before preprocessing"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (ARG_NAME.equalsIgnoreCase(key)) { context.setClearTarget(true); result = true; } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/CommandLineHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The interface describes a command line key handler. It is not just a handler, * but it will be called for all met keys to recognize one to be processed. * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public interface CommandLineHandler { /** * Get the key name for the handler * * @return the key name as a String, must not be null */ String getKeyName(); /** * Get the description of the key (it will be printed into the help text) * * @return the description as a String */ String getDescription(); /** * Process a command line key * * @param key the command line key to be processed, must not be null * @param context the preprocessor context, must not be null * @return true if the key has been recognized and processed else false */ boolean processCommandLineKey(String key, PreprocessorContext context); } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/DestinationDirectoryHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.io.File; import java.util.Locale; /** * The handler for the output directory command line key * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class DestinationDirectoryHandler implements CommandLineHandler { private static final String ARG_NAME = "/O:"; @Override public String getDescription() { return "set destination folder (default " + PreprocessorContext.DEFAULT_DEST_DIRECTORY + ')'; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (!key.isEmpty() && key.toUpperCase(Locale.ROOT).startsWith(ARG_NAME)) { final String name = PreprocessorUtils.extractTrimmedTail(ARG_NAME, key); if (!name.isEmpty()) { final String path = PreprocessorUtils.extractTail(ARG_NAME, key); context.setTarget(new File(path)); result = true; } } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/DontOverwriteSameContentHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * the Handler processes command to disable overriding of existing file if content the same. * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) * @since 6.0.1 */ public class DontOverwriteSameContentHandler implements CommandLineHandler { private static final String ARG_NAME = "/Z"; @Override public String getKeyName() { return ARG_NAME; } @Override public String getDescription() { return "skip writing target file if content unchanged"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (ARG_NAME.equalsIgnoreCase(key)) { context.setDontOverwriteSameContent(true); result = true; } return result; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/ExcludeFoldersHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.io.File; import java.util.Locale; /** * The Handler of subfolder names to be excluded from preprocessing, allows ANT pattern matching. * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class ExcludeFoldersHandler implements CommandLineHandler { private static final String ARG_NAME = "/ED:"; @Override public String getDescription() { return "folders to exclude (ANT pattern, delimited by system path separator)"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (!key.isEmpty() && key.toUpperCase(Locale.ROOT).startsWith(ARG_NAME)) { final String tail = PreprocessorUtils.extractTrimmedTail(ARG_NAME, key); if (!tail.isEmpty()) { context.setExcludeFolders(PreprocessorUtils.splitForChar(tail, File.pathSeparatorChar)); result = true; } } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/ExcludedFileExtensionsHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.util.Arrays; import java.util.Locale; import java.util.stream.Collectors; /** * The handler for the excluded extension list (with comma) * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class ExcludedFileExtensionsHandler implements CommandLineHandler { private static final String ARG_NAME = "/EF:"; @Override public String getDescription() { return "comma-separated file extensions to exclude (default: " + String.join(",", PreprocessorContext.DEFAULT_EXCLUDED_EXTENSIONS) + ')'; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (!key.isEmpty() && key.toUpperCase(Locale.ROOT).startsWith(ARG_NAME)) { final String extensions = PreprocessorUtils.extractTrimmedTail(ARG_NAME, key); if (!extensions.isEmpty()) { context.setExcludeExtensions( Arrays.stream(extensions.split(",")).map(String::trim).collect(Collectors.toList())); result = true; } } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/FileExtensionsHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.util.Arrays; import java.util.Locale; import java.util.stream.Collectors; /** * The handler for the preprocessing file extension list (with comma) * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class FileExtensionsHandler implements CommandLineHandler { private static final String ARG_NAME = "/F:"; @Override public String getDescription() { return "comma-separated allowed extensions (default: " + String.join(",", PreprocessorContext.DEFAULT_PROCESSING_EXTENSIONS) + ')'; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (!key.isEmpty() && key.toUpperCase(Locale.ROOT).startsWith(ARG_NAME)) { final String extensions = PreprocessorUtils.extractTrimmedTail(ARG_NAME, key); if (!extensions.isEmpty()) { context.setExtensions( Arrays.stream(extensions.split("\\,")).map(String::trim).collect(Collectors.toList())); result = true; } } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/GlobalVariableDefiningFileHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.io.File; /** * The handler for '@' prefixed files in the command string * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class GlobalVariableDefiningFileHandler implements CommandLineHandler { private static final String ARG_NAME = "@"; @Override public String getDescription() { return "load global variables from file (path or @@expression)"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (!key.isEmpty() && key.charAt(0) == '@') { String stringRest = PreprocessorUtils.extractTrimmedTail(ARG_NAME, key); if (stringRest.isEmpty()) { throw context.makeException("Empty string", null); } File file; if (stringRest.charAt(0) == '@') { stringRest = PreprocessorUtils.extractTrimmedTail("@", stringRest); if (context.isVerbose()) { context.logForVerbose( "Global parameter file defined through expression '" + stringRest + '\''); } final Value resultValue = Expression.evalExpression(stringRest, context); final String fileName = resultValue.toString(); file = new File(fileName); } else { file = new File(stringRest); } if (context.isVerbose()) { context.logForVerbose( "Reading global definition file [" + PreprocessorUtils.getFilePath(file) + "] '" + stringRest + '\''); } if (file.isFile()) { context.registerConfigFile(file); } else { throw context.makeException( "Can't find the global definition file '" + PreprocessorUtils.getFilePath(file) + '\'', null); } result = true; } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/GlobalVariableHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.util.Locale; /** * The handler for global variables, it adds met global variables into the * internal storage * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class GlobalVariableHandler implements CommandLineHandler { private static final String ARG_NAME = "/P:"; @Override public String getDescription() { return "define global variable (e.g., /P:DEBUG=true; use $ for \" in CLI)"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (!key.isEmpty() && key.toUpperCase(Locale.ROOT).startsWith(ARG_NAME)) { final String nameAndExpression = PreprocessorUtils.extractTrimmedTail(ARG_NAME, key); if (!nameAndExpression.isEmpty()) { final String[] split = PreprocessorUtils.splitForEqualChar(nameAndExpression); if (split.length != 2) { throw context.makeException( "Illegal expression for directive '" + ARG_NAME + "' [" + nameAndExpression + ']', null); } final String value = split[0]; final String expression = split[1]; if (context.containsGlobalVariable(value)) { throw context.makeException("Duplicated global definition [" + value + ']', null); } final Value resultVal = Expression.evalExpression(expression, context); context.setGlobalVariable(value, resultVal); result = true; } } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/HelpHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.util.Locale; /** * The handler processes a help command from the command string * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class HelpHandler implements CommandLineHandler { private static final String[] ARG_NAMES = new String[] {"/H", "/?", "-H", "-?"}; @Override public String getDescription() { return "display preprocessor usage and directives info"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (!key.isEmpty()) { final String argUpperCase = key.trim().toUpperCase(Locale.ROOT); for (final String str : ARG_NAMES) { if (str.equals(argUpperCase)) { result = true; break; } } } return result; } @Override public String getKeyName() { final StringBuilder result = new StringBuilder(); for (int li = 0; li < ARG_NAMES.length; li++) { if (li > 0) { result.append(','); } result.append(ARG_NAMES[li]); } return result.toString(); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/InCharsetHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.nio.charset.Charset; import java.util.Locale; /** * To set the input text character encoding * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class InCharsetHandler implements CommandLineHandler { private static final String ARG_NAME = "/T:"; @Override public String getKeyName() { return ARG_NAME; } @Override public String getDescription() { return "set input text file encoding (default: " + PreprocessorContext.DEFAULT_CHARSET + ')'; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (key.toUpperCase(Locale.ROOT).startsWith(ARG_NAME)) { final String value = PreprocessorUtils.extractTrimmedTail(ARG_NAME, key); if (!value.isEmpty() && Charset.isSupported(value)) { context.setSourceEncoding(Charset.forName(value)); result = true; } } return result; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/KeepAttributesHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The handler keep file attributes of copied or generated files. * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class KeepAttributesHandler implements CommandLineHandler { private static final String ARG_NAME = "/A"; @Override public String getDescription() { return "preserve original file attributes"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (ARG_NAME.equalsIgnoreCase(key)) { context.setKeepAttributes(true); result = true; } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/KeepCommentsHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static com.igormaznitsa.jcp.context.CommentRemoverType.makeListOfAllRemoverIds; import com.igormaznitsa.jcp.context.CommentRemoverType; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.util.Locale; /** * The handler allows to choose keep comments mode. * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) * @since 7.1.0 */ public class KeepCommentsHandler implements CommandLineHandler { private static final String ARG_NAME = "/M:"; @Override public String getDescription() { return "set comment handling mode (e.g., /M:remove_c_style; allowed: true,false," + makeListOfAllRemoverIds() + ')'; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (!key.isEmpty() && key.toUpperCase(Locale.ROOT).startsWith(ARG_NAME)) { final String tail = PreprocessorUtils.extractTrimmedTail(ARG_NAME, key); final CommentRemoverType mode; try { mode = PreprocessorUtils.findCommentRemoverForId(tail); } catch (IllegalArgumentException ex) { throw context.makeException( "Illegal keep comments mode '" + tail + "' in " + ARG_NAME + ", expected one of: true,false," + makeListOfAllRemoverIds(), null); } context.setKeepComments(mode); result = true; } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/KeepLineHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The handler processing the flag tells the preprocessor to be try to keep * non-executing lines of code as commented ones * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class KeepLineHandler implements CommandLineHandler { private static final String ARG_NAME = "/K"; @Override public String getDescription() { return "preserve line numbers, print unprocessed lines as comments"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (ARG_NAME.equalsIgnoreCase(key)) { context.setKeepLines(true); result = true; } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/OutCharsetHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.nio.charset.Charset; import java.util.Locale; /** * To set the output text character encoding * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class OutCharsetHandler implements CommandLineHandler { private static final String ARG_NAME = "/TT:"; @Override public String getKeyName() { return ARG_NAME; } @Override public String getDescription() { return "set output text file encoding (default: " + PreprocessorContext.DEFAULT_CHARSET + ')'; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (key.toUpperCase(Locale.ROOT).startsWith(ARG_NAME)) { final String value = PreprocessorUtils.extractTrimmedTail(ARG_NAME, key); if (!value.isEmpty()) { if (Charset.isSupported(value)) { context.setTargetEncoding(Charset.forName(value)); result = true; } } } return result; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/PreserveIndentDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * Preserve indent when removing line-prefixes "//$" and "//$$" */ public class PreserveIndentDirectiveHandler implements CommandLineHandler { private static final String ARG_NAME = "/PI"; @Override public String getDescription() { return "preserve indentation when removing //$ and //$$"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (ARG_NAME.equalsIgnoreCase(key)) { context.setPreserveIndents(true); result = true; } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/RemoveCommentsHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.CommentRemoverType; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * Processes the flag that clears all source files from the destination directory, stripping them even from within comments. * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class RemoveCommentsHandler implements CommandLineHandler { private static final String ARG_NAME = "/R"; @Override public String getDescription() { return "strip all comments in result files"; } @Override public boolean processCommandLineKey(final String argument, final PreprocessorContext configurator) { boolean result = false; if (ARG_NAME.equalsIgnoreCase(argument)) { configurator.setKeepComments(CommentRemoverType.REMOVE_C_STYLE); result = true; } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/SourceDirectoryHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static com.igormaznitsa.jcp.utils.PreprocessorUtils.extractTail; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.io.File; import java.util.Arrays; import java.util.Locale; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * The handler processing the key to set the source directory * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class SourceDirectoryHandler implements CommandLineHandler { private static final String ARG_NAME = "/I:"; @Override public String getDescription() { return "set source folder for preprocessing (default: " + PreprocessorContext.DEFAULT_SOURCE_DIRECTORY + ')'; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (!key.isEmpty() && key.toUpperCase(Locale.ROOT).startsWith(ARG_NAME)) { final String tail = PreprocessorUtils.extractTrimmedTail(ARG_NAME, key); if (!tail.isEmpty()) { context.setSources( Arrays.stream(extractTail(ARG_NAME, key).split(Pattern.quote(File.pathSeparator))) .map(String::trim).collect(Collectors.toList())); result = true; } } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/UnknownAsFalseHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The handler processing the flag tells the preprocessor to be try to keep * non-executing lines of code as commented ones * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class UnknownAsFalseHandler implements CommandLineHandler { private static final String ARG_NAME = "/U"; @Override public String getDescription() { return "treat unknown variables as FALSE"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (ARG_NAME.equalsIgnoreCase(key)) { context.setUnknownVariableAsFalse(true); result = true; } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/cmdline/VerboseHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The handler processing the flag that the preprocessor to be verbose in its * messages and information * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class VerboseHandler implements CommandLineHandler { private static final String ARG_NAME = "/V"; @Override public String getDescription() { return "enable verbose logging (info stream)"; } @Override public boolean processCommandLineKey(final String key, final PreprocessorContext context) { boolean result = false; if (ARG_NAME.equalsIgnoreCase(key)) { context.setVerbose(true); result = true; } return result; } @Override public String getKeyName() { return ARG_NAME; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/containers/FileInfoContainer.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.containers; import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNullElse; import com.igormaznitsa.jcp.context.CommentTextProcessor; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.context.PreprocessorContextAware; import com.igormaznitsa.jcp.directives.AbstractDirectiveHandler; import com.igormaznitsa.jcp.directives.AfterDirectiveProcessingBehaviour; import com.igormaznitsa.jcp.directives.DirectiveArgumentType; import com.igormaznitsa.jcp.exceptions.FilePositionInfo; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import com.igormaznitsa.jcp.utils.ResettablePrinter; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.IntStream; import lombok.Data; /** * The class is one from the main classes in the preprocessor because it describes a preprocessing file and contains business logic for the process * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ @Data public class FileInfoContainer { public static final String WARNING_SPACE_BEFORE_HASH = "Detected hash prefixed comment line with whitespace, directive may be lost: "; private static final Pattern DIRECTIVE_HASH_PREFIXED = Pattern.compile("^\\s*//\\s*#(.*)$"); private static final Pattern DIRECTIVE_TWO_DOLLARS_PREFIXED = Pattern.compile("^\\s*//\\s*\\$\\$(.*)$"); private static final Pattern DIRECTIVE_TWO_DOLLARS_BLOCK_PREFIXED = Pattern.compile("^\\s*//\\s*\\$\\$\"\"\"(.*)$"); private static final Pattern DIRECTIVE_SINGLE_DOLLAR_PREFIXED = Pattern.compile("^\\s*//\\s*\\$(.*)$"); private static final Pattern DIRECTIVE_SINGLE_DOLLAR_BLOCK_PREFIXED = Pattern.compile("^\\s*//\\s*\\$\"(.*)$"); private static final Pattern DIRECTIVE_TAIL_REMOVER = Pattern.compile("\\/\\*\\s*-\\s*\\*\\/"); private static final String EOL_MARKER = "-=$$$$$$$$__EOL__$$$$$$$$=-"; /** * The source file for the container */ private final File sourceFile; /** * The flag shows that the file should be just copied into the destination place without any preprocessing */ private final boolean copyOnly; /** * Collection of files generated with the file. */ private final Collection generatedResources = new HashSet<>(); /** * Collection of files which took part during preprocessing of the file */ private final Collection includedSources = new HashSet<>(); /** * The flag shows that the file has been excluded from preprocessing and it will not be preprocessed and copied */ private boolean excludedFromPreprocessing; /** * The destination directory for the file */ private String targetFolder; /** * The destination name for the file */ private String targetFileName; public FileInfoContainer(final File srcFile, final String targetFileName, final boolean copyOnly) { requireNonNull(srcFile, "Source file is null"); requireNonNull(targetFileName, "Target file name is null"); this.copyOnly = copyOnly; excludedFromPreprocessing = false; sourceFile = srcFile; int lastDirSeparator = targetFileName.lastIndexOf('/'); if (lastDirSeparator < 0) { lastDirSeparator = targetFileName.lastIndexOf('\\'); } if (lastDirSeparator < 0) { this.targetFolder = "." + File.separatorChar; this.targetFileName = targetFileName; } else { this.targetFolder = targetFileName.substring(0, lastDirSeparator); this.targetFileName = targetFileName.substring(lastDirSeparator + 1); } } private static String findTailRemover(final String str, final PreprocessorContext context) { String result = str; if (context.isAllowWhitespaces()) { final Matcher matcher = DIRECTIVE_TAIL_REMOVER.matcher(str); if (matcher.find()) { result = str.substring(0, matcher.start()); } } else { final int tailRemoverStart = str.indexOf("/*-*/"); if (tailRemoverStart >= 0) { result = str.substring(0, tailRemoverStart); } } return result; } /** * Check that text line starts with two commented dollar chars * * @param line text line to be examined, must not be null * @param allowedWhitespaces if true then whitespaces allowed after line comment * @return true if the line starts with two commented dollar chars, false otherwise * @since 7.0.6 */ public static boolean isDoubleDollarPrefixed(final String line, final boolean allowedWhitespaces) { if (allowedWhitespaces) { return DIRECTIVE_TWO_DOLLARS_PREFIXED.matcher(line).matches(); } else { return line.startsWith("//$$"); } } public static boolean isDollarBlockPrefixed(final String line, final boolean allowedWhitespaces) { if (allowedWhitespaces) { return DIRECTIVE_SINGLE_DOLLAR_BLOCK_PREFIXED.matcher(line).matches(); } else { return line.startsWith("//$\"\"\""); } } public static boolean isDoubleDollarBlockPrefixed(final String line, final boolean allowedWhitespaces) { if (allowedWhitespaces) { return DIRECTIVE_SINGLE_DOLLAR_BLOCK_PREFIXED.matcher(line).matches(); } else { return line.startsWith("//$$\"\"\""); } } /** * Check that text line starts with single dollar chars * * @param line text line to be examined, must not be null * @param allowedWhitespaces if true then whitespaces allowed after line comment * @return true if the line starts with single dollar chars, false otherwise * @since 7.0.6 */ public static boolean isSingleDollarPrefixed(final String line, final boolean allowedWhitespaces) { if (allowedWhitespaces) { return DIRECTIVE_SINGLE_DOLLAR_PREFIXED.matcher(line).matches(); } else { return line.startsWith("//$"); } } /** * Allows to check that a text line can be considered as a JCP directive or special line. * * @param line text line to be examined * @param allowedWhitespaces if true then whitespaces allowed after line comment * @return true if the line can be considered as JCP one, false otherwise * @since 7.0.6 */ public static boolean isJcpCommentLine(final String line, final boolean allowedWhitespaces) { return isJcpDirectiveLine(line, allowedWhitespaces) || isSingleDollarPrefixed(line, allowedWhitespaces); } /** * Check that a text line contains comment directive. * * @param line string to be examined * @param allowWhitespaces flag to allow spaces betwee hash and started comment chars * @return true if the line contains a directive, false otherwise * @since 7.0.6 */ public static boolean isJcpDirectiveLine(final String line, final boolean allowWhitespaces) { if (allowWhitespaces) { return DIRECTIVE_HASH_PREFIXED.matcher(line).matches(); } else { return line.startsWith(AbstractDirectiveHandler.DIRECTIVE_PREFIX); } } private static int findLastReadStringIndexInStack(final PreprocessingState nullableState) { if (nullableState == null) { return -1; } var fileData = nullableState.peekIncludeStackFile(); if (fileData == null) { return -1; } else { return fileData.getLastReadStringIndex(); } } public void setTargetFolder(final String folder) { this.targetFolder = requireNonNull(folder, "Target folder must not be null"); } public void setTargetFileName(final String name) { this.targetFileName = requireNonNull(name, "Target file name must not be null"); } public String makeTargetFilePathAsString() { String folder = this.getTargetFolder(); if (!folder.isEmpty() && folder.charAt(folder.length() - 1) != File.separatorChar) { folder = folder + File.separatorChar; } return folder + this.getTargetFileName(); } @Override public String toString() { return String .format("%s: source=%s, targetFolder=%s, targetName=%s", this.getClass().getSimpleName(), PreprocessorUtils.getFilePath(this.getSourceFile()), this.getTargetFolder(), this.getTargetFileName()); } public List processGlobalDirectives( final PreprocessorContext context, final PreprocessingState stateInUse) throws IOException { final PreprocessingState activeState = stateInUse == null ? context.produceNewPreprocessingState(this, 0) : stateInUse; activeState.setGlobalPhase(true); String leftTrimmedString = null; try { try { while (!Thread.currentThread().isInterrupted()) { String nonTrimmedProcessingString = activeState.nextLine(); final Set processFlags = activeState.getPreprocessingFlags(); if (processFlags.contains(PreprocessingFlag.END_PROCESSING) || processFlags.contains(PreprocessingFlag.ABORT_PROCESSING)) { if (!processFlags.contains(PreprocessingFlag.ABORT_PROCESSING)) { processFlags.remove(PreprocessingFlag.END_PROCESSING); } nonTrimmedProcessingString = null; } if (nonTrimmedProcessingString == null) { activeState.popTextContainer(); if (activeState.isIncludeStackEmpty()) { break; } else { continue; } } leftTrimmedString = PreprocessorUtils.leftTrim(nonTrimmedProcessingString); if (isHashPrefixed(leftTrimmedString, context)) { switch (processDirective(context, activeState, this.extractHashPrefixedDirective(leftTrimmedString, context))) { case PROCESSED: case READ_NEXT_LINE: case SHOULD_BE_COMMENTED: continue; default: throw new Error("Unsupported result"); } } } } catch (Exception unexpected) { final PreprocessorException pp = PreprocessorException.extractPreprocessorException(unexpected); if (pp == null) { throw activeState .makeException("Unexpected exception detected", leftTrimmedString, unexpected); } else { throw pp; } } if (!activeState.isIfStackEmpty()) { final TextFileDataContainer lastIf = requireNonNull(activeState.peekIf()); throw new PreprocessorException( "Unclosed " + AbstractDirectiveHandler.DIRECTIVE_PREFIX + "_if instruction detected", "", new FilePositionInfo[] { new FilePositionInfo(lastIf.getFile(), lastIf.getNextStringIndex())}, null); } return activeState.popAllExcludeIfInfoData(); } finally { activeState.setGlobalPhase(false); } } private boolean isHashPrefixed(final String line, final PreprocessorContext context) { final boolean allowedWhitespaces = context.isAllowWhitespaces(); final boolean result = isJcpDirectiveLine(line, allowedWhitespaces); if (!allowedWhitespaces) { if (context.getPreprocessingState().isGlobalPhase() && !result && line.startsWith("// ") && DIRECTIVE_HASH_PREFIXED.matcher(line).matches()) { final TextFileDataContainer textContainer = context.getPreprocessingState().getCurrentIncludeFileContainer(); String lineInfo = ""; if (textContainer != null) { lineInfo = String.format("%s:%d)", textContainer.getFile().getAbsolutePath(), textContainer.getNextStringIndex()); } context.logWarning(WARNING_SPACE_BEFORE_HASH + lineInfo); } } return result; } private String extractHashPrefixedDirective(final String line, final PreprocessorContext context) { if (context.isAllowWhitespaces()) { final Matcher matcher = DIRECTIVE_HASH_PREFIXED.matcher(line); if (matcher.find()) { return matcher.group(1); } else { throw new IllegalStateException( "Unexpected situation, directive is not found, contact developer! (" + line + ')'); } } else { return PreprocessorUtils.extractTail(AbstractDirectiveHandler.DIRECTIVE_PREFIX, line); } } private String extractDoubleDollarPrefixedDirective( final String line, final boolean block, final PreprocessorContext context) { String tail; if (context.isAllowWhitespaces()) { final Matcher matcher = block ? DIRECTIVE_TWO_DOLLARS_BLOCK_PREFIXED.matcher(line) : DIRECTIVE_TWO_DOLLARS_PREFIXED.matcher(line); if (matcher.find()) { tail = matcher.group(1); } else { throw new IllegalStateException( "Unexpected situation, '//$$' directive is not found, contact developer! (" + line + ')'); } } else { if (block) { tail = PreprocessorUtils.extractTail("//$$\"\"\"", line); } else { tail = PreprocessorUtils.extractTail("//$$", line); } } if (context.isPreserveIndents()) { tail = PreprocessorUtils.replacePartByChar(line, ' ', 0, line.length() - tail.length()); } return tail; } private String extractSingleDollarPrefixedDirective(final String line, final boolean block, final PreprocessorContext context) { String tail; if (context.isAllowWhitespaces()) { final Matcher matcher = block ? DIRECTIVE_SINGLE_DOLLAR_BLOCK_PREFIXED.matcher(line) : DIRECTIVE_SINGLE_DOLLAR_PREFIXED.matcher(line); if (matcher.find()) { tail = matcher.group(1); } else { throw new IllegalStateException( "Unexpected situation, '//$' directive is not found, contact developer! (" + line + ')'); } } else { if (block) { tail = PreprocessorUtils.extractTail("//$\"\"\"", line); } else { tail = PreprocessorUtils.extractTail("//$", line); } } if (context.isPreserveIndents()) { tail = PreprocessorUtils.replacePartByChar(line, ' ', 0, line.length() - tail.length()); } return tail; } /** * Preprocess the file described by the object, NB! it doesn't clear local variables automatically for cloned contexts * * @param context the preprocessor context, must not be null * @return the state for the preprocessed file * @throws IOException it will be thrown for IO errors * @throws PreprocessorException it will be thrown for violation of preprocessing logic, like undefined variable * @see #preprocessFileWithNotification(PreprocessorContext, PreprocessingState, boolean) * @since 7.3.0 */ public PreprocessingState preprocessFile(final PreprocessorContext context) throws IOException { return this.preprocessFileWithNotification(context, context.getPreprocessingState(), true); } @SuppressWarnings("StringEquality") private void flushTextBufferForRemovedComments( final PreprocessorContext context, final AtomicReference> firstDetectedUncommentLinePtr, final int stringIndex, final List textPieces, final ResettablePrinter resettablePrinter) { final Map.Entry firstUncommentLine = firstDetectedUncommentLinePtr.getAndSet(null); final boolean lastEol = !textPieces.isEmpty() && textPieces.get(textPieces.size() - 1) == EOL_MARKER; final String accumulated = (lastEol ? IntStream.range(0, textPieces.size() - 1) : IntStream.range(0, textPieces.size())) .mapToObj(textPieces::get) .map(x -> (x == EOL_MARKER ? context.getEol() : x)) .collect(Collectors.joining()); textPieces.clear(); if (accumulated.isEmpty()) { if (lastEol) { resettablePrinter.print(context.getEol()); } } else { final List processors = context.getCommentTextProcessors(); String text = accumulated; if (!processors.isEmpty()) { final FilePositionInfo filePositionInfo = new FilePositionInfo(this.sourceFile, stringIndex); final int indent = firstUncommentLine == null ? 0 : firstUncommentLine.getKey().length(); final List results = processors .stream() .filter(x -> x.isAllowed(context)) .map(x -> { try { return x.processUncommentedText( context, indent, accumulated); } catch (Exception ex) { throw new PreprocessorException( "Error during external comment text processor call: " + x.getClass().getCanonicalName(), accumulated, context.getPreprocessingState().makeIncludeStack(), ex); } }).collect(Collectors.toList()); if (results.isEmpty()) { context.logDebug("No any result from processors for text block at " + filePositionInfo); text = accumulated; } else { text = results.stream().collect(Collectors.joining(context.getEol())); } } resettablePrinter.print(text + (lastEol ? context.getEol() : "")); } } /** * Preprocess the file described by the object, NB! it doesn't clear local variables automatically for cloned contexts * * @param context the preprocessor context, must not be null * @param stateInUse initial preprocessing state, if it is null then it will be automatically created * @param notifyProcessors send notification to all processors registered in context about start and stop, * it should be true for direct call of preprocess of standalone file. Works only for non-cloned contexts. * @return the state for the preprocessed file * @throws IOException it will be thrown for IO errors * @throws PreprocessorException it will be thrown for violation of preprocessing logic, like undefined variable * @since 7.3.0 */ public PreprocessingState preprocessFileWithNotification( final PreprocessorContext context, final PreprocessingState stateInUse, final boolean notifyProcessors) throws IOException { if (!context.isCloned() && notifyProcessors) { final List successfullyNotified = new ArrayList<>(); try { context.fireNotificationStart(successfullyNotified); } catch (final Exception ex) { context.logError("Error during init of context aware processors: " + ex.getMessage()); successfullyNotified.forEach(x -> { try { x.onContextStopped(context, ex); } catch (Exception err) { context.logError("Error: " + err.getMessage()); } }); throw new IllegalStateException("Exception during notification of context aware listeners", ex); } } PreprocessingState state = null; Throwable error = null; try { // do not clear local variables for cloned context to keep them in the new context if (!context.isCloned()) { context.clearLocalVariables(); } if (stateInUse == null) { state = context.produceNewPreprocessingState(this, 1); } else { state = stateInUse; } String leftTrimmedString = null; TextFileDataContainer lastTextFileDataContainer = null; final List textPieces = new ArrayList<>(); Integer firstBlockLineIndex = null; try { final AtomicReference> firstUncommentLine = new AtomicReference<>(); while (!Thread.currentThread().isInterrupted()) { final ResettablePrinter thePrinter = requireNonNull(state.getSelectedPrinter(), "Printer must be defined"); String rawString = state.nextLine(); final boolean presentedNextLine = state.hasReadLineNextLineInEnd(); final Set processFlags = state.getPreprocessingFlags(); if (processFlags.contains(PreprocessingFlag.END_PROCESSING) || processFlags.contains(PreprocessingFlag.ABORT_PROCESSING)) { if (!processFlags.contains(PreprocessingFlag.ABORT_PROCESSING)) { processFlags.remove(PreprocessingFlag.END_PROCESSING); } rawString = null; } if (state.getPreprocessingFlags() .contains(PreprocessingFlag.END_PROCESSING)) { state.getPreprocessingFlags().remove(PreprocessingFlag.END_PROCESSING); rawString = null; } if (rawString == null) { this.flushTextBufferForRemovedComments( context, firstUncommentLine, requireNonNullElse(firstBlockLineIndex, findLastReadStringIndexInStack(state)), textPieces, thePrinter); firstBlockLineIndex = null; lastTextFileDataContainer = state.popTextContainer(); if (state.isIncludeStackEmpty()) { break; } else { continue; } } leftTrimmedString = PreprocessorUtils.leftTrim(rawString); final String stringPrefix; if (leftTrimmedString.isEmpty()) { stringPrefix = rawString; } else { final int numberOfSpacesAtTheLineBeginning = rawString.indexOf(leftTrimmedString); if (numberOfSpacesAtTheLineBeginning > 0) { stringPrefix = rawString.substring(0, numberOfSpacesAtTheLineBeginning); } else { stringPrefix = ""; } } String stringToBeProcessed = leftTrimmedString; final boolean doPrintEol = presentedNextLine || !context.isCareForLastEol(); if (isHashPrefixed(stringToBeProcessed, context)) { this.flushTextBufferForRemovedComments( context, firstUncommentLine, requireNonNullElse(firstBlockLineIndex, findLastReadStringIndexInStack(state)), textPieces, thePrinter); firstBlockLineIndex = null; final String extractedDirective = extractHashPrefixedDirective(stringToBeProcessed, context); switch (this.processDirective(context, state, extractedDirective)) { case PROCESSED: case READ_NEXT_LINE: { if (context.isKeepLines()) { final String text = stringPrefix + AbstractDirectiveHandler.PREFIX_FOR_KEEPING_LINES_PROCESSED_DIRECTIVES + extractedDirective; if (doPrintEol) { thePrinter.println(text, context.getEol()); } else { thePrinter.print(text); } } continue; } case SHOULD_BE_COMMENTED: { final String text = stringPrefix + AbstractDirectiveHandler.PREFIX_FOR_KEEPING_LINES_PROCESSED_DIRECTIVES + extractedDirective; if (doPrintEol) { thePrinter.println(text, context.getEol()); } else { thePrinter.print(text); } continue; } default: throw new IllegalStateException("Unsupported result"); } } if (state.isDirectiveCanBeProcessed() && !state.getPreprocessingFlags() .contains(PreprocessingFlag.TEXT_OUTPUT_DISABLED)) { final boolean startsWithTwoDollars = isDoubleDollarPrefixed(leftTrimmedString, context.isAllowWhitespaces()); if (!startsWithTwoDollars) { stringToBeProcessed = PreprocessorUtils.processMacroses(leftTrimmedString, context); } if (startsWithTwoDollars) { // Output the tail of the string to the output stream without comments and macros String text = extractDoubleDollarPrefixedDirective(leftTrimmedString, false, context); Map.Entry indentText = Map.entry(context.isPreserveIndents() ? stringPrefix : "", text); final boolean firstLineSet = firstUncommentLine.compareAndSet(null, indentText); if (context.isAllowsBlocks() && isDoubleDollarBlockPrefixed(leftTrimmedString, context.isAllowWhitespaces())) { text = extractDoubleDollarPrefixedDirective(leftTrimmedString, true, context); indentText = Map.entry(context.isPreserveIndents() ? stringPrefix : "", text); if (firstLineSet) { firstBlockLineIndex = findLastReadStringIndexInStack(state); firstUncommentLine.set(indentText); } textPieces.add(indentText.getValue()); if (doPrintEol) { textPieces.add(EOL_MARKER); } } else { this.flushTextBufferForRemovedComments( context, firstUncommentLine, requireNonNullElse(firstBlockLineIndex, findLastReadStringIndexInStack(state)), textPieces, thePrinter); firstBlockLineIndex = null; textPieces.add(stringPrefix); textPieces.add(indentText.getKey()); textPieces.add(indentText.getValue()); if (doPrintEol) { textPieces.add(EOL_MARKER); } this.flushTextBufferForRemovedComments( context, firstUncommentLine, requireNonNullElse(firstBlockLineIndex, findLastReadStringIndexInStack(state)), textPieces, thePrinter); firstBlockLineIndex = null; } } else if (isSingleDollarPrefixed(stringToBeProcessed, context.isAllowWhitespaces())) { // Output the tail of the string to the output stream without comments String text = extractSingleDollarPrefixedDirective(stringToBeProcessed, false, context); Map.Entry indentText = Map.entry(context.isPreserveIndents() ? stringPrefix : "", text); final boolean firstLineSet = firstUncommentLine.compareAndSet(null, indentText); if (context.isAllowsBlocks() && isDollarBlockPrefixed(stringToBeProcessed, context.isAllowWhitespaces())) { text = extractSingleDollarPrefixedDirective(stringToBeProcessed, true, context); indentText = Map.entry(context.isPreserveIndents() ? stringPrefix : "", text); if (firstLineSet) { firstBlockLineIndex = findLastReadStringIndexInStack(state); firstUncommentLine.set(indentText); } textPieces.add(indentText.getValue()); if (doPrintEol) { textPieces.add(EOL_MARKER); } } else { this.flushTextBufferForRemovedComments( context, firstUncommentLine, requireNonNullElse(firstBlockLineIndex, findLastReadStringIndexInStack(state)), textPieces, thePrinter); firstBlockLineIndex = null; textPieces.add(stringPrefix); textPieces.add(indentText.getKey()); textPieces.add(indentText.getValue()); if (doPrintEol) { textPieces.add(EOL_MARKER); } this.flushTextBufferForRemovedComments( context, firstUncommentLine, requireNonNullElse(firstBlockLineIndex, findLastReadStringIndexInStack(state)), textPieces, thePrinter); firstBlockLineIndex = null; } } else { // Just string this.flushTextBufferForRemovedComments( context, firstUncommentLine, requireNonNullElse(firstBlockLineIndex, findLastReadStringIndexInStack(state)), textPieces, thePrinter); firstBlockLineIndex = null; final String strToOut = findTailRemover(stringToBeProcessed, context); if (state.getPreprocessingFlags() .contains(PreprocessingFlag.COMMENT_NEXT_LINE)) { thePrinter.print(AbstractDirectiveHandler.ONE_LINE_COMMENT); state.getPreprocessingFlags() .remove(PreprocessingFlag.COMMENT_NEXT_LINE); } thePrinter.print(stringPrefix); if (doPrintEol) { thePrinter.println(strToOut, context.getEol()); } else { thePrinter.print(strToOut); } } } else if (context.isKeepLines()) { flushTextBufferForRemovedComments(context, firstUncommentLine, requireNonNullElse(firstBlockLineIndex, findLastReadStringIndexInStack(state)), textPieces, thePrinter); firstBlockLineIndex = null; final String text = AbstractDirectiveHandler.PREFIX_FOR_KEEPING_LINES + rawString; if (doPrintEol) { thePrinter.println(text, context.getEol()); } else { thePrinter.print(text); } } } } catch (Exception unexpected) { final String message = unexpected.getMessage() == null ? "Unexpected exception" : unexpected.getMessage(); throw state.makeException(message, leftTrimmedString, unexpected); } if (!state.isIfStackEmpty()) { final TextFileDataContainer lastIf = requireNonNull(state.peekIf(), "'IF' stack is empty"); throw new PreprocessorException( "Unclosed " + AbstractDirectiveHandler.DIRECTIVE_PREFIX + "if instruction detected", "", new FilePositionInfo[] { new FilePositionInfo(lastIf.getFile(), lastIf.getNextStringIndex())}, null); } if (!state.isWhileStackEmpty()) { final TextFileDataContainer lastWhile = requireNonNull(state.peekWhile(), "'WHILE' stack is empty"); throw new PreprocessorException( "Unclosed " + AbstractDirectiveHandler.DIRECTIVE_PREFIX + "while instruction detected", "", new FilePositionInfo[] { new FilePositionInfo(lastWhile.getFile(), lastWhile.getNextStringIndex())}, null); } if (!context.isDryRun() && requireNonNull(lastTextFileDataContainer).isAutoFlush()) { final File outFile = context.createDestinationFileForPath(makeTargetFilePathAsString()); final boolean wasSaved = state.saveBuffersToFile(outFile, context.getKeepComments()); if (context.isVerbose()) { context.logForVerbose(String .format("Content was %s into file '%s'", (wasSaved ? "saved" : "not saved"), outFile)); } if (this.sourceFile != null && context.isKeepAttributes() && !PreprocessorUtils.copyFileAttributes(this.getSourceFile(), outFile)) { throw new IOException("Can't copy attributes in result file: " + outFile); } this.getGeneratedResources().add(outFile); } } catch (Throwable ex) { error = ex; if (ex instanceof IOException) { throw (IOException) ex; } if (ex instanceof Error) { throw (Error) ex; } if (ex instanceof RuntimeException) { throw (RuntimeException) ex; } } finally { if (!context.isCloned() && notifyProcessors) { context.fireNotificationStop(error); } } return state; } private boolean checkDirectiveArgumentRoughly(final AbstractDirectiveHandler directive, final String rest) { final DirectiveArgumentType argument = directive.getArgumentType(); boolean result; final String trimmedRest = rest.trim(); switch (argument) { case NONE: { result = trimmedRest.isEmpty(); } break; case ON_OFF: { if (trimmedRest.isEmpty()) { result = false; } else { final char firstChar = rest.charAt(0); result = firstChar == '+' || firstChar == '-'; if (rest.length() > 1) { result = result && Character.isSpaceChar(rest.charAt(1)); } } } break; case TAIL: { result = true; } break; default: { result = !trimmedRest.isEmpty() && Character.isSpaceChar(rest.charAt(0)); } break; } return result; } private AfterDirectiveProcessingBehaviour processDirective( final PreprocessorContext context, final PreprocessingState stateInUse, final String directiveString) { final boolean executionEnabled = stateInUse.isDirectiveCanBeProcessed(); final boolean firstPass = stateInUse.isGlobalPhase(); for (final AbstractDirectiveHandler handler : context.getDirectiveHandlers()) { final String name = handler.getName(); if (directiveString.startsWith(name)) { if ((firstPass && !handler.isGlobalPhaseAllowed()) || (!firstPass && !handler.isPreprocessingPhaseAllowed())) { return AfterDirectiveProcessingBehaviour.READ_NEXT_LINE; } final boolean allowedForExecution = executionEnabled || !handler.executeOnlyWhenExecutionAllowed(); final String restOfString = PreprocessorUtils.extractTail(name, directiveString); if (checkDirectiveArgumentRoughly(handler, restOfString)) { if (allowedForExecution) { return handler.execute(restOfString, context); } else { return context.isKeepLines() ? AfterDirectiveProcessingBehaviour.SHOULD_BE_COMMENTED : AfterDirectiveProcessingBehaviour.PROCESSED; } } else { throw context.makeException( "Detected bad argument for " + AbstractDirectiveHandler.DIRECTIVE_PREFIX + handler.getName(), null); } } } throw context.makeException("Unknown preprocessor directive [" + directiveString + ']', null); } public void setExcluded(final boolean flag) { excludedFromPreprocessing = flag; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/containers/PreprocessingFlag.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.containers; /** * The enumeration contains flags describe inside special preprocessor states * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public enum PreprocessingFlag { /** * This flag shows that it is allowed to print texts into an output stream */ TEXT_OUTPUT_DISABLED, /** * This flag shows that we must comment the next line (one time flag) */ COMMENT_NEXT_LINE, /** * This flag shows that the current //#if construction in the passive state */ IF_CONDITION_FALSE, /** * This flag shows that //#break has been met */ BREAK_COMMAND, /** * This flag shows that preprocessing must be ended on the next string */ END_PROCESSING, /** * This flag allows to stop preprocessing immediately */ ABORT_PROCESSING } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/containers/TextFileDataContainer.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.containers; import java.io.File; import java.util.Objects; /** * The class contains text data of a file and the string position index for the file * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class TextFileDataContainer { private final String[] text; private final boolean fileEndedByNextLine; private final File file; /** * Flag shows to save automatically buffers after file preprocessing end. */ private boolean autoFlush = true; private int nextStringIndex; public TextFileDataContainer(final TextFileDataContainer item, final int stringIndex) { this(item.file, item.text, item.fileEndedByNextLine, stringIndex); } public TextFileDataContainer(final File currentFile, final String[] text, final boolean fileEndedByNextLine, final int stringIndex) { Objects.requireNonNull(currentFile, "File is null"); Objects.requireNonNull(text, "Text is null"); this.file = currentFile; this.text = text; setNextStringIndex(stringIndex); this.fileEndedByNextLine = fileEndedByNextLine; } public void disableAutoFlush() { this.autoFlush = false; } public boolean isAutoFlush() { return this.autoFlush; } public String[] getText() { return this.text.clone(); } public File getFile() { return this.file; } public void reset() { this.nextStringIndex = 0; } public boolean isPresentedNextLineOnReadString() { return this.nextStringIndex < this.text.length || fileEndedByNextLine; } public String nextLine() { if (this.nextStringIndex >= this.text.length) { return null; } else { return this.text[this.nextStringIndex++]; } } public int getLastReadStringIndex() { return this.nextStringIndex - 1; } public int getNextStringIndex() { return nextStringIndex; } public void setNextStringIndex(final int index) { if (index < 0 || index >= text.length) { throw new IndexOutOfBoundsException("String index out of bound [" + index + ']'); } this.nextStringIndex = index; } @Override public int hashCode() { return file.hashCode(); } @Override public boolean equals(final Object that) { if (this == that) { return true; } if (that instanceof TextFileDataContainer) { final TextFileDataContainer thatItem = (TextFileDataContainer) that; return file.equals(thatItem.file) && nextStringIndex == thatItem.nextStringIndex; } return false; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/context/CommentRemoverType.java ================================================ package com.igormaznitsa.jcp.context; import java.util.Arrays; import java.util.stream.Collectors; /** * Type of comment remover. * * @since 7.1.0 */ public enum CommentRemoverType { /** * To not remove comments. */ KEEP_ALL, /** * Remove all single line and multiline comments defined in C style. */ REMOVE_C_STYLE, /** * Remove only comments contain JCP directives. */ REMOVE_JCP_ONLY; /** * Make comma separated list of enum item names. * * @return comma separated list of all enum items, without spaces. */ public static String makeListOfAllRemoverIds() { return Arrays.stream(CommentRemoverType.values()) .map(Enum::name).collect(Collectors.joining(",")); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/context/CommentTextProcessor.java ================================================ package com.igormaznitsa.jcp.context; /** * A custom processor for detecting and handling uncommenting directives in source text. * This processor recognizes lines or blocks marked with `//$` and `//$$` and can either * return them unchanged or modify them as needed. It is invoked after the external text * is prepared for injection into the preprocessed source. * If block merging is enabled, consecutive lines beginning with `"""` will be merged * into a single text block, and the `"""` markers will be removed. * * @since 7.2.0 */ public interface CommentTextProcessor extends PreprocessorContextAware, ExecutionAllowable { /** * Processes uncommented text detected in `//$` or `//$$` sections. * If no transformation is needed, the original text must be returned unchanged. * * @param context the current preprocessor context; must not be null * @param recommendedIndent the suggested indentation level for the processed text, if any modifications are applied * @param uncommentedText the text that was uncommented and is subject to processing; must not be null * @return the processed text, which may be unchanged or modified * @since 7.3.0 */ String processUncommentedText( PreprocessorContext context, int recommendedIndent, String uncommentedText); } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/context/EnvironmentVariableProcessor.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.context; import com.igormaznitsa.jcp.expression.Value; import java.util.Collections; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; /** * The class allows to get access to environment variables from preprocessor * expression, the variables have the "env." prefix and all them are String type * All environment variables are allowed for reading and disallowing for writing * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class EnvironmentVariableProcessor implements SpecialVariableProcessor { private static final String PREFIX = "env."; private final Map environmentVars; public EnvironmentVariableProcessor() { final Map env = new HashMap<>(); final Properties properties = System.getProperties(); for (final String key : properties.stringPropertyNames()) { env.put(PREFIX + key.toLowerCase(Locale.ROOT).replace(' ', '_'), Value.valueOf(properties.getProperty(key))); } environmentVars = Collections.unmodifiableMap(env); } @Override public Set getVariableNames() { return environmentVars.keySet(); } @Override public Value getVariable(final String varName, final PreprocessorContext context) { final Value result = environmentVars.get(varName); if (result == null) { throw context.makeException("Can't find in environment: " + varName, null); } return result; } @Override public void setVariable(final String varName, final Value value, final PreprocessorContext context) { throw context.makeException("Illegal change of environment record '" + varName + "'. Environment records accessible only for reading!", null); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/context/ExecutionAllowable.java ================================================ package com.igormaznitsa.jcp.context; /** * Interface describes an abstract object which can decide to be executed or not during execution in specified point. * * @since 7.3.0 */ public interface ExecutionAllowable { /** * Indicates whether execution is allowed to run in the current context. * This method is invoked before each call and receives complete * information about the current context and source file, enabling it to make a * dynamic decision. * If execution in bounds of test or mock state then some arguments can be null. * * @param context the current preprocessor context; must not be null * @return {@code true} if it is allowed to run; {@code false} otherwise */ boolean isAllowed( PreprocessorContext context ); } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/context/JCPSpecialVariableProcessor.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.context; import com.igormaznitsa.jcp.InfoHelper; import com.igormaznitsa.jcp.containers.TextFileDataContainer; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Set; /** * The class implements the special variable processor interface and allows to get access to inside JCP variables Inside JCP variables have the "jcp." prefix * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class JCPSpecialVariableProcessor implements SpecialVariableProcessor { public static final String VAR_JCP_BUFFER_ALL = "jcp.text.buffer.all"; public static final String VAR_JCP_BUFFER_MIDDLE = "jcp.text.buffer.middle"; public static final String VAR_JCP_BUFFER_PREFIX = "jcp.text.buffer.prefix"; public static final String VAR_JCP_BUFFER_POSTFIX = "jcp.text.buffer.postfix"; public static final String VAR_DEST_DIR = "jcp.dst.dir"; public static final String VAR_VERSION = "jcp.version"; public static final String VAR_DEST_FILE_NAME = "jcp.dst.name"; public static final String VAR_DEST_FULLPATH = "jcp.dst.path"; public static final String VAR_SRC_FILE_NAME = "jcp.src.name"; public static final String VAR_SRC_FILE_NAME2 = "__filename__"; public static final String VAR_SRC_DIR = "jcp.src.dir"; public static final String VAR_SRC_DIR2 = "__filefolder__"; public static final String VAR_SRC_FULLPATH = "jcp.src.path"; public static final String VAR_SRC_FULLPATH2 = "__file__"; public static final String VAR_LINE = "__line__"; public static final String VAR_DATE = "__date__"; public static final String VAR_TIME = "__time__"; public static final String VAR_TIMESTAMP = "__timestamp__"; final SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd yyyy"); final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss"); final SimpleDateFormat timestampFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy"); public static List getReference() { final List result = new ArrayList<>(); result.add(new NameReferencePair(VAR_VERSION, "Preprocessor version")); result .add(new NameReferencePair(VAR_SRC_FULLPATH, "Full path to preprocessing file, read only")); result.add(new NameReferencePair(VAR_SRC_FULLPATH2, "Synonym for '" + VAR_SRC_FULLPATH + "', read only")); result.add(new NameReferencePair(VAR_SRC_DIR, "Preprocessing file folder, read only")); result.add(new NameReferencePair(VAR_SRC_DIR2, "Synonym for '" + VAR_SRC_DIR + "', read only")); result.add(new NameReferencePair(VAR_SRC_FILE_NAME, "Preprocessing file name, read only")); result.add(new NameReferencePair(VAR_SRC_FILE_NAME2, "Synonym for '" + VAR_SRC_FILE_NAME + "', read only")); result.add(new NameReferencePair(VAR_LINE, "Number of preprocessing line, read only")); result.add(new NameReferencePair(VAR_DEST_FULLPATH, "Full destination file path, read only")); result.add(new NameReferencePair(VAR_DEST_DIR, "Destination folder, read-write")); result.add(new NameReferencePair(VAR_DEST_FILE_NAME, "Destination file name, read-write")); result.add(new NameReferencePair(VAR_TIME, "Time (HH:mm:ss)")); result.add(new NameReferencePair(VAR_DATE, "Date (MMM dd yyyy)")); result.add( new NameReferencePair(VAR_TIMESTAMP, "Source file timestamp (EEE MMM dd HH:mm:ss yyyy)")); result.add(new NameReferencePair(VAR_JCP_BUFFER_ALL, "Whole current text buffer for preprocessing file")); result.add(new NameReferencePair(VAR_JCP_BUFFER_MIDDLE, "Current middle text buffer for preprocessing file")); result.add(new NameReferencePair(VAR_JCP_BUFFER_PREFIX, "Current prefix text buffer for preprocessing file")); result.add(new NameReferencePair(VAR_JCP_BUFFER_POSTFIX, "Current postfix text buffer for preprocessing file")); return result; } @Override public Set getVariableNames() { return Set.of( VAR_JCP_BUFFER_PREFIX, VAR_JCP_BUFFER_MIDDLE, VAR_JCP_BUFFER_POSTFIX, VAR_JCP_BUFFER_ALL, VAR_DEST_DIR, VAR_DEST_FILE_NAME, VAR_DEST_FULLPATH, VAR_SRC_DIR, VAR_SRC_DIR2, VAR_SRC_FILE_NAME, VAR_SRC_FILE_NAME2, VAR_SRC_FULLPATH, VAR_SRC_FULLPATH2, VAR_VERSION, VAR_LINE, VAR_TIME, VAR_TIMESTAMP, VAR_DATE ); } @Override public Value getVariable(final String varName, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); switch (varName) { case VAR_JCP_BUFFER_ALL: return Value.valueOf(context.getPreprocessingState().getCurrentText()); case VAR_JCP_BUFFER_POSTFIX: return Value.valueOf(context.getPreprocessingState().findPrinter( PreprocessingState.PrinterType.POSTFIX).getText()); case VAR_JCP_BUFFER_MIDDLE: return Value.valueOf(context.getPreprocessingState().findPrinter( PreprocessingState.PrinterType.NORMAL).getText()); case VAR_JCP_BUFFER_PREFIX: return Value.valueOf(context.getPreprocessingState().findPrinter( PreprocessingState.PrinterType.PREFIX).getText()); case VAR_DEST_DIR: return Value.valueOf(state.getRootFileInfo().getTargetFolder()); case VAR_DEST_FILE_NAME: return Value.valueOf(state.getRootFileInfo().getTargetFileName()); case VAR_DEST_FULLPATH: return Value.valueOf(state.getRootFileInfo().makeTargetFilePathAsString()); case VAR_SRC_DIR: case VAR_SRC_DIR2: return Value.valueOf(state.getRootFileInfo().getSourceFile().getParent()); case VAR_SRC_FILE_NAME: case VAR_SRC_FILE_NAME2: return Value.valueOf(state.getRootFileInfo().getSourceFile().getName()); case VAR_SRC_FULLPATH: case VAR_SRC_FULLPATH2: return Value .valueOf(PreprocessorUtils.getFilePath(state.getRootFileInfo().getSourceFile())); case VAR_VERSION: return Value.valueOf(InfoHelper.getVersion()); case VAR_TIME: return Value.valueOf(timeFormat.format(new Date())); case VAR_DATE: return Value.valueOf(dateFormat.format(new Date())); case VAR_TIMESTAMP: final TextFileDataContainer filedata = state.peekIncludeStackFile(); final Value result; if (filedata == null) { result = Value.valueOf(""); } else { result = Value.valueOf(timestampFormat.format(new Date(filedata.getFile().lastModified()))); } return result; case VAR_LINE: final TextFileDataContainer currentFile = state.peekIncludeStackFile(); final long line; if (currentFile == null) { line = -1L; } else { line = currentFile.getLastReadStringIndex() + 1; } return Value.valueOf(line); default: final String text = "Attempting to read unexpected special variable [" + varName + ']'; throw context.makeException(text, null); } } private void assertNotGlobalPhase(final String varName, final PreprocessorContext context) { if (context.getPreprocessingState().isGlobalPhase()) { throw context.makeException( "Variable '" + varName + "' is not allowed to set during global phase", null); } } @Override public void setVariable(final String varName, final Value value, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); switch (varName) { case VAR_JCP_BUFFER_ALL: { this.assertNotGlobalPhase(varName, context); state.setBufferText(value.toString()); } break; case VAR_JCP_BUFFER_POSTFIX: { this.assertNotGlobalPhase(varName, context); state.setBufferText(value.toString(), PreprocessingState.PrinterType.POSTFIX); } break; case VAR_JCP_BUFFER_MIDDLE: { this.assertNotGlobalPhase(varName, context); state.setBufferText(value.toString(), PreprocessingState.PrinterType.NORMAL); } break; case VAR_JCP_BUFFER_PREFIX: { this.assertNotGlobalPhase(varName, context); state.setBufferText(value.toString(), PreprocessingState.PrinterType.PREFIX); } break; case VAR_DEST_DIR: if (value.getType() != ValueType.STRING) { throw new IllegalArgumentException("Only STRING type allowed"); } state.getRootFileInfo().setTargetFolder(value.asString()); break; case VAR_DEST_FILE_NAME: if (value.getType() != ValueType.STRING) { throw new IllegalArgumentException("Only STRING type allowed"); } state.getRootFileInfo().setTargetFileName(value.asString()); break; case VAR_DEST_FULLPATH: case VAR_SRC_DIR: case VAR_SRC_DIR2: case VAR_SRC_FILE_NAME: case VAR_SRC_FILE_NAME2: case VAR_SRC_FULLPATH: case VAR_SRC_FULLPATH2: case VAR_VERSION: case VAR_LINE: case VAR_TIME: case VAR_TIMESTAMP: case VAR_DATE: { final String text = "The variable '" + varName + "' can't be set directly"; throw context.makeException(text, null); } default: { final String text = "Attempting to write unexpected special variable [" + varName + ']'; throw context.makeException(text, null); } } } public static final class NameReferencePair { private final String name; private final String reference; private NameReferencePair(final String name, final String reference) { this.name = name; this.reference = reference; } public String getName() { return this.name; } public String getReference() { return this.reference; } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/context/PreprocessingState.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.context; import static com.igormaznitsa.jcp.removers.AbstractCommentRemover.makeCommentRemover; import static com.igormaznitsa.jcp.utils.IOUtils.closeQuietly; import static com.igormaznitsa.jcp.utils.PreprocessorUtils.findActiveFileInfoContainer; import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNullElse; import com.igormaznitsa.jcp.containers.FileInfoContainer; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.containers.TextFileDataContainer; import com.igormaznitsa.jcp.exceptions.FilePositionInfo; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import com.igormaznitsa.jcp.utils.ResettablePrinter; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.ArrayList; import java.util.EnumSet; import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; /** * The class describes a preprocessor state also it contains inside buffers and save data on disk * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class PreprocessingState { public static final FilePositionInfo[] EMPTY_STACK = new FilePositionInfo[0]; public static final int MAX_WRITE_BUFFER_SIZE = 65536; public static final String FAKE_FILE_FOLDER = "/fake_test_folder"; public static final String FAKE_FILE_PATH = FAKE_FILE_FOLDER + "/some_fake_file.txt"; private final Charset globalInCharacterEncoding; private final Charset globalOutCharacterEncoding; private final TextFileDataContainer rootReference; private final FileInfoContainer rootFileInfo; private final LinkedList whileStack = new LinkedList<>(); private final LinkedList ifStack = new LinkedList<>(); private final LinkedList includeStack = new LinkedList<>(); private final LinkedList deferredExcludeStack = new LinkedList<>(); private final ResettablePrinter prefixPrinter = new ResettablePrinter(1024); private final ResettablePrinter postfixPrinter = new ResettablePrinter(64 * 1024); private final ResettablePrinter normalPrinter = new ResettablePrinter(1024); private final boolean overrideOnlyIfContentChanged; private final EnumSet preprocessingFlags = EnumSet.noneOf(PreprocessingFlag.class); private final PreprocessorContext context; private final boolean mockMode; private ResettablePrinter selectedPrinter; private TextFileDataContainer activeIf; private TextFileDataContainer activeWhile; private String lastReadString; private boolean globalPhase; PreprocessingState(final PreprocessorContext context, final Charset inEncoding, final Charset outEncoding) { this.mockMode = true; this.globalInCharacterEncoding = requireNonNull(inEncoding); this.globalOutCharacterEncoding = requireNonNull(outEncoding); this.rootReference = null; this.lastReadString = ""; this.rootFileInfo = new FileInfoContainer(new File("global"), "global", true); this.overrideOnlyIfContentChanged = true; this.context = context; init(); } PreprocessingState(final PreprocessorContext context, final FileInfoContainer rootFile, final Charset inEncoding, final Charset outEncoding, final boolean overrideOnlyIfContentChanged) throws IOException { this.mockMode = false; this.context = context; this.overrideOnlyIfContentChanged = overrideOnlyIfContentChanged; this.globalInCharacterEncoding = requireNonNull(inEncoding); this.globalOutCharacterEncoding = requireNonNull(outEncoding); this.rootFileInfo = requireNonNull(rootFile, "The root file is null"); init(); rootReference = openFile(rootFile.getSourceFile()); } PreprocessingState(final PreprocessorContext context, final FileInfoContainer rootFile, final TextFileDataContainer rootContainer, final Charset inEncoding, final Charset outEncoding, final boolean overrideOnlyIfContentChanged) { this.mockMode = false; this.context = context; this.globalInCharacterEncoding = requireNonNull(inEncoding); this.globalOutCharacterEncoding = requireNonNull(outEncoding); this.overrideOnlyIfContentChanged = overrideOnlyIfContentChanged; this.rootFileInfo = requireNonNull(rootFile, "The root file is null"); init(); rootReference = rootContainer; includeStack.push(rootContainer); } public static PreprocessingState makeMock(final PreprocessorContext context) { return new PreprocessingState(context, StandardCharsets.UTF_8, StandardCharsets.UTF_8); } public boolean isMockMode() { return this.mockMode; } public boolean isGlobalPhase() { return this.globalPhase; } public void setGlobalPhase(final boolean flag) { this.globalPhase = flag; } public String getLastReadString() { return this.lastReadString; } public void pushExcludeIfData( final FileInfoContainer infoContainer, final String excludeIfCondition, final int stringIndex ) { requireNonNull(infoContainer, "File info is null"); requireNonNull(excludeIfCondition, "Condition is null"); if (stringIndex < 0) { throw new IllegalArgumentException("Unexpected string index [" + stringIndex + ']'); } this.deferredExcludeStack.push( new ExcludeIfInfo(infoContainer, excludeIfCondition, stringIndex)); } public ResettablePrinter getSelectedPrinter() { return this.selectedPrinter; } public List popAllExcludeIfInfoData() { final List result = new ArrayList<>(deferredExcludeStack); this.deferredExcludeStack.clear(); return result; } public ExcludeIfInfo popExcludeIfData() { return this.deferredExcludeStack.pop(); } public Set getPreprocessingFlags() { return this.preprocessingFlags; } public ResettablePrinter findPrinter(final PrinterType type) { switch (requireNonNull(type, "Type is null")) { case NORMAL: return this.normalPrinter; case POSTFIX: return this.postfixPrinter; case PREFIX: return this.prefixPrinter; default: throw new IllegalArgumentException("Unsupported type detected [" + type.name() + ']'); } } public void selectPrinter(final PrinterType type) { switch (requireNonNull(type, "Type is null")) { case NORMAL: this.selectedPrinter = this.normalPrinter; break; case POSTFIX: this.selectedPrinter = this.postfixPrinter; break; case PREFIX: this.selectedPrinter = this.prefixPrinter; break; default: throw new IllegalArgumentException("Unsupported type detected [" + type.name() + ']'); } } public TextFileDataContainer getRootTextContainer() { return this.rootReference; } public TextFileDataContainer openFile(final File file) throws IOException { requireNonNull(file, "The file is null"); final AtomicBoolean endedByNextLineContainer = new AtomicBoolean(); final String[] texts = PreprocessorUtils .readWholeTextFileIntoArray(file, globalInCharacterEncoding, endedByNextLineContainer); final TextFileDataContainer newContainer = new TextFileDataContainer(file, texts, endedByNextLineContainer.get(), 0); includeStack.push(newContainer); return newContainer; } public TextFileDataContainer peekIncludeStackFile() { return this.includeStack.peek(); } public List getIncludeStack() { return this.includeStack; } public Optional findActiveTextFileDataContainer() { if (this.isMockMode()) { return Optional.of( new TextFileDataContainer(new File(FAKE_FILE_PATH), new String[] {""}, false, 0)); } final TextFileDataContainer includeFile = this.peekIncludeStackFile(); return includeFile == null ? Optional.ofNullable(this.getRootTextContainer()) : Optional.of(includeFile); } public Optional findFilePositionInfo() { return this.findActiveTextFileDataContainer().map( x -> new FilePositionInfo(x.getFile(), x.getLastReadStringIndex())); } public FilePositionInfo[] makeIncludeStack() { if (this.isMockMode()) { return EMPTY_STACK; } final FilePositionInfo[] stack = new FilePositionInfo[includeStack.size()]; for (int i = 0; i < includeStack.size(); i++) { final TextFileDataContainer fileContainer = this.includeStack.get(i); stack[i] = new FilePositionInfo(fileContainer.getFile(), fileContainer.getLastReadStringIndex()); } return stack; } public TextFileDataContainer getCurrentIncludeFileContainer() { return this.includeStack.isEmpty() ? null : this.includeStack.get(this.includeStack.size() - 1); } public TextFileDataContainer popTextContainer() { if (this.includeStack.isEmpty()) { throw new IllegalStateException("Include stack is empty"); } return this.includeStack.pop(); } public FileInfoContainer getRootFileInfo() { return this.rootFileInfo; } public boolean isIncludeStackEmpty() { return includeStack.isEmpty(); } private TextFileDataContainer cloneTopTextDataContainer() { final TextFileDataContainer topElement = requireNonNull(includeStack.peek()); return new TextFileDataContainer(topElement, topElement.getLastReadStringIndex()); } public PreprocessingState popWhile() { final TextFileDataContainer whileOnTop = whileStack.pop(); if (whileOnTop == activeWhile) { preprocessingFlags.remove(PreprocessingFlag.BREAK_COMMAND); if (whileStack.isEmpty()) { activeWhile = null; } else { activeWhile = whileStack.peek(); } } return this; } public PreprocessingState pushWhile(final boolean makeActive) { final TextFileDataContainer whileRef = cloneTopTextDataContainer(); whileStack.push(whileRef); if (makeActive) { activeWhile = whileRef; } return this; } public TextFileDataContainer peekWhile() { return whileStack.peek(); } public boolean hasReadLineNextLineInEnd() { return includeStack.peek().isPresentedNextLineOnReadString(); } public String nextLine() { final String result = includeStack.peek().nextLine(); this.lastReadString = result; return result; } public PreprocessingState goToString(final int stringIndex) { includeStack.peek().setNextStringIndex(stringIndex); return this; } public PreprocessingState pushIf(final boolean makeActive) { final TextFileDataContainer ifRef = cloneTopTextDataContainer(); ifStack.push(ifRef); if (makeActive) { activeIf = ifRef; } return this; } public void popAllIFUntilContainerWithFile(final TextFileDataContainer container) { final File file = container.getFile(); final int stringIndex = container.getNextStringIndex(); while (!ifStack.isEmpty()) { final TextFileDataContainer top = ifStack.peek(); if (!top.getFile().equals(file) || top.getNextStringIndex() <= stringIndex) { break; } else { ifStack.pop(); } } } public PreprocessingState popIf() { final TextFileDataContainer ifRef = ifStack.pop(); if (ifRef == activeIf) { if (ifStack.isEmpty()) { activeIf = null; } else { activeIf = ifStack.peek(); } } return this; } public boolean isAtActiveWhile() { if (whileStack.isEmpty()) { return true; } else { return activeWhile == whileStack.peek(); } } public boolean isAtActiveIf() { if (ifStack.isEmpty()) { return true; } else { return ifStack.peek() == activeIf; } } public boolean isDirectiveCanBeProcessedIgnoreBreak() { return isAtActiveIf() && isAtActiveWhile() && !preprocessingFlags.contains(PreprocessingFlag.IF_CONDITION_FALSE); } public boolean isDirectiveCanBeProcessed() { return isDirectiveCanBeProcessedIgnoreBreak() && !preprocessingFlags.contains(PreprocessingFlag.BREAK_COMMAND); } public TextFileDataContainer peekIf() { return ifStack.peek(); } public boolean isIfStackEmpty() { return ifStack.isEmpty(); } public boolean isWhileStackEmpty() { return whileStack.isEmpty(); } private void init() { preprocessingFlags.clear(); resetPrinters(); selectPrinter(PrinterType.NORMAL); } public void resetPrinters() { normalPrinter.reset(); prefixPrinter.reset(); postfixPrinter.reset(); selectedPrinter = normalPrinter; } public void setBufferText(final String text) { this.prefixPrinter.reset(); this.normalPrinter.reset(); this.postfixPrinter.reset(); this.setBufferText(text, PrinterType.NORMAL); } public void setBufferText(final String text, final PrinterType printerType) { switch (printerType) { case NORMAL: { this.normalPrinter.reset(); this.normalPrinter.print(requireNonNullElse(text, "")); } break; case PREFIX: { this.prefixPrinter.reset(); this.prefixPrinter.print(requireNonNullElse(text, "")); } break; case POSTFIX: { this.postfixPrinter.reset(); this.postfixPrinter.print(requireNonNullElse(text, "")); } break; default: throw new IllegalArgumentException("Unsupported printer type: " + printerType); } } public String getCurrentText() { return this.prefixPrinter.getText() + this.normalPrinter.getText() + this.postfixPrinter.getText(); } public void saveBuffersToStreams(final OutputStream prefix, final OutputStream normal, final OutputStream postfix) throws IOException { prefixPrinter.writeBufferTo( new BufferedWriter(new OutputStreamWriter(prefix, globalOutCharacterEncoding))); normalPrinter.writeBufferTo( new BufferedWriter(new OutputStreamWriter(normal, globalOutCharacterEncoding))); postfixPrinter.writeBufferTo( new BufferedWriter(new OutputStreamWriter(postfix, globalOutCharacterEncoding))); } public boolean saveBuffersToFile(final File outFile, final CommentRemoverType keepComments) throws IOException { final File path = outFile.getParentFile(); if (path != null && !path.exists() && !path.mkdirs()) { throw new IOException("Can't make directory [" + PreprocessorUtils.getFilePath(path) + ']'); } Writer writer = null; boolean wasSaved = false; try { final int totatBufferedChars = prefixPrinter.getSize() + normalPrinter.getSize() + postfixPrinter.getSize(); final int BUFFER_SIZE = Math.max(64, Math.min(totatBufferedChars << 1, MAX_WRITE_BUFFER_SIZE)); if (this.overrideOnlyIfContentChanged) { String content = writePrinterBuffers(new StringWriter(totatBufferedChars)).toString(); if (keepComments != CommentRemoverType.KEEP_ALL) { content = makeCommentRemover( keepComments, new StringReader(content), new StringWriter(totatBufferedChars), context.isAllowWhitespaces()).process().toString(); } boolean needWrite = true; // better write than not final byte[] contentInBinaryForm = content.getBytes(globalOutCharacterEncoding); if (outFile.isFile() && outFile.length() == contentInBinaryForm.length) { // If file exists and has the same content, then skip overwriting it try (InputStream currentFileInputStream = new BufferedInputStream( Files.newInputStream(outFile.toPath()), Math.max(16384, (int) outFile.length()))) { needWrite = !IOUtils.contentEquals(currentFileInputStream, new ByteArrayInputStream(contentInBinaryForm)); } } if (needWrite) { FileUtils.writeByteArrayToFile(outFile, contentInBinaryForm, false); wasSaved = true; } else { this.context.logDebug( "Ignore writing data for " + outFile + " because its content has not been changed"); } } else if (keepComments != CommentRemoverType.KEEP_ALL) { final String joinedBufferContent = writePrinterBuffers(new StringWriter(totatBufferedChars)).toString(); writer = new OutputStreamWriter( new BufferedOutputStream(new FileOutputStream(outFile, false), BUFFER_SIZE), globalOutCharacterEncoding); writer = makeCommentRemover(keepComments, new StringReader(joinedBufferContent), writer, context.isAllowWhitespaces()).process(); wasSaved = true; } else { writer = new OutputStreamWriter( new BufferedOutputStream(new FileOutputStream(outFile, false), BUFFER_SIZE), globalOutCharacterEncoding); writePrinterBuffers(writer); wasSaved = true; } } finally { closeQuietly(writer); } if (wasSaved) { findActiveFileInfoContainer(context).ifPresent(t -> t.getGeneratedResources().add(outFile)); if (this.context.isKeepAttributes() && outFile.exists()) { PreprocessorUtils.copyFileAttributes(this.getRootFileInfo().getSourceFile(), outFile); } } return wasSaved; } public Writer writePrinterBuffers(final Writer writer) throws IOException { if (!prefixPrinter.isEmpty()) { prefixPrinter.writeBufferTo(writer); } if (!normalPrinter.isEmpty()) { normalPrinter.writeBufferTo(writer); } if (!postfixPrinter.isEmpty()) { postfixPrinter.writeBufferTo(writer); } return writer; } public PreprocessorException makeException(final String message, final String causeString, final Throwable cause) { return new PreprocessorException(message, causeString, makeIncludeStack(), cause); } public enum PrinterType { NORMAL, PREFIX, POSTFIX } public static class ExcludeIfInfo { private final FileInfoContainer fileInfoContainer; private final String condition; private final int stringIndex; public ExcludeIfInfo(final FileInfoContainer fileInfoContainer, final String condition, final int stringIndex) { this.fileInfoContainer = fileInfoContainer; this.condition = condition.trim(); this.stringIndex = stringIndex; } public int getStringIndex() { return this.stringIndex; } public FileInfoContainer getFileInfoContainer() { return fileInfoContainer; } public String getCondition() { return condition; } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/context/PreprocessorContext.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.context; import static java.util.Collections.singletonList; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toUnmodifiableList; import com.igormaznitsa.jcp.containers.FileInfoContainer; import com.igormaznitsa.jcp.containers.TextFileDataContainer; import com.igormaznitsa.jcp.directives.AbstractDirectiveHandler; import com.igormaznitsa.jcp.exceptions.FilePositionInfo; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.extension.PreprocessorExtension; import com.igormaznitsa.jcp.logger.PreprocessorLogger; import com.igormaznitsa.jcp.logger.SystemOutLogger; import com.igormaznitsa.jcp.utils.GetUtils; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; import lombok.AccessLevel; import lombok.Data; import lombok.Getter; import lombok.Setter; import org.apache.commons.io.FilenameUtils; /** * Preprocessor context class is a main class which contains all options for preprocessin and allow to work with variables in expressions. */ @Data public class PreprocessorContext { public static final List DEFAULT_SOURCE_DIRECTORY = Collections.singletonList("." + File.separatorChar); public static final String DEFAULT_DEST_DIRECTORY = ".." + File.separatorChar + "preprocessed"; public static final List DEFAULT_PROCESSING_EXTENSIONS = List.of("java", "txt", "htm", "html"); public static final List DEFAULT_EXCLUDED_EXTENSIONS = singletonList("xml"); public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; private static final List directiveHandlers = AbstractDirectiveHandler.findAllDirectives(); @Setter(AccessLevel.NONE) @Getter(AccessLevel.NONE) protected final Collection preprocessedResources; @Setter(AccessLevel.NONE) @Getter(AccessLevel.NONE) protected final AtomicReference preprocessingState = new AtomicReference<>(); private final Map globalVarTable = new HashMap<>(); private final Map localVarTable = new HashMap<>(); private final Map> mapVariableNameToSpecialVarProcessor = new HashMap<>(); private final Map sharedResources = new HashMap<>(); private final List configFiles = new ArrayList<>(); @Setter(AccessLevel.NONE) private final boolean cloned; @Setter(AccessLevel.NONE) private final TextFileDataContainer currentInCloneSource; private final List sources = new ArrayList<>(); private final File baseDir; private final Collection activatedConfigFiles; private final List commentTextProcessors; private String eol = GetUtils .ensureNonNull(System.getProperty("jcp.line.separator", System.getProperty("line.separator")), "\n"); private boolean verbose = false; private CommentRemoverType keepComments = CommentRemoverType.KEEP_ALL; private boolean clearTarget = false; private boolean dryRun = false; private boolean keepLines = false; private boolean careForLastEol = false; private boolean dontOverwriteSameContent = false; private boolean allowWhitespaces = false; private boolean preserveIndents = false; private boolean keepAttributes = false; private boolean unknownVariableAsFalse = false; private boolean allowsBlocks = false; private File target; private Set extensions = new HashSet<>(DEFAULT_PROCESSING_EXTENSIONS); private Set excludeExtensions = new HashSet<>(DEFAULT_EXCLUDED_EXTENSIONS); private List preprocessorExtensions = List.of(); private Charset sourceEncoding = DEFAULT_CHARSET; private Charset targetEncoding = DEFAULT_CHARSET; @Setter(AccessLevel.NONE) private PreprocessorLogger preprocessorLogger = new SystemOutLogger(); private List excludeFolders = new ArrayList<>(); /** * Constructor * * @param baseDir the base folder for process, it must not be null */ public PreprocessorContext(final File baseDir) { this.preprocessedResources = new ArrayList<>(); this.activatedConfigFiles = new ArrayList<>(); this.baseDir = requireNonNull(baseDir, "Base folder must not be null"); this.setSources(DEFAULT_SOURCE_DIRECTORY).setTarget(new File(DEFAULT_DEST_DIRECTORY)); this.registerSpecialVariableProcessor(new JCPSpecialVariableProcessor()); this.registerSpecialVariableProcessor(new EnvironmentVariableProcessor()); this.cloned = false; this.currentInCloneSource = null; this.commentTextProcessors = new ArrayList<>(); this.preprocessingState .set(this.makeNewPreprocessorState(this.sourceEncoding, this.targetEncoding)); } /** * Make clone of a preprocessor context but without cloning state. * * @param context the context to be cloned, must not be null. */ public PreprocessorContext(final PreprocessorContext context) { requireNonNull(context, "Source context must not be null"); this.activatedConfigFiles = context.activatedConfigFiles; this.preprocessedResources = context.preprocessedResources; this.baseDir = context.getBaseDir(); this.verbose = context.isVerbose(); this.keepComments = context.getKeepComments(); this.clearTarget = context.isClearTarget(); this.dryRun = context.isDryRun(); this.keepLines = context.isKeepLines(); this.allowWhitespaces = context.isAllowWhitespaces(); this.preserveIndents = context.isPreserveIndents(); this.sources.addAll(context.sources); this.target = context.getTarget(); this.keepAttributes = context.isKeepAttributes(); this.careForLastEol = context.isCareForLastEol(); this.extensions.clear(); this.extensions.addAll(context.extensions); this.excludeExtensions.clear(); this.excludeExtensions.addAll(context.excludeExtensions); this.unknownVariableAsFalse = context.unknownVariableAsFalse; this.allowsBlocks = context.allowsBlocks; this.preprocessorExtensions = context.getPreprocessorExtensions(); this.sourceEncoding = context.getSourceEncoding(); this.targetEncoding = context.getTargetEncoding(); this.dontOverwriteSameContent = context.isDontOverwriteSameContent(); this.eol = context.getEol(); this.globalVarTable.clear(); this.globalVarTable.putAll(context.getGlobalVarTable()); this.localVarTable.clear(); this.localVarTable.putAll(context.getLocalVarTable()); this.excludeFolders = new ArrayList<>(context.getExcludeFolders()); this.mapVariableNameToSpecialVarProcessor .putAll(context.getMapVariableNameToSpecialVarProcessor()); this.sharedResources.putAll(context.getSharedResources()); this.configFiles.clear(); this.configFiles.addAll(context.getConfigFiles()); this.preprocessingState.set(requireNonNull(context.getPreprocessingState())); this.cloned = true; this.preprocessorLogger = context.getPreprocessorLogger(); this.commentTextProcessors = new ArrayList<>(context.commentTextProcessors); this.currentInCloneSource = context.getPreprocessingState().peekIncludeStackFile(); } private static String makeStackView( final TextFileDataContainer cloneSource, final boolean cloned, final List list ) { if (list == null || list.isEmpty()) { return ""; } final StringBuilder builder = new StringBuilder(); int tab = 5; builder.append(" ".repeat(tab)); builder.append('{'); if (cloned) { builder.append(cloneSource == null ? "*No src info" : "*" + cloneSource.getFile().getName() + ':' + cloneSource.getNextStringIndex()); } else { builder.append("File chain"); } builder.append('}'); tab += 5; int fileIndex = 1; for (int i = list.size() - 1; i >= 0; i--) { final TextFileDataContainer cur = list.get(i); builder.append('\n'); builder.append(" ".repeat(Math.max(0, tab))); builder.append("└>"); builder.append(fileIndex++).append(". "); builder.append(cur.getFile().getName()).append(':').append(cur.getLastReadStringIndex() + 1); tab += 3; } return builder.toString(); } private static Charset decodeCharset(final String charsetName) { final String normalized = charsetName.trim(); if (Charset.isSupported(normalized)) { return Charset.forName(normalized); } else { throw new IllegalArgumentException("Unsupported charset: " + charsetName); } } /** * Add comment text processor. * * @param commentTextProcessor comment text processor, must not be null * @since 7.2.0 */ public void addCommentTextProcessor(final CommentTextProcessor commentTextProcessor) { this.commentTextProcessors.add(requireNonNull(commentTextProcessor)); } /** * Remove comment text processor. * * @param commentTextProcessor remove registered comment text processor. * @since 7.2.0 */ public void removeCommentTextProcessor(final CommentTextProcessor commentTextProcessor) { this.commentTextProcessors.remove(commentTextProcessor); } /** * Get all directive handlers allowed for processing. * * @return list of direction handlers for the context * @since 7.0.6 */ public List getDirectiveHandlers() { return directiveHandlers; } public void addPreprocessedResource(final FileInfoContainer container) { if (container != null) { this.preprocessedResources.add(container); } } public void addAllPreprocessedResources(final Collection containers) { if (containers != null) { this.preprocessedResources.addAll(containers); } } public Set findPreprocessedResources() { return new HashSet<>(this.preprocessedResources); } /** * Send notification about context start to all registered listeners. * * @param initedList list accumulating successfully processed listeners, must not be immutable and must not be null * @since 7.2.0 */ public void fireNotificationStart(final List initedList) { this.getCommentTextProcessors().forEach(x -> { x.onContextStarted(this); initedList.add(x); }); this.getMapVariableNameToSpecialVarProcessor() .values().stream().flatMap(Collection::stream).forEach(x -> { x.onContextStarted(this); initedList.add(x); }); this.getPreprocessorExtensions().forEach(x -> { x.onContextStarted(this); initedList.add(x); }); } /** * Send notification about context stop to all registered listeners. * * @param error error to be detected during preprocess, can be null if no errors * @since 7.2.0 */ public void fireNotificationStop(final Throwable error) { this.getCommentTextProcessors().forEach(x -> x.onContextStopped(this, error)); this.getMapVariableNameToSpecialVarProcessor() .values().stream().flatMap(Collection::stream) .forEach(x -> x.onContextStopped(this, error)); this.getPreprocessorExtensions().forEach(x -> x.onContextStopped(this, error)); } /** * Find all files which have been used during preprocess, it includes configs, source files, copied files, * generated files, included files and binary files used by functions. Excluded files are not added if * they are not processed by included files. * * @return set of all input files, must not be null * @since 7.0.3 */ public Set findAllInputFiles() { final Set result = new HashSet<>(this.configFiles); this.preprocessedResources.forEach(x -> { result.addAll(x.getIncludedSources()); if (x.getSourceFile() != null && !(x.getIncludedSources().isEmpty() && x.isExcludedFromPreprocessing())) { result.add(x.getSourceFile()); } }); return result; } /** * Find all files which have been produced during preprocess, it includes also copied an generated files. * * @return set of all produced files, must not be null * @since 7.0.3 */ public Set findAllProducedFiles() { return this.preprocessedResources.stream() .flatMap(x -> x.getGeneratedResources().stream()) .collect(Collectors.toSet()); } public Optional findFileInfoContainer(final File file) { if (file == null) { return Optional.empty(); } else { return this.preprocessedResources.stream() .filter(x -> file.equals(x.getSourceFile())) .findFirst(); } } public void setEol(final String eol) { this.eol = requireNonNull(eol); } public void setTarget(final File file) { this.target = file.isAbsolute() ? file : new File(this.getBaseDir(), file.getPath()); } public List getPreprocessorExtensions() { return this.preprocessorExtensions; } public void setPreprocessorExtensions(final List extensions) { if (extensions == null) { this.logDebug("Removed all preprocessor extensions"); this.preprocessorExtensions = List.of(); } else { this.preprocessorExtensions = extensions.stream().filter(Objects::nonNull).collect(toUnmodifiableList()); this.logDebug( () -> "Replaces preprocessor extensions: " + this.preprocessorExtensions.stream() .map(x -> x.getClass().getCanonicalName()) .collect(Collectors.joining(","))); } } public void addPreprocessorExtension(final PreprocessorExtension extension) { if (extension == null) { return; } if (this.preprocessorExtensions.stream().anyMatch(x -> x == extension)) { return; } this.preprocessorExtensions = Stream.concat(this.preprocessorExtensions.stream(), Stream.of(extension)).collect( toUnmodifiableList()); this.logDebug("Added preprocessor extension: " + extension.getClass().getCanonicalName()); } /** * Check that the preprocessor context is a clone of another context. * * @return true if the context is a clone, false otherwise */ public boolean isCloned() { return this.cloned; } /** * Set the logger to print information and error messages * * @param logger a logger to be used for output, it can be null */ public void setPreprocessorLogger(final PreprocessorLogger logger) { preprocessorLogger = logger; } /** * It allows to register a special variable processor which can process some special global variables * * @param processor a variable processor to be registered, it must not be null * @see SpecialVariableProcessor */ public void registerSpecialVariableProcessor(final SpecialVariableProcessor processor) { requireNonNull(processor, "Processor is null"); for (final String varName : processor.getVariableNames()) { requireNonNull(varName, "A Special Var name is null"); if (mapVariableNameToSpecialVarProcessor.containsKey(varName)) { throw new IllegalStateException("There is already defined processor for " + varName); } mapVariableNameToSpecialVarProcessor.compute(varName, (k, l) -> l == null ? List.of(processor) : Stream.concat(l.stream(), Stream.of(processor)).collect(toUnmodifiableList())); } } /** * Print an information into the current log * * @param text a String to be printed into the information log, it can be null */ public void logInfo(final String text) { if (text != null && this.preprocessorLogger != null) { this.preprocessorLogger.info(text); } } /** * Print an information about an error into the current log * * @param text a String to be printed into the error log, it can be null */ public void logError(final String text) { if (text != null && this.preprocessorLogger != null) { this.preprocessorLogger.error(text); } } /** * Print some debug info into the current log * * @param text a String to be printed into the error log, it can be null * @since 6.0.1 */ public void logDebug(final String text) { if (text != null && this.preprocessorLogger != null) { this.preprocessorLogger.debug(text); } } /** * Print some debug info into the current log * * @param textSupplier a String supplier to generate text to be printed into the debug log, it can be null * @since 7.3.0 */ public void logDebug(final Supplier textSupplier) { if (textSupplier != null && this.preprocessorLogger != null) { this.preprocessorLogger.debug(textSupplier); } } /** * Print an information about a warning situation into the current log * * @param text a String to be printed into the warning log, it can be null */ public void logWarning(final String text) { if (text != null || this.preprocessorLogger != null) { this.preprocessorLogger.warning(text); } } /** * Set a shared source, it is an object saved into the internal map for a name * * @param name the name for the saved project, must not be null * @param obj the object to be saved in, must not be null */ public void setSharedResource(final String name, final Object obj) { requireNonNull(name, "Name is null"); requireNonNull(obj, "Object is null"); sharedResources.put(name, obj); } /** * Get a shared source from internal map * * @param name the name of the needed object, it must not be null * @return a cached object or null if it is not found */ public Object getSharedResource(final String name) { requireNonNull(name, "Name is null"); return sharedResources.get(name); } /** * Remove a shared object from the internal map for its name * * @param name the object name, it must not be null * @return removing object or null if it is not found */ public Object removeSharedResource(final String name) { requireNonNull(name, "Name is null"); return sharedResources.remove(name); } /** * Set source directories * * @param folderPaths list of source folder paths represented as strings * @return this preprocessor context instance */ public PreprocessorContext setSources(final List folderPaths) { this.sources.clear(); this.sources.addAll( folderPaths.stream().map(x -> new SourceFolder(this.baseDir, x)) .collect(Collectors.toList())); return this; } /** * Get file extensions of files to be preprocessed as a string array * * @return a string array of file extensions to be preprocessed */ public Set getExtensions() { return this.extensions; } /** * Set file extensions of files to be preprocessed, it is a comma separated list * * @param extensions comma separated extensions list of file extensions to be preprocessed, must not be null * @return this preprocessor context */ public PreprocessorContext setExtensions(final List extensions) { this.extensions = new HashSet<>(requireNonNull(extensions)); return this; } /** * Check that a file is allowed to be preprocessed fo its extension * * @param file a file to be checked * @return true if the file is allowed, false otherwise */ public final boolean isFileAllowedForPreprocessing(final File file) { boolean result = false; if (file != null && file.isFile() && file.length() != 0L) { result = this.extensions.contains(PreprocessorUtils.getFileExtension(file)); } return result; } /** * Check that a file is excluded from preprocessing and coping actions * * @param file a file to be checked * @return true if th file must be excluded, otherwise false */ public final boolean isFileExcludedByExtension(final File file) { return file == null || !file.isFile() || this.excludeExtensions.contains(PreprocessorUtils.getFileExtension(file)); } /** * Get excluded file extension list as a string array * * @return a string array contains file extensions to be excluded from preprocessing act */ public Set getExcludeExtensions() { return this.excludeExtensions; } /** * Set comma separated list of file extensions to be excluded from preprocessing * * @param extensions a comma separated file extension list, it must not be null * @return this preprocessor context */ public PreprocessorContext setExcludeExtensions( final List extensions) { this.excludeExtensions = new HashSet<>(requireNonNull(extensions)); return this; } /** * Set a local variable value * * @param name the variable name, must not be null, remember that the name will be normalized and will be entirely in lower case * @param value the value for the variable, it must not be null * @return this preprocessor context * @see Value */ public PreprocessorContext setLocalVariable(final String name, final Value value) { requireNonNull(name, "Variable name is null"); requireNonNull(value, "Value is null"); final String normalized = requireNonNull(PreprocessorUtils.normalizeVariableName(name)); if (normalized.isEmpty()) { throw makeException("Not defined variable name", null); } if (this.mapVariableNameToSpecialVarProcessor.containsKey(normalized)) { final SpecialVariableProcessor enabledProcessor = findAllowedSpecialVariableProcessor(normalized) .orElseThrow(() -> this.makeException("Set of local variable '" + normalized + "' is not allowed in the point by its processor", null)); enabledProcessor.setVariable(normalized, value, this); } else if (this.globalVarTable.containsKey(normalized)) { throw makeException( "Cannot override global variable with a local variable of the same name [" + normalized + ']', null); } else { this.localVarTable.put(normalized, value); } return this; } /** * Remove a local variable value from the context. * * @param name the variable name, must not be null, remember that the name will be normalized and will be entirely in lower case * @return this preprocessor context * @see Value */ public PreprocessorContext removeLocalVariable(final String name) { requireNonNull(name, "Variable name is null"); final String normalized = requireNonNull(PreprocessorUtils.normalizeVariableName(name)); if (normalized.isEmpty()) { throw makeException("Empty variable name", null); } if (mapVariableNameToSpecialVarProcessor.containsKey(normalized) || globalVarTable.containsKey(normalized)) { throw makeException( "Attempting to remove either a global variable or a special variable as a local one [" + normalized + ']', null); } if (isVerbose()) { logForVerbose("Removing local variable '" + normalized + "'"); } localVarTable.remove(normalized); return this; } /** * Remove a global variable value from the context. * * @param name the variable name, must not be null, remember that the name will be normalized and will be entirely in lower case * @return this preprocessor context * @see Value */ public PreprocessorContext removeGlobalVariable(final String name) { requireNonNull(name, "Variable name is null"); final String normalized = requireNonNull(PreprocessorUtils.normalizeVariableName(name)); if (normalized.isEmpty()) { throw makeException("Empty variable name", null); } if (mapVariableNameToSpecialVarProcessor.containsKey(normalized)) { throw makeException( "Attempting to remove a special variable as a global one [" + normalized + ']', null); } if (isVerbose()) { logForVerbose("Removing global variable '" + normalized + "'"); } globalVarTable.remove(normalized); return this; } /** * Get a local variable value * * @param name the name for the variable, it can be null. The name will be normalized to allowed one. * @return null either if the name is null or the variable is not found, otherwise its value */ public Value getLocalVariable(final String name) { if (name == null) { return null; } final String normalized = requireNonNull(PreprocessorUtils.normalizeVariableName(name)); if (normalized.isEmpty()) { return null; } return localVarTable.get(normalized); } /** * Check that a local variable for a name is presented * * @param name the checking name, it will be normalized to the support format and can be null * @return false either if the name is null or there is not any local variable for the name, otherwise true */ public boolean containsLocalVariable(final String name) { if (name == null) { return false; } final String normalized = requireNonNull(PreprocessorUtils.normalizeVariableName(name)); if (normalized.isEmpty()) { return false; } return localVarTable.containsKey(normalized); } /** * Remove all local variables from the internal storage * * @return this preprocessor context */ public PreprocessorContext clearLocalVariables() { this.localVarTable.clear(); return this; } private Optional findAllowedSpecialVariableProcessor( final String normalizedName) { return this.mapVariableNameToSpecialVarProcessor.get(normalizedName) .stream() .filter(x -> x.isAllowed(this)).findFirst(); } /** * Set a global variable value * * @param name the variable name, it must not be null and will be normalized to the supported format * @param value the variable value, it must not be null * @return this preprocessor context */ public PreprocessorContext setGlobalVariable(final String name, final Value value) { requireNonNull(name, "Variable name is null"); final String normalizedName = requireNonNull(PreprocessorUtils.normalizeVariableName(name)); if (normalizedName.isEmpty()) { throw makeException("Name is empty", null); } requireNonNull(value, "Value is null"); if (this.mapVariableNameToSpecialVarProcessor.containsKey(normalizedName)) { final SpecialVariableProcessor firstActiveProcessor = this.findAllowedSpecialVariableProcessor(normalizedName) .orElseThrow(() -> this.makeException( "Cannot set special variable '" + normalizedName + "' no valid processor available here, may be it is read only", null)); firstActiveProcessor.setVariable(normalizedName, value, this); } else { if (isVerbose()) { final String valueAsStr = value.toString(); if (globalVarTable.containsKey(normalizedName)) { logForVerbose("Replacing global variable [" + normalizedName + '=' + valueAsStr + ']'); } else { logForVerbose("Defining new global variable [" + normalizedName + '=' + valueAsStr + ']'); } } globalVarTable.put(normalizedName, value); } return this; } /** * Check that there is a named global variable in the internal storage * * @param name the checking name, it will be normalized to the supported format, it can be null * @return true if such variable is presented for its name in the internal storage, otherwise false (also it is false if the name is null) */ public boolean containsGlobalVariable(final String name) { if (name == null) { return false; } final String normalized = requireNonNull(PreprocessorUtils.normalizeVariableName(name)); if (normalized.isEmpty()) { return false; } return mapVariableNameToSpecialVarProcessor.containsKey(normalized) || globalVarTable.containsKey(normalized); } /** * Find value among local and global variables for a name. It finds in the order: special processors, local variables, global variables * * @param name the name for the needed variable, it will be normalized to the supported format * @param enforceUnknownVarAsNull if true then state of the unknownVariableAsFalse flag in context will be ignored * @return null if either the variable is not found or the name is null, otherwise the variable value */ public Value findVariableForName(final String name, final boolean enforceUnknownVarAsNull) { if (name == null) { return null; } final String normalized = requireNonNull(PreprocessorUtils.normalizeVariableName(name)); if (normalized.isEmpty()) { return null; } final SpecialVariableProcessor processor = mapVariableNameToSpecialVarProcessor.containsKey(normalized) ? mapVariableNameToSpecialVarProcessor.get(normalized). stream().filter(x -> x.isAllowed(this)).findFirst().orElse(null) : null; if (processor != null) { return processor.getVariable(normalized, this); } final Value val = getLocalVariable(normalized); if (val != null) { return val; } Value result = globalVarTable.get(normalized); if (result == null && !enforceUnknownVarAsNull && this.unknownVariableAsFalse) { logDebug("Unknown variable '" + name + "' is replaced by FALSE!"); result = Value.BOOLEAN_FALSE; } return result; } /** * Check that there is a global variable with such name. * * @param variableName a name to be checked, can be null * @return false if there is not such variable or it is null, true if such global or special variable exists */ public boolean isGlobalVariable(final String variableName) { boolean result = false; if (variableName != null) { final String normalized = PreprocessorUtils.normalizeVariableName(variableName); result = this.globalVarTable.containsKey(normalized) || mapVariableNameToSpecialVarProcessor.containsKey(normalized); } return result; } /** * Check that there is a local variable with such name. * * @param variableName a name to be checked, can be null * @return false if there is not such variable or it is null, true if such local variable exists */ public boolean isLocalVariable(final String variableName) { boolean result = false; if (variableName != null) { final String normalized = PreprocessorUtils.normalizeVariableName(variableName); result = this.localVarTable.containsKey(normalized); } return result; } /** * It allows to create a File object for its path subject to the destination directory path * * @param path the path to the file, it must not be null * @return a generated File object for the path */ public File createDestinationFileForPath(final String path) { requireNonNull(path, "Path is null"); if (path.isEmpty()) { throw makeException("File name is empty", null); } return new File(this.getTarget(), path); } /** * Ensure that the file is in the project folder hierarchy. * * @param file the file to be checked * @return true if there is no info about hierarchy or the file in the hierarchy, false if the file is outbounds * @since 7.2.1 */ public boolean isFileInBaseDir(final File file) { final String normalizedPath = FilenameUtils.normalizeNoEndSeparator(file.getAbsolutePath()); return normalizedPath.startsWith( FilenameUtils.normalizeNoEndSeparator(this.baseDir.getAbsolutePath())); } /** * It finds file among source folders, the file can be found only among source folders and * any outside place is disabled for security purposes. * * @param path the file path to find, it must not be null and must be existing file * @return found existing file object for the path, must not be null */ public File findFileInSources(final String path) { return this.findFileInSources(path, true); } /** * It finds file among source folders, the file can be found only among source folders and * any outside place is disabled for security purposes. * * @param path the file path to find, it must not be null and must be existing file * @param mustExist if true then the file must exist, false otherwise * @return created file object for the path * @since 7.2.1 */ public File findFileInSources(final String path, final boolean mustExist) { if (path == null) { throw makeException("File path is null", null); } if (path.trim().isEmpty()) { throw makeException("File path is empty", null); } File result = null; final TextFileDataContainer theFile = this.getPreprocessingState().peekIncludeStackFile(); final String parentDir = theFile == null ? null : theFile.getFile().getParent(); final File resultFile = new File(path); if (resultFile.isAbsolute()) { // absolute path // check that the file is a child of a preprocessing source root else usage of the file is prohibited final String normalizedPath = FilenameUtils.normalizeNoEndSeparator(resultFile.getAbsolutePath()); for (final SourceFolder root : getSources()) { if (normalizedPath.startsWith(root.getNormalizedAbsolutePath(true))) { result = resultFile; break; } } if (result == null) { throw makeException("Can't find file for path '" + path + "' in preprocessing source folders, allowed usage only files in preprocessing source folders!", null); } else if (!result.isFile()) { throw makeException("File '" + result + "' is either not found or not a file", null); } } else if (parentDir != null) { // relative path result = new File(parentDir, path); } else { final List setOfFoundFiles = new ArrayList<>(); getSources().stream().map((root) -> new File(root.getAsFile(), path)) .filter((variant) -> (variant.exists() && variant.isFile())).forEachOrdered( setOfFoundFiles::add); if (setOfFoundFiles.size() == 1) { result = setOfFoundFiles.get(0); } else if (setOfFoundFiles.isEmpty()) { result = null; } else { throw makeException( "Found several variants for path '" + path + "' in different source roots", null); } if (result == null) { throw makeException("Can't find file for path '" + path + "' among source files registered for preprocessing.", null); } else if (mustExist && !result.isFile()) { throw makeException("File '" + PreprocessorUtils.getFilePath(result) + "' is either not found or not a file", null); } } return result; } /** * Add a configuration file, it is a file which contains directives and global variable definitions * * @param file a file, it must not be null */ public void registerConfigFile(final File file) { requireNonNull(file, "File is null"); this.configFiles.add(file.isAbsolute() ? file : new File(this.getBaseDir(), file.getPath())); } /** * Generate new preprocessing state object, also the new preprocessing state will be saved as the current one in the context * * @param fileContainer a file container which will be using the preprocessor state, it must not be null * @param phaseIndex index of phase (0 - global, 1 - preprocessing) * @return new generated preprocessor state * @throws IOException it will be throws if there is any error in opening and reading operations */ public PreprocessingState produceNewPreprocessingState(final FileInfoContainer fileContainer, final int phaseIndex) throws IOException { requireNonNull(fileContainer, "File container is null"); if (verbose) { if (phaseIndex == 0) { logInfo("Start search global definitions in '" + PreprocessorUtils.getFilePath(fileContainer.getSourceFile()) + '\''); } else { logInfo( "Start preprocessing '" + PreprocessorUtils.getFilePath(fileContainer.getSourceFile()) + '\''); } } this.preprocessingState.set(this.makeNewPreprocessorState(fileContainer)); return this.getPreprocessingState(); } protected PreprocessingState makeNewPreprocessorState(final Charset sourceEncoding, final Charset targetEncoding) { return new PreprocessingState(this, sourceEncoding, targetEncoding); } protected PreprocessingState makeNewPreprocessorState(final FileInfoContainer fileContainer) throws IOException { return new PreprocessingState( this, fileContainer, getSourceEncoding(), getTargetEncoding(), this.isDontOverwriteSameContent() ); } protected PreprocessingState makeNewPreprocessorState(final FileInfoContainer fileContainer, final TextFileDataContainer textFileDataContainer) { return new PreprocessingState( this, fileContainer, textFileDataContainer, this.getSourceEncoding(), this.getTargetEncoding(), this.isDontOverwriteSameContent() ); } /** * Generate new preprocessing state for a file container and a text container, also the new preprocessing state will be saved as the current one in the context * * @param fileContainer the file container to be used to create the new preprocessing state, it must not be null * @param textContainer the text container to be used to create the new preprocessing state, it must not be null * @return new generated preprocessing state */ public PreprocessingState produceNewPreprocessingState(final FileInfoContainer fileContainer, final TextFileDataContainer textContainer) { this.preprocessingState.set( this.makeNewPreprocessorState(fileContainer, textContainer)); return this.getPreprocessingState(); } /** * Get the last generated preprocessing state, it is the current one * * @return the last generated preprocessing state */ public PreprocessingState getPreprocessingState() { return this.preprocessingState.get(); } /** * Prepare exception with message and cause, or return cause if it is a preprocessor exception * * @param text the message text, must not be null * @param cause the cause, it can be null * @return prepared exception with additional information */ public PreprocessorException makeException(final String text, final Throwable cause) { if (cause instanceof PreprocessorException) { return (PreprocessorException) cause; } final FilePositionInfo[] includeStack; final String sourceLine; includeStack = this.getPreprocessingState().makeIncludeStack(); sourceLine = this.getPreprocessingState().getLastReadString(); return new PreprocessorException(text, sourceLine, includeStack, cause); } public void logForVerbose(final String str) { if (isVerbose()) { final String stack; stack = makeStackView(this.currentInCloneSource, this.cloned, this.getPreprocessingState().getIncludeStack()); this.logInfo(str + (stack.isEmpty() ? ' ' : '\n') + stack); } } public final static class SourceFolder { private final String path; private final File pathFile; public SourceFolder(final File baseDir, final String path) { this.path = requireNonNull(path); final File pathAsFile = new File(path); this.pathFile = pathAsFile.isAbsolute() ? pathAsFile : new File(baseDir, path); } public String getAsString() { return this.path; } public File getAsFile() { return this.pathFile; } public String getNormalizedAbsolutePath(final boolean separatorCharEnded) { String result = FilenameUtils.normalizeNoEndSeparator(this.pathFile.getAbsolutePath()); if (separatorCharEnded) { result += File.separatorChar; } return result; } @Override public String toString() { return String.format("%s[%s]", this.getClass().getSimpleName(), this.path); } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/context/PreprocessorContextAware.java ================================================ package com.igormaznitsa.jcp.context; /** * Listener for preprocessor context work states. * * @since 7.3.0 */ public interface PreprocessorContextAware { /** * Called when context started. * * @param context the source context, must not be null */ default void onContextStarted(PreprocessorContext context) { } /** * Called when context work ended. * * @param context the source context, must not be null * @param error the error if it was thrown during context execution. */ default void onContextStopped(PreprocessorContext context, Throwable error) { } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/context/SpecialVariableProcessor.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.context; import com.igormaznitsa.jcp.expression.Value; import java.util.Set; /** * The interface describes a special variable processor which will be called for * variables met by a preprocessor in expressions * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public interface SpecialVariableProcessor extends PreprocessorContextAware, ExecutionAllowable { /** * Get all variable names allowed by the processor as an array, all names must * be in lower case * * @return allowed variable names as a String array */ Set getVariableNames(); @Override default boolean isAllowed(PreprocessorContext context) { return true; } /** * Get the value for the variable * * @param varName the variable name, must not be null * @param context the preprocessor context, it can be null * @return the value, it must not return null because it will notified * preprocessor that it supports the variable */ Value getVariable(String varName, PreprocessorContext context); /** * Set a value to the variable * * @param varName the variable name, must not be null * @param value the value to be set to the variable, must not be null * @param context the preprocessor context, it can be null */ void setVariable(String varName, Value value, PreprocessorContext context); } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/AbortDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.utils.PreprocessorUtils; /** * The class implements the //#abort directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class AbortDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "abort"; } @Override public String getReference() { return "abort preprocessing and print message (macros allowed)"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.TAIL; } @Override public AfterDirectiveProcessingBehaviour execute(final String rawTail, final PreprocessorContext context) { final String normal = (!rawTail.isEmpty() && Character.isSpaceChar(rawTail.charAt(0))) ? rawTail.substring(1) : rawTail; final String message = "ABORT: " + PreprocessorUtils.processMacroses(normal, context); if (context.isVerbose()) { context.logForVerbose(message); } else { context.logInfo(message); } context.getPreprocessingState().getPreprocessingFlags().add(PreprocessingFlag.ABORT_PROCESSING); return AfterDirectiveProcessingBehaviour.READ_NEXT_LINE; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/AbstractDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.util.ArrayList; import java.util.List; /** * The class is the abstract parent for all classes process preprocessor * directives * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public abstract class AbstractDirectiveHandler { /** * The common preprocessor prefix for all directives */ public static final String DIRECTIVE_PREFIX = "//#"; /** * The prefix for lines to be kept by preprocessor */ public static final String PREFIX_FOR_KEEPING_LINES = "//JCP> "; /** * The prefix for lines to be kept by preprocessor, which contain processed * directives */ public static final String PREFIX_FOR_KEEPING_LINES_PROCESSED_DIRECTIVES = "//JCP! "; /** * The prefix for one line comment */ public static final String ONE_LINE_COMMENT = "//"; public static List findAllDirectives() { final List result = new ArrayList<>(); result.add(new LocalDirectiveHandler()); result.add(new IfDefinedDirectiveHandler()); result.add(new IfNDefDirectiveHandler()); result.add(new IfDefDirectiveHandler()); result.add(new IfDirectiveHandler()); result.add(new ElseDirectiveHandler()); result.add(new EndIfDirectiveHandler()); result.add(new WhileDirectiveHandler()); result.add(new BreakDirectiveHandler()); result.add(new ContinueDirectiveHandler()); result.add(new EndDirectiveHandler()); result.add(new ExitIfDirectiveHandler()); result.add(new ExitDirectiveHandler()); result.add(new OutdirDirectiveHandler()); result.add(new OutEnabledDirectiveHandler()); result.add(new OutNameDirectiveHandler()); result.add(new OutDisabledDirectiveHandler()); result.add(new CommentNextLineDirectiveHandler()); result.add(new DefinelDirectiveHandler()); result.add(new DefineDirectiveHandler()); result.add(new UndefDirectiveHandler()); result.add(new FlushDirectiveHandler()); result.add(new IncludeDirectiveHandler()); result.add(new ActionDirectiveHandler()); result.add(new PostfixDirectiveHandler()); result.add(new PrefixDirectiveHandler()); result.add(new GlobalDirectiveHandler()); result.add(new GlobalElseDirectiveHandler()); result.add(new GlobalEndIfDirectiveHandler()); result.add(new GlobalIfDirectiveHandler()); result.add(new ExcludeIfDirectiveHandler()); result.add(new ErrorDirectiveHandler()); result.add(new WarningDirectiveHandler()); result.add(new EchoDirectiveHandler()); result.add(new MsgDirectiveHandler()); result.add(new NoAutoFlushHandler()); result.add(new AbortDirectiveHandler()); return result; } /** * Get the name of the directive without prefix * * @return the directive name, must not be null */ public abstract String getName(); /** * Get the directive reference, it will be printed for a help request * * @return the directive reference as a String, must not be null */ public abstract String getReference(); /** * Get the directive name with prefix * * @return the full directive name (it including prefix) */ public String getFullName() { return DIRECTIVE_PREFIX + getName(); } /** * Get the argument type needed by the directive * * @return the argument type needed by the directive, it can't be null */ public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.NONE; } /** * Execute directive * * @param tailString the tail of the string where the directive has been met, must not be null but can be empty * @param context the preprocessor context * @return the needed preprocessor behavior, must not be null */ public abstract AfterDirectiveProcessingBehaviour execute(String tailString, PreprocessorContext context); /** * Shows that the directive can be executed only when the preprocessing n * active state i.e. if it is in active block //#if..//#endif of //#while * * @return true if the directive can be executed only if it is in active * block, else the directive will be called in any case */ public boolean executeOnlyWhenExecutionAllowed() { return true; } /** * Shows that the directive can be executed during a global preprocessing * phase * * @return true if the directive allows the global directive phase, false if * the directive must be ignored during that phase */ public boolean isGlobalPhaseAllowed() { return false; } /** * Shows that the directive can be executed during the second preprocessing * phase * * @return true uf the directive can be executed during the second * preprocessing phase else false if the directive must be ignored */ public boolean isPreprocessingPhaseAllowed() { return true; } /** * Check that the directive is deprecated one and can be removed in a next release * * @return true if the directive is deprecated, false otherwise */ public boolean isDeprecated() { return false; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/ActionDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.exceptions.FilePositionInfo; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.ExpressionItem; import com.igormaznitsa.jcp.expression.ExpressionParser; import com.igormaznitsa.jcp.expression.ExpressionTree; import com.igormaznitsa.jcp.extension.PreprocessorExtension; import java.io.IOException; import java.io.PushbackReader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * The class implements the //#action directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class ActionDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "action"; } @Override public String getReference() { return "call extension action with args"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.MULTI_EXPRESSION; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final List extensions = context.getPreprocessorExtensions(); if (extensions.isEmpty()) { throw context.makeException( "Detected action directive but there is no any provided action preprocessor extension to process it [" + string + ']', null); } try { final List args = parseString(string, context); final PreprocessorExtension extension = extensions.stream() .filter(x -> x.isAllowed(context)) .filter(x -> x.hasAction(args.size())) .findFirst().orElse(null); if (extension == null) { throw context.makeException( "Can't find any preprocessor extension to process action: " + string, null); } if (!extension.processAction(context, args.stream().map(x -> Expression.evalTree(x, context)).collect( Collectors.toList()))) { throw context.makeException("Unable to process an action", null); } } catch (IOException ex) { throw context.makeException("Unexpected string detected [" + string + ']', ex); } return AfterDirectiveProcessingBehaviour.PROCESSED; } private List parseString(final String str, final PreprocessorContext context) throws IOException { final ExpressionParser parser = ExpressionParser.getInstance(); final PushbackReader reader = new PushbackReader(new StringReader(str)); final List result = new ArrayList<>(); final PreprocessingState state = context.getPreprocessingState(); final FilePositionInfo[] stack; final String sources; stack = state.makeIncludeStack(); sources = state.getLastReadString(); while (!Thread.currentThread().isInterrupted()) { final ExpressionTree tree; tree = new ExpressionTree(stack, sources); final ExpressionItem delimiter = parser.readExpression(reader, tree, context, false, true); if (delimiter != null && ExpressionParser.SpecialItem.COMMA != delimiter) { throw context.makeException("Wrong argument format detected", null); } if (tree.isEmpty()) { if (delimiter == null) { break; } else { throw context.makeException("Empty argument", null); } } else { result.add(tree); if (delimiter == null) { break; } } } return result; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/AfterDirectiveProcessingBehaviour.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; /** * The enumeration contains flags after directive processing behavior * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public enum AfterDirectiveProcessingBehaviour { /** * Notify preprocessor that a directive has been processed successfully */ PROCESSED, /** * Notify preprocessor that a directive has been processed and need to read * the next line immediately */ READ_NEXT_LINE, /** * Notify preprocessor that the directive has not been processed */ NOT_PROCESSED, /** * Notify preprocessor that the line should be commented */ SHOULD_BE_COMMENTED } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/BreakDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.util.Objects; /** * The class implements the //#break directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class BreakDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "break"; } @Override public String getReference() { return "break from " + DIRECTIVE_PREFIX + "while..." + DIRECTIVE_PREFIX + "end loop"; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = Objects.requireNonNull(context.getPreprocessingState()); if (state.isWhileStackEmpty()) { throw context .makeException("Detected " + getFullName() + " without " + DIRECTIVE_PREFIX + "while", null); } state.getPreprocessingFlags().add(PreprocessingFlag.BREAK_COMMAND); return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/CommentNextLineDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The class implements the //#// directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class CommentNextLineDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "//"; } @Override public String getReference() { return "comment line after"; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { context.getPreprocessingState().getPreprocessingFlags() .add(PreprocessingFlag.COMMENT_NEXT_LINE); return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/ContinueDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.TextFileDataContainer; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.util.Objects; /** * The class implements the //#continue directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class ContinueDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "continue"; } @Override public String getReference() { return "skip to next" + DIRECTIVE_PREFIX + "while iteration"; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); if (state.isWhileStackEmpty()) { throw context .makeException("Detected " + getFullName() + " without " + DIRECTIVE_PREFIX + "while", null); } final TextFileDataContainer whileContainer = Objects.requireNonNull(state.peekWhile()); state.popAllIFUntilContainerWithFile(whileContainer); state.popWhile(); state.goToString(whileContainer.getNextStringIndex()); return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/DefineDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.ExpressionItem; import com.igormaznitsa.jcp.expression.ExpressionItemType; import com.igormaznitsa.jcp.expression.ExpressionParser; import com.igormaznitsa.jcp.expression.ExpressionTree; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.Variable; import java.io.IOException; import java.util.Objects; /** * The class implements the //#define directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class DefineDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "define"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.TAIL; } @Override public String getReference() { return "add global BOOL variable (default TRUE or set from expression)"; } protected void process(final PreprocessorContext context, final String varName, final Value value, final boolean exists) { if (exists) { context.logWarning("Variable '" + varName + "' already defined"); } context.setGlobalVariable(varName, value); } @Override public AfterDirectiveProcessingBehaviour execute(final String rawTail, final PreprocessorContext context) { try { final String trimmedTail = rawTail.trim(); final int spaceIndex = trimmedTail.indexOf(' '); final String name; final String expression; if (spaceIndex > 0) { name = trimmedTail.substring(0, spaceIndex).trim(); final String trimmed = trimmedTail.substring(spaceIndex).trim(); expression = trimmed.isEmpty() || trimmed.startsWith("//") || trimmed.startsWith("/*") ? null : trimmed; } else { name = trimmedTail; expression = null; } final ExpressionTree nameTree = ExpressionParser.getInstance().parse(name, context); if (nameTree.isEmpty()) { throw context.makeException("Var name is empty", null); } final ExpressionItem item = Objects.requireNonNull(nameTree.getRoot().getItem()); if (item.getExpressionItemType() != ExpressionItemType.VARIABLE) { throw context.makeException("Can't recognize variable name [" + name + ']', null); } final Value value; if (expression != null) { value = Expression.evalExpression(expression, context); } else { value = Value.valueOf(Boolean.TRUE); } process(context, ((Variable) item).getName(), value, context.findVariableForName(name, true) != null); } catch (IOException ex) { throw context.makeException("Unexpected exception", ex); } return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/DefinelDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the //#definel directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class DefinelDirectiveHandler extends DefineDirectiveHandler { @Override public String getName() { return "definel"; } @Override public String getReference() { return "add local BOOL variable (default TRUE or from expression)"; } @Override protected void process(final PreprocessorContext context, final String varName, final Value value, final boolean exists) { context.setLocalVariable(varName, value); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/DirectiveArgumentType.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; /** * The enumeration contains possible argument types are being used by directives * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public enum DirectiveArgumentType { NONE(""), STRING("STRING"), TAIL("TAIL"), BOOLEAN("BOOLEAN"), VARNAME("VAR"), EXPRESSION("EXPR"), MULTI_EXPRESSION("EXPR1,EXPR2...EXPRn"), SET("VAR=EXPR"), ON_OFF("[+|-]"); private final String str; DirectiveArgumentType(final String str) { this.str = str; } public String getAsText() { return this.str; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/EchoDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.utils.PreprocessorUtils; /** * The class implements //#assert directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class EchoDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "echo"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.TAIL; } @Override public String getReference() { return "log info message (macros allowed)"; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { context.logInfo(PreprocessorUtils.processMacroses(string.trim(), context)); return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/ElseDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The class implements the //#else directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class ElseDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "else"; } @Override public String getReference() { return "invert " + DIRECTIVE_PREFIX + "if condition result"; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); if (state.isIfStackEmpty()) { throw context .makeException("Detected " + getFullName() + " without " + DIRECTIVE_PREFIX + "if", null); } if (state.isAtActiveIf()) { if (state.getPreprocessingFlags().contains(PreprocessingFlag.IF_CONDITION_FALSE)) { state.getPreprocessingFlags().remove(PreprocessingFlag.IF_CONDITION_FALSE); } else { state.getPreprocessingFlags().add(PreprocessingFlag.IF_CONDITION_FALSE); } } return AfterDirectiveProcessingBehaviour.PROCESSED; } @Override public boolean executeOnlyWhenExecutionAllowed() { return false; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/EndDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.containers.TextFileDataContainer; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.util.Objects; /** * The class implements the //#end directive * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class EndDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "end"; } @Override public String getReference() { return DIRECTIVE_PREFIX + "while loop end, continue next iteration"; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); if (state.isWhileStackEmpty()) { throw context .makeException("Detected " + getFullName() + " without " + DIRECTIVE_PREFIX + "while", null); } if (state.isDirectiveCanBeProcessedIgnoreBreak()) { final TextFileDataContainer thisWhile = Objects.requireNonNull(state.peekWhile(), "'WHILE' stack is empty!"); final boolean breakIsSet = state.getPreprocessingFlags().contains(PreprocessingFlag.BREAK_COMMAND); state.popWhile(); if (!breakIsSet) { state.goToString(thisWhile.getNextStringIndex()); } } else { state.popWhile(); } return AfterDirectiveProcessingBehaviour.PROCESSED; } @Override public boolean executeOnlyWhenExecutionAllowed() { return false; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/EndIfDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The class implements the //#endif directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class EndIfDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "endif"; } @Override public boolean executeOnlyWhenExecutionAllowed() { return false; } @Override public String getReference() { return "end of " + DIRECTIVE_PREFIX + "if..." + getFullName() + " block"; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); if (state.isIfStackEmpty()) { throw context .makeException("Detected " + getFullName() + " without " + DIRECTIVE_PREFIX + "if", null); } if (!state.isDirectiveCanBeProcessed() && state.isAtActiveIf()) { state.getPreprocessingFlags().remove(PreprocessingFlag.IF_CONDITION_FALSE); } state.popIf(); return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/ErrorDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.utils.PreprocessorUtils; /** * The class implements //#error directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class ErrorDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "error"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.EXPRESSION; } @Override public String getReference() { return "throw fatal preprocessor error with message and abort"; } protected void process(final PreprocessorContext context, final String message) { final String text = PreprocessorUtils.processMacroses(message, context); context.logError(text); throw context.makeException(text, null); } @Override public AfterDirectiveProcessingBehaviour execute(final String trimmedString, final PreprocessorContext context) { final String message = trimmedString.isEmpty() ? "Thrown fatal error" : Expression.evalExpression(trimmedString, context).toString(); process(context, message); return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/ExcludeIfDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static java.util.Objects.requireNonNull; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The class implements the //#excludeif directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class ExcludeIfDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "excludeif"; } @Override public String getReference() { return "ignore file if argument is TRUE"; } @Override public boolean isGlobalPhaseAllowed() { return true; } @Override public boolean isPreprocessingPhaseAllowed() { return false; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.BOOLEAN; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); state.pushExcludeIfData(state.getRootFileInfo(), string, requireNonNull(state.peekIncludeStackFile(), "'IF' stack is empty!") .getLastReadStringIndex()); return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/ExitDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The class implements the //#exit directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class ExitDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "exit"; } @Override public String getReference() { return "immediately end file preprocessing, return to caller"; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); state.getPreprocessingFlags().add(PreprocessingFlag.END_PROCESSING); if (context.isVerbose()) { context.logForVerbose("Detected " + getFullName()); } return AfterDirectiveProcessingBehaviour.READ_NEXT_LINE; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/ExitIfDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; /** * The class implements the //#exitif directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class ExitIfDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "exitif"; } @Override public String getReference() { return "conditionally end file preprocessing, return to caller"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.BOOLEAN; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); AfterDirectiveProcessingBehaviour result = AfterDirectiveProcessingBehaviour.PROCESSED; // To end processing the file processing immediately if the value is true final Value condition = Expression.evalExpression(string, context); if (condition.getType() != ValueType.BOOLEAN) { throw context.makeException(getFullName() + " needs boolean argument", null); } if (((Boolean) condition.getValue())) { state.getPreprocessingFlags().add(PreprocessingFlag.END_PROCESSING); result = AfterDirectiveProcessingBehaviour.READ_NEXT_LINE; if (context.isVerbose()) { context.logForVerbose("Detected " + getFullName() + " with active flag"); } } return result; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/FlushDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static com.igormaznitsa.jcp.utils.PreprocessorUtils.findActiveFileInfoContainer; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.io.File; import java.io.IOException; /** * The class implements the //#flush directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class FlushDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "flush"; } @Override public String getReference() { return "flush current text buffers to file and clear them"; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); if (!context.isDryRun()) { final File outFile = context .createDestinationFileForPath(state.getRootFileInfo().makeTargetFilePathAsString()); try { if (context.isVerbose()) { context.logForVerbose("Flushing buffers into file '" + outFile + '\''); } final boolean saved = state.saveBuffersToFile(outFile, context.getKeepComments()); if (context.isVerbose()) { context.logForVerbose( "Content was " + (saved ? "saved" : "not saved") + " into file '" + outFile + "'"); } findActiveFileInfoContainer(context) .ifPresent(f -> f.getGeneratedResources().add(outFile)); state.resetPrinters(); } catch (IOException ex) { throw context.makeException("Can't flush text buffers", ex); } } return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/GlobalDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.utils.PreprocessorUtils; /** * The class implements the //#global directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class GlobalDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "global"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.SET; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { processDefinition(string, context); return AfterDirectiveProcessingBehaviour.PROCESSED; } @Override public String getReference() { return "set or define a global (including special) variable"; } @Override public boolean isGlobalPhaseAllowed() { return true; } @Override public boolean isPreprocessingPhaseAllowed() { return false; } private void processDefinition(final String string, final PreprocessorContext context) { final String[] split = PreprocessorUtils.splitForEqualChar(string); if (split.length != 2) { throw context.makeException("Can't find expression [" + string + ']', null); } final String name = split[0].trim(); final Value newValue = Expression.evalExpression(split[1].trim(), context); context.setGlobalVariable(name, newValue); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/GlobalElseDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The class implements the //#_else directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class GlobalElseDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "_else"; } @Override public String getReference() { return "invert " + DIRECTIVE_PREFIX + "_if condition result"; } @Override public boolean isGlobalPhaseAllowed() { return true; } @Override public boolean isPreprocessingPhaseAllowed() { return false; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); if (state.isIfStackEmpty()) { throw context .makeException("Detected " + getFullName() + " without " + DIRECTIVE_PREFIX + "_if", null); } if (state.isAtActiveIf()) { if (state.getPreprocessingFlags().contains(PreprocessingFlag.IF_CONDITION_FALSE)) { state.getPreprocessingFlags().remove(PreprocessingFlag.IF_CONDITION_FALSE); } else { state.getPreprocessingFlags().add(PreprocessingFlag.IF_CONDITION_FALSE); } } return AfterDirectiveProcessingBehaviour.PROCESSED; } @Override public boolean executeOnlyWhenExecutionAllowed() { return false; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/GlobalEndIfDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The class implements the //#_endif directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class GlobalEndIfDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "_endif"; } @Override public boolean executeOnlyWhenExecutionAllowed() { return false; } @Override public String getReference() { return "end " + DIRECTIVE_PREFIX + "_if block"; } @Override public boolean isGlobalPhaseAllowed() { return true; } @Override public boolean isPreprocessingPhaseAllowed() { return false; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); if (state.isIfStackEmpty()) { throw context .makeException("Detected " + getFullName() + " without " + DIRECTIVE_PREFIX + "_if", null); } if (!state.isDirectiveCanBeProcessed() && state.isAtActiveIf()) { state.getPreprocessingFlags().remove(PreprocessingFlag.IF_CONDITION_FALSE); } state.popIf(); return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/GlobalIfDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; /** * The class implements the //#_if directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class GlobalIfDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "_if"; } @Override public String getReference() { return "start " + DIRECTIVE_PREFIX + getFullName() + " block"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.BOOLEAN; } @Override public boolean executeOnlyWhenExecutionAllowed() { return false; } @Override public boolean isGlobalPhaseAllowed() { return true; } @Override public boolean isPreprocessingPhaseAllowed() { return false; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); if (state.isDirectiveCanBeProcessed()) { final Value expressionResult = Expression.evalExpression(string, context); if (expressionResult.getType() != ValueType.BOOLEAN) { throw context.makeException("Non boolean argument", null); } state.pushIf(true); if (!expressionResult.asBoolean()) { state.getPreprocessingFlags().add(PreprocessingFlag.IF_CONDITION_FALSE); } } else { state.pushIf(false); } return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/IfDefDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; /** * The class implements short synonym for the //#ifdefined directive * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class IfDefDirectiveHandler extends IfDefinedDirectiveHandler { @Override public String getName() { return "ifdef"; } @Override public String getReference() { return "short form of " + DIRECTIVE_PREFIX + super.getName(); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/IfDefinedDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The class implements the //#ifdefined directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class IfDefinedDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "ifdefined"; } @Override public String getReference() { return "check if variable exists in current context and start " + DIRECTIVE_PREFIX + "ifdefined.." + DIRECTIVE_PREFIX + "else.." + DIRECTIVE_PREFIX + "endif block"; } protected boolean postprocessFlag(final boolean variableExists) { return !variableExists; } @Override public boolean executeOnlyWhenExecutionAllowed() { return false; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.VARNAME; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); if (state.isDirectiveCanBeProcessed()) { if (string.isEmpty()) { throw context.makeException(getFullName() + " needs variable name", null); } state.pushIf(true); final boolean variableExists = context.findVariableForName(string, true) != null; if (postprocessFlag(variableExists)) { state.getPreprocessingFlags().add(PreprocessingFlag.IF_CONDITION_FALSE); } } else { state.pushIf(false); } return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/IfDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; /** * The class implements the //#if directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class IfDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "if"; } @Override public String getReference() { return "start " + DIRECTIVE_PREFIX + "if.." + DIRECTIVE_PREFIX + "else.." + DIRECTIVE_PREFIX + "endif block"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.BOOLEAN; } @Override public boolean executeOnlyWhenExecutionAllowed() { return false; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); if (state.isDirectiveCanBeProcessed()) { final Value expressionResult = Expression.evalExpression(string, context); if (expressionResult.getType() != ValueType.BOOLEAN) { throw context.makeException("Non boolean flag", null); } state.pushIf(true); if (!expressionResult.asBoolean()) { state.getPreprocessingFlags().add(PreprocessingFlag.IF_CONDITION_FALSE); } } else { state.pushIf(false); } return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/IfNDefDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; /** * The class implements the //#ifndef directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class IfNDefDirectiveHandler extends IfDefinedDirectiveHandler { @Override public String getName() { return "ifndef"; } @Override protected boolean postprocessFlag(final boolean variableExists) { return variableExists; } @Override public String getReference() { return "same as " + DIRECTIVE_PREFIX + super.getName() + " but triggers if variable is undefined"; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/IncludeDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static com.igormaznitsa.jcp.utils.PreprocessorUtils.findActiveFileInfoContainer; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import java.io.File; import java.io.IOException; /** * The class implements the //#include directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class IncludeDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "include"; } @Override public String getReference() { return "include file content in current preprocessing context"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.STRING; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); final Value includingFilePath = Expression.evalExpression(string, context); final String filePath = includingFilePath.toString(); try { final File fileToInclude = context.findFileInSources(filePath); if (context.isVerbose()) { context.logForVerbose("Including file '" + fileToInclude.getCanonicalPath() + '\''); } state.openFile(fileToInclude); findActiveFileInfoContainer(context) .ifPresent(f -> f.getIncludedSources().add(fileToInclude)); } catch (IOException ex) { throw context.makeException("Can't open file '" + filePath + '\'', ex); } return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/LocalDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.utils.PreprocessorUtils; /** * The class implements the //#local directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class LocalDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "local"; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { processLocalDefinition(string, context); return AfterDirectiveProcessingBehaviour.PROCESSED; } @Override public String getReference() { return "define local variable (file-scoped, no special vars)"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.SET; } private void processLocalDefinition(final String string, final PreprocessorContext context) { final String[] split = PreprocessorUtils.splitForEqualChar(string); if (split.length != 2) { throw context.makeException("Can't find expression", null); } final String name = split[0]; final Value value = Expression.evalExpression(split[1], context); context.setLocalVariable(name, value); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/MsgDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.utils.PreprocessorUtils; /** * The class implements //#msg directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class MsgDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "msg"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.TAIL; } @Override public String getReference() { return "log info message with macros, add include stack if verbose"; } @Override public AfterDirectiveProcessingBehaviour execute(final String rawTail, final PreprocessorContext context) { final String normal = (!rawTail.isEmpty() && Character.isSpaceChar(rawTail.charAt(0))) ? rawTail.substring(1) : rawTail; final String message = PreprocessorUtils.processMacroses(normal, context); if (context.isVerbose()) { context.logForVerbose(message); } else { context.logInfo(message); } return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/NoAutoFlushHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.util.Objects; /** * The class implements the //#noautoflush directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class NoAutoFlushHandler extends AbstractDirectiveHandler { @Override public String getName() { return "noautoflush"; } @Override public String getReference() { return "disable auto-flush of buffers at EOF"; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); if (context.isVerbose()) { context.logForVerbose("Disabling auto-flush"); } Objects.requireNonNull(state.peekIncludeStackFile(), "File stack is empty!").disableAutoFlush(); return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/OutDisabledDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The class implements the //#- directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class OutDisabledDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "-"; } @Override public String getReference() { return "disable text output to buffers"; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { context.getPreprocessingState().getPreprocessingFlags() .add(PreprocessingFlag.TEXT_OUTPUT_DISABLED); return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/OutEnabledDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The class implements the //#+ directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class OutEnabledDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "+"; } @Override public String getReference() { return "enable text output to buffers"; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { context.getPreprocessingState().getPreprocessingFlags() .remove(PreprocessingFlag.TEXT_OUTPUT_DISABLED); return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/OutNameDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.JCPSpecialVariableProcessor; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the //#outname directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class OutNameDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "outname"; } @Override public String getReference() { return "change target file name (same as set the special var '" + JCPSpecialVariableProcessor.VAR_DEST_FILE_NAME + "')"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.STRING; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final Value fileName = Expression.evalExpression(string, context); final String fileNameAsStr = fileName.toString(); if (context.isVerbose()) { context.logForVerbose("Change target file name to '" + fileNameAsStr + "'"); } context.getPreprocessingState().getRootFileInfo().setTargetFileName(fileNameAsStr); return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/OutdirDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.JCPSpecialVariableProcessor; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the //#outdir directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class OutdirDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "outdir"; } @Override public String getReference() { return "change target file folder (same as set the special var '" + JCPSpecialVariableProcessor.VAR_DEST_DIR + "')"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.STRING; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final Value name = Expression.evalExpression(string, context); final String nameAsString = name.toString(); if (context.isVerbose()) { context.logForVerbose("Change result file folder '" + nameAsString + "'"); } context.getPreprocessingState().getRootFileInfo().setTargetFolder(nameAsString); return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/PostfixDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The class implements the //#postfix[+|-] directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class PostfixDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "postfix"; } @Override public String getReference() { return "enable (+) or disable (-) output to postfix buffer"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.ON_OFF; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); if (!string.isEmpty()) { switch (string.charAt(0)) { case '+': { state.selectPrinter(PreprocessingState.PrinterType.POSTFIX); } break; case '-': { state.selectPrinter(PreprocessingState.PrinterType.NORMAL); } break; default: { throw context.makeException("Unsupported ending [" + string + ']', null); } } return AfterDirectiveProcessingBehaviour.PROCESSED; } throw context.makeException(getFullName() + " needs ending [+|-]", null); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/PrefixDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; /** * The class implements the //#prefix[+|-] directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class PrefixDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "prefix"; } @Override public String getReference() { return "enable (+) or disable (-) output to prefix buffer"; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.ON_OFF; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); if (!string.isEmpty()) { switch (string.charAt(0)) { case '+': { state.selectPrinter(PreprocessingState.PrinterType.PREFIX); } break; case '-': { state.selectPrinter(PreprocessingState.PrinterType.NORMAL); } break; default: { throw context.makeException("Unsupported ending [" + string + ']', null); } } return AfterDirectiveProcessingBehaviour.PROCESSED; } throw context.makeException(getFullName() + " needs ending [+|-]", null); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/UndefDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the //#undef directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class UndefDirectiveHandler extends DefineDirectiveHandler { @Override public String getName() { return "undef"; } @Override public String getReference() { return "undefine variable from context"; } @Override protected void process(final PreprocessorContext context, final String varName, final Value value, final boolean exists) { if (context.isLocalVariable(varName)) { context.removeLocalVariable(varName); } else if (context.isGlobalVariable(varName)) { context.removeGlobalVariable(varName); } else { throw context.makeException("Attempting to undefine unknown variable '" + value + "'", null); } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/WarningDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.utils.PreprocessorUtils; /** * The class implements //#warning directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class WarningDirectiveHandler extends ErrorDirectiveHandler { @Override public String getName() { return "warning"; } @Override public String getReference() { return "log warning message (macros allowed)"; } @Override protected void process(final PreprocessorContext context, final String message) { context.logWarning(PreprocessorUtils.processMacroses(message, context)); if (context.isVerbose()) { context.logForVerbose("Detected warning : " + message); } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/directives/WhileDirectiveHandler.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.containers.PreprocessingFlag; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; /** * The class implements the //#while directive handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class WhileDirectiveHandler extends AbstractDirectiveHandler { @Override public String getName() { return "while"; } @Override public String getReference() { return "start " + getFullName() + ".." + DIRECTIVE_PREFIX + "end loop"; } @Override public boolean executeOnlyWhenExecutionAllowed() { return false; } @Override public DirectiveArgumentType getArgumentType() { return DirectiveArgumentType.BOOLEAN; } @Override public AfterDirectiveProcessingBehaviour execute(final String string, final PreprocessorContext context) { final PreprocessingState state = context.getPreprocessingState(); if (state.isDirectiveCanBeProcessed()) { final Value condition = Expression.evalExpression(string, context); if (condition.getType() != ValueType.BOOLEAN) { throw context.makeException("Non boolean argument", null); } state.pushWhile(true); if (!condition.asBoolean()) { state.getPreprocessingFlags().add(PreprocessingFlag.BREAK_COMMAND); } } else { state.pushWhile(false); } return AfterDirectiveProcessingBehaviour.PROCESSED; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/exceptions/FilePositionInfo.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.exceptions; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.io.File; import java.util.Objects; /** * The class implements a file data storage where an exception can store a * snapshot of the current preprocessing file data * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class FilePositionInfo { /** * The preprocessing file */ private final File file; /** * The current string index in the file */ private final int stringIndex; public FilePositionInfo(final File file, final int stringIndex) { Objects.requireNonNull(file, "File is null"); this.file = file; this.stringIndex = stringIndex; } public File getFile() { return this.file; } /** * Get zero based line index * * @return zero based line index or -1 if there is no info */ public int getStringIndex() { return this.stringIndex < 0 ? -1 : this.stringIndex; } /** * Get line number, starting position is one * * @return line number started from one, -1 if there is no info */ public int getLineNumber() { return this.stringIndex < 0 ? -1 : this.stringIndex + 1; } public String toShortString() { return this.file.getName() + ':' + this.getLineNumber(); } @Override public String toString() { final String filePath = PreprocessorUtils.getFilePath(this.file); return filePath + ':' + this.getLineNumber(); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/exceptions/PreprocessorException.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.exceptions; import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; /** * The exception allows to save some useful data about preprocessing files like the current include stack and the error string index * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class PreprocessorException extends RuntimeException { private static final long serialVersionUID = 2857499664112391862L; private final String processingString; private final transient FilePositionInfo[] includeStack; public PreprocessorException(final String message, final String processedText, final FilePositionInfo[] includeStack, final Throwable cause) { super(message, cause); this.processingString = processedText; this.includeStack = includeStack == null ? new FilePositionInfo[0] : includeStack.clone(); } private static String makeStackView(final FilePositionInfo[] list, final char fill) { if (list == null || list.length == 0) { return ""; } final StringBuilder builder = new StringBuilder(); int tab = 5; builder.append(String.valueOf(fill).repeat(tab)); builder.append("{File chain}"); tab += 5; int fileIndex = 1; for (int i = list.length - 1; i >= 0; i--) { final FilePositionInfo cur = list[i]; builder.append('\n'); builder.append(String.valueOf(fill).repeat(Math.max(0, tab))); builder.append("└>"); builder.append(fileIndex++).append(". "); builder.append(cur.getFile().getName()).append(':').append(cur.getLineNumber()); tab += 3; } return builder.toString(); } public static PreprocessorException extractPreprocessorException(final Throwable thr) { if (thr == null) { return null; } Throwable result = thr; do { if (result instanceof PreprocessorException) { return (PreprocessorException) result; } result = result.getCause(); } while (result != null); return null; } public static String referenceAsString(final char fillChar, final Throwable thr) { if (thr == null) { return ""; } final StringWriter buffer = new StringWriter(1024); final PrintWriter out = new PrintWriter(buffer); final PreprocessorException pp = PreprocessorException.extractPreprocessorException(thr); if (pp == null) { out.println(thr.getMessage()); thr.printStackTrace(out); } else { out.println(pp.getMessage()); out.println(makeStackView(pp.getIncludeChain(), fillChar)); if (pp.getCause() != null) { pp.getCause().printStackTrace(out); } } return buffer.toString(); } public File getRootFile() { if (includeStack.length == 0) { return null; } else { return includeStack[includeStack.length - 1].getFile(); } } public File getProcessingFile() { if (includeStack.length == 0) { return null; } else { return includeStack[0].getFile(); } } public int getLineNumber() { if (includeStack.length == 0) { return -1; } else { return includeStack[0].getLineNumber(); } } public String getProcessingString() { return this.processingString; } private String convertIncludeStackToString() { final StringBuilder result = new StringBuilder(); for (int i = 0; i < this.includeStack.length; i++) { if (i > 0) { result.append("<-"); } result.append(this.includeStack[i].toString()); } return result.toString(); } public FilePositionInfo[] getIncludeChain() { return this.includeStack.clone(); } @Override public String toString() { return getMessage() + ", include stack: " + convertIncludeStackToString() + ", source line: " + this.processingString; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/Expression.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression; import static com.igormaznitsa.jcp.expression.ExpressionTreeElement.ANY_ARITY; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.exceptions.FilePositionInfo; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.functions.AbstractFunction; import com.igormaznitsa.jcp.expression.functions.FunctionDefinedByUser; import com.igormaznitsa.jcp.expression.operators.AbstractOperator; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; /** * The main class to calculate expressions * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class Expression { /** * Pre-created array for speed up operations */ private static final Class[] OPERATOR_SIGNATURE_1 = new Class[] {Value.class}; /** * Pre-created array for speed up operations */ private static final Class[] OPERATOR_SIGNATURE_2 = new Class[] {Value.class, Value.class}; /** * The variable contains the expression tree */ private final ExpressionTree expressionTree; private Expression(final ExpressionTree tree) { this.expressionTree = tree; } /** * Evaluate expression * * @param expression the expression as a String, must not be null * @param context a preprocessor context to be used for expression operations * @return the result as a Value object, it can't be null */ public static Value evalExpression(final String expression, final PreprocessorContext context) { try { final ExpressionTree tree = ExpressionParser.getInstance().parse(expression, context); return evalTree(tree, context); } catch (IOException unexpected) { throw context .makeException("[Expression]Wrong expression format detected [" + expression + ']', unexpected); } } /** * Evaluate an expression tree * * @param tree an expression tree, it must not be null * @param context a preprocessor context to be used for expression operations * @return the result as a Value object, it can't be null */ public static Value evalTree(final ExpressionTree tree, final PreprocessorContext context) { final Expression exp = new Expression(tree); return exp.eval(context); } private ExpressionTreeElement evalFunction( final ExpressionTreeElement treeElement, final PreprocessorContext context) { final AbstractFunction functionElement = (AbstractFunction) treeElement.getItem(); final List children = treeElement.extractEffectiveChildren(); if (!functionElement.getArity().contains(-1) && !functionElement.getArity().contains(children.size())) { throw context .makeException( "Can't find '" + functionElement.getName() + "' for arity " + children.size(), null); } final int arity = children.size(); final List arguments = new ArrayList<>(); final Class[] methodArguments = new Class[arity + 1]; methodArguments[0] = PreprocessorContext.class; final FilePositionInfo[] stack; final String sources; stack = context.getPreprocessingState().makeIncludeStack(); sources = context.getPreprocessingState().getLastReadString(); final StringBuilder signature = new StringBuilder(AbstractFunction.EXECUTION_PREFIX); for (int i = 1; i <= arity; i++) { methodArguments[i] = Value.class; } for (int i = 0; i < arity; i++) { final ExpressionTreeElement item = this.calculateTreeElement(children.get(i), context); final ExpressionItem itemValue = item.getItem(); if (itemValue instanceof Value) { arguments.add((Value) itemValue); } else { throw context.makeException( "[Expression]Wrong argument type detected for the '" + functionElement.getName() + "' function", null); } } final List> allowedSignatures = functionElement.getAllowedArgumentTypes(); List allowed = null; for (final List current : allowedSignatures) { if (current.size() != arguments.size()) { continue; } boolean allCompatible = true; int thatIndex = 0; for (final ValueType type : current) { if (!type.isCompatible(arguments.get(thatIndex).getType())) { allCompatible = false; break; } thatIndex++; } if (allCompatible) { allowed = current; for (final ValueType type : allowed) { signature.append(type.getSignature()); } break; } } if (allowed == null) { if (functionElement.getArity().contains(ANY_ARITY)) { signature.append(ValueType.ANY.getSignature()); } else { throw context.makeException( "[Expression]Unsupported argument detected for '" + functionElement.getName() + '\'', null); } } if (functionElement instanceof FunctionDefinedByUser) { final FunctionDefinedByUser userFunction = (FunctionDefinedByUser) functionElement; try { return new ExpressionTreeElement(userFunction.execute(context, arguments), stack, sources); } catch (Exception unexpected) { throw context .makeException("[Expression]Unexpected exception during a user function processing", unexpected); } } else { try { final Method method = functionElement.getClass().getMethod(signature.toString(), methodArguments); final Object[] callArgs = new Object[arity + 1]; callArgs[0] = context; System.arraycopy(arguments.toArray(), 0, callArgs, 1, arity); final Value result = (Value) method.invoke(functionElement, callArgs); if (!result.getType().isCompatible(functionElement.getResultType())) { throw context.makeException("[Expression]Unsupported function result detected [" + result.getType().getSignature() + ']', null); } return new ExpressionTreeElement(result, stack, sources); } catch (NoSuchMethodException unexpected) { throw context.makeException( "[Expression]Can't find a function method to process data [" + signature + ']', unexpected); } catch (Exception unexpected) { final Throwable cause = unexpected.getCause(); if (cause instanceof PreprocessorException) { throw (PreprocessorException) cause; } throw context.makeException( "[Expression]Can't execute a function method to process data [" + functionElement.getClass().getName() + '.' + signature + ']', unexpected); } } } private ExpressionTreeElement evalOperator(final ExpressionTreeElement operatorElement, final PreprocessorContext context) { final AbstractOperator operator = (AbstractOperator) operatorElement.getItem(); final int arity = operator.getArity(); final Value[] arguments = new Value[arity]; final Class[] methodArguments = arity == 1 ? OPERATOR_SIGNATURE_1 : OPERATOR_SIGNATURE_2; final StringBuilder signatureNormal = new StringBuilder(AbstractOperator.EXECUTION_PREFIX); final StringBuilder signatureAnyLeft = new StringBuilder(AbstractOperator.EXECUTION_PREFIX); final StringBuilder signatureAnyRight = new StringBuilder(AbstractOperator.EXECUTION_PREFIX); final FilePositionInfo[] stack; final String sources; stack = context.getPreprocessingState().makeIncludeStack(); sources = context.getPreprocessingState().getLastReadString(); for (int i = 0; i < arity; i++) { final ExpressionTreeElement arg = operatorElement.getChildForIndex(i); if (arg == ExpressionTreeElement.EMPTY_SLOT) { throw context.makeException( "[Expression]There is not needed argument for the operator [" + operator.getKeyword() + ']', null); } final ExpressionTreeElement currentElement = calculateTreeElement(arg, context); final ExpressionItem item = currentElement.getItem(); if (item instanceof Value) { arguments[i] = (Value) item; } else { throw context.makeException( "[Expression]Non-value detected for the '" + operator.getKeyword() + "' operator", null); } } int argIndex = 0; for (final Value value : arguments) { final String typeSignature = value.getType().getSignature(); signatureNormal.append(typeSignature); if (argIndex == 0) { signatureAnyLeft.append(ValueType.ANY.getSignature()); } else { signatureAnyLeft.append(typeSignature); } if (argIndex == 1) { signatureAnyRight.append(ValueType.ANY.getSignature()); } else { signatureAnyRight.append(typeSignature); } argIndex++; } Method executeMethod = null; try { executeMethod = operator.getClass().getMethod(signatureNormal.toString(), methodArguments); } catch (NoSuchMethodException ex) { try { executeMethod = operator.getClass().getMethod(signatureAnyLeft.toString(), methodArguments); } catch (NoSuchMethodException ex2) { try { executeMethod = operator.getClass().getMethod(signatureAnyRight.toString(), methodArguments); } catch (NoSuchMethodException ex3) { // DO NOTHING } } } if (executeMethod == null) { throw context.makeException( "[Expression]Unsupported arguments detected for operator '" + operator.getKeyword() + "' " + Arrays.toString(arguments), null); } try { return new ExpressionTreeElement((Value) executeMethod.invoke(operator, (Object[]) arguments), stack, sources); } catch (ArithmeticException arithEx) { throw arithEx; } catch (InvocationTargetException ex) { final Throwable thr = ex.getTargetException(); if (thr instanceof ArithmeticException) { throw (ArithmeticException) thr; } throw new RuntimeException( "Invocation exception during '" + operator.getKeyword() + "' processing", thr); } catch (Exception unexpected) { throw context .makeException("[Exception]Exception during '" + operator.getKeyword() + "' processing", unexpected); } } private ExpressionTreeElement calculateTreeElement(final ExpressionTreeElement element, final PreprocessorContext context) { ExpressionTreeElement treeElement = element; switch (element.getItem().getExpressionItemType()) { case VARIABLE: { Objects.requireNonNull(context, "[Expression]Variable can't be used without context [" + element.getItem().toString() + ']'); final Variable var = (Variable) element.getItem(); final String name = var.getName(); final Value value = context.findVariableForName(name, false); if (value == null) { throw new RuntimeException("Unknown variable [" + name + ']'); } else { treeElement = new ExpressionTreeElement(value, context.getPreprocessingState().makeIncludeStack(), context.getPreprocessingState().getLastReadString()); } } break; case OPERATOR: { treeElement = this.evalOperator(element, context); } break; case FUNCTION: { treeElement = this.evalFunction(element, context); } break; } return treeElement; } private Value eval(final PreprocessorContext context) { if (expressionTree.isEmpty()) { throw context.makeException("[Expression]The expression is empty", null); } final ExpressionTreeElement result = calculateTreeElement(expressionTree.getRoot(), context); final ExpressionItem resultItem = result.getItem(); if (resultItem == null) { throw context.makeException("[Expression]Expression doesn't have result", null); } if (resultItem instanceof Value) { return (Value) resultItem; } else { throw context .makeException("[Expression]The expression returns non-value result [" + resultItem + ']', null); } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/ExpressionItem.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression; /** * The interface describes an object which can be used during expression * calculations * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public interface ExpressionItem { /** * Get the type of the item * * @return the item type */ ExpressionItemType getExpressionItemType(); /** * Get the priority of the item * * @return the item priority, must not be null */ ExpressionItemPriority getExpressionItemPriority(); } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/ExpressionItemPriority.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression; public enum ExpressionItemPriority { LOGICAL(0), COMPARISON(1), ARITHMETIC_ADD_SUB(2), ARITHMETIC_MUL_DIV_MOD(3), FUNCTION(5), VALUE(6); private final int priority; ExpressionItemPriority(final int priority) { this.priority = priority; } public int getPriority() { return priority; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/ExpressionItemType.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression; public enum ExpressionItemType { FUNCTION, OPERATOR, VALUE, VARIABLE, SPECIAL } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/ExpressionParser.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression; import static com.igormaznitsa.jcp.expression.ExpressionTreeElement.ANY_ARITY; import static com.igormaznitsa.jcp.expression.ExpressionTreeElement.MAX_FUNCTION_ARGUMENTS; import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNullElseGet; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.exceptions.FilePositionInfo; import com.igormaznitsa.jcp.expression.functions.AbstractFunction; import com.igormaznitsa.jcp.expression.functions.FunctionDefinedByUser; import com.igormaznitsa.jcp.expression.operators.AbstractOperator; import com.igormaznitsa.jcp.extension.PreprocessorExtension; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.io.IOException; import java.io.PushbackReader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.stream.Collectors; /** * This class is a parser allows to parse an expression and make a tree as the output * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class ExpressionParser { /** * It contains the instance for the parser, because the parser is a singleton */ private static final ExpressionParser INSTANCE = new ExpressionParser(); public static ExpressionParser getInstance() { return INSTANCE; } private static boolean isDelimiterOrOperatorChar(final char chr) { return isDelimiter(chr) || isOperatorChar(chr); } private static boolean isDelimiter(final char chr) { switch (chr) { case ',': case '(': case ')': return true; default: return false; } } private static boolean isOperatorChar(final char chr) { switch (chr) { case '-': case '+': case '%': case '*': case '/': case '&': case '|': case '!': case '^': case '=': case '<': case '>': return true; default: return false; } } /** * To parse an expression represented as a string and get a tree * * @param expressionStr the expression string to be parsed, must not be null * @param context a preprocessor context to be used to get variable values * @return a tree containing parsed expression * @throws IOException it will be thrown if there is a problem to read the expression string */ public ExpressionTree parse(final String expressionStr, final PreprocessorContext context) throws IOException { requireNonNull(expressionStr, "Expression is null"); final PushbackReader reader = new PushbackReader(new StringReader(expressionStr)); final ExpressionTree result; final PreprocessingState state = context.getPreprocessingState(); result = new ExpressionTree(state.makeIncludeStack(), state.getLastReadString()); if (this.readExpression(reader, result, context, false, false) != null) { final String text = "Unexpected result during parsing [" + expressionStr + ']'; throw context.makeException(text, null); } result.postProcess(); return result; } /** * It reads an expression from a reader and fill a tree * * @param reader the reader to be used as the character source, must not be null * @param tree the result tree to be filled by read items, must not be null * @param context a preprocessor context to be used for variables * @param inBrackets the flag shows that the expression can be ended by a bracket * @param argument the flag shows that the expression can be ended by a comma * @return the last read expression item (a comma or a bracket for instance), it can be null * @throws IOException it will be thrown if there is a problem in reading from the reader */ public ExpressionItem readExpression( final PushbackReader reader, final ExpressionTree tree, final PreprocessorContext context, final boolean inBrackets, final boolean argument ) throws IOException { boolean working = true; ExpressionItem result = null; final FilePositionInfo[] stack; final String sourceLine; final PreprocessingState state = context.getPreprocessingState(); stack = state.makeIncludeStack(); sourceLine = state.getLastReadString(); ExpressionItem prev = null; while (working) { final ExpressionItem nextItem = nextItem(reader, context); if (nextItem == null) { working = false; } else if (nextItem.getExpressionItemType() == ExpressionItemType.SPECIAL) { if (nextItem == SpecialItem.BRACKET_CLOSING) { if (inBrackets) { working = false; result = nextItem; } else if (argument) { working = false; result = nextItem; } else { final String text = "Detected alone closing bracket"; throw context.makeException("Detected alone closing bracket", null); } } else if (nextItem == SpecialItem.BRACKET_OPENING) { if (prev != null && prev.getExpressionItemType() == ExpressionItemType.VARIABLE) { final String text = "Unknown function detected [" + prev + ']'; throw context.makeException(text, null); } final ExpressionTree subExpression; subExpression = new ExpressionTree(stack, sourceLine); if (SpecialItem.BRACKET_CLOSING != readExpression(reader, subExpression, context, true, false)) { final String text = "Detected unclosed bracket"; throw context.makeException(text, null); } tree.addTree(subExpression); } else if (nextItem == SpecialItem.COMMA) { return nextItem; } } else if (nextItem.getExpressionItemType() == ExpressionItemType.FUNCTION) { final AbstractFunction function = (AbstractFunction) nextItem; tree.addTree(this.readFunction(function, reader, context, stack, sourceLine)); } else { tree.addItem(nextItem); } prev = nextItem; } return result; } /** * The auxiliary method allows to form a function and its arguments as a tree * * @param function the function which arguments will be read from the stream, must not be null * @param reader the reader to be used as the character source, must not be null * @param context a preprocessor context, it will be used for a user functions and variables * @param includeStack the current file include stack, can be null * @param sources the current source line, can be null * @return an expression tree containing parsed function arguments * @throws IOException it will be thrown if there is any problem to read chars */ private ExpressionTree readFunction( final AbstractFunction function, final PushbackReader reader, final PreprocessorContext context, final FilePositionInfo[] includeStack, final String sources) throws IOException { final ExpressionItem expectedBracket = nextItem(reader, context); if (expectedBracket == null) { throw context .makeException("Detected function without params [" + function.getName() + ']', null); } final Set arities = function.getArity(); final int maxArity = arities.contains(ANY_ARITY) ? MAX_FUNCTION_ARGUMENTS : arities.stream().mapToInt(x -> x).max().orElse(0); ExpressionTree functionTree; if (maxArity == 0) { final ExpressionTree subExpression = new ExpressionTree(includeStack, sources); final ExpressionItem lastItem = readFunctionArgument(reader, subExpression, context, includeStack, sources); if (SpecialItem.BRACKET_CLOSING != lastItem) { throw context .makeException("There is not closing bracket for function [" + function.getName() + ']', null); } else if (!subExpression.getRoot().isEmptySlot()) { throw context .makeException("The function '" + function.getName() + "' doesn't need arguments", null); } else { functionTree = new ExpressionTree(includeStack, sources); functionTree.addItem(function); } } else { final List arguments = new ArrayList<>(); for (int i = 0; i < maxArity; i++) { final ExpressionTree subExpression = new ExpressionTree(includeStack, sources); final ExpressionItem lastItem = readFunctionArgument(reader, subExpression, context, includeStack, sources); if (SpecialItem.BRACKET_CLOSING == lastItem) { arguments.add(subExpression); break; } else if (SpecialItem.COMMA == lastItem) { arguments.add(subExpression); } else { throw context .makeException("Error argument for function '" + function.getName() + '\'', null); } } functionTree = new ExpressionTree(includeStack, sources); functionTree.addItem(function); ExpressionTreeElement functionTreeElement = functionTree.getRoot(); final Set expectedArities = functionTreeElement.getExpectedArities(); if (!expectedArities.contains(ANY_ARITY) && !expectedArities.contains(arguments.size())) { throw context.makeException( "Wrong argument number detected for '" + function.getName() + "', expected " + function.getArity().stream().map(Object::toString) .collect(Collectors.joining(";")) + " argument(s)", null); } functionTreeElement.fillArguments(arguments); } return functionTree; } /** * The auxiliary method allows to read a function argument * * @param reader a reader to be the character source, must not be null * @param tree the result tree to be filled by read items, must not be null * @param context a preprocessor context * @param callStack the current file call stack, can be null * @param source the current source line, can be null * @return the last read expression item (a comma or a bracket) * @throws IOException it will be thrown if there is any error during char reading from the reader */ ExpressionItem readFunctionArgument(final PushbackReader reader, final ExpressionTree tree, final PreprocessorContext context, final FilePositionInfo[] callStack, final String source) throws IOException { boolean working = true; ExpressionItem result = null; while (working) { final ExpressionItem nextItem = nextItem(reader, context); if (nextItem == null) { throw context.makeException("Non-closed function detected", null); } else if (SpecialItem.COMMA == nextItem) { result = nextItem; working = false; } else if (SpecialItem.BRACKET_OPENING == nextItem) { final ExpressionTree subExpression = new ExpressionTree(callStack, source); if (SpecialItem.BRACKET_CLOSING != readExpression(reader, subExpression, context, true, false)) { throw context .makeException("Non-closed bracket inside a function argument detected", null); } tree.addTree(subExpression); } else if (SpecialItem.BRACKET_CLOSING == nextItem) { result = nextItem; working = false; } else if (nextItem.getExpressionItemType() == ExpressionItemType.FUNCTION) { final AbstractFunction function = (AbstractFunction) nextItem; ExpressionTree functionTree = readFunction(function, reader, context, callStack, source); tree.addTree(functionTree); } else { tree.addItem(nextItem); } } return result; } private int hex2int(final PreprocessorContext context, final char chr) { final int result; if (Character.isDigit(chr)) { result = chr - '0'; } else { result = 10 + (chr - Character.toLowerCase(chr) - 'a'); if (result < 10 || result > 15) { throw context.makeException("Unexpected hex digit detected: " + chr, null); } } return result; } /** * Read the next item from the reader * * @param reader a reader to be used as the char source, must not be null * @param context a preprocessor context * @return a read expression item, it can be null if the end is reached * @throws IOException it will be thrown if there is any error during a char reading */ ExpressionItem nextItem(final PushbackReader reader, final PreprocessorContext context) throws IOException { requireNonNull(reader, "Reader is null"); ParserState state = ParserState.WAIT; final StringBuilder builder = new StringBuilder(12); boolean found = false; char unicodeChar = 0; while (!found) { final int data = reader.read(); if (data < 0) { if (state != ParserState.WAIT) { found = true; } break; } final char chr = (char) data; switch (state) { case WAIT: { if (Character.isWhitespace(chr)) { // do nothing } else if (chr == ',') { return SpecialItem.COMMA; } else if (chr == '(') { return SpecialItem.BRACKET_OPENING; } else if (chr == ')') { return SpecialItem.BRACKET_CLOSING; } else if (Character.isDigit(chr)) { builder.append(chr); if (chr == '0') { state = ParserState.HEX_NUMBER; } else { state = ParserState.NUMBER; } } else if (chr == '.') { builder.append('.'); state = ParserState.FLOAT_NUMBER; } else if (Character.isLetter(chr) || chr == '$' || chr == '_') { builder.append(chr); state = ParserState.VALUE_OR_FUNCTION; } else if (chr == '\"') { state = ParserState.STRING; } else if (isOperatorChar(chr)) { builder.append(chr); state = ParserState.OPERATOR; } else { throw context .makeException("Unsupported token character detected '" + chr + '\'', null); } } break; case OPERATOR: { if (!isOperatorChar(chr) || isDelimiter(chr)) { reader.unread(data); found = true; } else { builder.append(chr); } } break; case FLOAT_NUMBER: { if (Character.isDigit(chr)) { builder.append(chr); } else { found = true; reader.unread(data); } } break; case HEX_NUMBER: { if (builder.length() == 1) { if (chr == 'X' || chr == 'x') { builder.append(chr); } else if (chr == '.') { builder.append(chr); state = ParserState.FLOAT_NUMBER; } else if (Character.isDigit(chr)) { state = ParserState.NUMBER; } else { state = ParserState.NUMBER; found = true; reader.unread(data); } } else if (Character.isDigit(chr) || (chr >= 'a' && chr <= 'f') || (chr >= 'A' && chr <= 'F')) { builder.append(chr); } else { found = true; reader.unread(data); } } break; case UNICODE_DIGIT0: unicodeChar = (char) (hex2int(context, chr) << 12); state = ParserState.UNICODE_DIGIT1; break; case UNICODE_DIGIT1: unicodeChar = (char) (unicodeChar | (hex2int(context, chr) << 8)); state = ParserState.UNICODE_DIGIT2; break; case UNICODE_DIGIT2: unicodeChar = (char) (unicodeChar | (hex2int(context, chr) << 4)); state = ParserState.UNICODE_DIGIT3; break; case UNICODE_DIGIT3: unicodeChar = (char) (unicodeChar | hex2int(context, chr)); state = ParserState.STRING; builder.append(unicodeChar); break; case NUMBER: { if (Character.isDigit(chr)) { builder.append(chr); } else if (chr == '.') { builder.append(chr); state = ParserState.FLOAT_NUMBER; } else { reader.unread(data); found = true; } } break; case VALUE_OR_FUNCTION: { if (Character.isWhitespace(chr) || isDelimiterOrOperatorChar(chr)) { reader.unread(data); found = true; } else { builder.append(chr); } } break; case SPECIAL_CHAR: { switch (chr) { case 'n': builder.append('\n'); break; case 't': builder.append('\t'); break; case 'b': builder.append('\b'); break; case 'f': builder.append('\f'); break; case 'r': builder.append('\r'); break; case '\\': builder.append('\\'); break; case '\"': builder.append('\"'); break; case '\'': builder.append('\''); break; case 'u': state = ParserState.UNICODE_DIGIT0; break; default: { throw context .makeException("Unsupported special char detected '\\" + chr + '\'', null); } } state = state == ParserState.SPECIAL_CHAR ? ParserState.STRING : state; } break; case STRING: { switch (chr) { case '\"': { found = true; } break; case '\\': { state = ParserState.SPECIAL_CHAR; } break; default: { builder.append(chr); } break; } } break; default: throw new Error("Unsupported parser state [" + state.name() + ']'); } } if (!found) { switch (state) { case UNICODE_DIGIT0: case UNICODE_DIGIT1: case UNICODE_DIGIT2: { throw context.makeException("Non-completed unicode char has been detected", null); } case SPECIAL_CHAR: case STRING: { throw context.makeException("Non-closed string has been detected", null); } default: return null; } } else { ExpressionItem result = null; switch (state) { case FLOAT_NUMBER: { result = Value.valueOf(Float.parseFloat(builder.toString())); } break; case HEX_NUMBER: { final String text = builder.toString(); if ("0".equals(text)) { result = Value.INT_ZERO; } else { final String str = PreprocessorUtils.extractTail("0x", text); result = Value.valueOf(Long.parseLong(str, 16)); } } break; case NUMBER: { result = Value.valueOf(Long.parseLong(builder.toString())); } break; case OPERATOR: { final String operatorLC = builder.toString().toLowerCase(Locale.ROOT); for (final AbstractOperator operator : AbstractOperator.getAllOperators()) { if (operator.getKeyword().equals(operatorLC)) { result = operator; break; } } if (result == null) { throw context.makeException("Unknown operator detected '" + operatorLC + '\'', null); } } break; case STRING: { result = Value.valueOf(builder.toString()); } break; case VALUE_OR_FUNCTION: { final String str = builder.toString().toLowerCase(); if (str.charAt(0) == '$') { requireNonNull(context, "There is not a preprocessor context to define a user function [" + str + ']'); final List extensions = context.getPreprocessorExtensions(); if (extensions.isEmpty()) { throw context.makeException( "There is not any defined preprocessor extension to get data about user functions [" + str + ']', null); } final String userFunctionName = PreprocessorUtils.extractTail("$", str); final PreprocessorExtension preprocessorExtension = context.getPreprocessorExtensions().stream() .filter(x -> x.isAllowed(context)) .filter(x -> x.hasUserFunction(userFunctionName, Set.of())) .findFirst().orElse(null); if (preprocessorExtension == null) { throw context.makeException( "Can't find any preprocessor extension processing the user functions [" + userFunctionName + ']', null); } else { final Set arities = preprocessorExtension.getUserFunctionArity(userFunctionName); if (arities.isEmpty()) { throw context.makeException( "Empty arity set for preprocessor extension processing the user functions [" + userFunctionName + ']', null); } result = new FunctionDefinedByUser(userFunctionName, arities, context); } } else if ("true".equals(str)) { result = Value.BOOLEAN_TRUE; } else if ("false".equals(str)) { result = Value.BOOLEAN_FALSE; } else { final AbstractFunction function = AbstractFunction.findForName(str); result = requireNonNullElseGet(function, () -> new Variable(str)); } } break; default: { throw new Error("Unsupported final parser state detected [" + state.name() + ']'); } } return result; } } /** * Internal parser states. */ private enum ParserState { WAIT, NUMBER, HEX_NUMBER, FLOAT_NUMBER, STRING, SPECIAL_CHAR, UNICODE_DIGIT0, UNICODE_DIGIT1, UNICODE_DIGIT2, UNICODE_DIGIT3, VALUE_OR_FUNCTION, OPERATOR } /** * The enumeration describes some special items which can be met in the expression * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public enum SpecialItem implements ExpressionItem { BRACKET_OPENING, BRACKET_CLOSING, COMMA; SpecialItem() { } @Override public ExpressionItemPriority getExpressionItemPriority() { return null; } @Override public ExpressionItemType getExpressionItemType() { return ExpressionItemType.SPECIAL; } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/ExpressionTree.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.exceptions.FilePositionInfo; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import java.util.Objects; /** * The class describes an object contains an expression tree * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class ExpressionTree { private final FilePositionInfo[] includeStack; private final String sources; private ExpressionTreeElement last = ExpressionTreeElement.EMPTY_SLOT; public ExpressionTree() { this(null, null); } public ExpressionTree(final FilePositionInfo[] callStack, final String sources) { this.includeStack = callStack == null ? PreprocessingState.EMPTY_STACK : callStack; this.sources = sources == null ? "" : sources; } /** * Allows to check that the tree is empty * * @return true if the tree is empty one else false */ public boolean isEmpty() { return last.isEmptySlot(); } /** * Add new expression item into tree * * @param item an item to be added, must not be null */ public void addItem(final ExpressionItem item) { if (item == null) { throw new PreprocessorException( "[Expression]Item is null", this.sources, this.includeStack, null); } if (this.last.isEmptySlot()) { this.last = new ExpressionTreeElement(item, this.includeStack, this.sources); } else { this.last = this.last.addTreeElement( new ExpressionTreeElement(item, this.includeStack, this.sources)); } } /** * Add whole tree as a tree element, also it sets the maximum priority to the new element * * @param tree a tree to be added as an item, must not be null */ public void addTree(final ExpressionTree tree) { Objects.requireNonNull(tree, "Tree is null"); if (last.isEmptySlot()) { final ExpressionTreeElement thatTreeRoot = tree.getRoot(); if (!thatTreeRoot.isEmptySlot()) { last = thatTreeRoot; last.makeMaxPriority(); } } else { last = last.addSubTree(tree); } } /** * Get the root of the tree * * @return the root of the tree or EMPTY_SLOT if the tree is empty */ public ExpressionTreeElement getRoot() { if (last.isEmptySlot()) { return this.last; } else { ExpressionTreeElement element = last; while (!Thread.currentThread().isInterrupted()) { final ExpressionTreeElement next = element.getParent(); if (next == null) { return element; } else { element = next; } } } return ExpressionTreeElement.EMPTY_SLOT; } /** * It can be called after the tree has been formed to optimize inside structures */ public void postProcess() { final ExpressionTreeElement root = getRoot(); if (!root.isEmptySlot()) { root.postProcess(); } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/ExpressionTreeElement.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression; import static com.igormaznitsa.jcp.expression.functions.AbstractFunction.ARITY_0; import com.igormaznitsa.jcp.exceptions.FilePositionInfo; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.functions.AbstractFunction; import com.igormaznitsa.jcp.expression.operators.AbstractOperator; import com.igormaznitsa.jcp.expression.operators.OperatorSUB; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; /** * The class describes a wrapper around an expression item to be saved into an expression tree * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class ExpressionTreeElement { public static final ExpressionTreeElement EMPTY_SLOT = new ExpressionTreeElement(); /** * Inside constant to be used for speed up some operations */ private static final OperatorSUB OPERATOR_SUB = AbstractOperator.findForClass(OperatorSUB.class); /** * Empty array to avoid unnecessary operations */ private static final ExpressionTreeElement[] EMPTY = new ExpressionTreeElement[0]; public static final int ANY_ARITY = -1; public static final int MAX_FUNCTION_ARGUMENTS = 256; /** * Contains the source string for the expression. */ private final String sourceString; /** * Current include stack of the preprocessor to the source string. */ private final FilePositionInfo[] includeStack; /** * The variable contains the wrapped expression item */ private ExpressionItem savedItem; /** * The array contains links to the tree element children */ private ExpressionTreeElement[] childrenSlots; /** * The link to the parent element, if it is the tree root then it contains null */ private ExpressionTreeElement parentTreeElement; /** * The priority of the tree element, it is very strongly used during tree sorting */ private int priority; /** * Because I fill children sequentially, the variable contains the index of the first empty child slot */ private int nextChildSlotIndex = 0; /** * Set of allowed arities. * * @since 7.3.0 */ private Set expectedArities = Set.of(); @Override public String toString() { return "ExpressionTreeElement(item=" + this.savedItem + ",slots=" + childrenSlots.length + ")"; } private ExpressionTreeElement() { this.sourceString = ""; this.includeStack = new FilePositionInfo[0]; } /** * The constructor * * @param item an expression item to be wrapped * @param callStack current call stack * @param sourceString source string for the expression */ ExpressionTreeElement(final ExpressionItem item, final FilePositionInfo[] callStack, final String sourceString) { this.sourceString = sourceString; this.includeStack = callStack; if (item == null) { throw new PreprocessorException("[Expression]The item is null", this.sourceString, this.includeStack, null); } if (item.getExpressionItemType() == ExpressionItemType.OPERATOR) { final int arity = ((AbstractOperator) item).getArity(); this.expectedArities = Set.of(arity); this.childrenSlots = new ExpressionTreeElement[arity]; } else if (item.getExpressionItemType() == ExpressionItemType.FUNCTION) { final AbstractFunction functionItem = (AbstractFunction) item; this.expectedArities = functionItem.getArity(); final int arity = this.expectedArities.stream().mapToInt(x -> x).max().orElse(0); this.childrenSlots = this.expectedArities.contains(ANY_ARITY) ? new ExpressionTreeElement[MAX_FUNCTION_ARGUMENTS] : new ExpressionTreeElement[arity]; } else { this.expectedArities = ARITY_0; this.childrenSlots = EMPTY; } this.priority = item.getExpressionItemPriority().getPriority(); this.savedItem = item; Arrays.fill(this.childrenSlots, EMPTY_SLOT); } /** * Get effective child slots. * * @return list of non-empty child slots. * @since 7.3.0 */ public List extractEffectiveChildren() { return Arrays.stream(this.childrenSlots).takeWhile(x -> x != EMPTY_SLOT) .collect(Collectors.toUnmodifiableList()); } /** * Variants of allowed arities by the expression tree element * * @return set contains number of expected arities * @since 7.3.0 */ public Set getExpectedArities() { return this.expectedArities; } /** * Allows to check that the element is EMPTY_SLOT * * @return true if the element is empty slot, false otherwise */ public boolean isEmptySlot() { return EMPTY_SLOT == this; } private void assertNotEmptySlot() { if (this.isEmptySlot()) { throw new UnsupportedOperationException("Unsupported operation for empty slot"); } } /** * Internal auxiliary function to set the maximum priority the element */ void makeMaxPriority() { this.priority = ExpressionItemPriority.VALUE.getPriority(); } /** * Get the wrapped item * * @return the item to be wrapped by the object */ public ExpressionItem getItem() { return this.savedItem; } /** * Get the parent for the element * * @return the parent for the element or null if the element is the tree root */ public ExpressionTreeElement getParent() { return this.parentTreeElement; } /** * Get the current priority of the element * * @return the priority */ public int getPriority() { return this.priority; } /** * Add a tree as new child and make the maximum priority for it * * @param tree a tree to be added as a child, must not be null * @return it returns this */ public ExpressionTreeElement addSubTree(final ExpressionTree tree) { assertNotEmptySlot(); final ExpressionTreeElement root = tree.getRoot(); if (!root.isEmptySlot()) { root.makeMaxPriority(); addElementToNextFreeSlot(root); } return this; } /** * It replaces a child element * * @param oldOne the old expression element to be replaced (must not be null) * @param newOne the new expression element to be used instead the old one (must not be null) * @return true if the element was found and replaced, else false */ public boolean replaceElement(final ExpressionTreeElement oldOne, final ExpressionTreeElement newOne) { assertNotEmptySlot(); if (oldOne == null) { throw new PreprocessorException("[Expression]The old element is null", this.sourceString, this.includeStack, null); } if (newOne == null) { throw new PreprocessorException("[Expression]The new element is null", this.sourceString, this.includeStack, null); } boolean replaced = false; for (int i = 0; i < this.childrenSlots.length; i++) { if (this.childrenSlots[i] == oldOne) { this.childrenSlots[i] = newOne; newOne.parentTreeElement = this; replaced = true; break; } } return replaced; } /** * Get the child element for its index (the first is 0) * * @param index the index of the needed child * @return the child or EMPTY_SLOT * @throws ArrayIndexOutOfBoundsException it will be thrown if an impossible index is being used * @see #EMPTY_SLOT */ public ExpressionTreeElement getChildForIndex(final int index) { assertNotEmptySlot(); return this.childrenSlots[index]; } /** * Add tree element with sorting operation depends on priority of the elements * * @param element the element to be added, must not be null * @return the element which should be used as the last for the current tree */ public ExpressionTreeElement addTreeElement(final ExpressionTreeElement element) { assertNotEmptySlot(); Objects.requireNonNull(element, "The element is null"); final int newElementPriority = element.getPriority(); ExpressionTreeElement result = this; final ExpressionTreeElement parentTreeElement = this.parentTreeElement; final int currentPriority = getPriority(); if (newElementPriority < currentPriority) { if (parentTreeElement == null) { element.addTreeElement(this); result = element; } else { result = parentTreeElement.addTreeElement(element); } } else if (newElementPriority == currentPriority) { if (parentTreeElement != null) { parentTreeElement.replaceElement(this, element); } if (element.nextChildSlotIndex >= element.childrenSlots.length) { throw new PreprocessorException( "[Expression] Can't add slot data, may be wrong number of arguments, slot index is " + element.nextChildSlotIndex + " but maximum slots is " + element.childrenSlots.length, this.sourceString, this.includeStack, null); } element.childrenSlots[element.nextChildSlotIndex++] = this; this.parentTreeElement = element; result = element; } else if (this.isFull()) { final int lastElementIndex = this.nextChildSlotIndex - 1; final ExpressionTreeElement lastElement = this.childrenSlots[lastElementIndex]; if (lastElement.getPriority() > newElementPriority) { element.addElementToNextFreeSlot(lastElement); this.childrenSlots[lastElementIndex] = element; element.parentTreeElement = this; result = element; } } else { addElementToNextFreeSlot(element); result = element; } return result; } /** * It allows to check that all children slots have been filled * * @return true if there is not any free child slot else false */ public boolean isFull() { return this.nextChildSlotIndex >= this.childrenSlots.length; } /** * It fills children slots from a list containing expression trees * * @param arguments the list containing trees to be used as children */ public void fillArguments(final List arguments) { assertNotEmptySlot(); if (arguments == null) { throw new PreprocessorException("[Expression]Argument list is null", this.sourceString, this.includeStack, null); } if (!this.expectedArities.contains(ANY_ARITY) && !this.expectedArities.contains(arguments.size())) { throw new PreprocessorException( "Wrong argument list size, expected arities: " + this.expectedArities, this.sourceString, this.includeStack, null); } int i = 0; for (ExpressionTree arg : arguments) { if (arg == null) { throw new PreprocessorException("[Expression]Argument [" + (i + 1) + "] is null", this.sourceString, this.includeStack, null); } if (!childrenSlots[i].isEmptySlot()) { throw new PreprocessorException( "[Expression]Non-empty slot detected, it is possible that there is a program error, contact a developer please", this.sourceString, this.includeStack, null); } final ExpressionTreeElement root = arg.getRoot(); if (root.isEmptySlot()) { throw new PreprocessorException("[Expression]Empty argument [" + (i + 1) + "] detected", this.sourceString, this.includeStack, null); } childrenSlots[i] = root; root.parentTreeElement = this; i++; } } /** * Add an expression element into the next free child slot * * @param element an element to be added, must not be null */ private void addElementToNextFreeSlot(final ExpressionTreeElement element) { if (element == null) { throw new PreprocessorException("[Expression]Element is null", this.sourceString, this.includeStack, null); } if (this.childrenSlots.length == 0) { throw new PreprocessorException( "[Expression]Unexpected element, may be unknown function [" + savedItem.toString() + ']', this.sourceString, this.includeStack, null); } else if (isFull()) { throw new PreprocessorException( "[Expression]There is not any possibility to add new argument [" + savedItem.toString() + ']', this.sourceString, this.includeStack, null); } else { childrenSlots[nextChildSlotIndex++] = element; } element.parentTreeElement = this; } /** * Post-processing after the tree is formed, the unary minus operation will be optimized */ public void postProcess() { if (!this.isEmptySlot()) { switch (savedItem.getExpressionItemType()) { case OPERATOR: { if (savedItem == OPERATOR_SUB) { if (!this.childrenSlots[0].isEmptySlot() && this.childrenSlots[1].isEmptySlot()) { final ExpressionTreeElement left = this.childrenSlots[0]; final ExpressionItem item = left.getItem(); if (item.getExpressionItemType() == ExpressionItemType.VALUE) { final Value val = (Value) item; switch (val.getType()) { case INT: { this.childrenSlots = EMPTY; this.savedItem = Value.valueOf(-val.asLong()); makeMaxPriority(); } break; case FLOAT: { this.childrenSlots = EMPTY; this.savedItem = Value.valueOf(0.0f - val.asFloat()); makeMaxPriority(); } break; default: { if (!left.isEmptySlot()) { left.postProcess(); } } break; } } } else { for (final ExpressionTreeElement element : this.childrenSlots) { if (!element.isEmptySlot()) { element.postProcess(); } } } } else { for (final ExpressionTreeElement element : this.childrenSlots) { if (!element.isEmptySlot()) { element.postProcess(); } } } } break; case FUNCTION: { for (final ExpressionTreeElement element : this.childrenSlots) { if (!element.isEmptySlot()) { element.postProcess(); } } } break; } } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/Value.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.util.Objects; /** * The class describes an expression value i.e. an atomic constant expression item like string or number * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) * @see ValueType */ public final class Value implements ExpressionItem { public static final Value BOOLEAN_TRUE = new Value(Boolean.TRUE); public static final Value BOOLEAN_FALSE = new Value(Boolean.FALSE); public static final Value INT_ZERO = new Value(0L); public static final Value INT_ONE = new Value(1L); public static final Value INT_TWO = new Value(2L); public static final Value INT_THREE = new Value(3L); public static final Value INT_FOUR = new Value(4L); public static final Value INT_FIVE = new Value(5L); private final Object value; private final ValueType type; private Value(final String val) { value = val == null ? "null" : val; type = ValueType.STRING; } private Value(final Long val) { value = val; type = ValueType.INT; } private Value(final Float val) { value = val; type = ValueType.FLOAT; } private Value(final Boolean val) { value = val; type = ValueType.BOOLEAN; } public static Value valueOf(final Long val) { return new Value(val); } public static Value valueOf(final Boolean val) { return val ? BOOLEAN_TRUE : BOOLEAN_FALSE; } public static Value valueOf(final Float val) { return new Value(val); } public static Value valueOf(final String val) { return new Value(val); } public static Value recognizeRawString(final String str) { Objects.requireNonNull(str, "Parameter is null"); if ("true".equals(str)) { return Value.BOOLEAN_TRUE; } if ("false".equals(str)) { return Value.BOOLEAN_FALSE; } try { return new Value(Long.parseLong(str)); } catch (NumberFormatException ex) { // DO NOTHING } try { return new Value(Float.parseFloat(str)); } catch (NumberFormatException ex) { // DO NOTHING } return new Value(str); } public static Value recognizeOf(final String str) { final ValueType type = recognizeType(str); final Value result; switch (type) { case BOOLEAN: { result = "true".equalsIgnoreCase(str) ? BOOLEAN_TRUE : BOOLEAN_FALSE; } break; case INT: { result = new Value((Long) getValue(str, ValueType.INT)); } break; case FLOAT: { result = new Value((Float) getValue(str, ValueType.FLOAT)); } break; case STRING: { result = new Value((String) getValue(str, ValueType.STRING)); } break; default: { throw new IllegalArgumentException("Illegal value [" + str + ']'); } } return result; } public static Object getValue(final String value, final ValueType type) { try { switch (type) { case STRING: { return value.substring(1, value.length() - 1); } case BOOLEAN: { return value.equalsIgnoreCase("true") ? Boolean.TRUE : Boolean.FALSE; } case INT: { if (value.length() > 2 && value.charAt(0) == '0' && (value.charAt(1) == 'x' || value.charAt(1) == 'X')) { // HEX value return Long.valueOf(PreprocessorUtils.extractTail("0x", value), 16); } else { // Decimal value return Long.valueOf(value); } } case FLOAT: { return Float.valueOf(value); } default: return null; } } catch (NumberFormatException e) { return null; } } public static ValueType recognizeType(final String value) { if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) // Boolean { return ValueType.BOOLEAN; } else if (value.length() > 1 && value.charAt(0) == '\"' && value.charAt(value.length() - 1) == '\"') // String value { return ValueType.STRING; } else { try { if (value.indexOf('.') >= 0) { // Float Float.parseFloat(value); return ValueType.FLOAT; } else { // Integer if (value.startsWith("0x")) { // HEX value Long.parseLong(PreprocessorUtils.extractTail("0x", value), 16); } else { // Decimal value Long.parseLong(value, 10); } return ValueType.INT; } } catch (NumberFormatException e) { return ValueType.UNKNOWN; } } } public ValueType getType() { return type; } public Object getValue() { return value; } public Long asLong() { if (type != ValueType.INT) { throw new IllegalStateException("Value is not integer"); } return (Long) value; } public Float asFloat() { if (type != ValueType.FLOAT) { throw new IllegalStateException("Value is not float"); } return (Float) value; } public String asString() { if (type != ValueType.STRING) { throw new IllegalStateException("Value is not string"); } return (String) value; } public Boolean asBoolean() { if (type != ValueType.BOOLEAN) { throw new IllegalStateException("Value is not boolean"); } return (Boolean) value; } public String toStringDetail() { switch (type) { case BOOLEAN: { return "Boolean: " + value; } case INT: { return "Integer: " + value; } case UNKNOWN: { return "Unknown: -"; } case FLOAT: { return "Float: " + value; } case STRING: { return "String: " + value; } } return "Unexpected unsupported type, contact developer [" + type + "]"; } @Override public String toString() { switch (this.type) { case BOOLEAN: return this.asBoolean().toString(); case INT: return this.asLong().toString(); case UNKNOWN: return ""; case FLOAT: return this.asFloat().toString(); case STRING: return asString(); default: return "Unexpected unsupported type, contact developer [" + type + "]"; } } public boolean toBoolean() { switch (this.type) { case BOOLEAN: return this.asBoolean(); case INT: return this.asLong() != 0L; case FLOAT: return Math.round(this.asFloat()) != 0; case STRING: return "true".equalsIgnoreCase(this.asString().trim()); default: return false; } } @Override public ExpressionItemType getExpressionItemType() { return ExpressionItemType.VALUE; } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.VALUE; } @Override public boolean equals(final Object var) { if (this == var) { return true; } if (var instanceof Value) { final Value thatValue = (Value) var; return this.type == thatValue.type && this.value.equals(thatValue.value); } return false; } @Override public int hashCode() { return this.value.hashCode(); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/ValueType.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression; /** * The enumeration contains all allowed types for expression values and their * signatures * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public enum ValueType { ANY("Any"), STRING("Str"), BOOLEAN("Bool"), INT("Int"), FLOAT("Float"), UNKNOWN("Unknown"); /** * The signature for the type it will be used in method calls */ private final String signature; ValueType(final String signature) { this.signature = signature; } public String getSignature() { return this.signature; } /** * To check that the type is compatible with another one * * @param type the type to be checked, must not be null * @return true if the type is compatible else false */ public boolean isCompatible(final ValueType type) { if (this == type) { return true; } return this != UNKNOWN && type != UNKNOWN && (this == ANY || type == ANY); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/Variable.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression; import java.util.Objects; /** * The class describes an expression variable * * @author Igor Mznitsa (igor.maznitsa@igormaznitsa.com) */ public final class Variable implements ExpressionItem { /** * The variable contains the expression variable name */ private final String variableName; /** * The constructor * * @param varName the variable name, it must not be null */ public Variable(final String varName) { Objects.requireNonNull(varName, "Var name is null"); this.variableName = varName; } /** * Get the variable name * * @return the name saved by the object */ public String getName() { return this.variableName; } /** * Get the expression item type * * @return it returns only ExpressionItemType.VARIABLE */ @Override public ExpressionItemType getExpressionItemType() { return ExpressionItemType.VARIABLE; } /** * Get the expression item priority * * @return it returns only ExpressionItemPriority.VALUE */ @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.VALUE; } @Override public String toString() { return this.variableName; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/AbstractFunction.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static com.igormaznitsa.jcp.expression.ExpressionTreeElement.ANY_ARITY; import com.igormaznitsa.jcp.expression.ExpressionItem; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.ExpressionItemType; import com.igormaznitsa.jcp.expression.ValueType; import com.igormaznitsa.jcp.expression.functions.xml.FunctionXML_ATTR; import com.igormaznitsa.jcp.expression.functions.xml.FunctionXML_GET; import com.igormaznitsa.jcp.expression.functions.xml.FunctionXML_LIST; import com.igormaznitsa.jcp.expression.functions.xml.FunctionXML_NAME; import com.igormaznitsa.jcp.expression.functions.xml.FunctionXML_OPEN; import com.igormaznitsa.jcp.expression.functions.xml.FunctionXML_ROOT; import com.igormaznitsa.jcp.expression.functions.xml.FunctionXML_SIZE; import com.igormaznitsa.jcp.expression.functions.xml.FunctionXML_TEXT; import com.igormaznitsa.jcp.expression.functions.xml.FunctionXML_XELEMENT; import com.igormaznitsa.jcp.expression.functions.xml.FunctionXML_XLIST; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; /** * The abstract class is the base for each function handler in the preprocessor * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public abstract class AbstractFunction implements ExpressionItem { public static final Set ARITY_ANY = Set.of(ANY_ARITY); public static final Set ARITY_0 = Set.of(0); public static final Set ARITY_1 = Set.of(1); public static final Set ARITY_1_2 = Set.of(1, 2); public static final Set ARITY_2 = Set.of(2); public static final Set ARITY_3 = Set.of(3); /** * The string contains the prefix for all executing methods of functions */ public static final String EXECUTION_PREFIX = "execute"; /** * Internal counter to generate UID for some cases */ protected static final AtomicLong UID_COUNTER = new AtomicLong(1); /** * Current internal map contains all preprocessor functions, mapped by their names */ private static final AtomicReference> allFunctions = new AtomicReference<>(); @SuppressWarnings("StaticInitializerReferencesSubClass") private static final List DEFAULT_INTERNAL_FUNCTIONS = List.of( new FunctionABS(), new FunctionROUND(), new FunctionESC(), new FunctionSTR2INT(), new FunctionSTR2WEB(), new FunctionSTR2CSV(), new FunctionSTR2JS(), new FunctionSTR2JSON(), new FunctionSTR2XML(), new FunctionSTR2JAVA(), new FunctionSTR2GO(), new FunctionTRIMLINES(), new FunctionSTRLEN(), new FunctionISSUBSTR(), new FunctionIS(), new FunctionEVALFILE(), new FunctionBINFILE(), new FunctionXML_GET(), new FunctionXML_SIZE(), new FunctionXML_ATTR(), new FunctionXML_ROOT(), new FunctionXML_NAME(), new FunctionXML_LIST(), new FunctionXML_TEXT(), new FunctionXML_OPEN(), new FunctionXML_XLIST(), new FunctionXML_XELEMENT() ); private static final Map DEFAULT_INTERNAL_FUNCTIONS_MAP = DEFAULT_INTERNAL_FUNCTIONS.stream() .collect(Collectors.toMap(AbstractFunction::getName, x -> x)); public static List findAllFunctions() { Map currentAllFunctions = allFunctions.get(); if (currentAllFunctions == null) { return DEFAULT_INTERNAL_FUNCTIONS; } else { return currentAllFunctions.values().stream() .sorted(Comparator.comparing(AbstractFunction::getName)) .collect(Collectors.toList()); } } public static Map getFunctionNameMap() { final Map result = allFunctions.get(); if (result == null) { return DEFAULT_INTERNAL_FUNCTIONS_MAP; } return result; } /** * Allows to find a function handler instance for its class * * @param the class of the needed function handler extends the * AbstractFunction class * @param functionClass the class of the needed handler, must not be null * @return an instance of the needed handler or null if there is not any such * one */ public static E findForClass(final Class functionClass) { E result = null; for (final AbstractFunction function : findAllFunctions()) { if (function.getClass() == functionClass) { result = functionClass.cast(function); break; } } return result; } /** * Find a function handler for its name * * @param functionName the function name, must not be null * @return an instance of the needed handler or null if there is not any such * one */ public static AbstractFunction findForName(final String functionName) { return getFunctionNameMap().get(functionName); } /** * Get the function name * * @return the function name in lower case, must not be null */ public abstract String getName(); /** * Get the function reference to be output for a help request * * @return the function information as a String, must not be null */ public abstract String getReference(); /** * Get the function arities * * @return all allowed arities for the function * @since 7.3.0 */ public abstract Set getArity(); /** * Get arrays of supported argument types * * @return list of argument type combinations allowed by the function * handler, must not be null */ public abstract List> getAllowedArgumentTypes(); /** * Get the result type * * @return the result type of the function, must not be null */ public abstract ValueType getResultType(); /** * Get the priority of the function in the expression tree * * @return the expression item priority for the function, must not be null */ @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.FUNCTION; } /** * Get the expression item type * * @return the expression item type, in the case it is always * ExpressionItemType.FUNCTION */ @Override public ExpressionItemType getExpressionItemType() { return ExpressionItemType.FUNCTION; } @Override public String toString() { return "FUNCTION: " + getName(); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/AbstractStrConverter.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; /** * The class is parent for converting classes. * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public abstract class AbstractStrConverter extends AbstractFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING)); public abstract Value executeStr(final PreprocessorContext context, final Value stringToConvert); @Override public final Set getArity() { return ARITY_1; } @Override public final List> getAllowedArgumentTypes() { return ARG_TYPES; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionABS.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; /** * The class implements the abs function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionABS extends AbstractFunction { private static final List> ARGUMENT_TYPES = List.of(List.of(ValueType.INT), List.of(ValueType.FLOAT)); @Override public String getName() { return "abs"; } public Value executeInt(final PreprocessorContext context, final Value value) { return Value.valueOf(Math.abs(value.asLong())); } public Value executeFloat(final PreprocessorContext context, final Value value) { return Value.valueOf(Math.abs(value.asFloat())); } @Override public Set getArity() { return ARITY_1; } @Override public List> getAllowedArgumentTypes() { return ARGUMENT_TYPES; } @Override public String getReference() { return "returns the absolute value of the given number"; } @Override public ValueType getResultType() { return ValueType.ANY; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionBINFILE.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.zip.Deflater; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; /** * The Function loads bin file and encodes it into string. * * @author Igor Maznitsa (http://www.igormaznitsa.com) * @since 6.1.0 */ public class FunctionBINFILE extends AbstractFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING, ValueType.STRING)); private static boolean hasSplitFlag(final String name, final Type type) { final String opts = name.substring(type.name.length()); return opts.contains("S") || opts.contains("s"); } private static boolean hasDeflateFlag(final String name, final Type type) { final String opts = name.substring(type.name.length()); return opts.contains("D") || opts.contains("d"); } private static String convertTo(final File file, final Type type, final boolean deflate, final int lineLength, final String endOfLine) throws IOException { final StringBuilder result = new StringBuilder(512); byte[] array = FileUtils.readFileToByteArray(file); if (deflate) { array = deflate(array); } boolean addNextLine = false; int visibleLineCharsCounter = 0; switch (type) { case BASE64: { final String baseEncoded = new Base64(lineLength, endOfLine.getBytes(StandardCharsets.UTF_8), false) .encodeAsString(array); result.append(baseEncoded.trim()); } break; case BYTEARRAY: case INT8: case UINT8: { for (final byte b : array) { if (result.length() > 0) { result.append(','); visibleLineCharsCounter++; } if (addNextLine) { addNextLine = false; visibleLineCharsCounter = 0; result.append(endOfLine); } final int initialBufferLength = result.length(); switch (type) { case BYTEARRAY: { result.append("(byte)0x") .append(Integer.toHexString(b & 0xFF).toUpperCase(Locale.ROOT)); } break; case UINT8: { result.append(Integer.toString(b & 0xFF).toUpperCase(Locale.ROOT)); } break; case INT8: { result.append(Integer.toString(b).toUpperCase(Locale.ROOT)); } break; default: throw new Error("Unexpected type : " + type); } visibleLineCharsCounter += result.length() - initialBufferLength; if (lineLength > 0 && visibleLineCharsCounter >= lineLength) { addNextLine = true; } } } break; default: throw new Error("Unexpected type : " + type); } return result.toString(); } private static byte[] deflate(final byte[] data) throws IOException { final Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION); deflater.setInput(data); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length); deflater.finish(); final byte[] buffer = new byte[1024]; while (!deflater.finished()) { final int count = deflater.deflate(buffer); outputStream.write(buffer, 0, count); } outputStream.close(); final byte[] output = outputStream.toByteArray(); deflater.end(); return output; } @Override public String getName() { return "binfile"; } @Override public String getReference() { final StringBuilder buffer = new StringBuilder(); for (final Type t : Type.values()) { if (buffer.length() > 0) { buffer.append('|'); } buffer.append(t.name); } buffer.append("[s|d|sd|ds]"); return "encode binary file as string, allowed types [" + buffer + "], s - split lines, d - deflate compression"; } @Override public Set getArity() { return ARITY_2; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public ValueType getResultType() { return ValueType.STRING; } public Value executeStrStr(final PreprocessorContext context, final Value strFilePath, final Value encodeType) { final String filePath = strFilePath.asString(); final String encodeTypeAsString = encodeType.asString(); final Type type = Type.find(encodeTypeAsString); if (type == null) { throw context.makeException("Unsupported encode type [" + encodeType.asString() + ']', null); } final int lengthOfLine = hasSplitFlag(encodeTypeAsString, type) ? 80 : -1; final boolean doDeflate = hasDeflateFlag(encodeTypeAsString, type); final File theFile = context.findFileInSources(filePath); if (context.isVerbose()) { context.logForVerbose("Loading content of bin file '" + theFile + '\''); } try { final String endOfLine = System.getProperty("line.separator", "\r\n"); PreprocessorUtils.findActiveFileInfoContainer(context) .ifPresent(t -> t.getIncludedSources().add(theFile)); return Value.valueOf(convertTo(theFile, type, doDeflate, lengthOfLine, endOfLine)); } catch (Exception ex) { throw context.makeException("Unexpected exception", ex); } } private enum Type { BASE64("base64"), BYTEARRAY("byte[]"), UINT8("uint8[]"), INT8("int8[]"); private final String name; Type(final String name) { this.name = name; } public static Type find(final String name) { Type result = null; if (name != null) { final String normalized = name.toLowerCase(Locale.ROOT).trim(); for (final Type t : values()) { if (normalized.startsWith(t.name)) { result = t; break; } } } return result; } public String getName() { return this.name; } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionDefinedByUser.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static com.igormaznitsa.jcp.expression.ExpressionTreeElement.ANY_ARITY; import static java.util.Objects.requireNonNull; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import com.igormaznitsa.jcp.extension.PreprocessorExtension; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * The class implements the user defined function handler (a function which name * starts with $) * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionDefinedByUser extends AbstractFunction { private static final List ARGS_0 = List.of(); private static final List ARGS_1 = List.of(ValueType.ANY); private static final List ARGS_2 = List.of(ValueType.ANY, ValueType.ANY); private static final List ARGS_3 = List.of(ValueType.ANY, ValueType.ANY, ValueType.ANY); private static final List ARGS_4 = List.of(ValueType.ANY, ValueType.ANY, ValueType.ANY, ValueType.ANY); private static final List ARGS_5 = List.of(ValueType.ANY, ValueType.ANY, ValueType.ANY, ValueType.ANY, ValueType.ANY); private final String name; private final Set allowedArities; private final List> argVariants; public FunctionDefinedByUser(final String name, final Set allowedArities, final PreprocessorContext context) { super(); requireNonNull(name, "Name is null"); requireNonNull(context, "Context is null"); this.name = name; this.allowedArities = Set.copyOf(allowedArities); if (this.allowedArities.contains(ANY_ARITY)) { this.argVariants = List.of(); } else { this.argVariants = new ArrayList<>(); for (final int arity : this.allowedArities) { final List record; switch (arity) { case 0: record = ARGS_0; break; case 1: record = ARGS_1; break; case 2: record = ARGS_2; break; case 3: record = ARGS_3; break; case 4: record = ARGS_4; break; case 5: record = ARGS_5; break; default: { record = IntStream.of(arity).mapToObj(x -> ValueType.ANY).collect(Collectors.toList()); } break; } this.argVariants.add(record); } } } @Override public String getName() { return name; } @Override public Set getArity() { return this.allowedArities; } public Value execute(final PreprocessorContext context, final List values) { final List extensionList = context.getPreprocessorExtensions(); if (extensionList.isEmpty()) { throw context .makeException( "Found user defined function, but there is not any preprocessor extension to process it", null); } final Set expectedArity = Set.of(values.size()); final PreprocessorExtension extension = extensionList.stream().filter(x -> x.hasUserFunction(this.name, expectedArity)) .findFirst().orElseThrow(() -> context .makeException( "Can't find any preprocessor extension to process function " + this.name + " for " + values.size() + " argument(s)", null)); context.logDebug("Processing " + this.name + '/' + values.size() + " by " + extension.getClass().getCanonicalName()); return extension.processUserFunction(context, name, values); } @Override public List> getAllowedArgumentTypes() { return this.argVariants; } @Override public String getReference() { return "user defined function"; } @Override public ValueType getResultType() { return ValueType.ANY; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionESC.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Locale; import java.util.Set; /** * The class implements escape function handler to escape strings to be used inside preprocessor string value definitions. */ public final class FunctionESC extends AbstractFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING)); @Override public String getName() { return "esc"; } public Value executeStr(final PreprocessorContext context, final Value source) { final String sourceString = source.asString(); final StringBuilder result = new StringBuilder(); for (int i = 0; i < sourceString.length(); i++) { final char chr = sourceString.charAt(i); switch (chr) { case '\n': result.append("\\n"); break; case '\t': result.append("\\t"); break; case '\b': result.append("\\b"); break; case '\f': result.append("\\f"); break; case '\r': result.append("\\r"); break; case '\\': result.append("\\\\"); break; case '\'': result.append("\\'"); break; case '\"': result.append("\\\""); break; default: { if (chr > 0x7F || Character.isISOControl(chr)) { String hexCode = Integer.toHexString(chr).toUpperCase(Locale.ROOT); if (hexCode.length() < 4) { hexCode = "0000".substring(0, 4 - hexCode.length()) + hexCode; } result.append("\\u").append(hexCode); } else { result.append(chr); } } } } return Value.valueOf(result.toString()); } @Override public Set getArity() { return ARITY_1; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "escape string chars"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionEVALFILE.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static com.igormaznitsa.jcp.utils.IOUtils.closeQuietly; import static com.igormaznitsa.jcp.utils.PreprocessorUtils.findActiveFileInfoContainer; import com.igormaznitsa.jcp.containers.FileInfoContainer; import com.igormaznitsa.jcp.context.CommentRemoverType; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.io.File; import java.io.StringWriter; import java.util.List; import java.util.Set; /** * The Function makes preprocessing of a file and return result as a string value. It uses the current preprocessor context as the context for preprocessing the file. * * @author Igor Maznitsa (...) */ public class FunctionEVALFILE extends AbstractFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING)); @Override public String getName() { return "evalfile"; } @Override public String getReference() { return "preprocess file and return result as string"; } @Override public Set getArity() { return ARITY_1; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public ValueType getResultType() { return ValueType.STRING; } private PreprocessorContext prepareContext(final PreprocessorContext base) { final PreprocessorContext result = new PreprocessorContext(base); result.setDryRun(true); result.setKeepLines(false); result.setClearTarget(false); result.setKeepComments(CommentRemoverType.REMOVE_C_STYLE); result.setCareForLastEol(true); return result; } public Value executeStr(final PreprocessorContext context, final Value strFilePath) { final String filePath = strFilePath.asString(); final File fileToEvaluate = context.findFileInSources(filePath); if (context.isVerbose()) { context.logForVerbose("Eval file '" + fileToEvaluate + '\''); } try { final FileInfoContainer fileContainer = new FileInfoContainer(fileToEvaluate, fileToEvaluate.getName(), false); final PreprocessorContext evalContext = this.prepareContext(context); final PreprocessingState state = fileContainer.preprocessFileWithNotification(evalContext, null, false); findActiveFileInfoContainer(context) .ifPresent(f -> { f.getIncludedSources().add(fileToEvaluate); f.getIncludedSources().addAll(evalContext.findAllInputFiles()); f.getGeneratedResources().addAll(evalContext.findAllProducedFiles()); }); final StringWriter strWriter = new StringWriter(1024); state.writePrinterBuffers(strWriter); closeQuietly(strWriter); return Value.valueOf(strWriter.toString()); } catch (Exception ex) { throw context.makeException("Unexpected exception", ex); } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionIS.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; /** * The class implements the IS function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionIS extends AbstractFunction { private static final List> SIGNATURES = List.of(List.of(ValueType.STRING, ValueType.ANY)); @Override public String getName() { return "is"; } // called through reflection! public Value executeStrAny( final PreprocessorContext context, final Value varName, final Value value) { final Value currentValue = context.findVariableForName(varName.asString(), false); Value result = Value.BOOLEAN_FALSE; if (currentValue != null) { result = value.toString().compareTo(currentValue.toString()) == 0 ? Value.BOOLEAN_TRUE : Value.BOOLEAN_FALSE; } return result; } @Override public Set getArity() { return ARITY_2; } @Override public List> getAllowedArgumentTypes() { return SIGNATURES; } @Override public String getReference() { return "check that string is string form of value"; } @Override public ValueType getResultType() { return ValueType.BOOLEAN; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionISSUBSTR.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; /** * The class implements the ISSUBSTR function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionISSUBSTR extends AbstractFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING, ValueType.STRING)); @Override public String getName() { return "issubstr"; } public Value executeStrStr(final PreprocessorContext context, final Value subStrValue, final Value strValue) { final String str = strValue.asString().toLowerCase(); final String subStr = subStrValue.asString().toLowerCase(); return Value.valueOf(str.contains(subStr)); } @Override public Set getArity() { return ARITY_2; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "check that string contains substring (case insensitive)"; } @Override public ValueType getResultType() { return ValueType.BOOLEAN; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionROUND.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; /** * The class implements the round function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionROUND extends AbstractFunction { private static final List> SIGNATURES = List.of(List.of(ValueType.FLOAT), List.of(ValueType.INT)); @Override public String getName() { return "round"; } public Value executeInt(final PreprocessorContext context, final Value value) { return value; } public Value executeFloat(final PreprocessorContext context, final Value value) { return Value.valueOf(Long.valueOf(Math.round(value.asFloat()))); } @Override public Set getArity() { return ARITY_1; } @Override public List> getAllowedArgumentTypes() { return SIGNATURES; } @Override public String getReference() { return "round float value to nearest integer"; } @Override public ValueType getResultType() { return ValueType.INT; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2CSV.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.apache.commons.text.StringEscapeUtils.escapeCsv; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; /** * The class implements the str2csv function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionSTR2CSV extends AbstractStrConverter { @Override public String getName() { return "str2csv"; } @Override public Value executeStr(final PreprocessorContext context, final Value value) { final String escaped = escapeCsv(value.asString()); return Value.valueOf(escaped); } @Override public String getReference() { return "escape string for CSV"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2GO.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.util.List; import java.util.Set; /** * The class implements escape function handler to escape strings to be used in Go. * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionSTR2GO extends AbstractFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING, ValueType.BOOLEAN)); private static String toUnicode(final char c) { final StringBuilder result = new StringBuilder(4); final String hex = Integer.toHexString(c); result.append("0".repeat(4 - hex.length())); result.append(hex); return result.toString(); } private static String escapeGo(final String value) { final StringBuilder result = new StringBuilder(); for (final char c : value.toCharArray()) { switch (c) { case '\u0007': result.append("\\a"); break; case '\u000b': result.append("\\v"); break; case '\b': result.append("\\b"); break; case '\f': result.append("\\f"); break; case '\n': result.append("\\n"); break; case '\r': result.append("\\r"); break; case '\t': result.append("\\t"); break; case '\\': result.append("\\\\"); break; case '\'': result.append("\\'"); break; case '\"': result.append("\\\""); break; case ' ': result.append(" "); break; default: { if (Character.isISOControl(c) || Character.isWhitespace(c) || c > 0xFF) { result.append("\\u").append(toUnicode(c)); } else { result.append(c); } } break; } } return result.toString(); } @Override public String getName() { return "str2go"; } // called through reflection public Value executeStrBool(final PreprocessorContext context, final Value source, final Value splitAndQuoteLines) { if (splitAndQuoteLines.asBoolean()) { final boolean endsWithNextLine = source.asString().endsWith("\n"); final List split = PreprocessorUtils.splitForCharAndHoldEmptyLine(source.asString(), '\n'); final StringBuilder result = new StringBuilder(source.asString().length() * 2); final String nextLineChars = PreprocessorUtils.getNextLineCodes(); int index = 0; for (final String s : split) { final boolean last = ++index == split.size(); if (result.length() > 0) { result.append(nextLineChars).append('+'); } result.append('\"').append(escapeGo(s)); if (last) { result.append(endsWithNextLine ? "\\n\"" : "\""); } else { result.append("\\n\""); } } return Value.valueOf(result.toString()); } else { return Value.valueOf(escapeGo(source.asString())); } } @Override public Set getArity() { return ARITY_2; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "escape string for GoLang"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2INT.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; /** * The class implements the str2int function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionSTR2INT extends AbstractStrConverter { @Override public String getName() { return "str2int"; } @Override public Value executeStr(final PreprocessorContext context, final Value value) { return Value.valueOf(Long.parseLong(value.asString().trim())); } @Override public String getReference() { return "string to integer"; } @Override public ValueType getResultType() { return ValueType.INT; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2JAVA.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.apache.commons.text.StringEscapeUtils.escapeJava; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.util.List; import java.util.Set; /** * The class implements escape function handler to escape strings to be used in java. * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionSTR2JAVA extends AbstractFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING, ValueType.BOOLEAN)); @Override public String getName() { return "str2java"; } public Value executeStrBool(final PreprocessorContext context, final Value source, final Value splitAndQuoteLines) { if (splitAndQuoteLines.asBoolean()) { final boolean endsWithNextLine = source.asString().endsWith("\n"); final List split = PreprocessorUtils.splitForCharAndHoldEmptyLine(source.asString(), '\n'); final StringBuilder result = new StringBuilder(source.asString().length() * 2); final String nextLineChars = PreprocessorUtils.getNextLineCodes(); int index = 0; for (final String s : split) { final boolean last = ++index == split.size(); if (result.length() > 0) { result.append(nextLineChars).append('+'); } result.append('\"').append(escapeJava(s)); if (last) { result.append(endsWithNextLine ? "\\n\"" : "\""); } else { result.append("\\n\""); } } return Value.valueOf(result.toString()); } else { return Value.valueOf(escapeJava(source.asString())); } } @Override public Set getArity() { return ARITY_2; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "escape string for Java"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2JS.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.apache.commons.text.StringEscapeUtils.escapeEcmaScript; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; /** * The class implements the str2js function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionSTR2JS extends AbstractStrConverter { @Override public String getName() { return "str2js"; } @Override public Value executeStr(final PreprocessorContext context, final Value value) { final String escaped = escapeEcmaScript(value.asString()); return Value.valueOf(escaped); } @Override public String getReference() { return "escape string for EcmaScript/JavaScript"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2JSON.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.apache.commons.text.StringEscapeUtils.escapeJson; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; /** * The class implements the str2json function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionSTR2JSON extends AbstractStrConverter { @Override public String getName() { return "str2json"; } @Override public Value executeStr(final PreprocessorContext context, final Value value) { final String escaped = escapeJson(value.asString()); return Value.valueOf(escaped); } @Override public String getReference() { return "escape string for JSON"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2WEB.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.apache.commons.text.StringEscapeUtils.escapeHtml3; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; /** * The class implements the str2web function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionSTR2WEB extends AbstractStrConverter { @Override public String getName() { return "str2web"; } @Override public Value executeStr(final PreprocessorContext context, final Value value) { final String escaped = escapeHtml3(value.asString()); final StringBuilder result = new StringBuilder(escaped.length() * 2); for (int i = 0; i < escaped.length(); i++) { final char ch = escaped.charAt(i); if (ch < 128) { result.append(ch); } else { result.append("&#").append(Character.codePointAt(escaped, i)).append(';'); } } return Value.valueOf(result.toString()); } @Override public String getReference() { return "escape string for HTML3"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2XML.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.apache.commons.text.StringEscapeUtils.escapeXml10; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; /** * The class implements the str2xml function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionSTR2XML extends AbstractStrConverter { @Override public String getName() { return "str2xml"; } @Override public Value executeStr(final PreprocessorContext context, final Value value) { final String escaped = escapeXml10(value.asString()); return Value.valueOf(escaped); } @Override public String getReference() { return "escape string for XML(1.0)"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionSTRLEN.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; /** * The class implements the STRLEN function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionSTRLEN extends AbstractFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING)); @Override public String getName() { return "strlen"; } public Value executeStr(final PreprocessorContext context, final Value value) { return Value.valueOf(Long.valueOf(value.asString().length())); } @Override public Set getArity() { return ARITY_1; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "get string length"; } @Override public ValueType getResultType() { return ValueType.INT; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/FunctionTRIMLINES.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import com.igormaznitsa.jcp.utils.PreprocessorUtils; /** * The class implements the TRIMLINES function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionTRIMLINES extends AbstractStrConverter { @Override public String getName() { return "trimlines"; } @Override public Value executeStr(final PreprocessorContext context, final Value value) { final String text = value.asString(); final StringBuilder result = new StringBuilder(text.length()); for (final String s : PreprocessorUtils.splitForChar(text, '\n')) { final String trimmed = s.trim(); if (!trimmed.isEmpty()) { if (result.length() > 0) { result.append(PreprocessorUtils.getNextLineCodes()); } result.append(trimmed); } } return Value.valueOf(result.toString()); } @Override public String getReference() { return "trim each line found in string, remove empty lines"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/xml/AbstractXMLFunction.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.functions.AbstractFunction; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.apache.xpath.jaxp.XPathFactoryImpl; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public abstract class AbstractXMLFunction extends AbstractFunction { public static String makeElementListId(final Element parentName, final String elementName) { return buildPathForElement(parentName) + "_#list_" + elementName; } public static String makeDocumentId(final String fileName) { return "xmlDocument_" + fileName; } public static String makeDocumentRootId(final String documentId) { return documentId + "_#root"; } public static String makeElementId(final String elementListId, final int elementIndex) { return elementListId + '_' + elementIndex; } public static String makeXPathListId(final String documentId, final String xpath) { return documentId + "_#xpath_" + xpath; } public static String makeXPathElementId(final String documentId, final String xpath) { return documentId + "_#xpathelement_" + xpath; } public static String buildPathForElement(final Element element) { final StringBuilder result = new StringBuilder(); Node theNode = element; while (theNode != null) { int level = 0; Node sibling = theNode; while (sibling != null) { level++; sibling = sibling.getPreviousSibling(); } result.append('/').append(theNode.getNodeName()).append('{').append(level).append('}'); theNode = theNode.getParentNode(); } return result.toString(); } public static String getFirstLevelTextContent(final Node node) { final NodeList list = node.getChildNodes(); final StringBuilder textContent = new StringBuilder(128); for (int i = 0; i < list.getLength(); ++i) { final Node child = list.item(i); if (child.getNodeType() == Node.TEXT_NODE) { textContent.append(child.getTextContent()); } } return textContent.toString(); } protected static XPathExpression prepareXPathExpression(final String path) throws XPathExpressionException { final XPathFactory factory = new XPathFactoryImpl(); final XPath xpath = factory.newXPath(); return xpath.compile(path); } public String getAttribute(final PreprocessorContext context, final String elementId, final String attributeName) { final NodeContainer container = (NodeContainer) context.getSharedResource(elementId); if (container == null) { throw context .makeException("Can't find any active element with the '" + elementId + "' id", null); } try { return ((Element) container.getNode()).getAttribute(attributeName); } catch (ClassCastException ex) { throw context.makeException( "Incompatible cached element type [" + elementId + '.' + attributeName + ']', ex); } } public Document getCachedDocument(final PreprocessorContext context, final String documentId) { final NodeContainer container = (NodeContainer) context.getSharedResource(documentId); if (container == null) { throw context .makeException("Can't find any document for the '" + documentId + "' id", null); } try { return (Document) container.getNode(); } catch (ClassCastException ex) { throw context.makeException("Incompatible cached element type [" + documentId + ']', ex); } } public Element findCachedElement(final PreprocessorContext context, final String elementId) { final NodeContainer container = (NodeContainer) context.getSharedResource(elementId); if (container == null) { return null; } try { return (Element) container.getNode(); } catch (ClassCastException ex) { throw context.makeException("Incompatible cached element type [" + elementId + ']', null); } } public Element getCachedElement(final PreprocessorContext context, final String elementId) { final Element element = findCachedElement(context, elementId); if (element == null) { throw context .makeException("Can't find any active element for the '" + elementId + "' id", null); } return element; } public NodeList findCachedElementList(final PreprocessorContext context, final String elementListId) { final NodeContainer container = (NodeContainer) context.getSharedResource(elementListId); if (container == null) { return null; } try { return container.getNodeList(); } catch (ClassCastException ex) { throw context.makeException("Incompatible cached element type [" + elementListId + ']', ex); } } public NodeList getCachedElementList(final PreprocessorContext context, final String elementListId) { final NodeList result = findCachedElementList(context, elementListId); if (result == null) { throw context .makeException("Can't find any active element list for the '" + elementListId + "' id", null); } return result; } public int getElementListSize(final PreprocessorContext context, final String elementListId) { return getCachedElementList(context, elementListId).getLength(); } public String findElementForIndex(final PreprocessorContext context, final String elementListId, final int elementIndex) { final String elementCacheId = makeElementId(elementListId, elementIndex); NodeContainer container = (NodeContainer) context.getSharedResource(elementCacheId); if (container == null) { container = (NodeContainer) context.getSharedResource(elementListId); if (container == null) { throw context .makeException("Can't find any active node list for the id '" + elementListId + '\'', null); } final NodeList list = container.getNodeList(); if (elementIndex < 0 || elementIndex >= list.getLength()) { throw context .makeException("The Element Index is out of bounds [" + elementIndex + ']', null); } final Element element = (Element) list.item(elementIndex); if (element == null) { throw context.makeException("Wrong index [" + elementIndex + ']', null); } container = new NodeContainer(UID_COUNTER.getAndIncrement(), element); context.setSharedResource(elementCacheId, container); } return elementCacheId; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_ATTR.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; /** * The class implements the xml_attr function * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionXML_ATTR extends AbstractXMLFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING, ValueType.STRING)); @Override public String getName() { return "xml_attr"; } public Value executeStrStr(final PreprocessorContext context, final Value elementId, final Value attributeName) { return Value.valueOf(getAttribute(context, elementId.asString(), attributeName.asString())); } @Override public Set getArity() { return ARITY_2; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "get value of named element attribute, if not found then empty string"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_GET.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; /** * The class implements the xml_get function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionXML_GET extends AbstractXMLFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING, ValueType.INT)); @Override public String getName() { return "xml_get"; } public Value executeStrInt(final PreprocessorContext context, final Value elementListId, final Value elementIndex) { return Value.valueOf( findElementForIndex(context, elementListId.asString(), elementIndex.asLong().intValue())); } @Override public Set getArity() { return ARITY_2; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "get positioned element from list by index (0 based)"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_LIST.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.w3c.dom.Element; import org.w3c.dom.NodeList; /** * The class implements the xml_list function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionXML_LIST extends AbstractXMLFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING, ValueType.STRING)); @Override public String getName() { return "xml_list"; } public Value executeStrStr(final PreprocessorContext context, final Value elementId, final Value elementTag) { final String tagName = elementTag.asString(); final Element element = getCachedElement(context, elementId.asString()); final String listId = makeElementListId(element, tagName); NodeContainer container = (NodeContainer) context.getSharedResource(listId); if (container == null) { final NodeList list = element.getElementsByTagName(tagName); container = new NodeContainer(UID_COUNTER.getAndIncrement(), list); context.setSharedResource(listId, container); } return Value.valueOf(listId); } @Override public Set getArity() { return ARITY_2; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "get list of elements by tag name"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_NAME.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.w3c.dom.Element; /** * The class implements the xml_name function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionXML_NAME extends AbstractXMLFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING)); @Override public String getName() { return "xml_name"; } public Value executeStr(final PreprocessorContext context, final Value elementId) { final Element cachedElement = getCachedElement(context, elementId.asString()); return Value.valueOf(cachedElement.getTagName()); } @Override public Set getArity() { return ARITY_1; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "get element name (tag)"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_OPEN.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import static com.igormaznitsa.jcp.utils.PreprocessorUtils.findActiveFileInfoContainer; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Set; import javax.xml.parsers.ParserConfigurationException; import org.apache.xerces.jaxp.DocumentBuilderFactoryImpl; import org.w3c.dom.Document; import org.xml.sax.SAXException; /** * The class implements the xml_open function handler * * @author Igor Maznits (igor.maznitsa@igormaznitsa.com) */ public final class FunctionXML_OPEN extends AbstractXMLFunction { public static final String RES_XML_DOC_PREFIX = "xml_doc_"; public static final String RES_XML_ELEMENT_PREFIX = "xml_elem_"; private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING)); @Override public String getName() { return "xml_open"; } public Value executeStr(final PreprocessorContext context, final Value filePath) { final String name = filePath.asString(); final String documentId = makeDocumentId(name); final String documentIdRoot = makeDocumentRootId(documentId); NodeContainer docContainer = (NodeContainer) context.getSharedResource(documentId); if (docContainer == null) { final File file = context.findFileInSources(name); final Document document = openFileAndParse(context, file); findActiveFileInfoContainer(context) .ifPresent(t -> t.getIncludedSources().add(file)); docContainer = new NodeContainer(UID_COUNTER.getAndIncrement(), document); context.setSharedResource(documentId, docContainer); final NodeContainer rootContainer = new NodeContainer(UID_COUNTER.getAndIncrement(), document.getDocumentElement()); context.setSharedResource(documentIdRoot, rootContainer); } return Value.valueOf(documentId); } private Document openFileAndParse(final PreprocessorContext context, final File file) { final DocumentBuilderFactoryImpl docBuilderFactory = new DocumentBuilderFactoryImpl(); docBuilderFactory.setIgnoringComments(true); docBuilderFactory.setCoalescing(true); docBuilderFactory.setValidating(false); try { return docBuilderFactory.newDocumentBuilder().parse(file); } catch (ParserConfigurationException unexpected) { throw context.makeException("XML parser configuration exception", unexpected); } catch (SAXException unexpected) { throw context.makeException("Exception during XML parsing", unexpected); } catch (IOException unexpected) { throw context.makeException("Can't read XML file", unexpected); } } @Override public Set getArity() { return ARITY_1; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "open and parse XML file"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_ROOT.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; /** * The class implements the xml_getroot function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionXML_ROOT extends AbstractXMLFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING)); @Override public String getName() { return "xml_root"; } public Value executeStr(final PreprocessorContext context, final Value documentId) { final String documentRootId = makeDocumentRootId(documentId.asString()); final NodeContainer root = (NodeContainer) context.getSharedResource(documentRootId); if (root == null) { throw context.makeException("Can't find any root for document [" + documentId + ']', null); } return Value.valueOf(documentRootId); } @Override public Set getArity() { return ARITY_1; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "get root element of document"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_SIZE.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; /** * The class implements the xml_elementsnumber function * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionXML_SIZE extends AbstractXMLFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING)); @Override public String getName() { return "xml_size"; } public Value executeStr(final PreprocessorContext context, final Value elementListId) { return Value.valueOf(Long.valueOf(getElementListSize(context, elementListId.asString()))); } @Override public Set getArity() { return ARITY_1; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "element list size"; } @Override public ValueType getResultType() { return ValueType.INT; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_TEXT.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.w3c.dom.Element; /** * The class implements the xml_getelementtext function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionXML_TEXT extends AbstractXMLFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING)); @Override public String getName() { return "xml_text"; } public Value executeStr(final PreprocessorContext context, final Value elementid) { final Element element = getCachedElement(context, elementid.asString()); return Value.valueOf(element.getTextContent()); } @Override public Set getArity() { return ARITY_1; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "text of element (child element texts will be included)"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_XELEMENT.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * The class implements the xml_xpathelement function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionXML_XELEMENT extends AbstractXMLFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING, ValueType.STRING)); @Override public String getName() { return "xml_xelement"; } public Value executeStrStr(final PreprocessorContext context, final Value documentId, final Value xPath) { final String documentIdStr = documentId.asString(); final String pathStr = xPath.asString(); final String xpathElementId = makeXPathElementId(documentIdStr, pathStr); final Document document = getCachedDocument(context, documentIdStr); Element elem = findCachedElement(context, xpathElementId); if (elem == null) { try { final XPathExpression expression = prepareXPathExpression(pathStr); elem = (Element) expression.evaluate(document, XPathConstants.NODE); if (elem == null) { throw context.makeException("Can't find element for xpath [" + pathStr + ']', null); } } catch (XPathExpressionException ex) { throw context.makeException("Error during XPath compilation [" + pathStr + ']', ex); } catch (ClassCastException ex) { throw context.makeException("Can't get element for XPath [" + pathStr + ']', ex); } final NodeContainer container = new NodeContainer(UID_COUNTER.getAndIncrement(), elem); context.setSharedResource(xpathElementId, container); } return Value.valueOf(xpathElementId); } @Override public Set getArity() { return ARITY_2; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "find single element with XPath, error if not found"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_XLIST.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import org.w3c.dom.Document; import org.w3c.dom.NodeList; /** * The class implements the xml_xpathlist function handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class FunctionXML_XLIST extends AbstractXMLFunction { private static final List> ARG_TYPES = List.of(List.of(ValueType.STRING, ValueType.STRING)); @Override public String getName() { return "xml_xlist"; } public Value executeStrStr(final PreprocessorContext context, final Value documentId, final Value xPath) { final String documentIdStr = documentId.asString(); final String pathStr = xPath.asString(); final String xpathId = makeXPathListId(documentIdStr, pathStr); final Document document = getCachedDocument(context, documentIdStr); NodeList list = findCachedElementList(context, xpathId); if (list == null) { try { final XPathExpression expression = prepareXPathExpression(pathStr); list = (NodeList) expression.evaluate(document, XPathConstants.NODESET); } catch (XPathExpressionException ex) { throw context.makeException("Error during XPath compilation [" + pathStr + ']', ex); } final NodeContainer container = new NodeContainer(UID_COUNTER.getAndIncrement(), list); context.setSharedResource(xpathId, container); } return Value.valueOf(xpathId); } @Override public Set getArity() { return ARITY_2; } @Override public List> getAllowedArgumentTypes() { return ARG_TYPES; } @Override public String getReference() { return "find element list with XPath"; } @Override public ValueType getResultType() { return ValueType.STRING; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/functions/xml/NodeContainer.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import java.util.Objects; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * It's a special auxiliary class to save XML node data in a preprocessor * storage * * @author Igor Maznitsa (igor.maznitsa@igormaznnitsa.com) */ public class NodeContainer { private final Node node; private final NodeList nodeList; private final long id; public NodeContainer(final long id, final Node node) { Objects.requireNonNull(node, "Node is null"); this.id = id; this.node = node; this.nodeList = null; } public NodeContainer(final long id, final NodeList list) { Objects.requireNonNull(list, "NodeList is null"); this.id = id; this.node = null; this.nodeList = list; } public NodeList getNodeList() { return this.nodeList; } public Node getNode() { return this.node; } public long getId() { return this.id; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/AbstractOperator.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItem; import com.igormaznitsa.jcp.expression.ExpressionItemType; import java.util.List; import java.util.concurrent.atomic.AtomicReference; /** * The class is the base for all operator handlers * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public abstract class AbstractOperator implements ExpressionItem { /** * The constant is the prefix for executing methods of operators */ public static final String EXECUTION_PREFIX = "execute"; /** * The list contains operators allowed by the preprocessor */ private static final AtomicReference> allOperators = new AtomicReference<>(); @SuppressWarnings("StaticInitializerReferencesSubClass") private static final List DEFAULT_OPERATORS = List.of( new OperatorEQU(), new OperatorGREAT(), new OperatorGREATEQU(), new OperatorLESS(), new OperatorLESSEQU(), new OperatorNOTEQU(), new OperatorADD(), new OperatorSUB(), new OperatorMUL(), new OperatorDIV(), new OperatorMOD(), new OperatorNOT(), new OperatorAND(), new OperatorOR(), new OperatorXOR() ); public static List getAllOperators() { final List current = allOperators.get(); if (current == null) { return DEFAULT_OPERATORS; } return current; } /** * Find an operator handler for its class * * @param the handler class extends AbstractOperator * @param operatorClass the class to be used for search, must not be null * @return an instance of the handler or null if there is not any such one */ public static E findForClass(final Class operatorClass) { for (final AbstractOperator operator : getAllOperators()) { if (operator.getClass() == operatorClass) { return operatorClass.cast(operator); } } return null; } /** * Get the expression item type * * @return for operators it is always ExpressionItemType.OPERATOR */ @Override public ExpressionItemType getExpressionItemType() { return ExpressionItemType.OPERATOR; } /** * Get the operator arity * * @return the operator arity (1 or 2) */ public abstract int getArity(); /** * Get the operator keyword * * @return the operator keyword, must not be null */ public abstract String getKeyword(); /** * Get the operator reference to be shown for a help information request * * @return the operator reference as a String, must not be null */ public abstract String getReference(); @Override public String toString() { return "OPERATOR: " + getKeyword(); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorADD.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the ADD operator handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class OperatorADD extends AbstractOperator { @Override public int getArity() { return 2; } @Override public String getReference() { return "additive operator (supports string concatenation)"; } @Override public String getKeyword() { return "+"; } public Value executeIntInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() + arg2.asLong()); } public Value executeFloatFloat(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asFloat() + arg2.asFloat()); } public Value executeIntFloat(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong().floatValue() + arg2.asFloat()); } public Value executeFloatInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asFloat() + arg2.asLong().floatValue()); } public Value executeStrAny(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asString() + arg2.toString()); } public Value executeAnyStr(final Value arg1, final Value arg2) { return Value.valueOf(arg1.toString() + arg2.asString()); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.ARITHMETIC_ADD_SUB; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorAND.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the AND operator handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class OperatorAND extends AbstractOperator { @Override public int getArity() { return 2; } @Override public String getReference() { return "conditional AND & bitwise AND"; } @Override public String getKeyword() { return "&&"; } public Value executeIntInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() & arg2.asLong()); } public Value executeBoolBool(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asBoolean() && arg2.asBoolean()); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.LOGICAL; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorDIV.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the DIV operator handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class OperatorDIV extends AbstractOperator { @Override public int getArity() { return 2; } @Override public String getReference() { return "division"; } @Override public String getKeyword() { return "/"; } public Value executeIntInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() / arg2.asLong()); } public Value executeIntFloat(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() / arg2.asFloat()); } public Value executeFloatInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asFloat() / arg2.asLong()); } public Value executeFloatFloat(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asFloat() / arg2.asFloat()); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.ARITHMETIC_MUL_DIV_MOD; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorEQU.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the EQU operator handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class OperatorEQU extends AbstractOperator { @Override public int getArity() { return 2; } @Override public String getReference() { return "equal to"; } @Override public String getKeyword() { return "=="; } public Value executeIntInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() == arg2.asLong().longValue()); } public Value executeFloatInt(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asFloat(), arg2.asLong().floatValue()) == 0); } public Value executeIntFloat(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asLong().floatValue(), arg2.asFloat()) == 0); } public Value executeFloatFloat(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asFloat(), arg2.asFloat()) == 0); } public Value executeStrStr(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asString().equals(arg2.asString())); } public Value executeBoolBool(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asBoolean() == arg2.asBoolean().booleanValue()); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.COMPARISON; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorGREAT.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the GREAT operator handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class OperatorGREAT extends AbstractOperator { @Override public int getArity() { return 2; } @Override public String getReference() { return "greater than"; } @Override public String getKeyword() { return ">"; } public Value executeIntInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() > arg2.asLong()); } public Value executeFloatInt(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asFloat(), arg2.asLong().floatValue()) > 0); } public Value executeIntFloat(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asLong().floatValue(), arg2.asFloat()) > 0); } public Value executeFloatFloat(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asFloat(), arg2.asFloat()) > 0); } public Value executeStrStr(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asString().compareTo(arg2.asString()) > 0); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.COMPARISON; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorGREATEQU.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the GREATEQU operator handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class OperatorGREATEQU extends AbstractOperator { @Override public int getArity() { return 2; } @Override public String getReference() { return "greater than or equal to"; } @Override public String getKeyword() { return ">="; } public Value executeIntInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() >= arg2.asLong()); } public Value executeFloatInt(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asFloat(), arg2.asLong().floatValue()) >= 0); } public Value executeIntFloat(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asLong().floatValue(), arg2.asFloat()) >= 0); } public Value executeFloatFloat(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asFloat(), arg2.asFloat()) >= 0); } public Value executeStrStr(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asString().compareTo(arg2.asString()) >= 0); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.COMPARISON; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorLESS.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the LESS operator handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class OperatorLESS extends AbstractOperator { @Override public int getArity() { return 2; } @Override public String getReference() { return "less than"; } @Override public String getKeyword() { return "<"; } public Value executeIntInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() < arg2.asLong()); } public Value executeFloatInt(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asFloat(), arg2.asLong().floatValue()) < 0); } public Value executeIntFloat(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asLong().floatValue(), arg2.asFloat()) < 0); } public Value executeFloatFloat(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asFloat(), arg2.asFloat()) < 0); } public Value executeStrStr(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asString().compareTo(arg2.asString()) < 0); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.COMPARISON; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorLESSEQU.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the LESSEQU operator handler * * @author igorm */ public final class OperatorLESSEQU extends AbstractOperator { @Override public int getArity() { return 2; } @Override public String getReference() { return "less than or equal to"; } @Override public String getKeyword() { return "<="; } public Value executeIntInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() <= arg2.asLong()); } public Value executeFloatInt(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asFloat(), arg2.asLong().floatValue()) <= 0); } public Value executeIntFloat(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asLong().floatValue(), arg2.asFloat()) <= 0); } public Value executeFloatFloat(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asFloat(), arg2.asFloat()) <= 0); } public Value executeStrStr(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asString().compareTo(arg2.asString()) <= 0); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.COMPARISON; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorMOD.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the MOD operator handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class OperatorMOD extends AbstractOperator { @Override public int getArity() { return 2; } @Override public String getReference() { return "remainder"; } @Override public String getKeyword() { return "%"; } public Value executeIntInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() % arg2.asLong()); } public Value executeIntFloat(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong().floatValue() % arg2.asFloat()); } public Value executeFloatInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asFloat() % arg2.asLong().floatValue()); } public Value executeFloatFloat(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asFloat() % arg2.asFloat()); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.ARITHMETIC_MUL_DIV_MOD; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorMUL.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the MOD operator handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class OperatorMUL extends AbstractOperator { @Override public int getArity() { return 2; } @Override public String getReference() { return "multiplication"; } @Override public String getKeyword() { return "*"; } public Value executeIntInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() * arg2.asLong()); } public Value executeIntFloat(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong().floatValue() * arg2.asFloat()); } public Value executeFloatInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asFloat() * arg2.asLong().floatValue()); } public Value executeFloatFloat(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asFloat() * arg2.asFloat()); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.ARITHMETIC_MUL_DIV_MOD; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorNOT.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the NOT operator handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class OperatorNOT extends AbstractOperator { @Override public int getArity() { return 1; } @Override public String getReference() { return "logical & bitwise NOT"; } @Override public String getKeyword() { return "!"; } public Value executeInt(final Value arg1) { return Value.valueOf(~arg1.asLong()); } public Value executeBool(final Value arg1) { return Value.valueOf(!arg1.asBoolean()); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.FUNCTION; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorNOTEQU.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the NOTEQU operator handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class OperatorNOTEQU extends AbstractOperator { @Override public int getArity() { return 2; } @Override public String getReference() { return "not equal to"; } @Override public String getKeyword() { return "!="; } public Value executeIntInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() != arg2.asLong().longValue()); } public Value executeFloatInt(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asFloat(), arg2.asLong().floatValue()) != 0); } public Value executeIntFloat(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asLong().floatValue(), arg2.asFloat()) != 0); } public Value executeFloatFloat(final Value arg1, final Value arg2) { return Value.valueOf(Float.compare(arg1.asFloat(), arg2.asFloat()) != 0); } public Value executeStrStr(final Value arg1, final Value arg2) { return Value.valueOf(!arg1.asString().equals(arg2.asString())); } public Value executeBoolBool(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asBoolean() != arg2.asBoolean().booleanValue()); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.COMPARISON; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorOR.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the OR operator handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class OperatorOR extends AbstractOperator { @Override public int getArity() { return 2; } @Override public String getReference() { return "conditional OR & bitwise OR"; } @Override public String getKeyword() { return "||"; } public Value executeIntInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() | arg2.asLong()); } public Value executeBoolBool(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asBoolean() || arg2.asBoolean()); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.LOGICAL; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorSUB.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the SUB operator handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class OperatorSUB extends AbstractOperator { @Override public int getArity() { return 2; } @Override public String getReference() { return "subtraction"; } @Override public String getKeyword() { return "-"; } public Value executeIntInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() - arg2.asLong()); } public Value executeIntFloat(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong().floatValue() - arg2.asFloat()); } public Value executeFloatInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asFloat() - arg2.asLong().floatValue()); } public Value executeFloatFloat(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asFloat() - arg2.asFloat()); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.ARITHMETIC_ADD_SUB; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/expression/operators/OperatorXOR.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; /** * The class implements the XOR operator handler * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class OperatorXOR extends AbstractOperator { @Override public int getArity() { return 2; } @Override public String getReference() { return "conditional XOR & bitwise XOR"; } @Override public String getKeyword() { return "^"; } public Value executeIntInt(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asLong() ^ arg2.asLong()); } public Value executeBoolBool(final Value arg1, final Value arg2) { return Value.valueOf(arg1.asBoolean() ^ arg2.asBoolean()); } @Override public ExpressionItemPriority getExpressionItemPriority() { return ExpressionItemPriority.LOGICAL; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/extension/LogPreprocessorExtension.java ================================================ package com.igormaznitsa.jcp.extension; import com.igormaznitsa.jcp.containers.TextFileDataContainer; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * Preprocessor extension which just make info logging for arguments of action calls and also * can log user function calls, their arity should be provided in the end of function name like '$hello2(1,2)' * It is for internal test purposes to log all calls of user defined functions. * * @since 7.1.2 */ public class LogPreprocessorExtension implements PreprocessorExtension { private static final Pattern PATTERN = Pattern.compile("^(\\D+)(\\d+)?$"); private static String findPosition(final PreprocessorContext context) { if (context == null) { return ""; } if (context.getPreprocessingState().getIncludeStack().isEmpty()) { return ""; } else { final TextFileDataContainer dataContainer = context.getPreprocessingState().getIncludeStack().get(0); return (dataContainer.getFile() == null ? "" : dataContainer.getFile().getName()) + ':' + (dataContainer.getLastReadStringIndex() + 1); } } @Override public boolean hasAction(int arity) { return true; } @Override public boolean hasUserFunction(String name, Set arity) { return true; } @Override public boolean processAction(final PreprocessorContext context, final List parameters) { context.logInfo(String.format("Called action: %s at %s", parameters.stream().map( Value::toString).collect(Collectors.joining(",")), findPosition(context))); return true; } @Override public Value processUserFunction(final PreprocessorContext context, final String functionName, final List arguments) { context.logInfo( String.format("Called user function '%s'(%s) at %s", functionName, arguments, findPosition(context))); return Value.BOOLEAN_TRUE; } @Override public Set getUserFunctionArity(final String functionName) { final Matcher matcher = PATTERN.matcher(functionName); if (matcher.find() && matcher.group(2) != null) { return Set.of(Integer.parseInt(matcher.group(2))); } return Set.of(0); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/extension/PreprocessorExtension.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.extension; import com.igormaznitsa.jcp.context.ExecutionAllowable; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.context.PreprocessorContextAware; import com.igormaznitsa.jcp.expression.Value; import java.util.List; import java.util.Set; /** * The interface describes an extension which can be connected to a preprocessor * and to be notified about some calls and actions * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public interface PreprocessorExtension extends PreprocessorContextAware, ExecutionAllowable { @Override default boolean isAllowed(PreprocessorContext context) { return true; } /** * Allows to check that the extension contains an action with required number of parameters. * * @param arity number of parameters for action, zero or great * @return true if such action is provided by the extension * @since 7.2.2 */ boolean hasAction(int arity); /** * Allows to check that the extension contains a user defined function with required number of parameters. * * @param name name of the function to be checked, must not be null * @param arity set of numbers of parameters for action, if empty set then check only name * @return true if such user defined function is provided by the extension * @since 7.3.0 */ boolean hasUserFunction(String name, Set arity); /** * To process an action (it will be called if the preprocessor is met * //#action directive) * * @param context the current preprocessor context, must not be null * @param parameters the parameters of the action directive, must not be null * @return true if the action has been processed successfully or false, if it * is false then exception will be thrown and preprocessing will be stopped * @since 7.3.0 */ boolean processAction(PreprocessorContext context, List parameters); /** * Call to process a user function (such functions start with $) * * @param context the current preprocessor context, must not be null * @param functionName the name of the function (without $ and in low case), * must not be null * @param arguments the function arguments, must not be null * @return a calculated value, it must not be null * @since 7.3.0 */ Value processUserFunction(PreprocessorContext context, String functionName, List arguments); /** * When a preprocessor meets a user defined function (the function starts with * $) then it will ask for its arity * * @param functionName the function name without $ and in low case, must not * be null * @return the function arity (the argument number), zero or a great values * @since 7.3.0 */ Set getUserFunctionArity(String functionName); } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/gradle/JcpGradlePlugin.java ================================================ package com.igormaznitsa.jcp.gradle; import org.gradle.api.Plugin; import org.gradle.api.Project; public class JcpGradlePlugin implements Plugin { @Override public void apply(final Project project) { project.getTasks().create(JcpTask.ID, JcpTask.class); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/gradle/JcpTask.java ================================================ package com.igormaznitsa.jcp.gradle; import static com.igormaznitsa.jcp.utils.PreprocessorUtils.fillContextByFoundServices; import static com.igormaznitsa.jcp.utils.PreprocessorUtils.findAndInstantiatePreprocessorExtensionForClassName; import static com.igormaznitsa.jcp.utils.PreprocessorUtils.findCommentRemoverForId; import static java.util.Collections.emptyMap; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.logger.PreprocessorLogger; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.function.Supplier; import java.util.stream.Collectors; import javax.inject.Inject; import org.apache.commons.io.FilenameUtils; import org.gradle.api.DefaultTask; import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.file.FileCollection; import org.gradle.api.logging.Logger; import org.gradle.api.model.ObjectFactory; import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.MapProperty; import org.gradle.api.provider.Property; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.OutputFiles; import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskExecutionException; import org.gradle.execution.commandline.TaskConfigurationException; public class JcpTask extends DefaultTask { public static final String ID = "preprocess"; /** * Source root folders for preprocessing, if it is empty then project provided * folders will be used. */ private final ListProperty sources; /** * End of line string to be used in reprocessed results. It supports java * escaping chars. */ private final Property eol; /** * Keep attributes for preprocessing file and copy them to result one. */ private final Property keepAttributes; /** * Target folder to place preprocessing result in regular source processing * phase. */ private final Property target; /** * Encoding for text read operations. */ private final Property sourceEncoding; /** * Encoding for text write operations. */ private final Property targetEncoding; /** * Property contains preprocessor action extension class names or blank string if not provided. * The class must have the default constructor. * * @see com.igormaznitsa.jcp.extension.PreprocessorExtension * @since 7.2.2 */ private final ListProperty actionPreprocessorExtensions; /** * Flag to ignore missing source folders, if false then mojo fail for any * missing source folder, if true then missing folder will be ignored. */ private final Property ignoreMissingSources; /** * List of file extensions to be excluded from preprocessing. By default * excluded xml. */ private final ListProperty excludeExtensions; /** * List of file extensions to be included into preprocessing. By default * java,txt,htm,html */ private final ListProperty fileExtensions; /** * Interpret unknown variable as containing boolean false flag. */ private final Property unknownVarAsFalse; /** * Dry run, making pre-processing but without output */ private final Property dryRun; /** * Allow merge preprocessed lines marked as block text for external processing. * * @since 7.2.0 */ private final Property allowBlocks; /** * Verbose mode. */ private final Property verbose; /** * Clear target folder if it exists. */ private final Property clearTarget; /** * Set base directory which will be used for relative source paths. * By default it is '$projectDir'. */ private final Property baseDir; /** * Carefully reproduce last EOL in result files. */ private final Property careForLastEol; /** * Keep comments in result files. */ private final Property keepComments; /** * List of variables to be registered in preprocessor as global ones. */ private final MapProperty vars; /** * List of patterns of folder paths to be excluded from preprocessing, It uses * ANT path pattern format. */ private final ListProperty excludeFolders; /** * List of external files containing variable definitions. */ private final ListProperty configFiles; /** * Keep preprocessing directives in result files as commented ones, it is * useful to not break line numeration in result files. */ private final Property keepLines; /** * Turn on support of white spaces in preprocessor directives between '//' and * the '#'. */ private final Property allowWhitespaces; /** * Preserve indents in lines marked by '//$' and '//$$' directives. Directives * will be replaced by white spaces chars. */ private final Property preserveIndents; /** * Turn on check of content body compare with existing result file to prevent * overwriting, if content is the same then preprocessor will not be writing * new result content. */ private final Property dontOverwriteSameContent; /** * Collection of all files which have been generated during preprocessing. */ private final ConfigurableFileCollection outcomingFiles; /** * Collection of all files which have been used for preprocessing (including configuration files) */ private final ConfigurableFileCollection incomingFiles; @Inject public JcpTask(final ObjectFactory factory) { this.actionPreprocessorExtensions = factory.listProperty(String.class); this.allowWhitespaces = factory.property(Boolean.class).convention(false); this.careForLastEol = factory.property(Boolean.class).convention(false); this.clearTarget = factory.property(Boolean.class).convention(false); this.dontOverwriteSameContent = factory.property(Boolean.class).convention(false); this.dryRun = factory.property(Boolean.class).convention(false); this.allowBlocks = factory.property(Boolean.class).convention(false); this.ignoreMissingSources = factory.property(Boolean.class).convention(false); this.keepAttributes = factory.property(Boolean.class).convention(false); this.keepComments = factory.property(Object.class).convention(false); this.keepLines = factory.property(Boolean.class).convention(true); this.preserveIndents = factory.property(Boolean.class).convention(false); this.unknownVarAsFalse = factory.property(Boolean.class).convention(false); this.verbose = factory.property(Boolean.class).convention(false); this.targetEncoding = factory.property(String.class).convention(StandardCharsets.UTF_8.name()); this.sourceEncoding = factory.property(String.class).convention(StandardCharsets.UTF_8.name()); this.eol = factory.property(String.class).convention(System.lineSeparator()); this.vars = factory.mapProperty(String.class, Object.class); this.sources = factory.listProperty(File.class); this.configFiles = factory.listProperty(String.class); this.excludeExtensions = factory.listProperty(String.class).convention(Collections.singletonList("xml")); this.excludeFolders = factory.listProperty(String.class); this.fileExtensions = factory.listProperty(String.class) .convention(new ArrayList<>(Arrays.asList("java", "txt", "htm", "html"))); this.baseDir = factory.property(File.class).convention(this.getProject().getProjectDir()); this.target = factory.property(File.class).convention(new File(this.getProject().getBuildDir(), "java-comment-preprocessor" + File.separatorChar + this.getTaskIdentity().name)); this.incomingFiles = factory.fileCollection(); this.outcomingFiles = factory.fileCollection(); } @OutputFiles public FileCollection getOutcomingFiles() { return this.outcomingFiles; } @Internal public FileCollection getIncomingFiles() { return this.incomingFiles; } @Internal @Override public String getDescription() { return "Preprocess sources and resources with JCP"; } @InputFiles public ListProperty getSources() { return this.sources; } @Input public Property getEol() { return this.eol; } @Input public Property getKeepAttributes() { return this.keepAttributes; } @Input public Property getTarget() { return this.target; } @Input public Property getSourceEncoding() { return this.sourceEncoding; } @Input public Property getTargetEncoding() { return this.targetEncoding; } @Input public Property getIgnoreMissingSources() { return ignoreMissingSources; } @Input public ListProperty getExcludeExtensions() { return excludeExtensions; } @Input public ListProperty getFileExtensions() { return fileExtensions; } @Input public Property getUnknownVarAsFalse() { return unknownVarAsFalse; } @Input public Property getDryRun() { return dryRun; } @Input public Property getAllowBlocks() { return allowBlocks; } @Input public Property getVerbose() { return verbose; } @Input public Property getClearTarget() { return clearTarget; } @Input public Property getBaseDir() { return baseDir; } @Input public ListProperty getActionPreprocessorExtensions() { return actionPreprocessorExtensions; } @Input public Property getCareForLastEol() { return careForLastEol; } @Input public Property getKeepComments() { return keepComments; } @Input public MapProperty getVars() { return vars; } @Input public ListProperty getExcludeFolders() { return excludeFolders; } @Input public ListProperty getConfigFiles() { return configFiles; } @Input public Property getKeepLines() { return keepLines; } @Input public Property getAllowWhitespaces() { return allowWhitespaces; } @Input public Property getPreserveIndents() { return preserveIndents; } @Input public Property getDontOverwriteSameContent() { return dontOverwriteSameContent; } @TaskAction public void preprocessTask() throws IOException { final Logger logger = getProject().getLogger(); final File baseDirFile; if (this.baseDir.isPresent()) { baseDirFile = this.baseDir.get(); } else { baseDirFile = this.getProject().getProjectDir(); } logger.info("Base folder: {}", baseDirFile); final PreprocessorContext preprocessorContext = new PreprocessorContext(baseDirFile); preprocessorContext.setPreprocessorLogger(new PreprocessorLogger() { @Override public void error(final String message) { logger.error(message); } @Override public void info(final String message) { logger.info(message); } @Override public void debug(final String message) { logger.debug(message); } @Override public void debug(final Supplier supplier) { if (logger.isDebugEnabled() && supplier != null) { final String text = supplier.get(); if (text != null) { logger.debug(text); } } } @Override public void warning(final String message) { logger.warn(message); } }); List configFilesList = this.configFiles.get(); configFilesList.forEach(x -> { final File cfgFile = new File(baseDirFile, x); if (cfgFile.isFile()) { logger.debug("Adding config file: " + cfgFile); preprocessorContext.registerConfigFile(cfgFile); } else { throw new TaskExecutionException(this, new IOException( "Can't find config file: " + FilenameUtils.normalize(cfgFile.getAbsolutePath()))); } }); final File targetFolder = this.target.get(); logger.info("Target folder: " + targetFolder); preprocessorContext.setTarget(targetFolder); final List sourcesList = this.sources.get(); if (sourcesList.isEmpty()) { throw new TaskConfigurationException(JcpTask.ID, "Source folder list must be defined as 'sources'", null); } List preparedSourcesList = new ArrayList<>(); for (final File srcFolder : sourcesList) { final File srcFolderFile = srcFolder.isAbsolute() ? srcFolder : new File(baseDirFile, srcFolder.getPath()); if (!this.ignoreMissingSources.get() || srcFolderFile.isDirectory()) { preparedSourcesList.add(srcFolderFile); } if (!srcFolderFile.isDirectory()) { logger.debug(String.format("Src.folder doesn't exist: %s", srcFolderFile)); } } logger.info("Source folders in use: " + preparedSourcesList); preprocessorContext.setSources( preparedSourcesList.stream().map(File::getAbsolutePath).collect(Collectors.toList())); preprocessorContext.setEol(this.eol.get()); preprocessorContext.setExcludeFolders(this.excludeFolders.get()); preprocessorContext.setDontOverwriteSameContent(this.dontOverwriteSameContent.get()); preprocessorContext.setClearTarget(this.clearTarget.get()); preprocessorContext.setCareForLastEol(this.careForLastEol.get()); preprocessorContext.setKeepComments( findCommentRemoverForId(String.valueOf(this.keepComments.get()))); preprocessorContext.setDryRun(this.dryRun.get()); preprocessorContext.setAllowsBlocks(this.allowBlocks.get()); preprocessorContext.setKeepAttributes(this.keepAttributes.get()); preprocessorContext.setKeepLines(this.keepLines.get()); preprocessorContext.setAllowWhitespaces(this.allowWhitespaces.get()); preprocessorContext.setExcludeExtensions(this.excludeExtensions.get()); preprocessorContext.setExtensions(this.fileExtensions.get()); preprocessorContext.setPreserveIndents(this.preserveIndents.get()); preprocessorContext.setSourceEncoding(Charset.forName(this.sourceEncoding.get())); preprocessorContext.setTargetEncoding(Charset.forName(this.targetEncoding.get())); preprocessorContext.setUnknownVariableAsFalse(this.unknownVarAsFalse.get()); preprocessorContext.setVerbose(this.verbose.get()); fillContextByFoundServices(preprocessorContext); if (!this.actionPreprocessorExtensions.get().isEmpty()) { this.actionPreprocessorExtensions.get() .forEach(x -> { final String className = x.trim(); logger.info( String.format("Detected action preprocessor extension class name: %s", className)); preprocessorContext.addPreprocessorExtension( findAndInstantiatePreprocessorExtensionForClassName(className)); }); } this.vars.getOrElse(emptyMap()).entrySet().stream() .filter(e -> { if (e.getValue() == null) { if (this.unknownVarAsFalse.get()) { logger.warn(String.format( "Global var '%s' ignored for null value (may be its content is empty in POM)", e.getKey())); return false; } else { throw new IllegalStateException(String.format( "Global var '%s' has null value, to ignore it set flag unknownVarAsFalse", e.getKey())); } } else { return true; } }) .forEach(e -> { logger.debug( String.format("Registering global variable: %s=%s", e.getKey(), e.getValue())); preprocessorContext.setGlobalVariable(e.getKey(), Value.recognizeRawString(String.valueOf(e.getValue()))); }); final JcpPreprocessor preprocessor = new JcpPreprocessor(preprocessorContext); logger.debug("Preprocessing starting"); preprocessor.execute(); final Collection foundAllGeneratedFiles = preprocessor.getContext().findAllProducedFiles(); final Collection foundAllInputFiles = preprocessor.getContext().findAllInputFiles(); this.outcomingFiles.setFrom(foundAllGeneratedFiles); this.incomingFiles.setFrom(foundAllInputFiles); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/logger/PreprocessorLogger.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.logger; import java.util.function.Supplier; /** * The interface describes a logger to be used by a preprocessor during its work * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public interface PreprocessorLogger { /** * Log an error message * * @param message the text to be output into the error log */ void error(String message); /** * Log an information message * * @param message the text to be output into the information log */ void info(String message); /** * Log a debug message * * @param message the text to be output into the debug log * @since 6.0.1 */ void debug(String message); /** * Log a debug message * * @param message text supplier of text to be output into the debug log * @since 7.3.3 */ default void debug(Supplier supplier) { if (supplier != null) { this.debug(supplier.get()); } } /** * Log a warning message * * @param message the text to be output into the warning log */ void warning(String message); } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/logger/SystemOutLogger.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.logger; /** * An Easy logger which just output log messages into the system output streams * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class SystemOutLogger implements PreprocessorLogger { /** * Name of system property to enable debug level logging. */ public static final String PROPERTY_DEBUG_FLAG = "jcp.log.debug"; private static final boolean FLAG_DEBUG_LEVEL = Boolean.parseBoolean(System.getProperty(PROPERTY_DEBUG_FLAG)); @Override public int hashCode() { return System.out.hashCode(); } @Override public boolean equals(final Object value) { return value instanceof SystemOutLogger; } @Override public void error(final String text) { if (text != null) { final String out = "[JCP.ERR] " + text; System.err.println(out); } } @Override public void info(final String text) { if (text != null) { final String out = "[JCP.INFO] " + text; System.out.println(out); } } @Override public void warning(final String text) { if (text != null) { final String out = "[JCP.WARN] " + text; System.out.println(out); } } @Override public void debug(final String text) { if (FLAG_DEBUG_LEVEL && text != null) { final String out = "[JCP.DEBUG] " + text; System.out.println(out); } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/maven/MavenPropertiesImporter.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.maven; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.context.SpecialVariableProcessor; import com.igormaznitsa.jcp.expression.Value; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.regex.Pattern; import org.apache.maven.execution.MavenSession; import org.apache.maven.model.Profile; import org.apache.maven.project.MavenProject; /** * The class imports some properties from the maven which can be accessible from preprocessed sources as global variables * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class MavenPropertiesImporter implements SpecialVariableProcessor { private static final Pattern PATTERN_FOR_PROPERTY_WHICH_CAN_CONTAIN_PRIVATE_INFO = Pattern.compile("key|pass", Pattern.CASE_INSENSITIVE); private static final Set TO_IMPORT = Set.of( "project.name", "project.version", "project.url", "project.packaging", "project.modelVersion", "project.inceptionYear", "project.id", "project.groupId", "project.description", "project.artifact.id", "project.artifact.artifactId", "project.artifact.baseVersion", "project.artifact.dependencyConflictId", "project.artifact.downloadUrl", "project.artifact.groupId", "project.artifact.scope", "project.artifact.type", "project.artifact.version", "project.build.directory", "project.build.defaultGoal", "project.build.outputDirectory", "project.build.scriptSourceDirectory", "project.build.sourceDirectory", "project.build.testOutputDirectory", "project.build.testSourceDirectory", "project.organization.name", "project.organization.url"); private final Map internalVarMap = new HashMap<>(); private final MavenProject project; private final MavenSession session; public MavenPropertiesImporter(final PreprocessorContext context, final MavenProject project, final MavenSession session, final boolean logAddedProperties) { this.session = session; this.project = project; for (final String paramName : TO_IMPORT) { final String varName = "mvn." + paramName.toLowerCase(Locale.ROOT); final String value = getProperty(this.project, paramName); addVariableIntoInternalMap(context, varName, Value.valueOf(value), logAddedProperties); } // add active profile ids final StringBuilder profileIds = new StringBuilder(); for (final Profile profile : project.getActiveProfiles()) { if (profileIds.length() > 0) { profileIds.append(';'); } profileIds.append(profile.getId()); } addVariableIntoInternalMap(context, "mvn.project.activeprofiles", Value.valueOf(profileIds.toString()), logAddedProperties); // add properties for (final String propertyName : this.project.getProperties().stringPropertyNames()) { final String varName = "mvn.project.property." + propertyName.toLowerCase(Locale.ROOT).replace(' ', '_'); final String value = this.findPropertyValue(propertyName); if (value != null) { addVariableIntoInternalMap(context, varName, Value.valueOf(value), logAddedProperties); } } } static String getProperty(final MavenProject project, final String name) { final String[] splitted = name.split("\\."); Object root = null; if ("project".equals(splitted[0])) { root = project; } try { if (root == null) { throw new IllegalArgumentException( "Unsupported root object detected [" + splitted[0] + ']'); } else { for (int i = 1; i < splitted.length - 1; i++) { final Method getter = root.getClass().getMethod(normalizeGetter(splitted[i])); root = getter.invoke(root); if (root == null) { return ""; } } final Method finalStringGetter = root.getClass().getMethod(normalizeGetter(splitted[splitted.length - 1])); final Object result = finalStringGetter.invoke(root); return result == null ? "" : result.toString(); } } catch (NoSuchMethodException ex) { throw new RuntimeException("Can't find method", ex); } catch (IllegalAccessException ex) { throw new RuntimeException("Security exception", ex); } catch (InvocationTargetException ex) { throw new RuntimeException("Exception during invocation", ex.getCause()); } } static String normalizeGetter(final String str) { return "get" + Character.toUpperCase(str.charAt(0)) + str.substring(1); } private String findPropertyValue(final String key) { final Properties properties = new Properties(this.project.getProperties()); properties.putAll(this.session.getSystemProperties()); properties.putAll(this.session.getUserProperties()); return properties.getProperty(key); } private void printInfoAboutVarIntoLog(final PreprocessorContext context, final String varName, final String value) { final boolean possibleContainsPrivateInfo = PATTERN_FOR_PROPERTY_WHICH_CAN_CONTAIN_PRIVATE_INFO.matcher(varName).find(); final String textValue = possibleContainsPrivateInfo ? "***** [hidden because may contain private info]" : value; context.logInfo("Added MAVEN property " + varName + '=' + textValue); } private void addVariableIntoInternalMap(final PreprocessorContext context, final String name, final Value value, final boolean verbose) { if (internalVarMap.containsKey(name)) { throw context.makeException("Duplicated importing value detected [" + name + ']', null); } internalVarMap.put(name, value); if (verbose) { printInfoAboutVarIntoLog(context, name, value.asString()); } } @Override public Set getVariableNames() { return this.internalVarMap.keySet(); } @Override public Value getVariable(final String varName, final PreprocessorContext context) { if (!internalVarMap.containsKey(varName)) { throw new IllegalArgumentException("Unsupported property request detected [" + varName + ']'); } return internalVarMap.get(varName); } @Override public void setVariable(final String varName, final Value value, final PreprocessorContext context) { throw new UnsupportedOperationException( "An attempt to change a maven property detected, those properties are accessible only for reading [" + varName + ']'); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/maven/PreprocessMojo.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.maven; import static com.igormaznitsa.jcp.utils.GetUtils.ensureNonNull; import static com.igormaznitsa.jcp.utils.PreprocessorUtils.fillContextByFoundServices; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.CommentRemoverType; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.logger.PreprocessorLogger; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Supplier; import java.util.stream.Collectors; import lombok.AccessLevel; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Setter; import org.apache.commons.text.StringEscapeUtils; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.AbstractMojoExecutionException; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; /** * Mojo to preprocess either standard maven project source roots or custom source roots and place prepsocessed result into defined target folder. */ @Data @EqualsAndHashCode(callSuper = false) @Mojo(name = "preprocess", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true) public class PreprocessMojo extends AbstractMojo implements PreprocessorLogger { /** * Maven project source roots for compilation phase. */ @Setter(AccessLevel.NONE) @Parameter(alias = "compileSourceRoots", defaultValue = "${project.compileSourceRoots}", required = true, readonly = true) private List compileSourceRoots = new ArrayList<>(); /** * Maven project test source roots for test phase. */ @Setter(AccessLevel.NONE) @Parameter(alias = "testCompileSourceRoots", defaultValue = "${project.testCompileSourceRoots}", required = true, readonly = true) private List testCompileSourceRoots = new ArrayList<>(); /** * Maven project to be preprocessed. */ @Setter(AccessLevel.NONE) @Parameter(defaultValue = "${project}", required = true, readonly = true) private MavenProject project; /** * Maven session to be preprocessed. * * @since 7.0.5 */ @Setter(AccessLevel.NONE) @Parameter(defaultValue = "${session}", required = true, readonly = true) private MavenSession session; /** * Source root folders for preprocessing, if it is empty then project provided folders will be used. * * @since 7.0.0 */ @Parameter(alias = "sources") private List sources = null; /** * End of line string to be used in reprocessed results. It supports java escaping chars. * * @since 7.0.0 */ @Parameter(alias = "eol", property = "jcp.line.separator", defaultValue = "${line.separator}") private String eol = null; /** * List of class names to be used as action preprocessor extensions. The class must have default constructor. * * @see com.igormaznitsa.jcp.extension.PreprocessorExtension * @since 7.2.2 */ @Parameter(alias = "actionPreprocessorExtensions", property = "jcp.action.preprocessor.extensions", defaultValue = "") private List actionPreprocessorExtensions = List.of(); /** * Keep attributes for preprocessing file and copy them to result one. * * @since 7.0.0 */ @Parameter(alias = "keepAttributes", defaultValue = "false") private boolean keepAttributes = false; /** * Target folder to place preprocessing result in regular source processing phase. * * @since 7.0.0 */ @Parameter(alias = "target", defaultValue = "${project.build.directory}${file.separator}generated-sources${file.separator}preprocessed") private File target = null; /** * Target folder to place preprocessing result in test source processing phase. * * @since 7.0.0 */ @Parameter(alias = "targetTest", defaultValue = "${project.build.directory}${file.separator}generated-test-sources${file.separator}preprocessed") private File targetTest = null; /** * Encoding for text read operations. * * @since 7.0.0 */ @Parameter(alias = "sourceEncoding", defaultValue = "${project.build.sourceEncoding}") private String sourceEncoding = StandardCharsets.UTF_8.name(); /** * Encoding for text write operations. * * @since 7.0.0 */ @Parameter(alias = "targetEncoding", defaultValue = "${project.build.sourceEncoding}") private String targetEncoding = StandardCharsets.UTF_8.name(); /** * Flag to ignore missing source folders, if false then mojo fail for any missing source folder, if true then missing folder will be ignored. * * @since 6.1.1 */ @Parameter(alias = "ignoreMissingSources", defaultValue = "false") private boolean ignoreMissingSources = false; /** * List of file extensions to be excluded from preprocessing. By default excluded xml. * * @since 7.0.0 */ @Parameter(alias = "excludeExtensions") private List excludeExtensions = Collections.singletonList("xml"); /** * List of file extensions to be included into preprocessing. By default java,txt,htm,html * * @since 7.0.0 */ @Parameter(alias = "extensions") private List extensions = new ArrayList<>(Arrays.asList("java", "txt", "htm", "html")); /** * Recognize a unknown variable as containing boolean false flag. */ @Parameter(alias = "unknownVarAsFalse", defaultValue = "false") private boolean unknownVarAsFalse = false; /** * Dry run, making preprocessing but without output * * @since 7.0.0. */ @Parameter(alias = "dryRun", defaultValue = "false") private boolean dryRun = false; /** * Allows merge preprocessed text lines as single text block for external processing. * * @since 7.2.0. */ @Parameter(alias = "allowBlocks", defaultValue = "false") private boolean allowBlocks = false; /** * Verbose mode. */ @Parameter(alias = "verbose", defaultValue = "false") private boolean verbose = false; /** * Clear target folder if it exists. * * @since 7.0.0 */ @Parameter(alias = "clearTarget", defaultValue = "false") private boolean clearTarget = false; /** * Set base directory which will be used for relative source paths. * * @since 7.0.0 */ @Parameter(alias = "baseDir", defaultValue = "${project.basedir}") private File baseDir = new File("."); /** * Carefully reproduce last EOL in result files. * * @since 7.0.0 */ @Parameter(alias = "careForLastEol", defaultValue = "false") private boolean careForLastEol = false; /** * Replace source root folders in maven project after preprocessing for following processing. * * @since 7.0.0 */ @Parameter(alias = "replaceSources", defaultValue = "true") private boolean replaceSources = true; /** * Keep comments in result files. * * @since 7.0.0 */ @Parameter(alias = "keepComments", defaultValue = "true") private String keepComments = CommentRemoverType.KEEP_ALL.name(); /** * List of variables to be registered in preprocessor as global ones. * * @since 7.0.0 */ @Parameter(alias = "vars") private Map vars = new HashMap<>(); /** * List of patterns of folder paths to be excluded from preprocessing, It uses ANT path pattern format. * * @since 7.0.0 */ @Parameter(alias = "excludeFolders") private List excludeFolders = new ArrayList<>(); /** * List of external files containing variable definitions. * * @since 7.0.0 */ @Parameter(alias = "configFiles") private List configFiles = new ArrayList<>(); /** * Keep preprocessing directives in result files as commented ones, it is useful to not break line numeration in result files. */ @Parameter(alias = "keepLines", defaultValue = "true") private boolean keepLines = true; /** * Turn on support of white spaces in preprocessor directives between '//' and the '#'. */ @Parameter(alias = "allowWhitespaces", defaultValue = "false") private boolean allowWhitespaces = false; /** * Preserve indents in lines marked by '//$' and '//$$' directives. Directives will be replaced by white spaces chars. */ @Parameter(alias = "preserveIndents", defaultValue = "false") private boolean preserveIndents = false; /** * Turn on test sources root use. * * @since 5.3.4 */ @Parameter(alias = "useTestSources", defaultValue = "false") private boolean useTestSources = false; /** * Skip preprocessing. Also can be defined by property 'jcp.preprocess.skip' * * @since 6.1.1 */ @Parameter(alias = "skip", property = "jcp.preprocess.skip", defaultValue = "false") private boolean skip = false; /** * Turn on check of content body compare with existing result file to prevent overwriting, if content is the same then preprocessor will not be writing new result content. * * @since 7.0.0 */ @Parameter(alias = "dontOverwriteSameContent", defaultValue = "false") private boolean dontOverwriteSameContent = false; private List formSourceRootList() { List result = Collections.emptyList(); if (this.getSources() == null) { if (this.project != null) { result = (this.isUseTestSources() ? this.testCompileSourceRoots : this.compileSourceRoots) .stream() .filter(Objects::nonNull) .map(File::new) .peek(x -> { if (!x.isDirectory()) { getLog().debug(String.format("Src.folder doesn't exist: %s", x)); } }) .filter(x -> !this.isIgnoreMissingSources() || x.isDirectory()) .map(File::getAbsolutePath) .collect(Collectors.toList()); } } else { result = new ArrayList<>(this.getSources()); } return result; } private void replaceSourceRootByPreprocessingDestinationFolder(final PreprocessorContext context) throws IOException { if (this.project != null) { final List sourceFolders = context.getSources(); final List sourceRoots = this.isUseTestSources() ? this.testCompileSourceRoots : this.compileSourceRoots; final List sourceRootsAsCanonical = new ArrayList<>(); for (final String src : sourceRoots) { sourceRootsAsCanonical.add(new File(src).getCanonicalPath()); } for (final PreprocessorContext.SourceFolder folder : sourceFolders) { int index = sourceRoots.indexOf(folder.getAsString()); if (index < 0) { // check for canonical paths final String canonicalPath = folder.getAsFile().getCanonicalPath(); index = sourceRootsAsCanonical.indexOf(canonicalPath); } if (index >= 0) { info("Source root is removed from the source root list: " + sourceRoots.get(index)); sourceRoots.remove(index); } } final String destinationDir = context.getTarget().getCanonicalPath(); sourceRoots.add(destinationDir); info("Source root is enlisted: " + destinationDir); } } PreprocessorContext makePreprocessorContext() throws AbstractMojoExecutionException { final PreprocessorContext context = new PreprocessorContext(this.getBaseDir()); context.setPreprocessorLogger(this); if (this.project != null) { final MavenPropertiesImporter mavenPropertiesImporter = new MavenPropertiesImporter(context, this.project, this.session, isVerbose() || getLog().isDebugEnabled() ); context.registerSpecialVariableProcessor(mavenPropertiesImporter); } if (this.actionPreprocessorExtensions != null && !this.actionPreprocessorExtensions.isEmpty()) { this.actionPreprocessorExtensions .forEach(x -> { final String extensionClassName = x.trim(); info("Adding preprocessor action extension class: " + extensionClassName); context.addPreprocessorExtension( PreprocessorUtils.findAndInstantiatePreprocessorExtensionForClassName( extensionClassName)); }); } context.setSources(formSourceRootList()); context.setTarget((this.isUseTestSources() ? this.getTargetTest() : this.getTarget())); context.setSourceEncoding(Charset.forName(this.getSourceEncoding().trim())); context.setTargetEncoding(Charset.forName(this.getTargetEncoding().trim())); context.setExcludeFolders(this.getExcludeFolders()); context.setExcludeExtensions(this.getExcludeExtensions()); context.setExtensions(this.getExtensions()); if (this.getEol() != null) { context.setEol(StringEscapeUtils.unescapeJava(this.getEol())); } info("Source folders: " + context.getSources().stream().map(PreprocessorContext.SourceFolder::getAsString) .collect(Collectors.joining(File.pathSeparator))); info("Target folder: " + context.getTarget()); context.setUnknownVariableAsFalse(this.isUnknownVarAsFalse()); context.setDontOverwriteSameContent(this.isDontOverwriteSameContent()); context.setClearTarget(this.isClearTarget()); context.setCareForLastEol(this.isCareForLastEol()); context.setKeepComments(PreprocessorUtils.findCommentRemoverForId(this.getKeepComments())); context.setVerbose(getLog().isDebugEnabled() || this.isVerbose()); context.setKeepLines(this.isKeepLines()); context.setDryRun(this.isDryRun()); context.setAllowsBlocks(this.isAllowBlocks()); context.setAllowWhitespaces(this.isAllowWhitespaces()); context.setPreserveIndents(this.isPreserveIndents()); context.setExcludeFolders(this.getExcludeFolders()); context.setKeepAttributes(this.isKeepAttributes()); this.configFiles.forEach(x -> context.registerConfigFile(new File(x))); // register global vars try { this.getVars().entrySet().stream() .filter(e -> { final String key = e.getKey(); final String value = e.getValue(); if (value == null) { if (this.isUnknownVarAsFalse()) { getLog().warn(String.format( "Global var '%s' ignored for null value (may be its content is empty in POM)", key)); return false; } else { throw new IllegalStateException(String.format( "Global var '%s' has null value (may be its content is empty in POM), to ignore it set unknownVarAsFalse as true", key)); } } else { return true; } }) .forEach(e -> { getLog().debug( String.format("Register global var: '%s' <- '%s'", e.getKey(), e.getValue())); context.setGlobalVariable(e.getKey(), Value.recognizeRawString(e.getValue())); }); } catch (final IllegalStateException ex) { getLog().error(ex.getMessage()); throw new MojoFailureException(ex.getMessage()); } return context; } @Override public void execute() throws MojoExecutionException, MojoFailureException { if (this.isSkip()) { getLog().info("Skip preprocessing"); } else { final PreprocessorContext context; try { context = makePreprocessorContext(); fillContextByFoundServices(context); } catch (Exception ex) { final PreprocessorException newException = PreprocessorException.extractPreprocessorException(ex); throw new MojoExecutionException( newException == null ? ex.getMessage() : newException.toString(), newException == null ? ex : newException); } if (context.getSources().isEmpty()) { if (this.isIgnoreMissingSources()) { getLog().warn("Source folders are not provided, preprocessing is ignored."); } else { throw new MojoFailureException( "Source folders are not provided, check parameters and project type"); } } else { try { final JcpPreprocessor preprocessor = new JcpPreprocessor(context); preprocessor.execute(); if (this.isReplaceSources()) { replaceSourceRootByPreprocessingDestinationFolder(context); } } catch (Exception ex) { final PreprocessorException pp = PreprocessorException.extractPreprocessorException(ex); throw new MojoFailureException( pp == null ? ex.getMessage() : PreprocessorException.referenceAsString('.', pp), pp == null ? ex : pp); } } } } @Override public void error(final String message) { getLog().error(ensureNonNull(message, "")); } @Override public void info(final String message) { getLog().info(ensureNonNull(message, "")); } @Override public void warning(final String message) { getLog().warn(ensureNonNull(message, "")); } @Override public void debug(final String message) { getLog().debug(ensureNonNull(message, "")); } @Override public void debug(Supplier supplier) { if (getLog().isDebugEnabled()) { final String text = supplier.get(); if (text != null) { getLog().debug(text); } } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/removers/AbstractCommentRemover.java ================================================ package com.igormaznitsa.jcp.removers; import static java.util.Objects.requireNonNull; import com.igormaznitsa.jcp.context.CommentRemoverType; import java.io.IOException; import java.io.Reader; import java.io.Writer; public abstract class AbstractCommentRemover { protected final Reader srcReader; protected final Writer targetWriter; protected final boolean whiteSpaceAllowed; protected AbstractCommentRemover( final Reader src, final Writer target, final boolean whiteSpaceAllowed ) { requireNonNull(src, "The reader is null"); requireNonNull(target, "The writer is null"); this.srcReader = src; this.targetWriter = target; this.whiteSpaceAllowed = whiteSpaceAllowed; } public static AbstractCommentRemover makeCommentRemover( final CommentRemoverType keepComments, final Reader src, final Writer dst, final boolean whiteSpaceAllowed) { switch (keepComments) { case KEEP_ALL: return new JustCopyRemover(src, dst, whiteSpaceAllowed); case REMOVE_C_STYLE: return new CStyleCommentRemover(src, dst, whiteSpaceAllowed); case REMOVE_JCP_ONLY: return new JcpCommentLineRemover(src, dst, whiteSpaceAllowed); default: throw new IllegalStateException("Unsupported keep comments value: " + keepComments); } } public abstract Writer process() throws IOException; protected void skipTillNextString() throws IOException { while (!Thread.currentThread().isInterrupted()) { final int chr = srcReader.read(); if (chr < 0) { return; } if (chr == '\n') { this.targetWriter.write(chr); return; } } } protected void skipTillClosingJavaComments() throws IOException { boolean starFound = false; while (!Thread.currentThread().isInterrupted()) { final int chr = srcReader.read(); if (chr < 0) { return; } if (starFound) { if (chr == '/') { return; } else { starFound = chr == '*'; } } else if (chr == '*') { starFound = true; } } } protected void copyTillClosingJavaComments() throws IOException { boolean starFound = false; while (!Thread.currentThread().isInterrupted()) { final int chr = this.srcReader.read(); if (chr < 0) { return; } this.targetWriter.write(chr); if (starFound) { if (chr == '/') { return; } else { starFound = chr == '*'; } } else if (chr == '*') { starFound = true; } } } protected void copyTillNextString() throws IOException { while (!Thread.currentThread().isInterrupted()) { final int chr = srcReader.read(); if (chr < 0) { return; } else { this.targetWriter.write(chr); if (chr == '\n') { break; } } } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/removers/CStyleCommentRemover.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.removers; import java.io.IOException; import java.io.Reader; import java.io.Writer; /** * A remover allows to cut off all Java like comments from a reader and write the result into a writer * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class CStyleCommentRemover extends AbstractCommentRemover { public CStyleCommentRemover(final Reader src, final Writer dst, final boolean whiteSpacesAllowed) { super(src, dst, whiteSpacesAllowed); } @Override public Writer process() throws IOException { final int STATE_NORMAL = 0; final int STATE_IN_STRING = 1; final int STATE_NEXT_SPECIAL_CHAR = 2; final int STATE_FORWARD_SLASH = 3; int state = STATE_NORMAL; while (!Thread.currentThread().isInterrupted()) { final int chr = this.srcReader.read(); if (chr < 0) { break; } switch (state) { case STATE_NORMAL: { switch (chr) { case '\"': { targetWriter.write(chr); state = STATE_IN_STRING; } break; case '/': { state = STATE_FORWARD_SLASH; } break; default: { targetWriter.write(chr); } break; } } break; case STATE_FORWARD_SLASH: { switch (chr) { case '*': { skipTillClosingJavaComments(); state = STATE_NORMAL; } break; case '/': { skipTillNextString(); state = STATE_NORMAL; } break; default: { targetWriter.write('/'); targetWriter.write(chr); state = STATE_NORMAL; } break; } } break; case STATE_IN_STRING: { switch (chr) { case '\\': { state = STATE_NEXT_SPECIAL_CHAR; } break; case '\"': { state = STATE_NORMAL; } break; default: break; } targetWriter.write(chr); } break; case STATE_NEXT_SPECIAL_CHAR: { targetWriter.write(chr); state = STATE_IN_STRING; } break; default: throw new IllegalStateException("Unexpected state: " + state); } } return targetWriter; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/removers/JcpCommentLineRemover.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.removers; import static com.igormaznitsa.jcp.directives.AbstractDirectiveHandler.PREFIX_FOR_KEEPING_LINES; import static com.igormaznitsa.jcp.directives.AbstractDirectiveHandler.PREFIX_FOR_KEEPING_LINES_PROCESSED_DIRECTIVES; import java.io.IOException; import java.io.Reader; import java.io.Writer; /** * A remover allows to cut off all Java like comments contains JCP directives (single line comments started by '#' or '$') * from a reader and write the result into a writer. * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) * @since 7.1.0 */ public class JcpCommentLineRemover extends AbstractCommentRemover { public JcpCommentLineRemover(final Reader src, final Writer dst, final boolean whiteSpaceAllowed) { super(src, dst, whiteSpaceAllowed); } @Override public Writer process() throws IOException { final int STATE_NORMAL = 0; final int STATE_FORWARD_SLASH = 1; final int STATE_POSSIBLE_JCP = 2; final StringBuilder jcpBuffer = new StringBuilder(); int state = STATE_NORMAL; while (!Thread.currentThread().isInterrupted()) { final int chr = this.srcReader.read(); if (chr < 0) { break; } switch (state) { case STATE_NORMAL: { if (chr == '/') { state = STATE_FORWARD_SLASH; } else if (Character.isWhitespace(chr)) { this.targetWriter.write(chr); } else { this.targetWriter.write(chr); this.copyTillNextString(); } } break; case STATE_POSSIBLE_JCP: { switch (chr) { case '$': case '#': { if (jcpBuffer.toString().equals("//") || (jcpBuffer.substring(2).trim().isEmpty() && this.whiteSpaceAllowed)) { jcpBuffer.setLength(0); skipTillNextString(); state = STATE_NORMAL; } else { this.targetWriter.write(jcpBuffer.toString()); this.targetWriter.write(chr); this.copyTillNextString(); } } break; default: { jcpBuffer.append((char) chr); final String currentBuffer = jcpBuffer.toString(); if (currentBuffer.startsWith(PREFIX_FOR_KEEPING_LINES) || currentBuffer.startsWith(PREFIX_FOR_KEEPING_LINES_PROCESSED_DIRECTIVES)) { jcpBuffer.setLength(0); this.skipTillNextString(); state = STATE_NORMAL; } else if (chr == '\n') { this.targetWriter.write(currentBuffer); jcpBuffer.setLength(0); state = STATE_NORMAL; } else if ((!PREFIX_FOR_KEEPING_LINES.startsWith(currentBuffer) && !PREFIX_FOR_KEEPING_LINES_PROCESSED_DIRECTIVES.startsWith(currentBuffer)) && (!this.whiteSpaceAllowed || !Character.isSpaceChar(chr))) { jcpBuffer.setLength(0); this.targetWriter.write(currentBuffer); this.copyTillNextString(); state = STATE_NORMAL; } } } } break; case STATE_FORWARD_SLASH: { switch (chr) { case '*': { this.targetWriter.write("/*"); copyTillClosingJavaComments(); state = STATE_NORMAL; } break; case '/': { jcpBuffer.append("//"); state = STATE_POSSIBLE_JCP; } break; default: { targetWriter.write('/'); targetWriter.write(chr); state = STATE_NORMAL; } break; } } break; default: throw new IllegalStateException("Unexpected state: " + state); } } if (jcpBuffer.length() > 0) { this.targetWriter.write(jcpBuffer.toString()); } return this.targetWriter; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/removers/JustCopyRemover.java ================================================ package com.igormaznitsa.jcp.removers; import java.io.IOException; import java.io.Reader; import java.io.Writer; public class JustCopyRemover extends AbstractCommentRemover { public JustCopyRemover(final Reader src, final Writer dst, final boolean whiteSpaceAllowed) { super(src, dst, whiteSpaceAllowed); } @Override public Writer process() throws IOException { final char[] buffer = new char[32768]; while (!Thread.currentThread().isInterrupted()) { final int read = this.srcReader.read(buffer); if (read < 0) { break; } this.targetWriter.write(buffer, 0, read); } return this.targetWriter; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/utils/AntPathMatcher.java ================================================ package com.igormaznitsa.jcp.utils; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Extracted from Spring utility Ant pattern matcher. * removed non-used methods and fields. */ public class AntPathMatcher { public static final String DEFAULT_PATH_SEPARATOR = "/"; private static final int CACHE_TURNOFF_THRESHOLD = 65536; private static final char[] WILDCARD_CHARS = {'*', '?', '{'}; private static final String[] EMPTY_STRING_ARRAY = {}; final Map stringMatcherCache = new ConcurrentHashMap<>(256); private final boolean caseSensitive = true; private final boolean trimTokens = false; private final Map tokenizedPatternCache = new ConcurrentHashMap<>(256); private final String pathSeparator; private volatile Boolean cachePatterns; public AntPathMatcher() { this.pathSeparator = DEFAULT_PATH_SEPARATOR; } public AntPathMatcher(String pathSeparator) { this.pathSeparator = pathSeparator; } public static String[] tokenizeToStringArray( String str, String delimiters, boolean trimTokens, boolean ignoreEmptyTokens) { if (str == null) { return EMPTY_STRING_ARRAY; } StringTokenizer st = new StringTokenizer(str, delimiters); List tokens = new ArrayList<>(); while (st.hasMoreTokens()) { String token = st.nextToken(); if (trimTokens) { token = token.trim(); } if (!ignoreEmptyTokens || !token.isEmpty()) { tokens.add(token); } } return toStringArray(tokens); } public static String[] toStringArray(Collection collection) { return (!isEmpty(collection) ? collection.toArray(EMPTY_STRING_ARRAY) : EMPTY_STRING_ARRAY); } public static boolean isEmpty(Collection collection) { return (collection == null || collection.isEmpty()); } private void deactivatePatternCache() { this.cachePatterns = false; this.tokenizedPatternCache.clear(); this.stringMatcherCache.clear(); } public boolean match(String pattern, String path) { return doMatch(pattern, path, true); } protected boolean doMatch(String pattern, String path, boolean fullMatch) { if (path == null || path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) { return false; } String[] patternDirs = tokenizePattern(pattern); if (this.caseSensitive && !isPotentialMatch(path, patternDirs)) { return false; } String[] pathDirs = tokenizePath(path); int pattIdxStart = 0; int pattIdxEnd = patternDirs.length - 1; int pathIdxStart = 0; int pathIdxEnd = pathDirs.length - 1; while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) { String patternDir = patternDirs[pattIdxStart]; if ("**".equals(patternDir)) { break; } if (!matchStrings(patternDir, pathDirs[pathIdxStart])) { return false; } pattIdxStart++; pathIdxStart++; } if (pathIdxStart > pathIdxEnd) { if (pattIdxStart > pattIdxEnd) { return (pattern.endsWith(this.pathSeparator) == path.endsWith(this.pathSeparator)); } if (!fullMatch) { return true; } if (pattIdxStart == pattIdxEnd && patternDirs[pattIdxStart].equals("*") && path.endsWith(this.pathSeparator)) { return true; } for (int i = pattIdxStart; i <= pattIdxEnd; i++) { if (!patternDirs[i].equals("**")) { return false; } } return true; } else if (pattIdxStart > pattIdxEnd) { return false; } else if (!fullMatch && "**".equals(patternDirs[pattIdxStart])) { return true; } while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) { String patternDir = patternDirs[pattIdxEnd]; if (patternDir.equals("**")) { break; } if (!matchStrings(patternDir, pathDirs[pathIdxEnd])) { return false; } if (pattIdxEnd == (patternDirs.length - 1) && pattern.endsWith(this.pathSeparator) != path.endsWith(this.pathSeparator)) { return false; } pattIdxEnd--; pathIdxEnd--; } if (pathIdxStart > pathIdxEnd) { for (int i = pattIdxStart; i <= pattIdxEnd; i++) { if (!patternDirs[i].equals("**")) { return false; } } return true; } while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) { int patIdxTmp = -1; for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) { if (patternDirs[i].equals("**")) { patIdxTmp = i; break; } } if (patIdxTmp == pattIdxStart + 1) { pattIdxStart++; continue; } int patLength = (patIdxTmp - pattIdxStart - 1); int strLength = (pathIdxEnd - pathIdxStart + 1); int foundIdx = -1; strLoop: for (int i = 0; i <= strLength - patLength; i++) { for (int j = 0; j < patLength; j++) { String subPat = patternDirs[pattIdxStart + j + 1]; String subStr = pathDirs[pathIdxStart + i + j]; if (!matchStrings(subPat, subStr)) { continue strLoop; } } foundIdx = pathIdxStart + i; break; } if (foundIdx == -1) { return false; } pattIdxStart = patIdxTmp; pathIdxStart = foundIdx + patLength; } for (int i = pattIdxStart; i <= pattIdxEnd; i++) { if (!patternDirs[i].equals("**")) { return false; } } return true; } private boolean isPotentialMatch(String path, String[] pattDirs) { if (!this.trimTokens) { int pos = 0; for (String patternDir : pattDirs) { int skipped = skipSeparator(path, pos, this.pathSeparator); pos += skipped; skipped = skipSegment(path, pos, patternDir); if (skipped < patternDir.length()) { return (skipped > 0 || (!patternDir.isEmpty() && isWildcardChar(patternDir.charAt(0)))); } pos += skipped; } } return true; } private int skipSegment(String path, int pos, String prefix) { int skipped = 0; for (int i = 0; i < prefix.length(); i++) { char c = prefix.charAt(i); if (isWildcardChar(c)) { return skipped; } int currPos = pos + skipped; if (currPos >= path.length()) { return 0; } if (c == path.charAt(currPos)) { skipped++; } } return skipped; } private int skipSeparator(String path, int pos, String separator) { int skipped = 0; while (path.startsWith(separator, pos + skipped)) { skipped += separator.length(); } return skipped; } private boolean isWildcardChar(char c) { for (char candidate : WILDCARD_CHARS) { if (c == candidate) { return true; } } return false; } protected String[] tokenizePattern(String pattern) { String[] tokenized = null; Boolean cachePatterns = this.cachePatterns; if (cachePatterns == null || cachePatterns) { tokenized = this.tokenizedPatternCache.get(pattern); } if (tokenized == null) { tokenized = tokenizePath(pattern); if (cachePatterns == null && this.tokenizedPatternCache.size() >= CACHE_TURNOFF_THRESHOLD) { deactivatePatternCache(); return tokenized; } if (cachePatterns == null || cachePatterns) { this.tokenizedPatternCache.put(pattern, tokenized); } } return tokenized; } protected String[] tokenizePath(String path) { return tokenizeToStringArray(path, this.pathSeparator, this.trimTokens, true); } private boolean matchStrings(String pattern, String str) { return getStringMatcher(pattern).matchStrings(str); } protected AntPathStringMatcher getStringMatcher(String pattern) { AntPathStringMatcher matcher = null; Boolean cachePatterns = this.cachePatterns; if (cachePatterns == null || cachePatterns) { matcher = this.stringMatcherCache.get(pattern); } if (matcher == null) { matcher = new AntPathStringMatcher(pattern, this.caseSensitive); if (cachePatterns == null && this.stringMatcherCache.size() >= CACHE_TURNOFF_THRESHOLD) { deactivatePatternCache(); return matcher; } if (cachePatterns == null || cachePatterns) { this.stringMatcherCache.put(pattern, matcher); } } return matcher; } protected static class AntPathStringMatcher { private static final Pattern GLOB_PATTERN = Pattern.compile("\\?|\\*|\\{((?:\\{[^/]+?\\}|[^/{}]|\\\\[{}])+?)\\}"); private static final String DEFAULT_VARIABLE_PATTERN = "((?s).*)"; private final String rawPattern; private final boolean caseSensitive; private final boolean exactMatch; private final Pattern pattern; public AntPathStringMatcher(String pattern, boolean caseSensitive) { this.rawPattern = pattern; this.caseSensitive = caseSensitive; StringBuilder patternBuilder = new StringBuilder(); Matcher matcher = GLOB_PATTERN.matcher(pattern); int end = 0; while (matcher.find()) { patternBuilder.append(quote(pattern, end, matcher.start())); String match = matcher.group(); if ("?".equals(match)) { patternBuilder.append('.'); } else if ("*".equals(match)) { patternBuilder.append(".*"); } else if (match.startsWith("{") && match.endsWith("}")) { int colonIdx = match.indexOf(':'); if (colonIdx == -1) { patternBuilder.append(DEFAULT_VARIABLE_PATTERN); } else { String variablePattern = match.substring(colonIdx + 1, match.length() - 1); patternBuilder.append('('); patternBuilder.append(variablePattern); patternBuilder.append(')'); } } end = matcher.end(); } if (end == 0) { this.exactMatch = true; this.pattern = null; } else { this.exactMatch = false; patternBuilder.append(quote(pattern, end, pattern.length())); this.pattern = (this.caseSensitive ? Pattern.compile(patternBuilder.toString()) : Pattern.compile(patternBuilder.toString(), Pattern.CASE_INSENSITIVE)); } } private String quote(String s, int start, int end) { if (start == end) { return ""; } return Pattern.quote(s.substring(start, end)); } public boolean matchStrings(String str) { if (this.exactMatch) { return this.caseSensitive ? this.rawPattern.equals(str) : this.rawPattern.equalsIgnoreCase(str); } else if (this.pattern != null) { Matcher matcher = this.pattern.matcher(str); return matcher.matches(); } return false; } } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/utils/ArrayUtils.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.utils; import java.lang.reflect.Array; public final class ArrayUtils { public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0]; public static final String[] EMPTY_STRING_ARRAY = new String[0]; public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; public static final char[] EMPTY_CHAR_ARRAY = new char[0]; public static final short[] EMPTY_SHORT_ARRAY = new short[0]; public static final boolean[] EMPTY_BOOL_ARRAY = new boolean[0]; public static final int[] EMPTY_INT_ARRAY = new int[0]; public static final long[] EMPTY_LONG_ARRAY = new long[0]; private ArrayUtils() { } /** * Join arrays provided as parameters, all arrays must be the same type, null values allowed. * * @param type of array * @param arrays array of arrays to be joined * @return all joined arrays as single array * @since 1.0 */ @SafeVarargs public static T[] joinArrays(final T[]... arrays) { int commonLength = 0; for (final T[] array : arrays) { if (array != null) { commonLength += array.length; } } @SuppressWarnings("unchecked") final T[] result = (T[]) Array .newInstance(arrays.getClass().getComponentType().getComponentType(), commonLength); int position = 0; for (final T[] array : arrays) { if (array != null) { System.arraycopy(array, 0, result, position, array.length); position += array.length; } } return result; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/utils/GetUtils.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.utils; import java.util.Objects; public final class GetUtils { private GetUtils() { } /** * Get value and ensure that the value is not null * * @param type of value * @param value the value * @param defaultValue the default value to be returned if the value is null * @return not null value * @throws AssertionError if both the value and the default value are null * @since 1.0 */ public static T ensureNonNull(final T value, final T defaultValue) { return value == null ? Objects.requireNonNull(defaultValue) : value; } /** * Ensure that a string will not be null. * * @param value value to be checked * @return the value if it is not null or empty string if the value is null * @since 1.1.1 */ public static String ensureNonNullStr(final String value) { return value == null ? "" : value; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/utils/IOUtils.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.utils; import java.io.Closeable; public final class IOUtils { private IOUtils() { } /** * Closing quietly any closeable object. Any exception will be caught (but global error listeners will be notified) * * @param closeable object to be closed quetly * @return the same object provided in args */ public static Closeable closeQuietly(final Closeable closeable) { if (closeable != null) { try { closeable.close(); } catch (Exception ex) { // DO NOTHING } } return closeable; } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/utils/PreprocessorUtils.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.utils; import static com.igormaznitsa.jcp.context.CommentRemoverType.KEEP_ALL; import static com.igormaznitsa.jcp.context.CommentRemoverType.REMOVE_C_STYLE; import static com.igormaznitsa.jcp.context.CommentRemoverType.makeListOfAllRemoverIds; import com.igormaznitsa.jcp.containers.FileInfoContainer; import com.igormaznitsa.jcp.containers.TextFileDataContainer; import com.igormaznitsa.jcp.context.CommentRemoverType; import com.igormaznitsa.jcp.context.CommentTextProcessor; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.context.SpecialVariableProcessor; import com.igormaznitsa.jcp.exceptions.FilePositionInfo; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.extension.PreprocessorExtension; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.Optional; import java.util.ServiceLoader; import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; /** * It is an auxiliary class contains some useful methods * * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public final class PreprocessorUtils { /** * Property if defined and true then search of services in class path is disabled. * * @since 7.2.0 */ public static final String SYSTEM_PROPERTY_DISABLE_SEARCH_SERVICES = "jcp.preprocessor.disable.search.services"; private static final Pattern PATTERN_MACROS_WITH_SPACES = Pattern.compile("\\/\\*\\s*\\$(.*?)\\$\\s*\\*\\/"); private PreprocessorUtils() { } /** * Find active FileInfoContainer in a context. * * @param context preprocessor context, must not be null * @return found FileInfoContainer or empty optional * @see FileInfoContainer * @since 7.3.0 */ public static Optional findActiveFileInfoContainer( final PreprocessorContext context ) { final Optional result = context.getPreprocessingState() .getIncludeStack() .stream() .findFirst() .map(TextFileDataContainer::getFile) .flatMap(context::findFileInfoContainer); return result.isPresent() ? result : Optional.ofNullable(context.getPreprocessingState().getRootFileInfo()); } /** * Find current file position info in a context. * * @param context preprocessor context, must not be null * @return found current file position info, must not be null * @since 7.3.0 * @throws PreprocessorException thrown if it is impossible to find position info. */ public static FilePositionInfo extractFilePositionInfo( final PreprocessorContext context ) { return context.getPreprocessingState().findFilePositionInfo() .orElseThrow(() -> context.makeException("Can't find position info in the context", null)); } /** * Find all services in class path and register them in provided context. * * @param context target context must not be null * @since 7.3.0 */ public static void fillContextByFoundServices(final PreprocessorContext context) { final List commentTextProcessors = findAndInstantiateAllServices( CommentTextProcessor.class); if (!commentTextProcessors.isEmpty()) { context.getPreprocessorLogger() .info(String.format("Detected %d comment text processing service(s): %s", commentTextProcessors.size(), commentTextProcessors.stream().map(x -> x.getClass().getCanonicalName()) .collect(Collectors.joining(",")))); commentTextProcessors.forEach(context::addCommentTextProcessor); } final List specialVariableProcessors = findAndInstantiateAllServices( SpecialVariableProcessor.class); if (!specialVariableProcessors.isEmpty()) { context.getPreprocessorLogger() .info(String.format("Detected %d special variable service(s): %s", specialVariableProcessors.size(), specialVariableProcessors.stream().map(x -> x.getClass().getCanonicalName()) .collect(Collectors.joining(",")))); specialVariableProcessors.forEach(context::registerSpecialVariableProcessor); } final List preprocessorExtensions = findAndInstantiateAllServices( PreprocessorExtension.class); if (!preprocessorExtensions.isEmpty()) { context.getPreprocessorLogger() .info(String.format("Detected %d preprocessor extension service(s): %s", preprocessorExtensions.size(), preprocessorExtensions.stream().map(x -> x.getClass().getCanonicalName()) .collect(Collectors.joining(",")))); preprocessorExtensions.forEach(context::addPreprocessorExtension); } } /** * Find and instantiate a preprocessor extension for its class name. Class must have default constructor. * The preprocessor extension will be called for action directives. * * @param className preprocessor extension class name, can be null. * @return found and instantiated preprocessor extension or null if class name is null * @throws RuntimeException with cause exception if any error during method call. * @since 7.1.2 */ public static PreprocessorExtension findAndInstantiatePreprocessorExtensionForClassName( final String className) { if (className == null) { return null; } try { final Class foundClass = Class.forName(className); return (PreprocessorExtension) foundClass.getConstructor().newInstance(); } catch (Exception ex) { throw new RuntimeException("Can't instantiate preprocessor extension class: " + className, ex); } } /** * Find comment remover type for provided identifier. Decoding also true and false values. * * @param text comment remover id as string, must not be null. * @return found appropriate comment remover type, must not be null * @since 7.1.0 */ public static CommentRemoverType findCommentRemoverForId(final String text) { CommentRemoverType result = null; if (text != null && !text.isEmpty()) { final String normalized = text.trim().toUpperCase(Locale.ROOT); if (normalized.equals("TRUE")) { result = KEEP_ALL; } else if (normalized.equals("FALSE")) { result = REMOVE_C_STYLE; } else { for (final CommentRemoverType value : CommentRemoverType.values()) { if (normalized.equals(value.name())) { result = value; break; } } } } if (result == null) { throw new IllegalArgumentException( "Can't recognize keep comment value '" + text + "' (allowed values: true,false," + makeListOfAllRemoverIds() + ')'); } return result; } public static String getFileExtension(final File file) { String result = null; if (file != null) { result = FilenameUtils.getExtension(file.getName()); } return result; } public static BufferedReader makeFileReader(final File file, final Charset charset, final int bufferSize) throws IOException { Objects.requireNonNull(file, "File is null"); Objects.requireNonNull(charset, "Charset is null"); BufferedReader result; if (bufferSize <= 0) { result = new BufferedReader(new InputStreamReader(new FileInputStream(file), charset)); } else { result = new BufferedReader(new InputStreamReader(new FileInputStream(file), charset), bufferSize); } return result; } public static String[] replaceChar(final String[] source, final char toBeReplaced, final char replacement) { final String[] result = new String[source.length]; int index = 0; for (final String curStr : source) { result[index++] = curStr.replace(toBeReplaced, replacement); } return result; } public static String extractTrimmedTail(final String prefix, final String value) { return extractTail(prefix, value).trim(); } public static String extractTail(final String prefix, final String value) { Objects.requireNonNull(prefix, "Prefix is null"); Objects.requireNonNull(value, "Value is null"); if (prefix.length() > value.length()) { throw new IllegalArgumentException("Prefix is too long"); } return value.substring(prefix.length()); } public static void copyFile(final File source, final File dest, final boolean copyFileAttributes) throws IOException { Objects.requireNonNull(source, "Source is null"); Objects.requireNonNull(dest, "Destination file is null"); if (source.isDirectory()) { throw new IllegalArgumentException("Source file is directory"); } if (!dest.getParentFile().exists() && !dest.getParentFile().mkdirs()) { throw new IOException("Can't make directory [" + getFilePath(dest.getParentFile()) + ']'); } FileUtils.copyFile(source, dest); if (copyFileAttributes) { copyFileAttributes(source, dest); } } public static boolean copyFileAttributes(final File from, final File to) { boolean result = to.setExecutable(from.canExecute()); result = result && to.setReadable(from.canRead()); result = result && to.setWritable(from.canWrite()); result = result && to.setLastModified(from.lastModified()); return result; } public static String replacePartByChar(final String text, final char chr, final int startPosition, final int length) { if (startPosition < 0) { throw new IllegalArgumentException("Start position must be great or equal zero"); } if (length < 0) { throw new IllegalArgumentException("Length must be great or equal zero"); } final StringBuilder result = new StringBuilder(text.length()); result.append(text.subSequence(0, Math.min(text.length(), startPosition))); result.append(String.valueOf(chr) .repeat(Math.max(0, Math.min(text.length(), startPosition + length) - startPosition))); result.append(text.subSequence(Math.min(startPosition + length, text.length()), text.length())); return result.toString(); } public static List findAndInstantiateAllServices(final Class serviceClass) { if (Boolean.getBoolean(SYSTEM_PROPERTY_DISABLE_SEARCH_SERVICES)) { return List.of(); } final ServiceLoader serviceLoader = ServiceLoader.load(serviceClass); return serviceLoader.stream().map(ServiceLoader.Provider::get).collect(Collectors.toList()); } public static String generateStringForChar(final char chr, final int length) { final StringBuilder buffer = new StringBuilder(Math.max(length, 1)); buffer.append(String.valueOf(chr).repeat(Math.max(0, length))); return buffer.toString(); } public static String processMacroses(final String processingString, final PreprocessorContext context) { int position; String result = processingString; if (context.isAllowWhitespaces()) { final Matcher matcher = PATTERN_MACROS_WITH_SPACES.matcher(processingString); final StringBuilder buffer = new StringBuilder(); int end = 0; while (matcher.find()) { final int start = matcher.start(); final int prevEnd = end; end = matcher.end(); final String macrosBody = matcher.group(1); final Value value = Expression.evalExpression(macrosBody, context); buffer.append(processingString, prevEnd, start); buffer.append(value); } if (end < processingString.length()) { buffer.append(processingString.substring(end)); } result = buffer.toString(); } else { while (!Thread.currentThread().isInterrupted()) { position = result.indexOf("/*$"); if (position >= 0) { final String leftPart = result.substring(0, position); final int beginIndex = position; position = result.indexOf("$*/", position); if (position >= 0) { final String macrosBody = result.substring(beginIndex + 3, position); final String rightPart = result.substring(position + 3); final Value value = Expression.evalExpression(macrosBody, context); result = leftPart + value + rightPart; } else { break; } } else { break; } } } return result; } private static void checkFile(final File file) throws IOException { Objects.requireNonNull(file, "File is null"); if (!file.isFile()) { throw new FileNotFoundException("File " + getFilePath(file) + " doesn't exist"); } } public static String[] readWholeTextFileIntoArray(final File file, final Charset encoding, final AtomicBoolean endedByNextLine) throws IOException { checkFile(file); final List strContainer = new ArrayList<>(1024); try (BufferedReader srcBufferedReader = PreprocessorUtils .makeFileReader(file, encoding == null ? StandardCharsets.UTF_8 : encoding, (int) file.length())) { final StringBuilder buffer = new StringBuilder(); boolean stringEndedByNextLine = false; boolean meetCR = false; while (!Thread.currentThread().isInterrupted()) { final int chr = srcBufferedReader.read(); if (chr < 0) { break; } switch (chr) { case '\n': { stringEndedByNextLine = true; strContainer.add(buffer.toString()); buffer.setLength(0); meetCR = false; } break; case '\r': { if (meetCR) { buffer.append((char) chr); } else { stringEndedByNextLine = false; meetCR = true; } } break; default: { if (meetCR) { buffer.append('\r'); } meetCR = false; stringEndedByNextLine = false; buffer.append((char) chr); } break; } } if (buffer.length() != 0) { strContainer.add(buffer.toString()); buffer.setLength(0); } if (endedByNextLine != null) { endedByNextLine.set(stringEndedByNextLine); } } return strContainer.toArray(new String[0]); } public static String[] splitForEqualChar(final String string) { final int index = string.indexOf('='); final String[] result; if (index < 0) { result = new String[] {string}; } else { final String leftPart = string.substring(0, index).trim(); final String rightPart = string.substring(index + 1).trim(); result = new String[] {leftPart, rightPart}; } return result; } public static List splitForCharAndHoldEmptyLine(final String string, final char delimiter) { final List result = splitForChar(string, delimiter); if (result.isEmpty()) { result.add(""); } return result; } public static List splitForChar(final String string, final char delimiter) { final char[] array = string.toCharArray(); final StringBuilder buffer = new StringBuilder((array.length >> 1) == 0 ? 1 : array.length >> 1); final List tokens = new ArrayList<>(10); for (final char curChar : array) { if (curChar == delimiter) { if (buffer.length() != 0) { tokens.add(buffer.toString()); buffer.setLength(0); } } else { buffer.append(curChar); } } if (buffer.length() != 0) { tokens.add(buffer.toString()); } return tokens; } public static String normalizeVariableName(final String name) { if (name == null) { return null; } return name.trim().toLowerCase(Locale.ROOT); } public static String getFilePath(final File file) { String result = ""; if (file != null) { try { result = file.getCanonicalPath(); } catch (IOException ex) { result = file.getAbsolutePath(); } } return result; } public static void throwPreprocessorException(final String msg, final String processingString, final File srcFile, final int nextStringIndex, final Throwable cause) { throw new PreprocessorException(msg, processingString, new FilePositionInfo[] {new FilePositionInfo(srcFile, nextStringIndex)}, cause); } public static String[] replaceStringPrefix( final String[] allowedPrefixesToBeReplaced, final String replacement, final String[] strings) { final String[] result = new String[strings.length]; for (int i = 0; i < strings.length; i++) { final String str = strings[i]; String detectedPrefix = null; for (final String prefix : allowedPrefixesToBeReplaced) { if (str.startsWith(prefix) && (detectedPrefix == null || detectedPrefix.length() < prefix.length())) { detectedPrefix = prefix; } } if (detectedPrefix != null) { result[i] = replacement + str.substring(detectedPrefix.length()); } else { result[i] = str; } } return result; } public static String getNextLineCodes() { return System.getProperty("line.separator", "\r\n"); } public static String leftTrim(String rawString) { int firstNonSpace = 0; for (int i = 0; i < rawString.length(); i++) { final char ch = rawString.charAt(i); if (ch > 32) { break; } firstNonSpace++; } return rawString.substring(firstNonSpace); } public static boolean isFileContentEquals(final File src, final File dst) throws IOException { if (src == null && dst == null) { return true; } if (src == null || dst == null) { return false; } if (src.isDirectory() && dst.isDirectory()) { return true; } if (src.isDirectory() || dst.isDirectory()) { return false; } if (src.length() != dst.length()) { return false; } return FileUtils.contentEquals(src, dst); } } ================================================ FILE: jcp/src/main/java/com/igormaznitsa/jcp/utils/ResettablePrinter.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.utils; import java.io.CharArrayWriter; import java.io.IOException; import java.io.Writer; /** * Text printer to keep text in internal buffer. * * @since 7.3.0 */ public class ResettablePrinter { private final CharArrayWriter internalBuffer; public ResettablePrinter(final int initialCapacity) { this.internalBuffer = new CharArrayWriter(initialCapacity); } public String getText() { return new String(this.internalBuffer.toCharArray()); } public boolean isEmpty() { return internalBuffer.size() == 0; } public void writeBufferTo(final Writer writer) throws IOException { this.internalBuffer.flush(); writer.write(internalBuffer.toCharArray()); writer.flush(); } public int getSize() { return internalBuffer.size(); } public void reset() { internalBuffer.reset(); } public void print(final String text) { for (final char chr : text.toCharArray()) { internalBuffer.write(chr); } } public void println(final String text, final String eol) { for (final char chr : text.toCharArray()) { this.internalBuffer.write(chr); } internalBuffer.write(eol, 0, eol.length()); } } ================================================ FILE: jcp/src/main/resources/META-INF/gradle-plugins/com.igormaznitsa.jcp.properties ================================================ implementation-class=com.igormaznitsa.jcp.gradle.JcpGradlePlugin ================================================ FILE: jcp/src/main/resources/com/igormaznitsa/jcp/ant/antlib.xml ================================================ ================================================ FILE: jcp/src/main/resources/com/igormaznitsa/jcp/ant/tasks.properties ================================================ preprocess=com.igormaznitsa.jcp.ant.PreprocessTask ================================================ FILE: jcp/src/main/resources/jcpversion.properties ================================================ version=${project.version} url=${project.url} year=${current.year} ================================================ FILE: jcp/src/site/markdown/examples/hello-world.md ================================================ # Hello World Just add the snippet into pom.xml ```xml com.igormaznitsa jcp 7.3.0 preprocessSources generate-sources preprocess ``` Then build project with `mvn clean install` and check the folder `target/generated-sources/preprocessed` ================================================ FILE: jcp/src/site/markdown/index.md ================================================ # Java Comment Preprocessor Java Comment Preprocessor (JCP) is a Maven plugin that allows preprocessing of source code for languages that support C-style comments. It stores its directives inside comments and supports some automation features, such as loops and file loading/processing. JCP was originally created for developing mobile J2ME games, but later evolved into a full-featured tool. Just add code-snippet below into build section and the plugin will be started during build. ```xml com.igormaznitsa jcp 7.3.0 preprocess-sources generate-sources preprocess ``` ================================================ FILE: jcp/src/site/markdown/usage.md ================================================ # Usage Just add the plugin into the module build section. ```xml com.igormaznitsa gosdk-wrapper-maven-plugin 1.0.5 1.24.4 go-help execute help ``` If you use `jar` packaging then you should deactivate default plugin calls. You can disable them with below code snippet. ```xml maven-clean-plugin default-clean none maven-jar-plugin default-jar none maven-surefire-plugin default-test none maven-compiler-plugin default-compile none default-testCompile none maven-install-plugin default-install none ``` ================================================ FILE: jcp/src/site/site.xml ================================================ org.apache.maven.skins maven-fluido-skin 2.0.1 ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/AbstractMockPreprocessorContextTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp; import static org.mockito.ArgumentMatchers.any; import static org.powermock.api.mockito.PowerMockito.doAnswer; import static org.powermock.api.mockito.PowerMockito.doThrow; import static org.powermock.api.mockito.PowerMockito.mock; import static org.powermock.api.mockito.PowerMockito.when; import com.igormaznitsa.jcp.containers.FileInfoContainer; import com.igormaznitsa.jcp.context.CommentRemoverType; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.exceptions.FilePositionInfo; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.utils.ResettablePrinter; import java.io.File; import java.util.concurrent.atomic.AtomicReference; import org.junit.runner.RunWith; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest({PreprocessorContext.class, PreprocessingState.class}) public abstract class AbstractMockPreprocessorContextTest { protected PreprocessorContext prepareMockContext() throws Exception { final PreprocessorContext preparedContext = mock(PreprocessorContext.class); final PreprocessingState preparedState = mock(PreprocessingState.class); final AtomicReference keepComments = new AtomicReference<>( CommentRemoverType.REMOVE_C_STYLE); doThrow(new PreprocessorException("mock_msg", "", new FilePositionInfo[0], null)) .when(preparedContext) .makeException(any(String.class), any()); final FileInfoContainer container = new FileInfoContainer( new File("src/fake.java"), "fake.java", false ); when(preparedContext.getKeepComments()).thenAnswer( invocationOnMock -> keepComments.get()); doAnswer(invocationOnMock -> { keepComments.set((CommentRemoverType) invocationOnMock.getArguments()[0]); return null; }).when(preparedContext).setKeepComments(any(CommentRemoverType.class)); when(preparedState.getRootFileInfo()).thenReturn(container); final ResettablePrinter printer = new ResettablePrinter(10); when(preparedState.getSelectedPrinter()).thenReturn(printer); when(preparedContext.getPreprocessingState()).thenReturn(preparedState); return preparedContext; } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/AbstractSpyPreprocessorContextTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp; import static org.apache.commons.io.FilenameUtils.normalize; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.io.File; import java.util.Collections; import java.util.List; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) @PrepareForTest({PreprocessorContext.class, PreprocessingState.class}) public abstract class AbstractSpyPreprocessorContextTest { protected static TemporaryFolder destinationFolder; @BeforeClass public static void prepareClassTests() throws Exception { destinationFolder = new TemporaryFolder(new File("./")); destinationFolder.create(); } @AfterClass public static void doJanitor() throws Exception { destinationFolder.delete(); } @Before public void beforeTest() throws Exception { FileUtils.cleanDirectory(destinationFolder.getRoot()); } protected List getCurrentTestFolder() { final String testFolder = FilenameUtils.normalizeNoEndSeparator(System.getProperty("test.folder")); final String fullClassPath = this.getClass().getName().replace('.', File.separatorChar); return Collections.singletonList(normalize(testFolder + File.separator + fullClassPath.substring(0, fullClassPath.lastIndexOf(File.separatorChar)))); } protected File getDestinationFolder() { return destinationFolder.getRoot(); } protected void assertDestinationFolderEmpty() throws Exception { assertEquals("Destination folder must be enpty", 0, destinationFolder.getRoot().list().length); } protected PreprocessorContext preparePreprocessorContext(final List sourceFolders) throws Exception { return this.preparePreprocessorContext(sourceFolders, () -> false); } protected PreprocessorContext preparePreprocessorContext(final List sourceFolders, final ContextDataProvider provider) throws Exception { final PreprocessorContext spyContext = PowerMockito.spy(new PreprocessorContext(new File("some_impossible_folder_121212"))); final PreprocessingState fakeState = PreprocessingState.makeMock(spyContext); PowerMockito.when(spyContext.getPreprocessingState()).thenReturn(fakeState); spyContext.setAllowWhitespaces(provider.getAllowSpaceBeforeDirectiveFlag()); spyContext.setSources(sourceFolders); spyContext.setTarget(destinationFolder.getRoot()); return spyContext; } public interface ContextDataProvider { boolean getAllowSpaceBeforeDirectiveFlag(); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/JCPreprocessorTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.igormaznitsa.jcp.cmdline.CommandLineHandler; import com.igormaznitsa.jcp.context.CommentRemoverType; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.junit.Test; public final class JCPreprocessorTest { private void assertGVDFPreprocessorException(final String file, final int stringIndexStartedFromOne) throws Exception { final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); context.registerConfigFile(new File(this.getClass().getResource(file).toURI())); final JcpPreprocessor preprocessor = new JcpPreprocessor(context); try { preprocessor.processConfigFiles(); fail("Must throw a PreprocessorException"); } catch (PreprocessorException expected) { if (stringIndexStartedFromOne != expected.getLineNumber()) { fail("Wrong error string index [" + expected.toString() + ']'); } } } @Test public void testProcessGlobalVarDefiningFiles() throws Exception { final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); context.registerConfigFile(new File(this.getClass().getResource("./global_ok.txt").toURI())); final JcpPreprocessor preprocessor = new JcpPreprocessor(context); preprocessor.processConfigFiles(); assertEquals("Must have the variable", "hello world", context.findVariableForName("globalVar1", true).asString()); assertEquals("Must have the variable", Value.INT_THREE, context.findVariableForName("globalVar2", true)); assertEquals("Character input encoding must be changed", StandardCharsets.ISO_8859_1, context.getSourceEncoding()); } @Test public void testProcessGlobalVarDefiningFiles_ATsymbol() throws Exception { assertGVDFPreprocessorException("global_error_at.txt", 8); } @Test public void testJavaCommentRemoving() throws Exception { final File testDirectory = new File(getClass().getResource("removers/java").toURI()); final File resultFile = new File(testDirectory, "w_o_comments.ttt"); final File etalonFile = new File(testDirectory, "etalon.etl"); if (resultFile.exists()) { assertTrue("We have to remove the existing result file", resultFile.delete()); } final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); context.setSources(Collections.singletonList(testDirectory.getCanonicalPath())); context.setTarget(testDirectory); context.setClearTarget(false); context.setKeepComments(CommentRemoverType.REMOVE_C_STYLE); context.setExtensions(Collections.singletonList("ppp")); context.setExcludeExtensions(Collections.singletonList("etl")); final JcpPreprocessor preprocessor = new JcpPreprocessor(context); preprocessor.execute(); assertTrue("There must be the result file", resultFile.exists()); assertTrue("There must be the etalon file", etalonFile.exists()); String differentLine = null; int lineIndex = 1; try (BufferedReader resultReader = new BufferedReader( new InputStreamReader(new FileInputStream(resultFile), StandardCharsets.UTF_8))) { try (BufferedReader etalonReader = new BufferedReader( new InputStreamReader(new FileInputStream(etalonFile), StandardCharsets.UTF_8))) { while (!Thread.currentThread().isInterrupted()) { final String resultStr = resultReader.readLine(); final String etalonStr = etalonReader.readLine(); if (resultStr == null && etalonStr == null) { break; } if (resultStr == null || !resultStr.equals(etalonStr)) { differentLine = resultStr; break; } lineIndex++; } } } if (differentLine != null) { fail("Line " + lineIndex + " There is a different strings [" + differentLine + '['); } } @Test public void testCLIHandlerNameConflicts() { final List checked = new ArrayList<>(); for (final CommandLineHandler h : JcpPreprocessor.COMMAND_LINE_HANDLERS) { final String name = h.getKeyName(); for (final String l : checked) { if (l.startsWith(name) || name.startsWith(l)) { fail("Conflict [" + l + " and " + name + ']'); } } checked.add(name); } } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/TestUtils.java ================================================ /* * Copyright 2019 Igor Maznitsa. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.igormaznitsa.jcp; import java.io.File; import java.nio.file.Path; import org.junit.Assert; public final class TestUtils { private TestUtils() { } public static String normalizeNextLine(final String text) { return text == null ? null : text.replace("\r\n", "\n"); } public static void assertFilePath(final String message, final File expected, final File check) { final Path pathExpected = expected.toPath().normalize(); final Path pathCheck = check.toPath().normalize(); if (!pathExpected.equals(pathCheck)) { Assert.fail("Expected path '" + pathExpected.toString() + "' but detected path '" + pathCheck.toString() + "'"); } } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/ant/PreprocessTaskTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.ant; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import com.igormaznitsa.jcp.context.CommentRemoverType; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import java.io.File; import java.nio.charset.StandardCharsets; import java.util.Hashtable; import java.util.List; import java.util.Set; import org.apache.tools.ant.Project; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class PreprocessTaskTest { final static Project projectMock = mock(Project.class); static File THIS_DIRECTORY; static { when(projectMock.getBaseDir()).thenReturn(new File("base/dir")); when(projectMock.getProperties()).thenReturn(new Hashtable()); } PreprocessTask antTask; @BeforeClass public static void beforeClass() throws Exception { THIS_DIRECTORY = new File(com.igormaznitsa.jcp.ant.PreprocessTaskTest.class.getResource("./").toURI()); } @Before public void beforeTest() { antTask = new PreprocessTask(); antTask.setProject(projectMock); final PreprocessTask.Sources sources = new PreprocessTask.Sources(); sources.createPath().setValue(THIS_DIRECTORY.getAbsolutePath()); antTask.setSources(sources); } @Test public void testSetSources() { final List sourceDirs = antTask.makePreprocessorContext().getSources(); assertEquals(1, sourceDirs.size()); assertEquals(THIS_DIRECTORY, sourceDirs.get(0).getAsFile()); } @Test public void testTarget() { antTask.setTarget(THIS_DIRECTORY.getAbsolutePath()); assertEquals(THIS_DIRECTORY, antTask.makePreprocessorContext().getTarget()); } @Test public void testSourceEncoding() { final String TEST = "ISO-8859-1"; antTask.setSourceEncoding(TEST); assertEquals(StandardCharsets.ISO_8859_1, antTask.makePreprocessorContext().getSourceEncoding()); } @Test public void testTargetEncoding() { final String TEST = "ISO-8859-1"; antTask.setTargetEncoding(TEST); assertEquals(StandardCharsets.ISO_8859_1, antTask.makePreprocessorContext().getTargetEncoding()); } @Test public void testExcludedExtensions() { final PreprocessTask.ExcludeExtensions antextensions = antTask.createExcludeExtensions(); antextensions.createExtension().addText("bin"); antextensions.createExtension().addText("vb"); antextensions.createExtension().addText("cpp"); final Set extensions = antTask.makePreprocessorContext().getExcludeExtensions(); assertEquals(3, extensions.size()); assertTrue(extensions.contains("bin")); assertTrue(extensions.contains("vb")); assertTrue(extensions.contains("cpp")); } @Test public void testExtensions() { final PreprocessTask.Extensions antextensions = antTask.createExtensions(); antextensions.createExtension().addText("bin"); antextensions.createExtension().addText("vb"); antextensions.createExtension().addText("cpp"); final Set extensions = antTask.makePreprocessorContext().getExtensions(); assertEquals(3, extensions.size()); assertTrue(extensions.contains("bin")); assertTrue(extensions.contains("vb")); assertTrue(extensions.contains("cpp")); } @Test public void testClearTarget() { antTask.setClearTarget(true); assertTrue(antTask.makePreprocessorContext().isClearTarget()); antTask.setClearTarget(false); assertFalse(antTask.makePreprocessorContext().isClearTarget()); } @Test public void testKeepComments() throws Exception { antTask.setKeepComments("true"); assertEquals(CommentRemoverType.KEEP_ALL, antTask.makePreprocessorContext().getKeepComments()); antTask.setKeepComments("false"); assertEquals(CommentRemoverType.REMOVE_C_STYLE, antTask.makePreprocessorContext().getKeepComments()); } @Test public void testVerbose() throws Exception { antTask.setVerbose(true); assertTrue(antTask.makePreprocessorContext().isVerbose()); antTask.setVerbose(false); assertFalse(antTask.makePreprocessorContext().isVerbose()); } @Test public void testAllowWhitespace() { antTask.setAllowWhitespaces(true); assertTrue(antTask.makePreprocessorContext().isAllowWhitespaces()); antTask.setAllowWhitespaces(false); assertFalse(antTask.makePreprocessorContext().isVerbose()); } @Test public void testCareForLastEol() { antTask.setCareForLastEol(true); assertTrue(antTask.makePreprocessorContext().isCareForLastEol()); antTask.setCareForLastEol(false); assertFalse(antTask.makePreprocessorContext().isCareForLastEol()); } @Test public void testEol() { antTask.setEol("someeol\\r\\n"); assertEquals("someeol\r\n", antTask.makePreprocessorContext().getEol()); } @Test public void testPreserveIndents() { antTask.setPreserveIndents(true); assertTrue(antTask.makePreprocessorContext().isPreserveIndents()); antTask.setPreserveIndents(false); assertFalse(antTask.makePreprocessorContext().isPreserveIndents()); } @Test public void testDontOverwriteSameContent() { antTask.setDontOverwriteSameContent(true); assertTrue(antTask.makePreprocessorContext().isDontOverwriteSameContent()); antTask.setDontOverwriteSameContent(false); assertFalse(antTask.makePreprocessorContext().isDontOverwriteSameContent()); } @Test public void testDryRun() { antTask.setDryRun(true); assertTrue(antTask.makePreprocessorContext().isDryRun()); antTask.setDryRun(false); assertFalse(antTask.makePreprocessorContext().isDryRun()); } @Test public void testUnknownVarAsFalse() { antTask.setUnknownVarAsFalse(true); assertTrue(antTask.makePreprocessorContext().isUnknownVariableAsFalse()); antTask.setUnknownVarAsFalse(false); assertFalse(antTask.makePreprocessorContext().isUnknownVariableAsFalse()); } @Test public void testAddGlobal() { final PreprocessTask.Vars vars = antTask.createVars(); final PreprocessTask.Vars.Var var = vars.createVar(); var.setName("hello_world"); var.setValue("4"); assertEquals(Value.INT_FOUR, antTask.makePreprocessorContext().findVariableForName("hello_world", false)); } @Test public void testAddCfgFile() { final PreprocessTask.ConfigFiles configFiles = antTask.createConfigFiles(); configFiles.createPath().setValue("what/that"); configFiles.createPath().setValue("what/those"); final List foundConfigFiles = antTask.makePreprocessorContext().getConfigFiles(); assertEquals("Must be 2", 2, foundConfigFiles.size()); assertEquals("base/dir/what/that".replace('/', File.separatorChar), foundConfigFiles.get(0).getPath()); assertEquals("base/dir/what/those".replace('/', File.separatorChar), foundConfigFiles.get(1).getPath()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/AbstractCommandLineHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.igormaznitsa.jcp.AbstractMockPreprocessorContextTest; import com.igormaznitsa.jcp.JcpPreprocessor; import org.junit.Test; public abstract class AbstractCommandLineHandlerTest extends AbstractMockPreprocessorContextTest { @Test public abstract void testExecution() throws Exception; @Test public abstract void testName(); @Test public abstract void testDescription(); @Test public abstract void testThatTheHandlerInTheHandlerList(); protected void assertDescription(final CommandLineHandler handler) { assertNotNull("Reference must not be null", handler.getDescription()); assertFalse("Reference must not be empty one", handler.getDescription().isEmpty()); assertTrue("Reference length must be great than 10 chars", handler.getDescription().length() > 10); } protected void assertHandlerInTheHandlerList(final CommandLineHandler handler) { for (final CommandLineHandler h : JcpPreprocessor.getCommandLineHandlers()) { if (handler.getClass() == h.getClass()) { return; } } fail("There is not the handler in the common command line handler list"); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/ActionPreprocessorExtensionHandlerTest.java ================================================ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; import org.junit.Test; public class ActionPreprocessorExtensionHandlerTest extends AbstractCommandLineHandlerTest { private static final ActionPreprocessorExtensionHandler HANDLER = new ActionPreprocessorExtensionHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Test public void testErrorWithoutFlag() { } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertTrue(HANDLER.processCommandLineKey("/EA:", mock)); assertFalse(HANDLER.processCommandLineKey("/AE", mock)); assertFalse(HANDLER.processCommandLineKey("/E ", mock)); verify(mock, never()).setAllowWhitespaces(anyBoolean()); assertFalse(HANDLER.processCommandLineKey("/EA", mock)); reset(mock); } @Override public void testName() { assertEquals("/EA:", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/AllowMergeBlockLineHandlerTest.java ================================================ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; public class AllowMergeBlockLineHandlerTest extends AbstractCommandLineHandlerTest { private static final AllowMergeBlockLineHandler HANDLER = new AllowMergeBlockLineHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("", mock)); assertFalse(HANDLER.processCommandLineKey("/b:", mock)); assertFalse(HANDLER.processCommandLineKey("/BB", mock)); assertTrue(HANDLER.processCommandLineKey("/B", mock)); verify(mock).setAllowsBlocks(true); } @Override public void testName() { assertEquals("/B", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/AllowWhitespaceDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; import org.junit.Test; public class AllowWhitespaceDirectiveHandlerTest extends AbstractCommandLineHandlerTest { private static final AllowWhitespaceDirectiveHandler HANDLER = new AllowWhitespaceDirectiveHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Test public void testErrorWithoutFlag() { } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("/es:", mock)); assertFalse(HANDLER.processCommandLineKey("/EK", mock)); assertFalse(HANDLER.processCommandLineKey("/E ", mock)); verify(mock, never()).setAllowWhitespaces(anyBoolean()); assertTrue(HANDLER.processCommandLineKey("/ES", mock)); verify(mock).setAllowWhitespaces(true); reset(mock); assertTrue(HANDLER.processCommandLineKey("/es", mock)); verify(mock).setAllowWhitespaces(true); reset(mock); } @Override public void testName() { assertEquals("/ES", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/CareForLastEolHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; public class CareForLastEolHandlerTest extends AbstractCommandLineHandlerTest { private static final CareForLastEolHandler HANDLER = new CareForLastEolHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("/n:", mock)); assertFalse(HANDLER.processCommandLineKey("/NN", mock)); assertFalse(HANDLER.processCommandLineKey("/N ", mock)); verify(mock, never()).setClearTarget(anyBoolean()); assertTrue(HANDLER.processCommandLineKey("/N", mock)); verify(mock).setCareForLastEol(true); reset(mock); assertTrue(HANDLER.processCommandLineKey("/n", mock)); verify(mock).setCareForLastEol(true); reset(mock); } @Override public void testName() { assertEquals("/N", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/ClearTargetFolderHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; public class ClearTargetFolderHandlerTest extends AbstractCommandLineHandlerTest { private static final ClearTargetHandler HANDLER = new ClearTargetHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("/c:", mock)); assertFalse(HANDLER.processCommandLineKey("/CC", mock)); assertFalse(HANDLER.processCommandLineKey("/C ", mock)); verify(mock, never()).setClearTarget(anyBoolean()); assertTrue(HANDLER.processCommandLineKey("/C", mock)); verify(mock).setClearTarget(true); reset(mock); assertTrue(HANDLER.processCommandLineKey("/c", mock)); verify(mock).setClearTarget(true); reset(mock); } @Override public void testName() { assertEquals("/C", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/CommentRemoverTypeHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import com.igormaznitsa.jcp.context.CommentRemoverType; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.exceptions.PreprocessorException; public class CommentRemoverTypeHandlerTest extends AbstractCommandLineHandlerTest { private static final KeepCommentsHandler HANDLER = new KeepCommentsHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("", mock)); assertFalse(HANDLER.processCommandLineKey("/m", mock)); assertFalse(HANDLER.processCommandLineKey("/mm:", mock)); assertThrows(PreprocessorException.class, () -> HANDLER.processCommandLineKey("/m:", mock)); assertEquals(CommentRemoverType.REMOVE_C_STYLE, mock.getKeepComments()); assertTrue(HANDLER.processCommandLineKey("/m:keep_all", mock)); assertEquals(CommentRemoverType.KEEP_ALL, mock.getKeepComments()); } @Override public void testName() { assertEquals("/M:", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/DestinationDirectoryHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.io.File; import org.mockito.ArgumentCaptor; public class DestinationDirectoryHandlerTest extends AbstractCommandLineHandlerTest { private static final DestinationDirectoryHandler HANDLER = new DestinationDirectoryHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("/s:", mock)); assertFalse(HANDLER.processCommandLineKey("/O:", mock)); assertTrue(HANDLER.processCommandLineKey("/O:test", mock)); ArgumentCaptor captor = ArgumentCaptor.forClass(File.class); verify(mock).setTarget(captor.capture()); assertEquals("test", captor.getValue().getPath()); } @Override public void testName() { assertEquals("/O:", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/DontOverwriteSameContentHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; public class DontOverwriteSameContentHandlerTest extends AbstractCommandLineHandlerTest { private static final DontOverwriteSameContentHandler HANDLER = new DontOverwriteSameContentHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("/z:", mock)); assertFalse(HANDLER.processCommandLineKey("/ZZ", mock)); assertFalse(HANDLER.processCommandLineKey("/Z ", mock)); verify(mock, never()).setDontOverwriteSameContent(anyBoolean()); assertTrue(HANDLER.processCommandLineKey("/Z", mock)); verify(mock).setDontOverwriteSameContent(true); reset(mock); assertTrue(HANDLER.processCommandLineKey("/z", mock)); verify(mock).setDontOverwriteSameContent(true); reset(mock); } @Override public void testName() { assertEquals("/Z", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/ExcludeFoldersHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.io.File; import java.util.List; import org.mockito.ArgumentCaptor; @SuppressWarnings("unchecked") public class ExcludeFoldersHandlerTest extends AbstractCommandLineHandlerTest { private static final ExcludeFoldersHandler HANDLER = new ExcludeFoldersHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("", mock)); assertFalse(HANDLER.processCommandLineKey("/ed:", mock)); assertFalse(HANDLER.processCommandLineKey("/Ed:", mock)); assertFalse(HANDLER.processCommandLineKey("/ED", mock)); assertTrue(HANDLER.processCommandLineKey( "/ed:testdir/**/hd" + File.pathSeparator + "zoom" + File.pathSeparator + "g?df", mock)); final ArgumentCaptor> captor = ArgumentCaptor.forClass(List.class); verify(mock).setExcludeFolders(captor.capture()); assertArrayEquals(new String[] {"testdir/**/hd", "zoom", "g?df"}, captor.getValue().toArray(new String[0])); } @Override public void testName() { assertEquals("/ED:", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/ExcludedFileExtensionsHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.util.Arrays; public class ExcludedFileExtensionsHandlerTest extends AbstractCommandLineHandlerTest { private static final ExcludedFileExtensionsHandler HANDLER = new ExcludedFileExtensionsHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("", mock)); assertFalse(HANDLER.processCommandLineKey("/ef:", mock)); assertFalse(HANDLER.processCommandLineKey("/ef", mock)); assertFalse(HANDLER.processCommandLineKey("/EF:", mock)); verify(mock, never()).setExcludeExtensions(any()); assertTrue(HANDLER.processCommandLineKey("/ef:rrr,Ggg,bBb", mock)); verify(mock).setExcludeExtensions(Arrays.asList("rrr", "Ggg", "bBb")); } @Override public void testName() { assertEquals("/EF:", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/FileExtensionsHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.util.Arrays; public class FileExtensionsHandlerTest extends AbstractCommandLineHandlerTest { private static final FileExtensionsHandler HANDLER = new FileExtensionsHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("", mock)); assertFalse(HANDLER.processCommandLineKey("/f:", mock)); assertFalse(HANDLER.processCommandLineKey("/f", mock)); assertFalse(HANDLER.processCommandLineKey("/F:", mock)); verify(mock, never()).setExcludeExtensions(any()); assertTrue(HANDLER.processCommandLineKey("/f:rrr,Ggg,bBb", mock)); verify(mock).setExtensions(Arrays.asList("rrr", "Ggg", "bBb")); } @Override public void testName() { assertEquals("/F:", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/GlobalVariableDefiningFileHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.TestUtils; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.io.File; import java.util.List; import org.junit.Test; public final class GlobalVariableDefiningFileHandlerTest extends AbstractCommandLineHandlerTest { private static final GlobalVariableDefiningFileHandler HANDLER = new GlobalVariableDefiningFileHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); final File testFile = new File(this.getClass().getResource("./global_variable_def.txt").toURI()); final String param = "@" + PreprocessorUtils.getFilePath(testFile); HANDLER.processCommandLineKey(param, context); final List configFiles = context.getConfigFiles(); assertEquals("File must be added", 1, configFiles.size()); TestUtils.assertFilePath("File must be equal", testFile, configFiles.get(0)); } @Test public void testExecution_Expression() throws Exception { final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); final File testFile = new File(this.getClass().getResource("./global_variable_def.txt").toURI()); final String path = testFile.getParent().replace('\'', '/').replace("\"", "\\\""); final String param = "@@\"" + path.replace("\\", "\\\\") + "\"+\"/\"+\"" + "global_variable_def.txt" + "\""; HANDLER.processCommandLineKey(param, context); final List configFiles = context.getConfigFiles(); assertEquals("File must be added", 1, configFiles.size()); assertEquals("File must be equal", testFile, configFiles.get(0)); } @Test(expected = PreprocessorException.class) public void testExecution_nonExistingFileWithExpression() { final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); HANDLER.processCommandLineKey("@@\"undefinded_file.111111.txtt\"", context); } @Test(expected = PreprocessorException.class) public void testExecution_nonExistingFile() { final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); HANDLER.processCommandLineKey("@undefinded_file.111111.txtt", context); } @Test(expected = PreprocessorException.class) public void testExecution_emptyFile() { final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); HANDLER.processCommandLineKey("@", context); } @Test(expected = PreprocessorException.class) public void testExecution_emptyFileForExpressionMode() { final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); HANDLER.processCommandLineKey("@@", context); } @Override public void testName() { assertEquals("@", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/GlobalVariableHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; public class GlobalVariableHandlerTest extends AbstractCommandLineHandlerTest { private static final GlobalVariableHandler HANDLER = new GlobalVariableHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("", mock)); assertFalse(HANDLER.processCommandLineKey("/p", mock)); assertFalse(HANDLER.processCommandLineKey("/pp:", mock)); assertFalse(HANDLER.processCommandLineKey("/P:", mock)); assertTrue(HANDLER.processCommandLineKey("/P:hello=0", mock)); verify(mock).setGlobalVariable("hello", Value.INT_ZERO); } @Override public void testName() { assertEquals("/P:", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/HelpHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import com.igormaznitsa.jcp.context.PreprocessorContext; public class HelpHandlerTest extends AbstractCommandLineHandlerTest { private static final HelpHandler HANDLER = new HelpHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext context = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("", context)); assertFalse(HANDLER.processCommandLineKey("/HH", context)); assertFalse(HANDLER.processCommandLineKey("/??", context)); assertFalse(HANDLER.processCommandLineKey("-??", context)); assertTrue(HANDLER.processCommandLineKey("/?", context)); assertTrue(HANDLER.processCommandLineKey("/h", context)); assertTrue(HANDLER.processCommandLineKey("-H", context)); assertTrue(HANDLER.processCommandLineKey("-?", context)); } @Override public void testName() { assertEquals("/H,/?,-H,-?", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/InCharsetHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.nio.charset.StandardCharsets; import org.mockito.Mockito; public class InCharsetHandlerTest extends AbstractCommandLineHandlerTest { private static final InCharsetHandler HANDLER = new InCharsetHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("/o:UUU", mock)); assertFalse(HANDLER.processCommandLineKey("/T:", mock)); assertFalse(HANDLER.processCommandLineKey("/t", mock)); assertTrue(HANDLER.processCommandLineKey("/t:" + StandardCharsets.UTF_16.name(), mock)); verify(mock).setSourceEncoding(StandardCharsets.UTF_16); reset(mock); assertTrue(HANDLER.processCommandLineKey("/T:" + StandardCharsets.UTF_16LE, mock)); Mockito.verify(mock).setSourceEncoding(StandardCharsets.UTF_16LE); } @Override public void testName() { assertEquals("/T:", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/KeepLineHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; public class KeepLineHandlerTest extends AbstractCommandLineHandlerTest { private static final KeepLineHandler HANDLER = new KeepLineHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("/k:", mock)); assertFalse(HANDLER.processCommandLineKey("/KK", mock)); assertFalse(HANDLER.processCommandLineKey("/K ", mock)); verify(mock, never()).setKeepLines(anyBoolean()); assertTrue(HANDLER.processCommandLineKey("/K", mock)); verify(mock).setKeepLines(true); reset(mock); assertTrue(HANDLER.processCommandLineKey("/k", mock)); verify(mock).setKeepLines(true); reset(mock); } @Override public void testName() { assertEquals("/K", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/OutCharsetHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.nio.charset.StandardCharsets; public class OutCharsetHandlerTest extends AbstractCommandLineHandlerTest { private static final OutCharsetHandler HANDLER = new OutCharsetHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("/o:UUU", mock)); assertFalse(HANDLER.processCommandLineKey("/TT:", mock)); assertFalse(HANDLER.processCommandLineKey("/tT", mock)); assertTrue(HANDLER.processCommandLineKey("/tt:" + StandardCharsets.UTF_16.name(), mock)); verify(mock).setTargetEncoding(StandardCharsets.UTF_16); reset(mock); assertTrue(HANDLER.processCommandLineKey("/TT:" + StandardCharsets.UTF_16LE.name(), mock)); verify(mock).setTargetEncoding(StandardCharsets.UTF_16LE); } @Override public void testName() { assertEquals("/TT:", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/PreserveIndentDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; public class PreserveIndentDirectiveHandlerTest extends AbstractCommandLineHandlerTest { private static final PreserveIndentDirectiveHandler HANDLER = new PreserveIndentDirectiveHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("/Pi:", mock)); assertFalse(HANDLER.processCommandLineKey("/PI ", mock)); verify(mock, never()).setPreserveIndents(anyBoolean()); assertTrue(HANDLER.processCommandLineKey("/PI", mock)); verify(mock).setPreserveIndents(true); reset(mock); assertTrue(HANDLER.processCommandLineKey("/PI", mock)); verify(mock).setPreserveIndents(true); reset(mock); } @Override public void testName() { assertEquals("/PI", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/RemoveCommentsHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.CommentRemoverType; import com.igormaznitsa.jcp.context.PreprocessorContext; public class RemoveCommentsHandlerTest extends AbstractCommandLineHandlerTest { private static final RemoveCommentsHandler HANDLER = new RemoveCommentsHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("", mock)); assertFalse(HANDLER.processCommandLineKey("/r:", mock)); assertFalse(HANDLER.processCommandLineKey("/R:", mock)); assertFalse(HANDLER.processCommandLineKey("/RR", mock)); assertTrue(HANDLER.processCommandLineKey("/r", mock)); verify(mock).setKeepComments(CommentRemoverType.REMOVE_C_STYLE); } @Override public void testName() { assertEquals("/R", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/SourceDirectoryHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.io.File; import java.util.Arrays; public class SourceDirectoryHandlerTest extends AbstractCommandLineHandlerTest { private static final SourceDirectoryHandler HANDLER = new SourceDirectoryHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("", mock)); assertFalse(HANDLER.processCommandLineKey("/i:", mock)); assertFalse(HANDLER.processCommandLineKey("/I:", mock)); assertFalse(HANDLER.processCommandLineKey("/II", mock)); assertTrue( HANDLER.processCommandLineKey("/i:testdir" + File.pathSeparatorChar + "somedir", mock)); verify(mock).setSources(Arrays.asList("testdir", "somedir")); } @Override public void testName() { assertEquals("/I:", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/UnknownAsFalseHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; public class UnknownAsFalseHandlerTest extends AbstractCommandLineHandlerTest { private static final UnknownAsFalseHandler HANDLER = new UnknownAsFalseHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("/u:", mock)); assertFalse(HANDLER.processCommandLineKey("/UU", mock)); assertFalse(HANDLER.processCommandLineKey("/U:", mock)); verify(mock, never()).setUnknownVariableAsFalse(anyBoolean()); assertTrue(HANDLER.processCommandLineKey("/U", mock)); verify(mock).setUnknownVariableAsFalse(true); reset(mock); assertTrue(HANDLER.processCommandLineKey("/u", mock)); verify(mock).setUnknownVariableAsFalse(true); reset(mock); } @Override public void testName() { assertEquals("/U", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/cmdline/VerboseHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.cmdline; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.context.PreprocessorContext; public class VerboseHandlerTest extends AbstractCommandLineHandlerTest { private static final VerboseHandler HANDLER = new VerboseHandler(); @Override public void testThatTheHandlerInTheHandlerList() { assertHandlerInTheHandlerList(HANDLER); } @Override public void testExecution() throws Exception { final PreprocessorContext mock = prepareMockContext(); assertFalse(HANDLER.processCommandLineKey("", mock)); assertFalse(HANDLER.processCommandLineKey("/v:", mock)); assertFalse(HANDLER.processCommandLineKey("/VV", mock)); assertTrue(HANDLER.processCommandLineKey("/v", mock)); verify(mock).setVerbose(true); } @Override public void testName() { assertEquals("/V", HANDLER.getKeyName()); } @Override public void testDescription() { assertDescription(HANDLER); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/context/EnvironmentVariableProcessorTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.context; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import com.igormaznitsa.jcp.AbstractMockPreprocessorContextTest; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import org.junit.Test; public class EnvironmentVariableProcessorTest extends AbstractMockPreprocessorContextTest { @Test public void testReadVariable() throws Exception { final PreprocessorContext context = prepareMockContext(); final String javaVersion = System.getProperty("java.version"); final String osName = System.getProperty("os.name"); assertNotNull("Must not be null", javaVersion); assertNotNull("Must not be null", osName); final EnvironmentVariableProcessor test = new EnvironmentVariableProcessor(); assertEquals("Must be equal", javaVersion, test.getVariable("env.java.version", context).asString()); assertEquals("Must be equal", osName, test.getVariable("env.os.name", context).asString()); } @Test(expected = PreprocessorException.class) public void testReadUnknownVariable() throws Exception { new EnvironmentVariableProcessor().getVariable("kjhaksjdhksajqwoiueoqiwue", prepareMockContext()); } @Test(expected = PreprocessorException.class) public void testWriteVariable() throws Exception { PreprocessorContext context = prepareMockContext(); new EnvironmentVariableProcessor().setVariable("kjhaksjdhksajqwoiueoqiwue", Value.BOOLEAN_FALSE, context); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/context/JCPSpecialVariableProcessorTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.context; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import com.igormaznitsa.jcp.AbstractMockPreprocessorContextTest; import com.igormaznitsa.jcp.InfoHelper; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import java.io.File; import org.junit.Test; public class JCPSpecialVariableProcessorTest extends AbstractMockPreprocessorContextTest { @Test public void testReadVariable() throws Exception { final PreprocessorContext context = prepareMockContext(); assertEquals("Must be equal", InfoHelper.getVersion(), new JCPSpecialVariableProcessor().getVariable("jcp.version", context).asString()); assertNotNull(new JCPSpecialVariableProcessor().getVariable("__line__", context).toString()); assertNotNull(new JCPSpecialVariableProcessor().getVariable("__date__", context).asString()); assertNotNull(new JCPSpecialVariableProcessor().getVariable("__time__", context).asString()); assertNotNull( new JCPSpecialVariableProcessor().getVariable("__timestamp__", context).asString()); } @Test(expected = PreprocessorException.class) public void testReadUnknownVariable() { new JCPSpecialVariableProcessor().getVariable("jcp.version2", new PreprocessorContext(new File("some_impossible_folder_121212"))); } @Test(expected = PreprocessorException.class) public void testWriteDisallowed() { new JCPSpecialVariableProcessor().setVariable("jcp.version", Value.INT_ONE, new PreprocessorContext(new File("some_impossible_folder_121212"))); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/context/PreprocessorContextTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.context; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.extension.PreprocessorExtension; import com.igormaznitsa.jcp.logger.PreprocessorLogger; import java.io.File; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; import org.junit.Test; @SuppressWarnings("rawtypes") public class PreprocessorContextTest { private static final Random RND = new Random(776655); private static Set extractDeclaredNonStaticNonFinalFields(final Class targetClass) { final Set result = new HashSet<>(); for (final Field f : targetClass.getDeclaredFields()) { if ((f.getModifiers() & (Modifier.STATIC | Modifier.FINAL)) != 0) { continue; } result.add(f); } return result; } private static Map extractValues(final PreprocessorContext context) throws Exception { final Map result = new HashMap<>(); for (final Field f : extractDeclaredNonStaticNonFinalFields(PreprocessorContext.class)) { f.setAccessible(true); result.put(f, f.get(context)); } return result; } private static void assertObjectValue(final String fieldName, final Object value, final Object that) { if (value != that) { if (value == null || that == null) { assertSame(fieldName, value, that); } else if (List.class.isAssignableFrom(value.getClass())) { final List thisList = (List) value; final List thatList = (List) that; assertEquals(fieldName, thisList.size(), thatList.size()); for (int i = 0; i < thisList.size(); i++) { assertObjectValue(fieldName, thisList.get(i), thatList.get(i)); } } else if (Map.class.isAssignableFrom(value.getClass())) { final Map thisMap = (Map) value; final Map thatMap = (Map) that; assertEquals(fieldName, thisMap.size(), thatMap.size()); for (final Object k : thisMap.keySet()) { final Object thisValue = thisMap.get(k); assertTrue(fieldName, thatMap.containsKey(k)); assertObjectValue(fieldName, thisValue, thatMap.get(k)); } } else if (Set.class.isAssignableFrom(value.getClass())) { final Set thisSet = (Set) value; final Set thatSet = (Set) that; assertEquals(fieldName, thisSet.size(), thatSet.size()); for (final Object v : thisSet) { assertTrue(fieldName, thatSet.contains(v)); } } else if (value.getClass().isArray()) { assertEquals(Array.getLength(value), Array.getLength(that)); for (int i = 0; i < Array.getLength(value); i++) { assertObjectValue(fieldName, Array.get(value, i), Array.get(that, i)); } } else { assertEquals(fieldName, value, that); } } } private static void assertMapFields(final String mapFieldName, final PreprocessorContext etalon, final PreprocessorContext that) throws Exception { Field field = null; for (final Field f : PreprocessorContext.class.getDeclaredFields()) { if (mapFieldName.equals(f.getName())) { field = f; field.setAccessible(true); break; } } assertNotNull("Can't find field " + mapFieldName, field); final Map thisMap = (Map) field.get(etalon); final Map thatMap = (Map) field.get(that); assertEquals("Map fields must have same size '" + mapFieldName + '\'', thisMap, thatMap); for (final Object k : thisMap.keySet()) { assertTrue(thatMap.containsKey(k)); assertSame("Key '" + k + "' at map field '" + mapFieldName + "'", thisMap.get(k), thatMap.get(k)); } } private static void assertPreprocessorContextMaps(final PreprocessorContext etalon, final PreprocessorContext that) throws Exception { int detected = 0; for (final Field f : PreprocessorContext.class.getDeclaredFields()) { if (Modifier.isFinal(f.getModifiers()) && Map.class.isAssignableFrom(f.getType())) { assertMapFields(f.getName(), etalon, that); detected++; } } assertEquals(4, detected); } private static void assertContextEquals(final Map etalon, final Map value) { assertEquals("Must have same number of elements", etalon.size(), value.size()); for (final Field f : etalon.keySet()) { assertObjectValue(f.getName(), etalon.get(f), value.get(f)); } } private static String randomString() { final StringBuilder result = new StringBuilder(); for (int i = 0; i < 32; i++) { result.append((char) ('a' + RND.nextInt(52))); } return result.toString(); } @SuppressWarnings("unchecked") private static void fillByRandomValues(final PreprocessorContext context) throws Exception { for (final Field f : extractDeclaredNonStaticNonFinalFields(PreprocessorContext.class)) { f.setAccessible(true); final Class type = f.getType(); if (type.isArray()) { if (type.getComponentType() == String.class) { final String[] arr = new String[RND.nextInt(32) + 1]; for (int i = 0; i < arr.length; i++) { arr[i] = randomString(); } f.set(context, arr); } else if (type.getComponentType() == File.class) { final File[] arr = new File[RND.nextInt(32) + 1]; for (int i = 0; i < arr.length; i++) { arr[i] = new File(randomString()); } f.set(context, arr); } else { throw new Error("Unexpected array field type : " + type.getComponentType().getName()); } } else if (type == Boolean.class || type == boolean.class) { f.set(context, RND.nextBoolean()); } else if (type == Integer.class || type == int.class) { f.set(context, RND.nextInt(10000)); } else if (type == String.class) { f.set(context, randomString()); } else if (type == File.class) { f.set(context, new File(randomString())); } else if (Set.class.isAssignableFrom(type)) { final String[] arr = new String[RND.nextInt(32) + 1]; for (int i = 0; i < arr.length; i++) { arr[i] = randomString(); } try { f.set(context, new HashSet<>(Arrays.asList(arr))); } catch (Exception ex) { fail("Can't set value to '" + f.getName() + '\''); } } else if (type == Charset.class) { final Charset charset; switch (RND.nextInt(4)) { case 0: charset = StandardCharsets.ISO_8859_1; break; case 1: charset = StandardCharsets.US_ASCII; break; case 2: charset = StandardCharsets.UTF_16; break; case 3: charset = StandardCharsets.UTF_16BE; break; default: charset = StandardCharsets.UTF_8; break; } f.set(context, charset); } else if (type == PreprocessingState.class) { f.set(context, new PreprocessingState(context, StandardCharsets.UTF_8, StandardCharsets.UTF_8)); } else if (type == PreprocessorLogger.class) { f.set(context, new PreprocessorLogger() { @Override public void error(String message) { } @Override public void info(String message) { } @Override public void debug(String message) { } @Override public void warning(String message) { } }); } else if (type == PreprocessorExtension.class) { final PreprocessorExtension exx = new PreprocessorExtension() { @Override public boolean hasAction(int arity) { return true; } @Override public boolean hasUserFunction(String name, Set arity) { return true; } @Override public boolean processAction(PreprocessorContext context, List parameters) { throw new UnsupportedOperationException( "Not supported yet."); } @Override public Value processUserFunction(PreprocessorContext context, String functionName, List arguments) { throw new UnsupportedOperationException( "Not supported yet."); } @Override public Set getUserFunctionArity(String functionName) { throw new UnsupportedOperationException( "Not supported yet."); } }; f.set(context, exx); } else if (type.isAssignableFrom(CommentRemoverType.class)) { f.set(context, CommentRemoverType.values()[((int) System.nanoTime() & 0x1FFFFFFF) % CommentRemoverType.values().length]); } else if (type.isAssignableFrom(List.class) || type.isAssignableFrom(Set.class)) { // ignored } else { throw new Error(String.format("Unexpected %s %s", f.getName(), type.getName())); } } context.setLocalVariable("LocalHelloOne", Value.INT_ONE); context.setGlobalVariable("GlobalHelloOne", Value.INT_FIVE); context.setSharedResource("RESOURCE111", "Some string"); context.registerSpecialVariableProcessor(new SpecialVariableProcessor() { @Override public Set getVariableNames() { return Set.of("uno::", "tuo::"); } @Override public Value getVariable(String varName, PreprocessorContext context) { throw new UnsupportedOperationException( "Not supported yet."); } @Override public void setVariable(String varName, Value value, PreprocessorContext context) { throw new UnsupportedOperationException( "Not supported yet."); } }); } @Test public void testConstuctorWithBaseContext_DefaultValues() throws Exception { final PreprocessorContext baseContext = new PreprocessorContext(new File("some_impossible_folder_121212")); final Map baseContextValues = extractValues(baseContext); assertFalse(baseContextValues.isEmpty()); final PreprocessorContext clonedContext = new PreprocessorContext(baseContext); final Map clonedContextValues = extractValues(clonedContext); assertFalse(baseContext.isCloned()); assertTrue(clonedContext.isCloned()); assertContextEquals(baseContextValues, clonedContextValues); assertPreprocessorContextMaps(baseContext, clonedContext); } @Test public void testConstructorWithBaseContext_RandomValues() throws Exception { for (int i = 0; i < 100; i++) { final PreprocessorContext etalon = new PreprocessorContext(new File("some_impossible_folder_121212")); fillByRandomValues(etalon); final PreprocessorContext cloned = new PreprocessorContext(etalon); assertFalse(etalon.isCloned()); assertTrue(cloned.isCloned()); assertContextEquals(extractValues(etalon), extractValues(cloned)); assertPreprocessorContextMaps(etalon, cloned); } } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/context/ProcessContentWithSpacesAndWithoutTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.context; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.igormaznitsa.jcp.AbstractSpyPreprocessorContextTest; import com.igormaznitsa.jcp.TestUtils; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Expression; import org.junit.Test; public class ProcessContentWithSpacesAndWithoutTest extends AbstractSpyPreprocessorContextTest { @Test public void testProcess_NoSpaced_SpacesNotAllowed() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); final String text = Expression.evalExpression("evalfile(\"./standardFile.txt\")", context).asString(); assertEquals(" hello\n /*$VAR$*/ Universe\nsome test", TestUtils.normalizeNextLine(text)); } @Test public void testProcess_NoSpaced_SpacesAllowed() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder(), () -> true); final String text = Expression.evalExpression("evalfile(\"./standardFile.txt\")", context).asString(); assertEquals(" hello\n /*$VAR$*/ Universe\nsome test", TestUtils.normalizeNextLine(text)); } @Test public void testProcess_Spaced_SpacesNotAllowed() throws Exception { try { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); Expression.evalExpression("evalfile(\"./spacedFile.txt\")", context).asString(); fail("Must throw preprocessor exception"); } catch (PreprocessorException ex) { assertTrue(ex.getMessage().contains("Unknown variable")); } } @Test public void testProcess_Spaced_SpacesAllowed() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder(), () -> true); final String text = Expression.evalExpression("evalfile(\"./spacedFile.txt\")", context).asString(); assertEquals(" hello\n /*$VAR$*/ Universe\nsome test", TestUtils.normalizeNextLine(text)); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/AbortDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; public class AbortDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final AbortDirectiveHandler HANDLER = new AbortDirectiveHandler(); @Test public void testExecution_wrongExpression() { assertPreprocessorException("\n\n //#abort /*$akljldksajdsad$*/", 3, null); } @Override public void testExecution() throws Exception { assertFilePreprocessing("directive_abort.txt", false, null, null); } @Override public void testKeyword() throws Exception { assertEquals("abort", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.TAIL, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/AbstractDirectiveHandlerAcceptanceTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static java.util.Collections.emptyList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import com.igormaznitsa.jcp.containers.FileInfoContainer; import com.igormaznitsa.jcp.containers.TextFileDataContainer; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessingState.ExcludeIfInfo; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.extension.PreprocessorExtension; import com.igormaznitsa.jcp.logger.PreprocessorLogger; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.function.Consumer; import org.junit.BeforeClass; import org.junit.Test; public abstract class AbstractDirectiveHandlerAcceptanceTest { protected static File THIS_CLASS_FILE; @BeforeClass public static void beforeClass() throws Exception { THIS_CLASS_FILE = new File(AbstractDirectiveHandler.class.getResource( AbstractDirectiveHandlerAcceptanceTest.class.getSimpleName() + ".class").toURI()); } @Test public abstract void testExecution() throws Exception; @Test public abstract void testKeyword() throws Exception; @Test public abstract void testExecutionCondition() throws Exception; @Test public abstract void testReference() throws Exception; @Test public abstract void testArgumentType() throws Exception; @Test public abstract void testPhase() throws Exception; protected void assertReference(final AbstractDirectiveHandler handler) { assertNotNull("Handler must not be null", handler); final String reference = handler.getReference(); assertNotNull("Reference must not be null", reference); assertNotNull("Reference must not empty", reference.isEmpty()); assertFalse("Reference must not be too short", reference.length() < 10); } private PreprocessorContext setGlobalVars(final PreprocessorContext context, final VariablePair... vars) { if (vars.length != 0) { for (final VariablePair p : vars) { context.setGlobalVariable(p.getName(), p.getValue()); } } return context; } public void assertPreprocessorException(final String preprocessingText, final int exceptionStringIndex, final PreprocessorExtension extension, final VariablePair... globalVars) { try { preprocessString(preprocessingText, null, extension, globalVars); fail("Must throw PreprocessorException"); } catch (PreprocessorException expected) { assertEquals("Expected " + PreprocessorException.class.getCanonicalName(), exceptionStringIndex, expected.getLineNumber()); } catch (Exception unExpected) { unExpected.printStackTrace(); fail("Unexpected exception " + unExpected.getClass().getCanonicalName()); } } public void assertGlobalPhaseException(final String preprocessingText, final int exceptionStringIndex, final PreprocessorExtension extension) { try { preprocessStringAtGlobalPhase(preprocessingText, null); fail("Must throw PreprocessorException"); } catch (PreprocessorException expected) { assertEquals("Expected " + PreprocessorException.class.getCanonicalName(), exceptionStringIndex, expected.getLineNumber()); } catch (Exception unExpected) { unExpected.printStackTrace(); fail("Unexpected exception " + unExpected.getClass().getCanonicalName()); } } private PreprocessorContext preprocessStringAtGlobalPhase(final String encoding, final List excludeInfoList) throws IOException { final List parsedText = parseStringForLines(encoding); final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); context.setDryRun(true); final FileInfoContainer reference = new FileInfoContainer(THIS_CLASS_FILE, "fake_name", false); final TextFileDataContainer textContainer = new TextFileDataContainer(reference.getSourceFile(), parsedText.toArray(new String[0]), false, 0); final PreprocessingState state = context.produceNewPreprocessingState(reference, textContainer); final List result = reference.processGlobalDirectives(context, state); if (excludeInfoList != null) { excludeInfoList.addAll(result); } return context; } public PreprocessorContext executeGlobalPhase(final String fileName, final List excludeIf) throws Exception { final File file = new File(getClass().getResource(fileName).toURI()); final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); context.setDryRun(true); final FileInfoContainer reference = new FileInfoContainer(file, file.getName(), false); final List result = reference.processGlobalDirectives(context, null); if (excludeIf != null) { excludeIf.addAll(result); } return context; } private void readWholeDataFromReader(final BufferedReader reader, final List accumulator) throws IOException { while (!Thread.currentThread().isInterrupted()) { final String line = reader.readLine(); if (line == null) { break; } accumulator.add(line); } } private void assertEqualsStringLists(final List etalon, final List result) { final String[] etalonStrings = etalon.toArray(new String[0]); final String[] resultStrings = result.toArray(new String[0]); final int len = Math.max(etalonStrings.length, resultStrings.length); for (int i = 0; i < len; i++) { final String etalonStr = i < etalonStrings.length ? etalonStrings[i] : null; final String resultStr = i < resultStrings.length ? resultStrings[i] : null; if ((etalonStr != null && !etalonStr.equals(resultStr)) || (resultStr != null && !resultStr.equals(etalonStr))) { throw new LinesNotMatchException(etalonStrings.length, resultStrings.length, i, etalonStr, resultStr); } } } private PreprocessorContext internalPreprocessAndMatch(final File srcfile, final List preprocessingText, final List result, final List etalonList, final PreprocessorExtension extension, final PreprocessorLogger logger, final boolean keepLines, final boolean allowBlocks, final Consumer contextTuner, final VariablePair... globalVariables) throws Exception { assertNotNull("Preprocessing text is null", preprocessingText); assertNotNull("Result container is null", result); final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); if (logger != null) { context.setPreprocessorLogger(logger); } context.setDryRun(true); context.setSources(Collections.singletonList(srcfile.getParent())); context.setKeepLines(keepLines); context.setAllowsBlocks(allowBlocks); context.addPreprocessorExtension(extension); setGlobalVars(context, globalVariables); final FileInfoContainer reference = new FileInfoContainer(srcfile, srcfile.getName(), false); final PreprocessingState state = context.produceNewPreprocessingState(reference, new TextFileDataContainer(reference.getSourceFile(), preprocessingText.toArray(new String[0]), false, 0)); context.addPreprocessedResource(reference); if (contextTuner != null) { contextTuner.accept(context); } reference.preprocessFileWithNotification(context, state, true); final ByteArrayOutputStream prefix = new ByteArrayOutputStream(); final ByteArrayOutputStream normal = new ByteArrayOutputStream(); final ByteArrayOutputStream postfix = new ByteArrayOutputStream(); state.saveBuffersToStreams(prefix, normal, postfix); final BufferedReader prefixReader = new BufferedReader( new InputStreamReader(new ByteArrayInputStream(prefix.toByteArray()), StandardCharsets.UTF_8)); final BufferedReader normalReader = new BufferedReader( new InputStreamReader(new ByteArrayInputStream(normal.toByteArray()), StandardCharsets.UTF_8)); final BufferedReader postfixReader = new BufferedReader( new InputStreamReader(new ByteArrayInputStream(postfix.toByteArray()), StandardCharsets.UTF_8)); readWholeDataFromReader(prefixReader, result); readWholeDataFromReader(normalReader, result); readWholeDataFromReader(postfixReader, result); try { if (etalonList != null) { assertEqualsStringLists(etalonList, result); } } catch (Exception unexpected) { int index = 1; for (final String str : etalonList) { System.out.print(index++); System.out.print('\t'); println(str, true); } System.out.println("---------------------"); index = 1; for (final String str : result) { System.out.print(index++); System.out.print('\t'); println(str, true); } throw unexpected; } return context; } private void println(final String str, final boolean showWhitespaces) { for (final char chr : str.toCharArray()) { if (Character.isWhitespace(chr)) { System.out.print(showWhitespaces ? '.' : chr); } else { System.out.print(chr); } } System.out.println(); } private List parseStringForLines(final String text) throws IOException { if (text == null || text.isEmpty()) { return emptyList(); } final List preprocessingPart = new ArrayList<>(100); try (final BufferedReader reader = new BufferedReader(new StringReader(text), text.length() * 2)) { while (!Thread.currentThread().isInterrupted()) { final String line = reader.readLine(); if (line == null) { break; } preprocessingPart.add(line); } } return preprocessingPart; } private PreprocessorContext preprocessString( final String text, final List preprocessedText, final PreprocessorExtension ext, final VariablePair... globalVars) throws Exception { final List preprocessingPart = parseStringForLines(text); return internalPreprocessAndMatch(THIS_CLASS_FILE, preprocessingPart, preprocessedText == null ? new ArrayList<>() : preprocessedText, null, ext, null, false, false, null, globalVars); } public PreprocessorContext assertFilePreprocessing( final String testFileName, final boolean keepLines, final PreprocessorExtension ext, final PreprocessorLogger logger, final VariablePair... globalVars) throws Exception { return this.assertFilePreprocessing(testFileName, keepLines, false, ext, logger, null, globalVars); } public PreprocessorContext assertFilePreprocessing(final String testFileName, boolean keepLines, boolean allowsBlocks, final PreprocessorExtension ext, final PreprocessorLogger logger, final Consumer contextTuner, final VariablePair... globalVars) throws Exception { final File file = new File(getClass().getResource(testFileName).toURI()); if (!file.exists() || !file.isFile()) { throw new FileNotFoundException("Can't find the test file " + testFileName); } final InputStream stream = new FileInputStream(file); final List preprocessingPart = new ArrayList<>(100); final List etalonPart = new ArrayList<>(100); boolean readFirestPart = true; try (final BufferedReader reader = new BufferedReader( new InputStreamReader(stream, StandardCharsets.UTF_8), 1024)) { while (!Thread.currentThread().isInterrupted()) { final String line = reader.readLine(); if (line == null) { break; } if (line.startsWith("---START_ETALON---")) { if (readFirestPart) { readFirestPart = false; continue; } else { throw new IllegalStateException("Check etalon prefix for duplication"); } } if (readFirestPart) { preprocessingPart.add(line); } else { etalonPart.add(line); } } } return internalPreprocessAndMatch(file, preprocessingPart, new ArrayList<>(), etalonPart, ext, logger, keepLines, allowsBlocks, contextTuner, globalVars); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/AbstractDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertFalse; import java.util.ArrayList; import java.util.List; import org.junit.Test; public class AbstractDirectiveHandlerTest { @Test public void testPotentialConflictsBetweenDirectives() { final List processed = new ArrayList<>(); for (final AbstractDirectiveHandler h : AbstractDirectiveHandler.findAllDirectives()) { final String name = h.getName(); for (final String p : processed) { assertFalse( h.getFullName() + " conflicts with " + (AbstractDirectiveHandler.DIRECTIVE_PREFIX + p), name.startsWith(p)); } processed.add(name); } } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/ActionDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.any; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.extension.PreprocessorExtension; import java.util.List; import org.junit.Test; import org.mockito.Mockito; public class ActionDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final ActionDirectiveHandler HANDLER = new ActionDirectiveHandler(); @Test @Override public void testExecution() throws Exception { final PreprocessorExtension mockup = mock(PreprocessorExtension.class); when(mockup.hasUserFunction(anyString(), any())).thenReturn(true); when(mockup.hasAction(anyInt())).thenReturn(true); when(mockup.isAllowed(any())).thenReturn(true); when(mockup.processAction(any(PreprocessorContext.class), anyList())).thenReturn( Boolean.TRUE); assertFilePreprocessing("directive_action.txt", false, mockup, null); final Value val1 = Value.valueOf(1L); final Value val2 = Value.valueOf(2L); final Value val3 = Value.valueOf(7L); final Value val4 = Value.valueOf(11L); final Value val5 = Value.valueOf(Boolean.TRUE); final Value val6 = Value.valueOf("hello,"); verify(mockup).processAction(any(PreprocessorContext.class), eq(List.of(val1, val2, val3, val4, val5, val6))); } @Test public void testExecutionWrongExpression() { final PreprocessorExtension mock = Mockito.mock(PreprocessorExtension.class); assertPreprocessorException("\n//#action", 2, mock); assertPreprocessorException("\n//#action illegal_variable", 2, mock); assertPreprocessorException("\n//#actionno_space", 2, mock); assertPreprocessorException("\n//#action 1,2,3,4,,5", 2, mock); assertPreprocessorException("\n//#action 1,2,3,4,", 2, mock); } @Test @Override public void testKeyword() throws Exception { assertEquals("action", HANDLER.getName()); } @Test @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Test @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.MULTI_EXPRESSION, HANDLER.getArgumentType()); } @Test @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/CommentNextLineDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class CommentNextLineDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final CommentNextLineDirectiveHandler HANDLER = new CommentNextLineDirectiveHandler(); @Override public void testExecution() throws Exception { assertFilePreprocessing("directive_comment_next_line.txt", false, null, null); } @Override public void testKeyword() throws Exception { assertEquals("//", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.NONE, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/DefineDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; public class DefineDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final DefineDirectiveHandler HANDLER = new DefineDirectiveHandler(); @Override public void testExecution() throws Exception { assertTrue(assertFilePreprocessing("directive_define.txt", false, null, null).isGlobalVariable( "somevar")); } @Test public void testExecution_wrongCases() { assertPreprocessorException("\n\n//#define \n", 3, null); assertPreprocessorException("\n\n//#define 1223\n", 3, null); assertPreprocessorException("\n\n//#define \"test\"\n", 3, null); } @Override public void testKeyword() throws Exception { assertEquals("define", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.TAIL, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/DefinelDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; public class DefinelDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final DefinelDirectiveHandler HANDLER = new DefinelDirectiveHandler(); @Override public void testExecution() throws Exception { assertTrue(assertFilePreprocessing("directive_definel.txt", false, null, null).isLocalVariable( "somevar")); } @Test public void testExecution_wrongCases() { assertPreprocessorException("\n\n//#definel \n", 3, null); assertPreprocessorException("\n\n//#definel 1223\n", 3, null); assertPreprocessorException("\n\n//#definel \"test\"\n", 3, null); assertPreprocessorException("\n\n//#definel var 3*8 \\\\ test \n", 3, null); assertPreprocessorException("\n\n//#definel var 3*8 /* hhhh */ \n", 3, null); } @Override public void testKeyword() throws Exception { assertEquals("definel", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.TAIL, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/EchoDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import com.igormaznitsa.jcp.logger.PreprocessorLogger; import org.mockito.Mockito; public class EchoDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final EchoDirectiveHandler HANDLER = new EchoDirectiveHandler(); @Override public void testExecution() throws Exception { final PreprocessorLogger mock = Mockito.mock(PreprocessorLogger.class); assertFilePreprocessing("directive_echo.txt", false, null, mock); Mockito.verify(mock).info("string 2 ok"); } @Override public void testKeyword() throws Exception { assertEquals("echo", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.TAIL, HANDLER.getArgumentType()); } @Override public void testPhase() throws Exception { assertTrue(HANDLER.isPreprocessingPhaseAllowed()); assertFalse(HANDLER.isGlobalPhaseAllowed()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/ErrorDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.logger.PreprocessorLogger; import org.junit.Test; import org.mockito.Mockito; public class ErrorDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final ErrorDirectiveHandler HANDLER = new ErrorDirectiveHandler(); @Override public void testExecution() throws Exception { final PreprocessorLogger mock = Mockito.mock(PreprocessorLogger.class); try { assertFilePreprocessing("directive_error.txt", false, null, mock); } catch (Exception ex) { Mockito.verify(mock).error("string2"); final PreprocessorException pp = PreprocessorException.extractPreprocessorException(ex); assertEquals(3, pp.getIncludeChain()[0].getLineNumber()); } } @Test public void testExecution_wrongCases() { assertPreprocessorException("\n\n//#error 324444444444987987987982374987294873294324324\n", 3, null); assertPreprocessorException("\n\n//#error sjdasd\n", 3, null); assertPreprocessorException("\n\n//#error \n", 3, null); } @Override public void testKeyword() throws Exception { assertEquals("error", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.EXPRESSION, HANDLER.getArgumentType()); } @Override public void testPhase() throws Exception { assertTrue(HANDLER.isPreprocessingPhaseAllowed()); assertFalse(HANDLER.isGlobalPhaseAllowed()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/ExcludeIfDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import com.igormaznitsa.jcp.context.PreprocessingState.ExcludeIfInfo; import java.util.ArrayList; import java.util.List; public class ExcludeIfDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final ExcludeIfDirectiveHandler HANDLER = new ExcludeIfDirectiveHandler(); @Override public void testExecution() throws Exception { final List list = new ArrayList<>(); executeGlobalPhase("directive_excludeif.txt", list); assertEquals("Must be two //#excludeif ", list.size(), 2); final ExcludeIfInfo info1 = list.get(1); final ExcludeIfInfo info2 = list.get(0); assertEquals("true", info1.getCondition()); assertEquals(2, info1.getStringIndex()); assertNotNull(info1.getFileInfoContainer()); assertEquals("hello+world", info2.getCondition()); assertEquals(6, info2.getStringIndex()); assertNotNull(info2.getFileInfoContainer()); } @Override public void testKeyword() throws Exception { assertEquals("excludeif", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertTrue(HANDLER.isGlobalPhaseAllowed()); assertFalse(HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.BOOLEAN, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/ExitDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class ExitDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final ExitDirectiveHandler HANDLER = new ExitDirectiveHandler(); @Override public void testExecution() throws Exception { assertFilePreprocessing("directive_exit.txt", false, null, null); } @Override public void testKeyword() throws Exception { assertEquals("exit", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.NONE, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/ExitIfDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; public class ExitIfDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final ExitIfDirectiveHandler HANDLER = new ExitIfDirectiveHandler(); @Override public void testExecution() throws Exception { assertFilePreprocessing("directive_exitif.txt", false, null, null); } @Test public void testExecution_wrongExpression() { assertPreprocessorException("\n\n //#exitif \"test\"", 3, null); assertPreprocessorException("\n\n //#exitif ", 3, null); assertPreprocessorException("\n\n //#exitif 111", 3, null); assertPreprocessorException("\n\n //#exitif", 3, null); } @Override public void testKeyword() throws Exception { assertEquals("exitif", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.BOOLEAN, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/FlushDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class FlushDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final FlushDirectiveHandler HANDLER = new FlushDirectiveHandler(); @Override public void testExecution() throws Exception { //TODO make execution test } @Override public void testKeyword() throws Exception { assertEquals("flush", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.NONE, HANDLER.getArgumentType()); } @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/GlobalDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import org.junit.Test; public class GlobalDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final GlobalDirectiveHandler HANDLER = new GlobalDirectiveHandler(); @Override public void testExecution() throws Exception { final PreprocessorContext context = executeGlobalPhase("directive_global.txt", null); assertTrue(context.containsGlobalVariable("xxx")); final Value var = context.findVariableForName("xxx", true); assertEquals(Long.valueOf(10), var.asLong()); } @Test public void testExecution_PreprocessingPhase() throws Exception { final PreprocessorContext context = assertFilePreprocessing("directive_global.txt", false, null, null); assertFalse(context.containsGlobalVariable("xxx")); assertNull(context.findVariableForName("xxx", true)); } @Test public void testExecution_WrongCases() throws Exception { assertGlobalPhaseException("\n\n//#global 23123", 3, null); assertGlobalPhaseException("\n\n//#global", 3, null); assertGlobalPhaseException("\n\n//#global ", 3, null); assertGlobalPhaseException("\n\n//#global hh=", 3, null); assertGlobalPhaseException("\n\n//#global xx==10", 3, null); assertGlobalPhaseException("\n\n//#global =10", 3, null); assertGlobalPhaseException("\n\n//#global ====", 3, null); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testKeyword() throws Exception { assertEquals("global", HANDLER.getName()); } @Override public void testPhase() throws Exception { assertTrue(HANDLER.isGlobalPhaseAllowed()); assertFalse(HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.SET, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/GlobalIfElseEndifTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import com.igormaznitsa.jcp.context.PreprocessorContext; import org.junit.Test; public class GlobalIfElseEndifTest extends AbstractDirectiveHandlerAcceptanceTest { private static final GlobalIfDirectiveHandler HANDLER_GLOBAL_IF = new GlobalIfDirectiveHandler(); private static final GlobalElseDirectiveHandler HANDLER_GLOBAL_ELSE = new GlobalElseDirectiveHandler(); private static final GlobalEndIfDirectiveHandler HANDLER_GLOBAL_ENDIF = new GlobalEndIfDirectiveHandler(); @Override public void testExecution() throws Exception { final PreprocessorContext context = executeGlobalPhase("directive_globalifelseendif.txt", null); assertTrue(context.containsGlobalVariable("expected")); assertFalse(context.containsGlobalVariable("unexpected")); assertEquals(Boolean.TRUE, context.findVariableForName("expected", true).asBoolean()); } @Test public void testExecution_PreprocessingPhase() throws Exception { assertFilePreprocessing("directive_globalifelseendif.txt", false, null, null); assertFilePreprocessing("directive_globalifelseendif2.txt", false, null, null); } @Test public void testExecution_wrongCases() throws Exception { assertGlobalPhaseException("\n//#_if true", 2, null); assertGlobalPhaseException("\n//#_if true\n//#_else", 2, null); assertGlobalPhaseException("\n//#_if true\n//#_if true\n//#_else\n//#_endif", 2, null); assertGlobalPhaseException("\n//#_if true\n//#_if 111\n//#_else\n//#_endif", 3, null); assertGlobalPhaseException("\n//#_endif", 2, null); assertGlobalPhaseException("\n//#_else", 2, null); assertGlobalPhaseException("\n//#_else\n//#_endif", 2, null); assertGlobalPhaseException("\n//#_if xxx\n//#_endif", 2, null); assertGlobalPhaseException("\n//#global xxx=1\n//#_if xxx\n//#_endif", 3, null); } @Override public void testKeyword() throws Exception { assertEquals("_if", HANDLER_GLOBAL_IF.getName()); assertEquals("_else", HANDLER_GLOBAL_ELSE.getName()); assertEquals("_endif", HANDLER_GLOBAL_ENDIF.getName()); } @Override public void testExecutionCondition() throws Exception { assertFalse(HANDLER_GLOBAL_IF.executeOnlyWhenExecutionAllowed()); assertFalse(HANDLER_GLOBAL_ELSE.executeOnlyWhenExecutionAllowed()); assertFalse(HANDLER_GLOBAL_ENDIF.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER_GLOBAL_IF); assertReference(HANDLER_GLOBAL_ELSE); assertReference(HANDLER_GLOBAL_ENDIF); } @Override public void testPhase() throws Exception { assertTrue(HANDLER_GLOBAL_IF.isGlobalPhaseAllowed()); assertFalse(HANDLER_GLOBAL_IF.isPreprocessingPhaseAllowed()); assertTrue(HANDLER_GLOBAL_ELSE.isGlobalPhaseAllowed()); assertFalse(HANDLER_GLOBAL_ELSE.isPreprocessingPhaseAllowed()); assertTrue(HANDLER_GLOBAL_ENDIF.isGlobalPhaseAllowed()); assertFalse(HANDLER_GLOBAL_ENDIF.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.BOOLEAN, HANDLER_GLOBAL_IF.getArgumentType()); assertEquals(DirectiveArgumentType.NONE, HANDLER_GLOBAL_ELSE.getArgumentType()); assertEquals(DirectiveArgumentType.NONE, HANDLER_GLOBAL_ENDIF.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/IfDefDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class IfDefDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final IfDefDirectiveHandler HANDLER = new IfDefDirectiveHandler(); @Override public void testExecution() throws Exception { assertFilePreprocessing("directive_ifdef.txt", false, null, null, new VariablePair("BYTECODE", "true")); try { assertFilePreprocessing("directive_ifdef.txt", false, null, null); } catch (LinesNotMatchException expected) { assertEquals("somebytecode", expected.getEtalonString()); assertEquals("end", expected.getResultString()); } } @Override public void testKeyword() throws Exception { assertEquals("ifdef", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertFalse(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.VARNAME, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/IfDefinedDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class IfDefinedDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final IfDefinedDirectiveHandler HANDLER = new IfDefinedDirectiveHandler(); @Override public void testExecution() throws Exception { // with defined global var assertFilePreprocessing("directive_ifdefined.txt", false, null, null, new VariablePair("BYTECODE", "true")); // with non-defined global var try { assertFilePreprocessing("directive_ifdefined.txt", false, null, null); } catch (LinesNotMatchException expected) { assertEquals("somebytecode", expected.getEtalonString()); assertEquals("end", expected.getResultString()); } } @Override public void testKeyword() throws Exception { assertEquals("ifdefined", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertFalse(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.VARNAME, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/IfElseEndifDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; public class IfElseEndifDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final IfDirectiveHandler IF_HANDLER = new IfDirectiveHandler(); private static final ElseDirectiveHandler ELSE_HANDLER = new ElseDirectiveHandler(); private static final EndIfDirectiveHandler ENDIF_HANDLER = new EndIfDirectiveHandler(); @Override public void testExecution() throws Exception { assertFilePreprocessing("directive_if_else_endif.txt", false, null, null); } @Test public void testIf_ExceptionWithoutExpression() throws Exception { assertPreprocessorException("\n\n\n \n //#if \ntest\n //#endif", 5, null); assertPreprocessorException("\n\n\n \n //#if\ntest\n //#endif", 5, null); } @Test public void testIf_ExceptionWithoutEndIf() throws Exception { assertPreprocessorException("\n\n\n \n //#if true\n\n", 5, null); assertPreprocessorException("\n\n\n \n //#if true\n//#if true\n//#endif\n", 5, null); } @Test public void testElse_ExeptionWithoutIf() throws Exception { assertPreprocessorException("\n\n\n \n //#else \ntest\n //#endif", 5, null); } @Test public void testEndIf_ExceptionWithoutIf() throws Exception { assertPreprocessorException("\n\n\n \n //#endif", 5, null); } @Override public void testKeyword() throws Exception { assertEquals("if", IF_HANDLER.getName()); assertEquals("else", ELSE_HANDLER.getName()); assertEquals("endif", ENDIF_HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertFalse(IF_HANDLER.executeOnlyWhenExecutionAllowed()); assertFalse(ELSE_HANDLER.executeOnlyWhenExecutionAllowed()); assertFalse(ENDIF_HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(IF_HANDLER); assertReference(ELSE_HANDLER); assertReference(ENDIF_HANDLER); } @Override public void testPhase() throws Exception { assertTrue(IF_HANDLER.isPreprocessingPhaseAllowed()); assertFalse(IF_HANDLER.isGlobalPhaseAllowed()); assertTrue(ELSE_HANDLER.isPreprocessingPhaseAllowed()); assertFalse(ELSE_HANDLER.isGlobalPhaseAllowed()); assertTrue(ENDIF_HANDLER.isPreprocessingPhaseAllowed()); assertFalse(ENDIF_HANDLER.isGlobalPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.BOOLEAN, IF_HANDLER.getArgumentType()); assertEquals(DirectiveArgumentType.NONE, ELSE_HANDLER.getArgumentType()); assertEquals(DirectiveArgumentType.NONE, ENDIF_HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/IfElseEndifDirectiveWithKeepLinesHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertNotNull; public class IfElseEndifDirectiveWithKeepLinesHandlerTest extends IfElseEndifDirectiveHandlerTest { @Override public void testExecution() throws Exception { assertNotNull(new IfDirectiveHandler()); assertNotNull(new ElseDirectiveHandler()); assertNotNull(new EndIfDirectiveHandler()); assertFilePreprocessing("directive_if_else_endif_with_keptlines.txt", true, null, null); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/IfNDefDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class IfNDefDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final IfNDefDirectiveHandler HANDLER = new IfNDefDirectiveHandler(); @Override public void testExecution() throws Exception { assertFilePreprocessing("directive_ifndef.txt", false, null, null); try { assertFilePreprocessing("directive_ifndef.txt", false, null, null, new VariablePair("BYTECODE", "123")); } catch (LinesNotMatchException expected) { assertEquals("somebytecode", expected.getEtalonString()); assertEquals("end", expected.getResultString()); } } @Override public void testKeyword() throws Exception { assertEquals("ifndef", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertFalse(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.VARNAME, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/IncludeDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import com.igormaznitsa.jcp.context.PreprocessorContext; import org.junit.Test; public class IncludeDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final IncludeDirectiveHandler HANDLER = new IncludeDirectiveHandler(); @Test @Override public void testExecution() throws Exception { final PreprocessorContext context = assertFilePreprocessing("directive_include.txt", false, null, null); assertEquals(3, context.findAllInputFiles().size()); } @Test public void testExecution_wrongCases() throws Exception { assertPreprocessorException("\n\n\n//#include 111\n", 4, null); assertPreprocessorException("\n\n\n//#include\n", 4, null); assertPreprocessorException("\n\n\n//#include \n", 4, null); assertPreprocessorException("\n\n\n//#include =\n", 4, null); assertPreprocessorException("\n\n\n//#include=\n", 4, null); assertPreprocessorException("\n\n\n//#include333\n", 4, null); assertPreprocessorException("\n\n\n//#include true\n", 4, null); assertPreprocessorException("\n\n\n//#include \"/some/nonexist/absolutnonexist/file.ttxt\"\n", 4, null); } @Override public void testKeyword() throws Exception { assertEquals("include", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.STRING, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/LinesNotMatchException.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; public class LinesNotMatchException extends RuntimeException { private static final long serialVersionUID = 0x129894723894A123L; private final int etalonLineNumber; private final int resultLineNumber; private final int problemStringIndex; private final String etalonString; private final String resultString; public LinesNotMatchException(final int etalonLineNumber, final int resultLineNumber, final int problemStringIndex, final String etalonString, final String resultString) { super("Lines not match in the etalon and the result"); this.etalonLineNumber = etalonLineNumber; this.resultLineNumber = resultLineNumber; this.etalonString = etalonString; this.resultString = resultString; this.problemStringIndex = problemStringIndex; } public int getProblemStringIndex() { return this.problemStringIndex; } public int getEtalonLineNumber() { return this.etalonLineNumber; } public int getResultLineNumber() { return this.resultLineNumber; } public String getEtalonString() { return this.etalonString; } public String getResultString() { return this.resultString; } @Override public String toString() { return LinesNotMatchException.class.getName() + "(etalonLineNum=" + this.etalonLineNumber + ",resultLineNum=" + this.resultLineNumber + ",problemLine=" + (this.problemStringIndex + 1) + ",etalonString=" + this.etalonString + ",resultString=" + this.resultString + ')'; } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/LocalDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import com.igormaznitsa.jcp.context.PreprocessorContext; import org.junit.Test; public class LocalDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final LocalDirectiveHandler HANDLER = new LocalDirectiveHandler(); @Override public void testExecution() throws Exception { final PreprocessorContext context = assertFilePreprocessing("directive_local.txt", false, null, null); assertEquals(Long.valueOf(5), context.getLocalVariable("x").asLong()); assertEquals(Long.valueOf(10), context.getLocalVariable("y").asLong()); assertEquals(Long.valueOf(15), context.getLocalVariable("z").asLong()); assertEquals("", context.getLocalVariable("l_stringgamesNumber").asString()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Test public void testExecution_ExceptionOnExpressionAbsence() { assertPreprocessorException("1\n2\n //#local \n3 ", 3, null); assertPreprocessorException("1\n2\n //#local\n3 ", 3, null); } @Test public void testExecution_ExceptionOnWrongExpression() { assertPreprocessorException("1\n2\n //#local 3\n3 ", 3, null); assertPreprocessorException("1\n2\n //#local a=\n3", 3, null); } @Override public void testKeyword() throws Exception { assertEquals("local", HANDLER.getName()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.SET, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/MsgDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import com.igormaznitsa.jcp.logger.PreprocessorLogger; import java.util.List; import org.mockito.ArgumentCaptor; public class MsgDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final MsgDirectiveHandler HANDLER = new MsgDirectiveHandler(); @Override public void testExecution() throws Exception { final PreprocessorLogger mock = mock(PreprocessorLogger.class); assertFilePreprocessing("directive_msg.txt", false, null, mock); ArgumentCaptor varArgs = ArgumentCaptor.forClass(String.class); verify(mock, times(2)).info(varArgs.capture()); final List calls = varArgs.getAllValues(); assertEquals(2, calls.size()); assertEquals(" string 2 ok ", calls.get(0)); assertEquals("string 48 ok", calls.get(1)); } @Override public void testKeyword() throws Exception { assertEquals("msg", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.TAIL, HANDLER.getArgumentType()); } @Override public void testPhase() throws Exception { assertTrue(HANDLER.isPreprocessingPhaseAllowed()); assertFalse(HANDLER.isGlobalPhaseAllowed()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/NoAutoFlushDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class NoAutoFlushDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final NoAutoFlushHandler HANDLER = new NoAutoFlushHandler(); @Override public void testExecution() throws Exception { //TODO make execution test } @Override public void testKeyword() throws Exception { assertEquals("noautoflush", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.NONE, HANDLER.getArgumentType()); } @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/OnlySpacesTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; public class OnlySpacesTest extends AbstractDirectiveHandlerAcceptanceTest { @Override public void testExecution() throws Exception { assertFilePreprocessing("only_spaces.txt", true, null, null); } @Override public void testKeyword() throws Exception { } @Override public void testExecutionCondition() throws Exception { } @Override public void testReference() throws Exception { } @Override public void testArgumentType() throws Exception { } @Override public void testPhase() throws Exception { } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/OutDisabledDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class OutDisabledDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final OutDisabledDirectiveHandler HANDLER = new OutDisabledDirectiveHandler(); @Override public void testExecution() throws Exception { assertFilePreprocessing("directive_outdisabled.txt", false, null, null); } @Override public void testKeyword() throws Exception { assertEquals("-", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertTrue(HANDLER.isPreprocessingPhaseAllowed()); assertFalse(HANDLER.isGlobalPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.NONE, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/OutEnabledDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class OutEnabledDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final OutEnabledDirectiveHandler HANDLER = new OutEnabledDirectiveHandler(); @Override public void testExecution() throws Exception { assertFilePreprocessing("directive_outenabled.txt", false, null, null); } @Override public void testKeyword() throws Exception { assertEquals("+", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertTrue(HANDLER.isPreprocessingPhaseAllowed()); assertFalse(HANDLER.isGlobalPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.NONE, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/OutNameDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; public class OutNameDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final OutNameDirectiveHandler HANDLER = new OutNameDirectiveHandler(); @Override public void testExecution() throws Exception { assertFilePreprocessing("directive_outname.txt", false, null, null); } @Test public void testExecution_wrongExpressionResult() { assertPreprocessorException("\n//#outname", 2, null); assertPreprocessorException("\n//#outname 882772 k", 2, null); } @Override public void testKeyword() throws Exception { assertEquals("outname", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertTrue(HANDLER.isPreprocessingPhaseAllowed()); assertFalse(HANDLER.isGlobalPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.STRING, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/OutdirDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; public class OutdirDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final OutdirDirectiveHandler HANDLER = new OutdirDirectiveHandler(); @Override public void testExecution() throws Exception { assertFilePreprocessing("directive_outdir.txt", false, null, null); } @Test public void testExecution_wrongExpression() { assertPreprocessorException("\n //#outdir", 2, null); assertPreprocessorException("\n //#outdir ", 2, null); assertPreprocessorException("\n //#outdir 234324 8", 2, null); } @Override public void testKeyword() throws Exception { assertEquals("outdir", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertTrue(HANDLER.isPreprocessingPhaseAllowed()); assertFalse(HANDLER.isGlobalPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.STRING, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/PrefixPostfixDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; public class PrefixPostfixDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final PrefixDirectiveHandler HANDLER_PREFIX = new PrefixDirectiveHandler(); private static final PostfixDirectiveHandler HANDLER_POSTFIX = new PostfixDirectiveHandler(); @Override public void testExecution() throws Exception { assertFilePreprocessing("directive_prefixpostfix.txt", false, null, null); } @Test public void testPrefix_wrongArgument() { assertPreprocessorException("\n //#prefix -", 2, null); assertPreprocessorException("\n //#prefix-1", 2, null); assertPreprocessorException("\n //#prefixa", 2, null); } @Test public void testPostfix_wrongArgument() { assertPreprocessorException("\n //#postfix -", 2, null); assertPreprocessorException("\n //#postfix1", 2, null); assertPreprocessorException("\n //#postfix+q", 2, null); } @Override public void testKeyword() throws Exception { assertEquals("prefix", HANDLER_PREFIX.getName()); assertEquals("postfix", HANDLER_POSTFIX.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER_PREFIX.executeOnlyWhenExecutionAllowed()); assertTrue(HANDLER_POSTFIX.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER_PREFIX); assertReference(HANDLER_POSTFIX); } @Override public void testPhase() throws Exception { assertTrue(HANDLER_POSTFIX.isPreprocessingPhaseAllowed()); assertFalse(HANDLER_POSTFIX.isGlobalPhaseAllowed()); assertTrue(HANDLER_PREFIX.isPreprocessingPhaseAllowed()); assertFalse(HANDLER_PREFIX.isGlobalPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.ON_OFF, HANDLER_POSTFIX.getArgumentType()); assertEquals(DirectiveArgumentType.ON_OFF, HANDLER_PREFIX.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/SpecVarsROTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.logger.PreprocessorLogger; import org.mockito.Mockito; /** * Test for special read only predefined variables */ public class SpecVarsROTest extends AbstractDirectiveHandlerAcceptanceTest { @Override public void testExecution() throws Exception { final PreprocessorLogger mock = Mockito.mock(PreprocessorLogger.class); assertFilePreprocessing("specvars_ro.txt", false, null, mock); } @Override public void testKeyword() throws Exception { } @Override public void testExecutionCondition() throws Exception { } @Override public void testReference() throws Exception { } @Override public void testArgumentType() throws Exception { } @Override public void testPhase() throws Exception { } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/SpecialDirectivesBlockTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.igormaznitsa.jcp.context.CommentTextProcessor; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.exceptions.FilePositionInfo; import java.util.Arrays; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; // This test checks work of //$$""", //$""" // Those directives are very specific and they don't have any distinguished handler public class SpecialDirectivesBlockTest extends AbstractDirectiveHandlerAcceptanceTest { @Override public void testExecution() throws Exception { final StringBuilder calledForText = new StringBuilder(); final AtomicBoolean started = new AtomicBoolean(); final AtomicBoolean stopped = new AtomicBoolean(); final CommentTextProcessor testProcessor = new CommentTextProcessor() { @Override public void onContextStarted(PreprocessorContext context) { if (!started.compareAndSet(false, true)) { fail(); } } @Override public void onContextStopped(PreprocessorContext context, Throwable error) { if (!stopped.compareAndSet(false, true)) { fail(); } } @Override public boolean isAllowed(PreprocessorContext context) { return true; } @Override public String processUncommentedText(PreprocessorContext context, int recommendedIndent, String uncommentedText) { final FilePositionInfo positionInfo = context.getPreprocessingState().findFilePositionInfo().orElseThrow(); assertTrue(positionInfo.getLineNumber() >= 0); assertNotNull(uncommentedText); assertNotNull(context); calledForText.append("\n...\n").append(uncommentedText); final String indent = context.isPreserveIndents() ? " ".repeat(recommendedIndent) : ""; return Arrays.stream(uncommentedText.split("\\R")) .map(x -> indent + x) .collect(Collectors.joining(context.getEol())); } }; assertFilePreprocessing("directive_special_block.txt", false, true, null, null, c -> { c.setPreserveIndents(true); c.addCommentTextProcessor(testProcessor); }); assertTrue(started.get()); assertTrue(stopped.get()); assertEquals("\n...\n" + " hello 223 world\n" + " next" + "\n...\n" + " hello /*$111+112$*/ world\n" + " next/*$111+112$*/" + "\n...\n" + " hello /*$111+112$*/ world\n" + " middle\n" + " next/*$111+112$*/" + "\n...\n" + " hello /*$111+112$*/ world" + "\n...\n" + " split" + "\n...\n" + " next/*$111+112$*/" + "\n...\n" + " hello 223 world" + "\n...\n" + " split" + "\n...\n" + " next223" + "\n...\n" + " line1" + "\n...\n" + " line2" + "\n...\n" + " hello\n" + " world earth" , calledForText.toString()); } @Override public void testKeyword() throws Exception { // do nothing because it is a group test } @Override public void testExecutionCondition() throws Exception { // do nothing because it is a group test } @Override public void testReference() throws Exception { // do nothing because it is a group test } @Override public void testArgumentType() throws Exception { // do nothing because it is a group test } @Override public void testPhase() throws Exception { // do nothing because it is a group test } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/SpecialDirectivesTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.igormaznitsa.jcp.context.CommentTextProcessor; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.util.concurrent.atomic.AtomicBoolean; // This test checks work of //$$, //$ and /*-*/ // Those directives are very specific and they don't have any distinguished handler public class SpecialDirectivesTest extends AbstractDirectiveHandlerAcceptanceTest { @Override public void testExecution() throws Exception { final StringBuilder calledForText = new StringBuilder(); final AtomicBoolean started = new AtomicBoolean(); final AtomicBoolean stopped = new AtomicBoolean(); final CommentTextProcessor testProcessor = new CommentTextProcessor() { @Override public void onContextStarted(PreprocessorContext context) { if (!started.compareAndSet(false, true)) { fail(); } } @Override public void onContextStopped(PreprocessorContext context, Throwable error) { if (!stopped.compareAndSet(false, true)) { fail(); } } @Override public boolean isAllowed(PreprocessorContext context) { return true; } @Override public String processUncommentedText(PreprocessorContext context, int recommendedIndent, String uncommentedText) { assertNotNull(uncommentedText); assertNotNull(context); calledForText.append("\n...\n").append(uncommentedText); return uncommentedText; } }; assertFilePreprocessing("directive_special.txt", false, false, null, null, c -> c.addCommentTextProcessor(testProcessor)); assertTrue(started.get()); assertTrue(stopped.get()); assertEquals("\n...\n" + "hello 223 world" + "\n...\n" + "hello /*$111+112$*/ world" + "\n...\n" + "\"\"\"hello 223 world" + "\n...\n" + "\"\"\"hello /*$111+112$*/ world", calledForText.toString()); } @Override public void testKeyword() throws Exception { // do nothing because it is a group test } @Override public void testExecutionCondition() throws Exception { // do nothing because it is a group test } @Override public void testReference() throws Exception { // do nothing because it is a group test } @Override public void testArgumentType() throws Exception { // do nothing because it is a group test } @Override public void testPhase() throws Exception { // do nothing because it is a group test } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/UndefDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import com.igormaznitsa.jcp.context.PreprocessorContext; import org.junit.Test; public class UndefDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final UndefDirectiveHandler HANDLER = new UndefDirectiveHandler(); @Override public void testExecution() throws Exception { final PreprocessorContext context = assertFilePreprocessing("directive_undef.txt", false, null, null, new VariablePair("somevar", "true")); assertFalse(context.isGlobalVariable("somevar")); assertFalse(context.isLocalVariable("localone")); } @Test public void testExecution_wrongCases() { assertPreprocessorException("\n\n//#undef \n", 3, null); assertPreprocessorException("\n\n//#undef 1223\n", 3, null); assertPreprocessorException("\n\n//#undef \"test\"\n", 3, null); } @Override public void testKeyword() throws Exception { assertEquals("undef", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testPhase() throws Exception { assertFalse(HANDLER.isGlobalPhaseAllowed()); assertTrue(HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.TAIL, HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/VariablePair.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import com.igormaznitsa.jcp.expression.Value; public class VariablePair { private final String name; private final Value value; public VariablePair(final String name, final String value) { this.name = name; this.value = Value.recognizeOf(value); } public String getName() { return this.name; } public Value getValue() { return this.value; } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/WarningDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import com.igormaznitsa.jcp.logger.PreprocessorLogger; import org.junit.Test; import org.mockito.Mockito; public class WarningDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final WarningDirectiveHandler HANDLER = new WarningDirectiveHandler(); @Override public void testExecution() throws Exception { final PreprocessorLogger mock = Mockito.mock(PreprocessorLogger.class); assertFilePreprocessing("directive_warning.txt", false, null, mock); Mockito.verify(mock).warning("string2"); } @Test public void testExecution_wrongCases() { assertPreprocessorException("\n\n//#warning 324444444444987987987982374987294873294324324\n", 3, null); assertPreprocessorException("\n\n//#warning sjdasd\n", 3, null); assertPreprocessorException("\n\n//#warning \n", 3, null); } @Override public void testKeyword() throws Exception { assertEquals("warning", HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertTrue(HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(HANDLER); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.EXPRESSION, HANDLER.getArgumentType()); } @Override public void testPhase() throws Exception { assertTrue(HANDLER.isPreprocessingPhaseAllowed()); assertFalse(HANDLER.isGlobalPhaseAllowed()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/directives/WhileContinueBreakEndDirectiveHandlerTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.directives; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; public class WhileContinueBreakEndDirectiveHandlerTest extends AbstractDirectiveHandlerAcceptanceTest { private static final WhileDirectiveHandler WHILE_HANDLER = new WhileDirectiveHandler(); private static final ContinueDirectiveHandler CONTINUE_HANDLER = new ContinueDirectiveHandler(); private static final BreakDirectiveHandler BREAK_HANDLER = new BreakDirectiveHandler(); private static final EndDirectiveHandler END_HANDLER = new EndDirectiveHandler(); @Override public void testExecution() throws Exception { assertFilePreprocessing("directive_while_continue_break_end.txt", false, null, null); } @Test public void testWhile_ExceptionWithoutExpression() throws Exception { assertPreprocessorException("\n\n\n \n\n //#while \ntest\n //#end", 6, null); } @Test public void testWhile_ExceptionForNonBooleanExpression() throws Exception { assertPreprocessorException("\n\n\n \n\n //#while 234 \ntest\n //#end", 6, null); } @Test public void testWhile_ExceptionForNonClosed() throws Exception { assertPreprocessorException("\n\n\n \n\n //#while true \ntest\n", 6, null); } @Test public void testBreak_ExceptionWithoutWhile() throws Exception { assertPreprocessorException("\n\n\n \n\n //#break \ntest\n", 6, null); } @Test public void testContinue_ExceptionWithoutWhile() throws Exception { assertPreprocessorException("\n\n\n \n\n //#continue \ntest\n", 6, null); } @Test public void testEnd_ExceptionWithoutWhile() throws Exception { assertPreprocessorException("\n\n\n \n\n //#end \ntest\n", 6, null); } @Override public void testKeyword() throws Exception { assertEquals("while", WHILE_HANDLER.getName()); assertEquals("break", BREAK_HANDLER.getName()); assertEquals("continue", CONTINUE_HANDLER.getName()); assertEquals("end", END_HANDLER.getName()); } @Override public void testExecutionCondition() throws Exception { assertFalse(WHILE_HANDLER.executeOnlyWhenExecutionAllowed()); assertTrue(BREAK_HANDLER.executeOnlyWhenExecutionAllowed()); assertTrue(CONTINUE_HANDLER.executeOnlyWhenExecutionAllowed()); assertFalse(END_HANDLER.executeOnlyWhenExecutionAllowed()); } @Override public void testReference() throws Exception { assertReference(WHILE_HANDLER); assertReference(BREAK_HANDLER); assertReference(CONTINUE_HANDLER); assertReference(END_HANDLER); } @Override public void testPhase() throws Exception { assertFalse(WHILE_HANDLER.isGlobalPhaseAllowed()); assertFalse(BREAK_HANDLER.isGlobalPhaseAllowed()); assertFalse(CONTINUE_HANDLER.isGlobalPhaseAllowed()); assertFalse(END_HANDLER.isGlobalPhaseAllowed()); assertTrue(WHILE_HANDLER.isPreprocessingPhaseAllowed()); assertTrue(BREAK_HANDLER.isPreprocessingPhaseAllowed()); assertTrue(CONTINUE_HANDLER.isPreprocessingPhaseAllowed()); assertTrue(END_HANDLER.isPreprocessingPhaseAllowed()); } @Override public void testArgumentType() throws Exception { assertEquals(DirectiveArgumentType.BOOLEAN, WHILE_HANDLER.getArgumentType()); assertEquals(DirectiveArgumentType.NONE, BREAK_HANDLER.getArgumentType()); assertEquals(DirectiveArgumentType.NONE, CONTINUE_HANDLER.getArgumentType()); assertEquals(DirectiveArgumentType.NONE, END_HANDLER.getArgumentType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/exceptions/PreprocessorExceptionTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.exceptions; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import com.igormaznitsa.jcp.containers.FileInfoContainer; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.io.File; import java.util.Collections; import java.util.Objects; import org.junit.Test; public final class PreprocessorExceptionTest { @Test public void testExceptionStringIndex_WrongBracket() throws Exception { final File file = new File(this.getClass().getResource("wrong_bracket.txt").toURI()); final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); context.setDryRun(true); final FileInfoContainer container = new FileInfoContainer(file, "test", false); try { container.preprocessFileWithNotification(context, null, true); fail("Must throw PreprocessorException"); } catch (PreprocessorException expected) { assertEquals("Expected correct line number", 17, expected.getLineNumber()); } } @Test public void testExceptionStringIndex_WrongBracketClosing() throws Exception { final File file = new File( Objects.requireNonNull(this.getClass().getResource("wrong_bracket_closing.txt")).toURI()); final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); context.setDryRun(true); final FileInfoContainer container = new FileInfoContainer(file, "test", false); try { container.preprocessFileWithNotification(context, null, true); fail("Must throw PreprocessorException"); } catch (PreprocessorException expected) { assertEquals("Expected correct line number", 17, expected.getLineNumber()); } } @Test public void testExceptionStringIndex_WrongBracketInIncluded() throws Exception { final File file = new File(this.getClass().getResource("wrong_bracket_include.txt").toURI()); final PreprocessorContext context = new PreprocessorContext(new File("some_impossible_folder_121212")); context.setSources(Collections.singletonList(file.getParent())); context.setDryRun(true); final FileInfoContainer container = new FileInfoContainer(file, "test", false); try { container.preprocessFileWithNotification(context, null, true); fail("Must throw PreprocessorException"); } catch (PreprocessorException expected) { final FilePositionInfo[] fileStack = expected.getIncludeChain(); assertEquals("Must have depth 2", 2, fileStack.length); assertEquals("String index in the including file is 26", 26, fileStack[1].getLineNumber()); assertEquals("String index in the wrong bracket file is 15", 17, fileStack[0].getLineNumber()); assertEquals("Expected correct line number", 17, expected.getLineNumber()); } } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/ExpressionParserTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import com.igormaznitsa.jcp.AbstractMockPreprocessorContextTest; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.functions.AbstractFunction; import com.igormaznitsa.jcp.expression.functions.FunctionABS; import com.igormaznitsa.jcp.expression.functions.xml.FunctionXML_ATTR; import com.igormaznitsa.jcp.expression.operators.AbstractOperator; import com.igormaznitsa.jcp.expression.operators.OperatorADD; import com.igormaznitsa.jcp.expression.operators.OperatorDIV; import com.igormaznitsa.jcp.expression.operators.OperatorEQU; import com.igormaznitsa.jcp.expression.operators.OperatorLESS; import com.igormaznitsa.jcp.expression.operators.OperatorMOD; import com.igormaznitsa.jcp.expression.operators.OperatorMUL; import com.igormaznitsa.jcp.expression.operators.OperatorSUB; import java.io.PushbackReader; import java.io.StringReader; import org.junit.Test; public class ExpressionParserTest extends AbstractMockPreprocessorContextTest { @Test public void testReplacingNegativeNumber() throws Exception { final ExpressionTree tree = new ExpressionTree(); final OperatorSUB SUB = AbstractOperator.findForClass(OperatorSUB.class); assertNotNull(SUB); tree.addItem(SUB); tree.addItem(Value.INT_ONE); tree.addItem(SUB); tree.addItem(Value.INT_TWO); tree.postProcess(); final ExpressionTreeElement root = tree.getRoot(); assertEquals("Root must be SUB", SUB, root.getItem()); assertEquals("Left must be -1", Value.valueOf(-1L), root.getChildForIndex(0).getItem()); assertEquals("Right must be 2", Value.INT_TWO, root.getChildForIndex(1).getItem()); } @Test public void testNextItem_zero() throws Exception { final PreprocessorContext context = prepareMockContext(); final PushbackReader reader = new PushbackReader(new StringReader("0")); assertEquals("Must be 0", Value.INT_ZERO, ExpressionParser.getInstance().nextItem(reader, context)); assertNull("Must be null", ExpressionParser.getInstance().nextItem(reader, context)); } @Test public void testNextItem_negativeNumber() throws Exception { final PreprocessorContext context = prepareMockContext(); final PushbackReader reader = new PushbackReader(new StringReader("-1")); assertEquals("Must be SUB", AbstractOperator.findForClass(OperatorSUB.class), ExpressionParser.getInstance().nextItem(reader, context)); assertEquals("Must be 1", Value.INT_ONE, ExpressionParser.getInstance().nextItem(reader, context)); assertNull("Must be null", ExpressionParser.getInstance().nextItem(reader, context)); } @Test public void testNextItem_zeroLess() throws Exception { final PreprocessorContext context = prepareMockContext(); final PushbackReader reader = new PushbackReader(new StringReader("0<")); assertEquals("Must be 0", Value.INT_ZERO, ExpressionParser.getInstance().nextItem(reader, context)); assertEquals("Must be LESS", AbstractOperator.findForClass(OperatorLESS.class), ExpressionParser.getInstance().nextItem(reader, context)); assertNull("Must be null", ExpressionParser.getInstance().nextItem(reader, context)); } @Test public void testNextItem_oneValue() throws Exception { final PreprocessorContext context = prepareMockContext(); final PushbackReader reader = new PushbackReader(new StringReader("3")); assertEquals("Must be 3", Value.INT_THREE, ExpressionParser.getInstance().nextItem(reader, context)); assertNull("Must be null", ExpressionParser.getInstance().nextItem(reader, context)); } @Test public void testNextItem_oneHexValue() throws Exception { final PreprocessorContext context = prepareMockContext(); final PushbackReader reader = new PushbackReader(new StringReader("0xfF")); assertEquals("Must be 255", Value.valueOf(255L), ExpressionParser.getInstance().nextItem(reader, context)); assertNull("Must be null", ExpressionParser.getInstance().nextItem(reader, context)); } @Test public void testNextItem_oneBooleanTrueValue() throws Exception { final PreprocessorContext context = prepareMockContext(); final PushbackReader reader = new PushbackReader(new StringReader("true")); assertEquals("Must be TRUE", Value.BOOLEAN_TRUE, ExpressionParser.getInstance().nextItem(reader, context)); assertNull("Must be null", ExpressionParser.getInstance().nextItem(reader, context)); } @Test public void testNextItem_oneBooleanFalseValue() throws Exception { final PreprocessorContext context = prepareMockContext(); final PushbackReader reader = new PushbackReader(new StringReader("false")); assertEquals("Must be FALSE", Value.BOOLEAN_FALSE, ExpressionParser.getInstance().nextItem(reader, context)); assertNull("Must be null", ExpressionParser.getInstance().nextItem(reader, context)); } @Test public void testNextItem_oneOperator() throws Exception { final PreprocessorContext context = prepareMockContext(); final PushbackReader reader = new PushbackReader(new StringReader("/")); assertEquals("Must be DIV", AbstractOperator.findForClass(OperatorDIV.class), ExpressionParser.getInstance().nextItem(reader, context)); assertNull("Must be null", ExpressionParser.getInstance().nextItem(reader, context)); } @Test public void testNextItem_complexExpression() throws Exception { final PreprocessorContext context = prepareMockContext(); final PushbackReader reader = new PushbackReader(new StringReader("xml_attr(1.3%abs(1+2)*3/4,\"hello\"==\"\nworld\t\")")); final ExpressionItem[] items = new ExpressionItem[] { AbstractFunction.findForClass(FunctionXML_ATTR.class), ExpressionParser.SpecialItem.BRACKET_OPENING, Value.valueOf(1.3f), AbstractOperator.findForClass(OperatorMOD.class), AbstractFunction.findForClass(FunctionABS.class), ExpressionParser.SpecialItem.BRACKET_OPENING, Value.INT_ONE, AbstractOperator.findForClass(OperatorADD.class), Value.INT_TWO, ExpressionParser.SpecialItem.BRACKET_CLOSING, AbstractOperator.findForClass(OperatorMUL.class), Value.INT_THREE, AbstractOperator.findForClass(OperatorDIV.class), Value.INT_FOUR, ExpressionParser.SpecialItem.COMMA, Value.valueOf("hello"), AbstractOperator.findForClass(OperatorEQU.class), Value.valueOf("\nworld\t"), ExpressionParser.SpecialItem.BRACKET_CLOSING }; int index = 0; for (final ExpressionItem item : items) { assertEquals("Position " + index + " must be equal", item, ExpressionParser.getInstance().nextItem(reader, context)); index++; } assertNull(ExpressionParser.getInstance().nextItem(reader, context)); } @Test public void testParsing_oneValue() throws Exception { final PreprocessorContext context = prepareMockContext(); final ExpressionParser parser = ExpressionParser.getInstance(); final ExpressionTree tree = parser.parse("3", context); final ExpressionTreeElement root = tree.getRoot(); assertEquals("Root is 3", Value.INT_THREE, root.getItem()); } @Test public void testParsing_negativeNumber() throws Exception { final PreprocessorContext context = prepareMockContext(); final ExpressionParser parser = ExpressionParser.getInstance(); final ExpressionTree tree = parser.parse(Long.toString(Long.MIN_VALUE + 1), context); final ExpressionTreeElement root = tree.getRoot(); assertEquals("Root is Long.MIN_VALUE+1", Value.valueOf(Long.MIN_VALUE + 1), root.getItem()); } @Test public void testParsing_easyExpression() throws Exception { final PreprocessorContext context = prepareMockContext(); final ExpressionParser parser = ExpressionParser.getInstance(); final ExpressionTree tree = parser.parse("3*4/8", context); final ExpressionTreeElement root = tree.getRoot(); assertEquals("Root is DIV", AbstractOperator.findForClass(OperatorDIV.class), root.getItem()); assertEquals("Right is 8", Value.valueOf(8L), root.getChildForIndex(1).getItem()); final ExpressionTreeElement left = root.getChildForIndex(0); assertEquals("Left is MUL", AbstractOperator.findForClass(OperatorMUL.class), left.getItem()); assertEquals("Left-left is 3", Value.INT_THREE, left.getChildForIndex(0).getItem()); assertEquals("Left-right is 4", Value.INT_FOUR, left.getChildForIndex(1).getItem()); } @Test public void testParsing_complexExpression() throws Exception { final PreprocessorContext context = prepareMockContext(); final ExpressionParser parser = ExpressionParser.getInstance(); final ExpressionTree tree = parser.parse("(var1+1)*xml_attr(\"first\",\"hello\"+\"world\")", context); final ExpressionTreeElement root = tree.getRoot(); assertEquals("Root must be MUL", AbstractOperator.findForClass(OperatorMUL.class), root.getItem()); final ExpressionTreeElement left = root.getChildForIndex(0); final ExpressionTreeElement right = root.getChildForIndex(1); assertEquals("Left must be ADD", AbstractOperator.findForClass(OperatorADD.class), left.getItem()); assertEquals("Right must be Function", AbstractFunction.findForClass(FunctionXML_ATTR.class), right.getItem()); } @Test public void testParsing_deepIncludingBrackets() throws Exception { final PreprocessorContext context = prepareMockContext(); final ExpressionParser parser = ExpressionParser.getInstance(); final ExpressionTree tree = parser.parse("((((((1+2))))))", context); final ExpressionTreeElement root = tree.getRoot(); assertEquals("Root must be ADD", AbstractOperator.findForClass(OperatorADD.class), root.getItem()); assertEquals("Left must be 1", Value.INT_ONE, root.getChildForIndex(0).getItem()); assertEquals("Left must be 2", Value.INT_TWO, root.getChildForIndex(1).getItem()); } @Test public void testParsing_insideFunctionCall() throws Exception { final PreprocessorContext context = prepareMockContext(); final ExpressionParser parser = ExpressionParser.getInstance(); final ExpressionTree tree = parser.parse("xml_get(xml_get(1,2),3)", context); final AbstractFunction xmlElementAt = AbstractFunction.findForName("xml_get"); assertNotNull(xmlElementAt); final ExpressionTreeElement root = tree.getRoot(); assertEquals("Must be xml_get", xmlElementAt, root.getItem()); final ExpressionTreeElement left = root.getChildForIndex(0); final ExpressionTreeElement right = root.getChildForIndex(1); assertEquals("Must be 3", Value.INT_THREE, right.getItem()); assertEquals("Must be xml_get", xmlElementAt, left.getItem()); assertEquals("Must be 1", Value.INT_ONE, left.getChildForIndex(0).getItem()); assertEquals("Must be 2", Value.INT_TWO, left.getChildForIndex(1).getItem()); } @Test public void testParsing_notEasyBrackets() throws Exception { final PreprocessorContext context = prepareMockContext(); final ExpressionParser parser = ExpressionParser.getInstance(); final ExpressionTree tree = parser.parse("(1+2*(3-4))", context); final OperatorADD ADD = AbstractOperator.findForClass(OperatorADD.class); final OperatorSUB SUB = AbstractOperator.findForClass(OperatorSUB.class); final OperatorMUL MUL = AbstractOperator.findForClass(OperatorMUL.class); final ExpressionTreeElement root = tree.getRoot(); assertEquals("Root must be ADD", ADD, root.getItem()); assertEquals("Left must be 1", Value.INT_ONE, root.getChildForIndex(0).getItem()); final ExpressionTreeElement right = root.getChildForIndex(1); assertEquals("Right must be MUL", MUL, right.getItem()); assertEquals("Right-left must be 2", Value.INT_TWO, right.getChildForIndex(0).getItem()); final ExpressionTreeElement rightRight = right.getChildForIndex(1); assertEquals("Right-right must be SUB", SUB, rightRight.getItem()); assertEquals("Right-right-left must be 3", Value.INT_THREE, rightRight.getChildForIndex(0).getItem()); assertEquals("Right-right-right must be 4", Value.INT_FOUR, rightRight.getChildForIndex(1).getItem()); } @Test public void testParsing_emptyBrakes() throws Exception { final PreprocessorContext context = prepareMockContext(); final ExpressionParser parser = ExpressionParser.getInstance(); final ExpressionTree tree = parser.parse("()", context); assertTrue("Must be empty", tree.getRoot().isEmptySlot()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/ExpressionTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.AbstractSpyPreprocessorContextTest; import org.junit.Test; public class ExpressionTest extends AbstractSpyPreprocessorContextTest { @Test public void testSimpleExpression() throws Exception { assertEquals("Must be equal", Value.INT_TWO, Expression.evalExpression("40/4-2*4", preparePreprocessorContext(getCurrentTestFolder()))); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/ExpressionTreeTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import com.igormaznitsa.jcp.expression.operators.AbstractOperator; import com.igormaznitsa.jcp.expression.operators.OperatorADD; import com.igormaznitsa.jcp.expression.operators.OperatorDIV; import com.igormaznitsa.jcp.expression.operators.OperatorEQU; import com.igormaznitsa.jcp.expression.operators.OperatorMUL; import com.igormaznitsa.jcp.expression.operators.OperatorNOT; import org.junit.Test; public class ExpressionTreeTest { @Test public void testAddHierarchyTree() { // 1+2 final ExpressionTree tree = new ExpressionTree(); tree.addItem(Value.INT_ONE); tree.addItem(AbstractOperator.findForClass(OperatorADD.class)); tree.addItem(Value.INT_TWO); final ExpressionTreeElement root = tree.getRoot(); assertNotNull("Root must not be null", root); assertEquals("Root must be add", AbstractOperator.findForClass(OperatorADD.class), root.getItem()); assertEquals("Left must be 1", Value.INT_ONE, root.getChildForIndex(0).getItem()); assertEquals("Right must be 2", Value.INT_TWO, root.getChildForIndex(1).getItem()); } @Test public void testAddDivHierarchyTree() { // 1+2/3 final ExpressionTree tree = new ExpressionTree(); tree.addItem(Value.INT_ONE); tree.addItem(AbstractOperator.findForClass(OperatorADD.class)); tree.addItem(Value.INT_TWO); tree.addItem(AbstractOperator.findForClass(OperatorDIV.class)); tree.addItem(Value.INT_THREE); final ExpressionTreeElement root = tree.getRoot(); assertNotNull("Root must not be null", root); assertEquals("Root must be add", AbstractOperator.findForClass(OperatorADD.class), root.getItem()); assertEquals("Left must be 1", Value.INT_ONE, root.getChildForIndex(0).getItem()); final ExpressionTreeElement right = root.getChildForIndex(1); assertEquals("Right must be div", AbstractOperator.findForClass(OperatorDIV.class), right.getItem()); assertEquals("Left for div must be 2", Value.INT_TWO, right.getChildForIndex(0).getItem()); assertEquals("Right for div must be 3", Value.INT_THREE, right.getChildForIndex(1).getItem()); } @Test public void testDivAddHierarchyTree() { // 1/2+3 final ExpressionTree tree = new ExpressionTree(); tree.addItem(Value.INT_ONE); tree.addItem(AbstractOperator.findForClass(OperatorDIV.class)); tree.addItem(Value.INT_TWO); tree.addItem(AbstractOperator.findForClass(OperatorADD.class)); tree.addItem(Value.INT_THREE); final ExpressionTreeElement root = tree.getRoot(); assertNotNull("Root must not be null", root); assertEquals("Root must be add", AbstractOperator.findForClass(OperatorADD.class), root.getItem()); assertEquals("Left must be div", AbstractOperator.findForClass(OperatorDIV.class), root.getChildForIndex(0).getItem()); final ExpressionTreeElement left = root.getChildForIndex(0); assertEquals("Left for div must be 1", Value.INT_ONE, left.getChildForIndex(0).getItem()); assertEquals("Right for div must be 2", Value.INT_TWO, left.getChildForIndex(1).getItem()); assertEquals("Right for add must be 3", Value.INT_THREE, root.getChildForIndex(1).getItem()); } @Test public void testAddAddAddHierarchyTree() { // 1+2+3+4 final ExpressionTree TREE = new ExpressionTree(); final OperatorADD ADD = AbstractOperator.findForClass(OperatorADD.class); TREE.addItem(Value.INT_ONE); TREE.addItem(ADD); TREE.addItem(Value.INT_TWO); TREE.addItem(ADD); TREE.addItem(Value.INT_THREE); TREE.addItem(ADD); TREE.addItem(Value.INT_FOUR); final ExpressionTreeElement root = TREE.getRoot(); assertEquals("Root is ADD", ADD, root.getItem()); assertEquals("Left for root is ADD", ADD, root.getChildForIndex(0).getItem()); assertEquals("Right for root is 4", Value.INT_FOUR, root.getChildForIndex(1).getItem()); ExpressionTreeElement left = root.getChildForIndex(0); assertEquals("Left is ADD", ADD, left.getChildForIndex(0).getItem()); assertEquals("Right is 3", Value.INT_THREE, left.getChildForIndex(1).getItem()); left = left.getChildForIndex(0); assertEquals("Left is 1", Value.INT_ONE, left.getChildForIndex(0).getItem()); assertEquals("Right is 2", Value.INT_TWO, left.getChildForIndex(1).getItem()); } @Test public void testMulAddMulHierarchyTree() { // 1*2+3*4 final ExpressionTree TREE = new ExpressionTree(); final OperatorADD ADD = AbstractOperator.findForClass(OperatorADD.class); final OperatorMUL MUL = AbstractOperator.findForClass(OperatorMUL.class); TREE.addItem(Value.INT_ONE); TREE.addItem(MUL); TREE.addItem(Value.INT_TWO); TREE.addItem(ADD); TREE.addItem(Value.INT_THREE); TREE.addItem(MUL); TREE.addItem(Value.INT_FOUR); final ExpressionTreeElement root = TREE.getRoot(); assertEquals("Root is ADD", ADD, root.getItem()); final ExpressionTreeElement left = root.getChildForIndex(0); final ExpressionTreeElement right = root.getChildForIndex(1); assertEquals("Left is MUL", MUL, left.getItem()); assertEquals("Right is MUL", MUL, right.getItem()); assertEquals("Left-Left is 1", Value.INT_ONE, left.getChildForIndex(0).getItem()); assertEquals("Left-Right is 2", Value.INT_TWO, left.getChildForIndex(1).getItem()); assertEquals("Right-Left is 3", Value.INT_THREE, right.getChildForIndex(0).getItem()); assertEquals("Right-Right is 4", Value.INT_FOUR, right.getChildForIndex(1).getItem()); } @Test public void testAddInBrakesMulHierarchyTree() { // (1+2)*3 final ExpressionTree MAIN_TREE = new ExpressionTree(); final ExpressionTree BRAKE_TREE = new ExpressionTree(); final OperatorADD ADD = AbstractOperator.findForClass(OperatorADD.class); final OperatorMUL MUL = AbstractOperator.findForClass(OperatorMUL.class); BRAKE_TREE.addItem(Value.INT_ONE); BRAKE_TREE.addItem(ADD); BRAKE_TREE.addItem(Value.INT_TWO); MAIN_TREE.addTree(BRAKE_TREE); MAIN_TREE.addItem(MUL); MAIN_TREE.addItem(Value.INT_THREE); final ExpressionTreeElement root = MAIN_TREE.getRoot(); assertEquals("Root must be MUL", MUL, root.getItem()); assertEquals("Right must be 3", Value.INT_THREE, root.getChildForIndex(1).getItem()); final ExpressionTreeElement left = root.getChildForIndex(0); assertEquals("Must be ADD", ADD, left.getItem()); assertEquals("Must be 1", Value.INT_ONE, left.getChildForIndex(0).getItem()); assertEquals("Must be 2", Value.INT_TWO, left.getChildForIndex(1).getItem()); } @Test public void testMulAddInBrakesMulHierarchyTree() { // 1*(2+3)*4 final ExpressionTree MAIN_TREE = new ExpressionTree(); final ExpressionTree BRAKE_TREE = new ExpressionTree(); final OperatorADD ADD = AbstractOperator.findForClass(OperatorADD.class); final OperatorMUL MUL = AbstractOperator.findForClass(OperatorMUL.class); BRAKE_TREE.addItem(Value.INT_TWO); BRAKE_TREE.addItem(ADD); BRAKE_TREE.addItem(Value.INT_THREE); MAIN_TREE.addItem(Value.INT_ONE); MAIN_TREE.addItem(MUL); MAIN_TREE.addTree(BRAKE_TREE); MAIN_TREE.addItem(MUL); MAIN_TREE.addItem(Value.INT_FOUR); final ExpressionTreeElement root = MAIN_TREE.getRoot(); assertEquals("Root must be MUL", MUL, root.getItem()); assertEquals("Right must be 4", Value.INT_FOUR, root.getChildForIndex(1).getItem()); final ExpressionTreeElement right = root.getChildForIndex(0); assertEquals("Right must be MUL", MUL, right.getItem()); assertEquals("Right-right must be 1", Value.INT_ONE, right.getChildForIndex(0).getItem()); final ExpressionTreeElement rightLeft = right.getChildForIndex(1); assertEquals("Right-left must be ADD", ADD, rightLeft.getItem()); assertEquals("Right-left-right must be 2", Value.INT_TWO, rightLeft.getChildForIndex(0).getItem()); assertEquals("Right-left-right must be 3", Value.INT_THREE, rightLeft.getChildForIndex(1).getItem()); } @Test public void testNotEquHierarchy() { // !true==false final OperatorNOT NOT = AbstractOperator.findForClass(OperatorNOT.class); final OperatorEQU EQU = AbstractOperator.findForClass(OperatorEQU.class); final ExpressionTree MAIN_TREE = new ExpressionTree(); MAIN_TREE.addItem(NOT); MAIN_TREE.addItem(Value.BOOLEAN_TRUE); MAIN_TREE.addItem(EQU); MAIN_TREE.addItem(Value.BOOLEAN_FALSE); final ExpressionTreeElement root = MAIN_TREE.getRoot(); assertEquals("Root must be EQU", EQU, root.getItem()); assertEquals("Root right must be FALSE", Value.BOOLEAN_FALSE, root.getChildForIndex(1).getItem()); final ExpressionTreeElement rootLeft = root.getChildForIndex(0); assertEquals("Left must be NOT", NOT, rootLeft.getItem()); assertEquals("Left-left must be TRUE", Value.BOOLEAN_TRUE, rootLeft.getChildForIndex(0).getItem()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/AbstractFunctionTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static java.util.Collections.singletonList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.igormaznitsa.jcp.AbstractSpyPreprocessorContextTest; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Test; public abstract class AbstractFunctionTest extends AbstractSpyPreprocessorContextTest { protected static Map var(final Map map, final String name, final Value val) { map.put(name, val); return map; } protected static Map var(final String name, final Value val) { final Map result = new HashMap<>(); result.put(name, val); return result; } @Test public abstract void testName(); @Test public abstract void testReference(); @Test public abstract void testArity(); @Test public abstract void testAllowedArgumentTypes(); @Test public abstract void testResultType(); protected void assertReference(final AbstractFunction function) { final String reference = function.getReference(); assertNotNull("Reference must not be null", reference); assertFalse("Reference must not be empty", reference.isEmpty()); assertTrue("Reference must not be too short", reference.length() > 10); } protected void assertAllowedArguments(final AbstractFunction function, final List> checkingData) { final List> argTypes = function.getAllowedArgumentTypes(); for (final List currentTypes : argTypes) { boolean found = false; for (final List etalon : checkingData) { if (currentTypes.equals(etalon)) { found = true; break; } } if (!found) { fail("Found not allowed argument types " + currentTypes); } } } protected void assertFunction(final String expression, final Value expected) throws Exception { this.assertFunction(expression, expected, null, null); } protected void assertFunction(final String expression, final Value expected, final Map localVars, final Map globalVars) throws Exception { final PreprocessorContext context = preparePreprocessorContext(singletonList("./")); if (localVars != null) { for (final Map.Entry e : localVars.entrySet()) { context.setLocalVariable(e.getKey(), e.getValue()); } } if (globalVars != null) { for (final Map.Entry e : globalVars.entrySet()) { context.setLocalVariable(e.getKey(), e.getValue()); } } final Value result = Expression.evalExpression(expression, context); assertEquals("Must be equal", expected, result); } protected Throwable getRootCause(final Throwable thr) { if (thr == null) { return null; } Throwable t = thr; while (t != null) { if (t.getCause() == null) { return t; } t = t.getCause(); } return t; } protected void assertFunctionException(final String expression) throws Exception { final PreprocessorContext context = preparePreprocessorContext(this.getCurrentTestFolder()); try { Expression.evalExpression(expression, context); fail("Must throw RuntimeException [" + expression + ']'); } catch (RuntimeException ex) { final PreprocessorException cause = PreprocessorException.extractPreprocessorException(ex); if (cause != null) { return; } ex.printStackTrace(); fail("Expression must contain preprocessor exception as cause [" + expression + "] but it doesn't have [" + ex.getClass().getName() + ']'); } } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionABSTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionABSTest extends AbstractFunctionTest { private static final FunctionABS HANDLER = new FunctionABS(); @Test public void testExecution_Int() throws Exception { assertFunction("abs(-10)", Value.valueOf(Long.valueOf(10))); assertFunction("abs(1-3*2)", Value.valueOf(Long.valueOf(5))); assertDestinationFolderEmpty(); } @Test public void testExecution_Float() throws Exception { assertFunction("abs(-10.5)", Value.valueOf(10.5f)); assertDestinationFolderEmpty(); } @Test public void testExecution_wrongCases() throws Exception { assertFunctionException("abs(\"test\")"); assertFunctionException("abs()"); assertFunctionException("abs(false)"); assertFunctionException("abs(1,2,3)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("abs", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.INT), List.of(ValueType.FLOAT))); } @Override public void testResultType() { assertEquals(ValueType.ANY, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionBINFILETest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionBINFILETest extends AbstractFunctionTest { private static final FunctionBINFILE HANDLER = new FunctionBINFILE(); @Test public void testExecution_Base64Encoding() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setLocalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression("binfile(\"./eval/TestBin.txt\",\"base64\")", context); assertEquals("SGVsbG8gUHJlcHJvY2Vzc29yIQ==", result.asString().trim()); assertDestinationFolderEmpty(); } @Test public void testExecution_Base64Encoding_Deflate() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setLocalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression("binfile(\"./eval/TestBin.txt\",\"base64d\")", context); assertEquals("eNrzSM3JyVcIKEotKMpPTi0uzi9SBABHuwc9", result.asString().trim()); assertDestinationFolderEmpty(); } @Test public void testExecution_Base64EncodingSplitted() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setLocalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression("binfile(\"./eval/TestBin.txt\",\"base64s\")", context); assertEquals("SGVsbG8gUHJlcHJvY2Vzc29yIQ==", result.asString().trim()); assertDestinationFolderEmpty(); } @Test public void testExecution_ByteArrayEncoding() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setLocalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression("binfile(\"./eval/TestBin.txt\",\"byte[]\")", context); assertEquals( "(byte)0x48,(byte)0x65,(byte)0x6C,(byte)0x6C,(byte)0x6F,(byte)0x20,(byte)0x50,(byte)0x72,(byte)0x65,(byte)0x70,(byte)0x72,(byte)0x6F,(byte)0x63,(byte)0x65,(byte)0x73,(byte)0x73,(byte)0x6F,(byte)0x72,(byte)0x21", result.asString().trim()); assertDestinationFolderEmpty(); } @Test public void testExecution_ByteArrayEncodingSplitted() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setLocalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression("binfile(\"./eval/TestBin.txt\",\"byte[]s\")", context); final String eof = System.getProperty("line.separator"); assertEquals( "(byte)0x48,(byte)0x65,(byte)0x6C,(byte)0x6C,(byte)0x6F,(byte)0x20,(byte)0x50,(byte)0x72," + eof + "(byte)0x65,(byte)0x70,(byte)0x72,(byte)0x6F,(byte)0x63,(byte)0x65,(byte)0x73,(byte)0x73," + eof + "(byte)0x6F,(byte)0x72,(byte)0x21", result.asString().trim()); assertDestinationFolderEmpty(); } @Test public void testExecution_UINT8ArrayEncoding() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setLocalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression("binfile(\"./eval/TestBinLong.txt\",\"uint8[]\")", context); assertEquals( "208,186,208,176,208,186,208,184,208,181,32,209,130,208,190,32,209,128,209,131,209,129,209,129,208,186,208,184,208,181,32,208,177,209,131,208,186,208,178,209,139,10,72,101,108,108,111,32,80,114,101,112,114,111,99,101,115,115,111,114,33,32,105,116,32,105,115,32,118,101,114,121,32,118,101,114,121,32,118,101,114,121,32,108,111,110,103,32,108,105,110,101,32,116,111,32,102,105,108,108,32,116,104,101,32,102,105,108,101,33,32,115,111,109,101,116,105,109,101,32,105,116,32,105,115,32,117,115,101,102,117,108,32,102,111,114,32,116,101,115,116,115,33,10,97,108,115,32,73,32,100,101,99,105,100,101,100,32,116,111,32,97,100,100,32,111,110,101,32,109,111,114,101,32,108,105,110,101,46", result.asString().trim()); assertDestinationFolderEmpty(); } @Test public void testExecution_INT8ArrayEncoding() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setLocalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression("binfile(\"./eval/TestBinLong.txt\",\"int8[]\")", context); assertEquals( "-48,-70,-48,-80,-48,-70,-48,-72,-48,-75,32,-47,-126,-48,-66,32,-47,-128,-47,-125,-47,-127,-47,-127,-48,-70,-48,-72,-48,-75,32,-48,-79,-47,-125,-48,-70,-48,-78,-47,-117,10,72,101,108,108,111,32,80,114,101,112,114,111,99,101,115,115,111,114,33,32,105,116,32,105,115,32,118,101,114,121,32,118,101,114,121,32,118,101,114,121,32,108,111,110,103,32,108,105,110,101,32,116,111,32,102,105,108,108,32,116,104,101,32,102,105,108,101,33,32,115,111,109,101,116,105,109,101,32,105,116,32,105,115,32,117,115,101,102,117,108,32,102,111,114,32,116,101,115,116,115,33,10,97,108,115,32,73,32,100,101,99,105,100,101,100,32,116,111,32,97,100,100,32,111,110,101,32,109,111,114,101,32,108,105,110,101,46", result.asString().trim()); assertDestinationFolderEmpty(); } @Test public void testExecution_DEFLATEINT8ArrayEncoding() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setLocalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression("binfile(\"./eval/TestBinLong.txt\",\"int8[]d\")", context); assertEquals( "120,-38,77,-116,49,10,-62,64,16,69,-5,-100,-30,-25,2,-98,67,59,-81,16,-78,19,93,-104,100,100,103,35,-40,25,45,-67,-116,10,-126,-92,-16,12,51,55,50,-111,20,54,-97,-57,-121,-9,108,-76,-69,-115,-10,-74,23,-4,98,31,-8,-39,-81,62,-8,-80,124,-10,-16,-21,-124,79,-65,21,107,98,22,108,19,29,-110,-44,-92,42,-87,68,-52,-120,-118,35,-91,-45,-33,-80,116,59,112,-20,8,89,-48,68,102,-28,61,-51,64,37,84,90,-54,-79,-91,-59,-20,-107,-102,-98,-47,72,66,38,-51,90,22,21,43,54,8,84,-57,64,97,14,84,33,64,-90,86,43,-119,126,-43,-43,23,-66,-35,76,-84", result.asString().trim()); assertDestinationFolderEmpty(); } @Test public void testExecution_UINT8ArrayEncodingSplitted() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setLocalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression("binfile(\"./eval/TestBinLong.txt\",\"uint8[]s\")", context); final String eof = System.getProperty("line.separator"); assertEquals( "208,186,208,176,208,186,208,184,208,181,32,209,130,208,190,32,209,128,209,131,209," + eof + "129,209,129,208,186,208,184,208,181,32,208,177,209,131,208,186,208,178,209,139,10," + eof + "72,101,108,108,111,32,80,114,101,112,114,111,99,101,115,115,111,114,33,32,105,116," + eof + "32,105,115,32,118,101,114,121,32,118,101,114,121,32,118,101,114,121,32,108,111,110," + eof + "103,32,108,105,110,101,32,116,111,32,102,105,108,108,32,116,104,101,32,102,105,108," + eof + "101,33,32,115,111,109,101,116,105,109,101,32,105,116,32,105,115,32,117,115,101,102," + eof + "117,108,32,102,111,114,32,116,101,115,116,115,33,10,97,108,115,32,73,32,100,101,99," + eof + "105,100,101,100,32,116,111,32,97,100,100,32,111,110,101,32,109,111,114,101,32,108," + eof + "105,110,101,46", result.asString().trim()); assertDestinationFolderEmpty(); } @Test public void testExecution_INT8ArrayEncodingSplitted() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setLocalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression("binfile(\"./eval/TestBinLong.txt\",\"int8[]s\")", context); final String eof = System.getProperty("line.separator"); assertEquals( "-48,-70,-48,-80,-48,-70,-48,-72,-48,-75,32,-47,-126,-48,-66,32,-47,-128,-47,-125," + eof + "-47,-127,-47,-127,-48,-70,-48,-72,-48,-75,32,-48,-79,-47,-125,-48,-70,-48,-78,-47," + eof + "-117,10,72,101,108,108,111,32,80,114,101,112,114,111,99,101,115,115,111,114,33,32," + eof + "105,116,32,105,115,32,118,101,114,121,32,118,101,114,121,32,118,101,114,121,32,108," + eof + "111,110,103,32,108,105,110,101,32,116,111,32,102,105,108,108,32,116,104,101,32,102," + eof + "105,108,101,33,32,115,111,109,101,116,105,109,101,32,105,116,32,105,115,32,117,115," + eof + "101,102,117,108,32,102,111,114,32,116,101,115,116,115,33,10,97,108,115,32,73,32,100," + eof + "101,99,105,100,101,100,32,116,111,32,97,100,100,32,111,110,101,32,109,111,114,101," + eof + "32,108,105,110,101,46", result.asString().trim()); assertDestinationFolderEmpty(); } @Test public void testExecution_DEFLATEINT8ArrayEncodingSplitted() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setLocalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression("binfile(\"./eval/TestBinLong.txt\",\"int8[]ds\")", context); final String eof = System.getProperty("line.separator"); assertEquals( "120,-38,77,-116,49,10,-62,64,16,69,-5,-100,-30,-25,2,-98,67,59,-81,16,-78,19,93,-104," + eof + "100,100,103,35,-40,25,45,-67,-116,10,-126,-92,-16,12,51,55,50,-111,20,54,-97,-57," + eof + "-121,-9,108,-76,-69,-115,-10,-74,23,-4,98,31,-8,-39,-81,62,-8,-80,124,-10,-16,-21," + eof + "-124,79,-65,21,107,98,22,108,19,29,-110,-44,-92,42,-87,68,-52,-120,-118,35,-91,-45," + eof + "-33,-80,116,59,112,-20,8,89,-48,68,102,-28,61,-51,64,37,84,90,-54,-79,-91,-59,-20," + eof + "-107,-102,-98,-47,72,66,38,-51,90,22,21,43,54,8,84,-57,64,97,14,84,33,64,-90,86,43," + eof + "-119,126,-43,-43,23,-66,-35,76,-84", result.asString().trim()); assertDestinationFolderEmpty(); } @Test public void testExecution_Str_wrongCases() throws Exception { assertFunctionException("binfile()"); assertFunctionException("binfile(true)"); assertFunctionException("binfile(,)"); assertFunctionException("binfile(1,\"ttt\")"); assertFunctionException("binfile(\"d\",\"ttt\",1)"); assertFunctionException("binfile(123)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("binfile", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(2), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING, ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionDefinedByUserTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static com.igormaznitsa.jcp.expression.ExpressionTreeElement.ANY_ARITY; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.powermock.api.mockito.PowerMockito.mock; import static org.powermock.api.mockito.PowerMockito.when; import com.igormaznitsa.jcp.AbstractSpyPreprocessorContextTest; import com.igormaznitsa.jcp.containers.FileInfoContainer; import com.igormaznitsa.jcp.context.PreprocessingState; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.extension.PreprocessorExtension; import java.io.File; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionDefinedByUserTest extends AbstractSpyPreprocessorContextTest { @Test public void testExecution_withArguments() throws Exception { final PreprocessorExtension mock = mock(PreprocessorExtension.class); when(mock.hasUserFunction(anyString(), any())).thenReturn(true); when(mock.isAllowed(any())).thenReturn(true); final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); final Value testResult = Value.valueOf("result"); context.addPreprocessorExtension(mock); when(mock.processUserFunction(any(), eq("test"), anyList())).thenReturn(testResult); when(mock.getUserFunctionArity(eq("test"))).thenReturn(Set.of(5)); assertEquals(testResult, Expression.evalExpression("$test(1,2,3,4,5+6)", context)); verify(mock).processUserFunction(any(), eq("test"), eq(List.of( Value.valueOf(1L), Value.valueOf(2L), Value.valueOf(3L), Value.valueOf(4L), Value.valueOf(11L)))); } @Test public void testExecution_withAnyArguments() throws Exception { final PreprocessorExtension mock = mock(PreprocessorExtension.class); when(mock.hasUserFunction(anyString(), any())).thenReturn(true); when(mock.isAllowed(any())).thenReturn(true); final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); final Value testResult = Value.valueOf("result"); context.addPreprocessorExtension(mock); when(mock.processUserFunction(any(), eq("test"), anyList())).thenReturn(testResult); when(mock.getUserFunctionArity(eq("test"))).thenReturn(Set.of(ANY_ARITY)); assertEquals(testResult, Expression.evalExpression("$test(1,2,3,4,5+6)", context)); verify(mock).processUserFunction(any(), eq("test"), eq(List.of( Value.valueOf(1L), Value.valueOf(2L), Value.valueOf(3L), Value.valueOf(4L), Value.valueOf(11L)))); } @Test public void testExecution_withoutArguments() throws Exception { final PreprocessorExtension mock = mock(PreprocessorExtension.class); when(mock.hasUserFunction(anyString(), any())).thenReturn(true); when(mock.isAllowed(any())).thenReturn(true); final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.addAllPreprocessedResources(List.of( new FileInfoContainer(new File(PreprocessingState.FAKE_FILE_PATH), PreprocessingState.FAKE_FILE_PATH, false))); final Value testResult = Value.valueOf("result"); context.addPreprocessorExtension(mock); when(mock.processUserFunction(any(), eq("test"), anyList())).thenReturn(testResult); when(mock.getUserFunctionArity(eq("test"))).thenReturn(Set.of(0)); assertEquals(testResult, Expression.evalExpression("$test()", context)); verify(mock).processUserFunction(any(), eq("test"), eq(List.of())); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionESCTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionESCTest extends AbstractFunctionTest { private static final FunctionESC HANDLER = new FunctionESC(); @Test public void testExecution() throws Exception { assertFunction("esc(\"\")", Value.valueOf("")); assertFunction("esc(\"hello\nworld\")", Value.valueOf("hello\\nworld")); assertFunction("esc(\"\u0011abc\r\t\f\b\n\")", Value.valueOf("\\u0011abc\\r\\t\\f\\b\\n")); assertDestinationFolderEmpty(); } @Test public void testExecution_wrongCases() throws Exception { assertFunctionException("esc()"); assertFunctionException("esc(1)"); assertFunctionException("esc(1,2)"); assertFunctionException("esc(true)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("esc", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionEVALFILETest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.io.File; import java.util.List; import java.util.Set; import org.apache.commons.text.StringEscapeUtils; import org.junit.Test; public class FunctionEVALFILETest extends AbstractFunctionTest { private static final FunctionEVALFILE HANDLER = new FunctionEVALFILE(); private static final String TEST_EVAL_PATH = "/eval/TestEval.java".replace('/', File.separatorChar); private static final String TEST_EVAL_WITH_INCLUDED_PATH = "/eval/TestEvalWithIncluded.java".replace('/', File.separatorChar); @Test public void testExecution_ErrorForUndefinedVariable() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); try { Expression.evalExpression( String.format("evalfile(\".%s\")", StringEscapeUtils.escapeJava(TEST_EVAL_PATH)), context); } catch (Exception ex) { assertTrue(getRootCause(ex).getMessage().contains("hello_world")); } assertDestinationFolderEmpty(); } @Test public void testExecution_VisibilityLocalVariable() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setLocalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression("evalfile(\"./eval/TestEval.java\")", context); assertEquals("System.out.println(\"Hello World!\");", result.asString().trim()); assertDestinationFolderEmpty(); } @Test public void testExecution_AbsolutePath() throws Exception { final List theTestFolder = getCurrentTestFolder(); final PreprocessorContext context = preparePreprocessorContext(theTestFolder); context.setLocalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression(String.format("evalfile(\"%s\")", StringEscapeUtils.escapeJava(theTestFolder.get(0) + TEST_EVAL_PATH)), context); assertEquals("System.out.println(\"Hello World!\");", result.asString().trim()); assertDestinationFolderEmpty(); } @Test public void testExecution_IncludedEvalCall() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setLocalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression(String .format("evalfile(\".%s\")", StringEscapeUtils.escapeJava(TEST_EVAL_WITH_INCLUDED_PATH)), context); final String resultstr = result.asString().trim(); assertTrue(resultstr.startsWith("System.out.println(\"Hello World!\");")); assertTrue(resultstr.endsWith("TestEvalWithIncluded.java")); assertDestinationFolderEmpty(); } @Test public void testExecution_VisibilityGlobalVariable() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setGlobalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression( String.format("evalfile(\".%s\")", StringEscapeUtils.escapeJava(TEST_EVAL_PATH)), context); assertEquals("System.out.println(\"Hello World!\");", result.asString().trim()); assertDestinationFolderEmpty(); } @Test public void testExecution_ConditionsInsideFile() throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); context.setGlobalVariable("includemeth", Value.valueOf(true)); context.setGlobalVariable("hello_world", Value.valueOf("Hello World!")); final Value result = Expression.evalExpression( String.format("evalfile(\".%s\")", StringEscapeUtils.escapeJava(TEST_EVAL_PATH)), context); assertTrue(result.asString().contains("public void main(String ... args){")); assertDestinationFolderEmpty(); } @Test public void testExecution_Str_wrongCases() throws Exception { assertFunctionException("evalfile()"); assertFunctionException("evalfile(true)"); assertFunctionException("evalfile(,)"); assertFunctionException("evalfile(1,\"ttt\")"); assertFunctionException("evalfile(\"d\",\"ttt\")"); assertFunctionException("evalfile(123)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("evalfile", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionISSUBSTRTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionISSUBSTRTest extends AbstractFunctionTest { private static final FunctionISSUBSTR HANDLER = new FunctionISSUBSTR(); @Test public void testExecution_StrStr() throws Exception { assertFunction("issubstr(\"test\",\"onetesttwo\")", Value.BOOLEAN_TRUE); assertFunction("issubstr(\"Test\",\"onetesttwo\")", Value.BOOLEAN_TRUE); assertFunction("issubstr(\"test\",\"oneTesttwo\")", Value.BOOLEAN_TRUE); assertFunction("issubstr(\"test\",\"one\")", Value.BOOLEAN_FALSE); assertFunction("issubstr(\"\",\"one\")", Value.BOOLEAN_TRUE); assertFunction("issubstr(\"\",\"\")", Value.BOOLEAN_TRUE); assertDestinationFolderEmpty(); } @Test public void testExecution_StrStr_wrongCases() throws Exception { assertFunctionException("issubstr()"); assertFunctionException("issubstr(\"test\")"); assertFunctionException("issubstr(,)"); assertFunctionException("issubstr(1,\"ttt\")"); assertFunctionException("issubstr(false,\"ttt\")"); assertFunctionException("issubstr(false,true)"); assertFunctionException("issubstr(\"d\",1)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("issubstr", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(2), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING, ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.BOOLEAN, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionISTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionISTest extends AbstractFunctionTest { private static final FunctionIS HANDLER = new FunctionIS(); @Test public void testExecution_StrAny_VarPresented() throws Exception { assertFunction("is(\"hello_var\",true)", Value.BOOLEAN_TRUE, var("hello_var", Value.BOOLEAN_TRUE), null); assertFunction("is(\"HELLO_VAR\",true)", Value.BOOLEAN_TRUE, var("hello_var", Value.BOOLEAN_TRUE), null); assertFunction("is(\"hello_var\",false)", Value.BOOLEAN_FALSE, var("hello_var", Value.BOOLEAN_TRUE), null); assertFunction("is(\"hello_var\",true)", Value.BOOLEAN_TRUE, null, var("hello_var", Value.BOOLEAN_TRUE)); assertFunction("is(\"hello_var\",false)", Value.BOOLEAN_FALSE, null, var("hello_var", Value.BOOLEAN_TRUE)); assertFunction("is(\"hello_var\",\"true\")", Value.BOOLEAN_TRUE, null, var("hello_var", Value.BOOLEAN_TRUE)); assertFunction("is(\"hello_var\",\"false\")", Value.BOOLEAN_FALSE, null, var("hello_var", Value.BOOLEAN_TRUE)); assertFunction("is(\"hello_var\",\"1\")", Value.BOOLEAN_TRUE, null, var("hello_var", Value.INT_ONE)); assertFunction("is(\"hello_var\",\"2\")", Value.BOOLEAN_FALSE, null, var("hello_var", Value.INT_ONE)); assertFunction("is(\"hello_var\",1)", Value.BOOLEAN_TRUE, null, var("hello_var", Value.valueOf("1"))); assertFunction("is(\"hello_var\",2)", Value.BOOLEAN_FALSE, null, var("hello_var", Value.valueOf("1"))); assertDestinationFolderEmpty(); } @Test public void testExecution_StrAny_VarNotPresented() throws Exception { assertFunction("is(\"hello_var\",true)", Value.BOOLEAN_FALSE); assertFunction("is(\"hello_var\",false)", Value.BOOLEAN_FALSE); assertFunction("is(\"hello_var\",true)", Value.BOOLEAN_FALSE); assertFunction("is(\"hello_var\",false)", Value.BOOLEAN_FALSE); assertFunction("is(\"hello_var\",\"true\")", Value.BOOLEAN_FALSE); assertFunction("is(\"hello_var\",\"false\")", Value.BOOLEAN_FALSE); assertFunction("is(\"hello_var\",\"1\")", Value.BOOLEAN_FALSE); assertFunction("is(\"hello_var\",\"2\")", Value.BOOLEAN_FALSE); assertFunction("is(\"hello_var\",1)", Value.BOOLEAN_FALSE); assertFunction("is(\"hello_var\",2)", Value.BOOLEAN_FALSE); assertDestinationFolderEmpty(); } // // @Test // public void testExecution_StrStr_wrongCases() throws Exception { // assertFunctionException("issubstr()"); // assertFunctionException("issubstr(\"test\")"); // assertFunctionException("issubstr(,)"); // assertFunctionException("issubstr(1,\"ttt\")"); // assertFunctionException("issubstr(false,\"ttt\")"); // assertFunctionException("issubstr(false,true)"); // assertFunctionException("issubstr(\"d\",1)"); // assertDestinationFolderEmpty(); // } @Override public void testName() { assertEquals("is", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(2), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING, ValueType.ANY))); } @Override public void testResultType() { assertEquals(ValueType.BOOLEAN, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionROUNDTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionROUNDTest extends AbstractFunctionTest { private static final FunctionROUND HANDLER = new FunctionROUND(); @Test public void testExecution_Float() throws Exception { assertFunction("round(4.7)", Value.valueOf(5L)); assertFunction("round(3.1+3.6)", Value.valueOf(7L)); assertDestinationFolderEmpty(); } @Test public void testExecution_Int() throws Exception { assertFunction("round(4)", Value.valueOf(4L)); assertDestinationFolderEmpty(); } @Test public void testExecution_wrongCases() throws Exception { assertFunctionException("round(true)"); assertFunctionException("round(\"aaa\")"); assertFunctionException("round()"); assertFunctionException("round(0.3,2.1)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("round", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.INT), List.of(ValueType.FLOAT))); } @Override public void testResultType() { assertEquals(ValueType.INT, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2CSVTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionSTR2CSVTest extends AbstractFunctionTest { private static final FunctionSTR2CSV HANDLER = new FunctionSTR2CSV(); @Test public void testExecution_Str() throws Exception { assertFunction("str2csv(\"1,2\")", Value.valueOf("\"1,2\"")); assertFunction("str2csv(\"33\")", Value.valueOf("33")); assertDestinationFolderEmpty(); } @Test public void testExecution_wrongCases() throws Exception { assertFunctionException("str2csv()"); assertFunctionException("str2csv(1,2)"); assertFunctionException("str2csv(true)"); assertFunctionException("str2csv(3)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("str2csv", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2GOTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.util.List; import org.junit.Test; public class FunctionSTR2GOTest extends AbstractFunctionTest { private static final FunctionSTR2GO HANDLER = new FunctionSTR2GO(); @Test public void testExecution_NoSplit() throws Exception { assertFunction("str2go(\"\",false)", Value.valueOf("")); assertFunction("str2go(\"hello\nworld\",false)", Value.valueOf("hello\\nworld")); assertDestinationFolderEmpty(); } @Test public void testExecution_Split() throws Exception { assertFunction("str2go(\"\",true)", Value.valueOf("\"\"")); assertFunction("str2go(\"hello\nworld\",true)", Value.valueOf("\"hello\\n\"" + PreprocessorUtils.getNextLineCodes() + "+\"world\"")); assertFunction("str2go(\"hello\nworld\n\",true)", Value.valueOf("\"hello\\n\"" + PreprocessorUtils.getNextLineCodes() + "+\"world\\n\"")); assertFunction("str2go(\"\u000bhello\u0007\nworld\n\",true)", Value.valueOf( "\"\\vhello\\a\\n\"" + PreprocessorUtils.getNextLineCodes() + "+\"world\\n\"")); assertFunction("str2go(\"Здравствуй\nМир\n\",true)", Value.valueOf( "\"\\u0417\\u0434\\u0440\\u0430\\u0432\\u0441\\u0442\\u0432\\u0443\\u0439\\n\"" + PreprocessorUtils.getNextLineCodes() + "+\"\\u041c\\u0438\\u0440\\n\"")); assertDestinationFolderEmpty(); } @Test public void testExecution_wrongCases() throws Exception { assertFunctionException("str2go()"); assertFunctionException("str2go(1,2)"); assertFunctionException("str2go(true)"); assertFunctionException("str2go(true,\"ss\")"); assertFunctionException("str2go(\"ss\",3)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("str2go", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(AbstractFunction.ARITY_2, HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING, ValueType.BOOLEAN))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2INTTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionSTR2INTTest extends AbstractFunctionTest { private static final FunctionSTR2INT HANDLER = new FunctionSTR2INT(); @Test public void testExecute_Str() throws Exception { assertFunction("str2int(\"100\")", Value.valueOf(100L)); assertFunction("str2int(\"0\")", Value.INT_ZERO); assertDestinationFolderEmpty(); } @Test public void testExecute_wrongCase() throws Exception { assertFunctionException("str2int(true)"); assertFunctionException("str2int(0.3)"); assertFunctionException("str2int(1,2)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("str2int", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.INT, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2JAVATest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionSTR2JAVATest extends AbstractFunctionTest { private static final FunctionSTR2JAVA HANDLER = new FunctionSTR2JAVA(); @Test public void testExecution_NoSplit() throws Exception { assertFunction("str2java(\"\",false)", Value.valueOf("")); assertFunction("str2java(\"hello\nworld\",false)", Value.valueOf("hello\\nworld")); assertDestinationFolderEmpty(); } @Test public void testExecution_Split() throws Exception { assertFunction("str2java(\"\",true)", Value.valueOf("\"\"")); assertFunction("str2java(\"hello\nworld\",true)", Value.valueOf("\"hello\\n\"" + PreprocessorUtils.getNextLineCodes() + "+\"world\"")); assertFunction("str2java(\"hello\nworld\n\",true)", Value.valueOf("\"hello\\n\"" + PreprocessorUtils.getNextLineCodes() + "+\"world\\n\"")); assertDestinationFolderEmpty(); } @Test public void testExecution_wrongCases() throws Exception { assertFunctionException("str2java()"); assertFunctionException("str2java(1,2)"); assertFunctionException("str2java(true)"); assertFunctionException("str2java(true,\"ss\")"); assertFunctionException("str2java(\"ss\",3)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("str2java", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(2), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING, ValueType.BOOLEAN))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2JSONTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionSTR2JSONTest extends AbstractFunctionTest { private static final FunctionSTR2JSON HANDLER = new FunctionSTR2JSON(); @Test public void testExecution_Str() throws Exception { assertFunction("str2json(\"\\\"hmm\\\"\")", Value.valueOf("\\\"hmm\\\"")); assertFunction("str2json(\"33\")", Value.valueOf("33")); assertDestinationFolderEmpty(); } @Test public void testExecution_wrongCases() throws Exception { assertFunctionException("str2json()"); assertFunctionException("str2json(1,2)"); assertFunctionException("str2json(true)"); assertFunctionException("str2json(3)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("str2json", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2JSTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionSTR2JSTest extends AbstractFunctionTest { private static final FunctionSTR2JS HANDLER = new FunctionSTR2JS(); @Test public void testExecution_Str() throws Exception { assertFunction("str2js(\"\\\"1,2\\\"\")", Value.valueOf("\\\"1,2\\\"")); assertFunction("str2js(\"33\")", Value.valueOf("33")); assertDestinationFolderEmpty(); } @Test public void testExecution_wrongCases() throws Exception { assertFunctionException("str2js()"); assertFunctionException("str2js(1,2)"); assertFunctionException("str2js(true)"); assertFunctionException("str2js(3)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("str2js", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2WEBTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionSTR2WEBTest extends AbstractFunctionTest { private static final FunctionSTR2WEB HANDLER = new FunctionSTR2WEB(); @Test public void testExecution_Str() throws Exception { assertFunction("str2web(\"\")", Value.valueOf("<hello>")); assertFunction("str2web(\"<привет>\")", Value.valueOf("<привет>")); assertDestinationFolderEmpty(); } @Test public void testExecution_wrongCases() throws Exception { assertFunctionException("str2web()"); assertFunctionException("str2web(1,2)"); assertFunctionException("str2web(true)"); assertFunctionException("str2web(3)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("str2web", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionSTR2XMLTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionSTR2XMLTest extends AbstractFunctionTest { private static final FunctionSTR2XML HANDLER = new FunctionSTR2XML(); @Test public void testExecution_Str() throws Exception { assertFunction("str2xml(\"<12/>\")", Value.valueOf("<12/>")); assertFunction("str2xml(\"33\")", Value.valueOf("33")); assertDestinationFolderEmpty(); } @Test public void testExecution_wrongCases() throws Exception { assertFunctionException("str2xml()"); assertFunctionException("str2xml(1,2)"); assertFunctionException("str2xml(true)"); assertFunctionException("str2xml(3)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("str2xml", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionSTRLENTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionSTRLENTest extends AbstractFunctionTest { private static final FunctionSTRLEN HANDLER = new FunctionSTRLEN(); @Test public void testExecution_Str() throws Exception { assertFunction("strlen(\"hello world\")", Value.valueOf(11L)); assertDestinationFolderEmpty(); } @Test public void testExecution_wrongCases() throws Exception { assertFunctionException("strlen()"); assertFunctionException("strlen(11)"); assertFunctionException("strlen(true)"); assertFunctionException("strlen(1,2)"); assertFunctionException("strlen(,)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("strlen", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.INT, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/FunctionTRIMLINESTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionTRIMLINESTest extends AbstractFunctionTest { private static final FunctionTRIMLINES HANDLER = new FunctionTRIMLINES(); @Test public void testExecution_WorkingCases() throws Exception { assertFunction("trimlines(\"\")", Value.valueOf("")); assertFunction("trimlines(\"hello world\")", Value.valueOf("hello world")); assertFunction("trimlines(\" hello \n \n world\n\")", Value.valueOf("hello" + PreprocessorUtils.getNextLineCodes() + "world")); assertDestinationFolderEmpty(); } @Test public void testExecution_wrongCases() throws Exception { assertFunctionException("trimlines()"); assertFunctionException("trimlines(1)"); assertFunctionException("trimlines(true)"); assertFunctionException("trimlines(true,\"ss\")"); assertFunctionException("trimlines(\"ss\",3)"); assertDestinationFolderEmpty(); } @Override public void testName() { assertEquals("trimlines", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/xml/AbstractFunctionXMLTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.spy; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.functions.AbstractFunctionTest; import java.io.File; import org.junit.Before; import org.mockito.stubbing.Answer; public abstract class AbstractFunctionXMLTest extends AbstractFunctionTest { protected PreprocessorContext SPY_CONTEXT; protected Value OPENED_DOCUMENT_ID; protected Value OPENED_DOCUMENT_ROOT; @Before public void initTest() throws Exception { SPY_CONTEXT = spy(new PreprocessorContext(new File("some_impossible_folder_121212"))); final File thisRoot = new File(this.getClass().getResource("./").toURI()); doAnswer((Answer) invocation -> { final String name = (String) invocation.getArguments()[0]; return new File(thisRoot, name); }).when(SPY_CONTEXT).findFileInSources(any(String.class)); OPENED_DOCUMENT_ID = new FunctionXML_OPEN().executeStr(SPY_CONTEXT, Value.valueOf("test.xml")); OPENED_DOCUMENT_ROOT = new FunctionXML_ROOT().executeStr(SPY_CONTEXT, OPENED_DOCUMENT_ID); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_ATTRTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionXML_ATTRTest extends AbstractFunctionXMLTest { private static final FunctionXML_ATTR HANDLER = new FunctionXML_ATTR(); @Test(expected = PreprocessorException.class) public void testExecution_WrongAttributeName() throws Exception { HANDLER.executeStrStr(SPY_CONTEXT, OPENED_DOCUMENT_ID, Value.valueOf("lasjdlksajdlksajdlksad")); } @Test(expected = PreprocessorException.class) public void testExecution_WrongElementId() throws Exception { HANDLER.executeStrStr(SPY_CONTEXT, Value.valueOf("kajshdjksaoiqweqwjdsa"), Value.valueOf("test")); } @Test public void testExecution_ExistsAttribute() throws Exception { assertEquals("hello", HANDLER.executeStrStr(SPY_CONTEXT, OPENED_DOCUMENT_ROOT, Value.valueOf("attr")).asString()); } @Test public void testExecution_nonExistsAttribute() throws Exception { assertEquals("", HANDLER.executeStrStr(SPY_CONTEXT, OPENED_DOCUMENT_ROOT, Value.valueOf("hhhmattr")) .asString()); } @Override public void testName() { assertEquals("xml_attr", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(2), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING, ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_GETTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import com.igormaznitsa.jcp.expression.functions.AbstractFunction; import java.util.List; import org.junit.Test; public class FunctionXML_GETTest extends AbstractFunctionXMLTest { private static final FunctionXML_GET HANDLER = new FunctionXML_GET(); private static final FunctionXML_TEXT GETTEXT = new FunctionXML_TEXT(); @Test(expected = PreprocessorException.class) public void testExecution_WrongElementId() throws Exception { HANDLER.executeStrInt(SPY_CONTEXT, Value.valueOf("12qwewqe"), Value.INT_ZERO); } @Test(expected = PreprocessorException.class) public void testExecution_WrongIndex() throws Exception { final Value elementList = new FunctionXML_LIST().executeStrStr(SPY_CONTEXT, OPENED_DOCUMENT_ROOT, Value.valueOf("element")); HANDLER.executeStrInt(SPY_CONTEXT, elementList, Value.valueOf(Long.valueOf(-1))); } @Test public void testExecution() throws Exception { final Value elementList = new FunctionXML_LIST().executeStrStr(SPY_CONTEXT, OPENED_DOCUMENT_ROOT, Value.valueOf("element")); assertEquals("elem1", GETTEXT.executeStr(SPY_CONTEXT, HANDLER.executeStrInt(SPY_CONTEXT, elementList, Value.INT_ZERO)).asString()); assertEquals("elem2", GETTEXT.executeStr(SPY_CONTEXT, HANDLER.executeStrInt(SPY_CONTEXT, elementList, Value.INT_ONE)).asString()); assertEquals("elem3", GETTEXT.executeStr(SPY_CONTEXT, HANDLER.executeStrInt(SPY_CONTEXT, elementList, Value.INT_TWO)).asString()); assertEquals("", GETTEXT.executeStr(SPY_CONTEXT, HANDLER.executeStrInt(SPY_CONTEXT, elementList, Value.INT_THREE)).asString()); final Value elementList2 = new FunctionXML_LIST().executeStrStr(SPY_CONTEXT, OPENED_DOCUMENT_ROOT, Value.valueOf("element")); assertEquals("elem1", GETTEXT.executeStr(SPY_CONTEXT, HANDLER.executeStrInt(SPY_CONTEXT, elementList2, Value.INT_ZERO)).asString()); assertEquals("elem2", GETTEXT.executeStr(SPY_CONTEXT, HANDLER.executeStrInt(SPY_CONTEXT, elementList2, Value.INT_ONE)).asString()); assertEquals("elem3", GETTEXT.executeStr(SPY_CONTEXT, HANDLER.executeStrInt(SPY_CONTEXT, elementList2, Value.INT_TWO)).asString()); assertEquals("", GETTEXT.executeStr(SPY_CONTEXT, HANDLER.executeStrInt(SPY_CONTEXT, elementList2, Value.INT_THREE)).asString()); } @Override public void testName() { assertEquals("xml_get", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(AbstractFunction.ARITY_2, HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING, ValueType.INT))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_LISTTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionXML_LISTTest extends AbstractFunctionXMLTest { private static final FunctionXML_LIST HANDLER = new FunctionXML_LIST(); @Test(expected = PreprocessorException.class) public void testExecution_ForWrongElement() throws Exception { assertNotNull( HANDLER.executeStrStr(SPY_CONTEXT, Value.valueOf("some wrong"), Value.valueOf("nonexist"))); } @Test public void testExecution_ForNonExistElements() throws Exception { assertNotNull( HANDLER.executeStrStr(SPY_CONTEXT, OPENED_DOCUMENT_ROOT, Value.valueOf("nonexist"))); } @Test public void testExecution_ForExistElements() throws Exception { assertNotNull( HANDLER.executeStrStr(SPY_CONTEXT, OPENED_DOCUMENT_ROOT, Value.valueOf("element"))); } @Override public void testName() { assertEquals("xml_list", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(2), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING, ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_NAMETest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionXML_NAMETest extends AbstractFunctionXMLTest { private static final FunctionXML_NAME HANDLER = new FunctionXML_NAME(); @Test(expected = PreprocessorException.class) public void testExecution_WrongElementId() throws Exception { HANDLER.executeStr(SPY_CONTEXT, Value.valueOf("nonexistelementaaaaaaaaaaa")); } @Test public void testExecution_RootElement() throws Exception { assertEquals("root", HANDLER.executeStr(SPY_CONTEXT, OPENED_DOCUMENT_ROOT).asString()); } @Override public void testName() { assertEquals("xml_name", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_OPENTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionXML_OPENTest extends AbstractFunctionXMLTest { private static final FunctionXML_OPEN HANDLER = new FunctionXML_OPEN(); @Test(expected = PreprocessorException.class) public void testExecute_FileNotFound() throws Exception { HANDLER.executeStr(SPY_CONTEXT, Value.valueOf("unknown_file.xxxxml")); } @Test(expected = PreprocessorException.class) public void testExecute_NoXMLFile() throws Exception { HANDLER.executeStr(SPY_CONTEXT, Value.valueOf("noxml.txt")); } @Test public void testExecute() throws Exception { HANDLER.executeStr(SPY_CONTEXT, Value.valueOf("test.xml")); } @Override public void testName() { assertEquals("xml_open", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_ROOTTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionXML_ROOTTest extends AbstractFunctionXMLTest { private static final FunctionXML_ROOT HANDLER = new FunctionXML_ROOT(); @Test(expected = PreprocessorException.class) public void testExecution_WrongDocId() throws Exception { HANDLER.executeStr(SPY_CONTEXT, Value.valueOf("jlskjlasjdsa123213213")); } @Test public void testExecution() throws Exception { assertEquals(OPENED_DOCUMENT_ID.asString() + "_#root", HANDLER.executeStr(SPY_CONTEXT, OPENED_DOCUMENT_ID).asString()); } @Override public void testName() { assertEquals("xml_root", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_SIZETest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionXML_SIZETest extends AbstractFunctionXMLTest { private static final FunctionXML_SIZE HANDLER = new FunctionXML_SIZE(); @Test(expected = PreprocessorException.class) public void testExecution_WrongElementListID() throws Exception { HANDLER.executeStr(SPY_CONTEXT, Value.valueOf("ieqoidqoiuoiq")); } @Test(expected = PreprocessorException.class) public void testExecution_WrongElementType() throws Exception { HANDLER.executeStr(SPY_CONTEXT, OPENED_DOCUMENT_ID); } @Test public void testExecution() throws Exception { final Value languageElement = new FunctionXML_GET().executeStrInt(SPY_CONTEXT, new FunctionXML_LIST().executeStrStr(SPY_CONTEXT, OPENED_DOCUMENT_ROOT, Value.valueOf("languages")), Value.valueOf(0L)); final Value elementList = new FunctionXML_LIST().executeStrStr(SPY_CONTEXT, languageElement, Value.valueOf("language")); assertNotNull(elementList); assertEquals(6L, HANDLER.executeStr(SPY_CONTEXT, elementList).asLong().longValue()); } @Override public void testName() { assertEquals("xml_size", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.INT, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_TEXTTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionXML_TEXTTest extends AbstractFunctionXMLTest { private static final FunctionXML_TEXT HANDLER = new FunctionXML_TEXT(); @Test(expected = PreprocessorException.class) public void testExecution_IncompatibleCachedObjectId() throws Exception { HANDLER.executeStr(SPY_CONTEXT, OPENED_DOCUMENT_ID); } @Test public void testExecution() throws Exception { final Value elements = HANDLER.executeStr(SPY_CONTEXT, new FunctionXML_XELEMENT().executeStrStr(SPY_CONTEXT, OPENED_DOCUMENT_ID, Value.valueOf("/root/languages"))); assertEquals("rustext\n gertext\n esttext\n fintext\n frtext\n ittext", elements.asString().trim()); } @Override public void testName() { assertEquals("xml_text", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(1), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_XELEMENTTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionXML_XELEMENTTest extends AbstractFunctionXMLTest { private static final FunctionXML_XELEMENT HANDLER = new FunctionXML_XELEMENT(); @Test(expected = PreprocessorException.class) public void testExecution_ForWrongElement() throws Exception { assertNotNull( HANDLER.executeStrStr(SPY_CONTEXT, Value.valueOf("some wrong"), Value.valueOf("nonexist"))); } @Test(expected = PreprocessorException.class) public void testExecution_NonExistElement() throws Exception { HANDLER.executeStrStr(SPY_CONTEXT, OPENED_DOCUMENT_ID, Value.valueOf("/root/nonexist")); } @Test public void testExecution_ForExistElements() throws Exception { final Value value = HANDLER.executeStrStr(SPY_CONTEXT, OPENED_DOCUMENT_ID, Value.valueOf("/root/element")); assertNotNull(value); assertEquals("first", new FunctionXML_ATTR().executeStrStr(SPY_CONTEXT, value, Value.valueOf("attr")).asString()); } @Override public void testName() { assertEquals("xml_xelement", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(2), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING, ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/functions/xml/FunctionXML_XLISTTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.functions.xml; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.expression.ValueType; import java.util.List; import java.util.Set; import org.junit.Test; public class FunctionXML_XLISTTest extends AbstractFunctionXMLTest { private static final FunctionXML_XLIST HANDLER = new FunctionXML_XLIST(); @Test(expected = PreprocessorException.class) public void testExecution_ForWrongElement() throws Exception { assertNotNull( HANDLER.executeStrStr(SPY_CONTEXT, Value.valueOf("some wrong"), Value.valueOf("nonexist"))); } @Test public void testExecution_NonExistElement() throws Exception { final Value value = HANDLER.executeStrStr(SPY_CONTEXT, OPENED_DOCUMENT_ID, Value.valueOf("/root/nonexist")); assertNotNull(value); assertEquals(0, new FunctionXML_SIZE().executeStr(SPY_CONTEXT, value).asLong().intValue()); } @Test public void testExecution_ForExistElements() throws Exception { final Value value = HANDLER.executeStrStr(SPY_CONTEXT, OPENED_DOCUMENT_ID, Value.valueOf("/root/element")); assertNotNull(value); assertEquals(4, new FunctionXML_SIZE().executeStr(SPY_CONTEXT, value).asLong().intValue()); } @Override public void testName() { assertEquals("xml_xlist", HANDLER.getName()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(Set.of(2), HANDLER.getArity()); } @Override public void testAllowedArgumentTypes() { assertAllowedArguments(HANDLER, List.of(List.of(ValueType.STRING, ValueType.STRING))); } @Override public void testResultType() { assertEquals(ValueType.STRING, HANDLER.getResultType()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/operators/AbstractOperatorTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.igormaznitsa.jcp.AbstractSpyPreprocessorContextTest; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Expression; import com.igormaznitsa.jcp.expression.Value; import org.junit.Test; public abstract class AbstractOperatorTest extends AbstractSpyPreprocessorContextTest { @Test public abstract void testKeyword(); @Test public abstract void testReference(); @Test public abstract void testArity(); @Test public abstract void testPriority(); @Test public abstract void testExecution() throws Exception; @Test public abstract void testExecution_PreprocessorException() throws Exception; public void assertReference(final AbstractOperator operator) { final String reference = operator.getReference(); assertNotNull("The reference must not be null", reference); assertFalse("The reference must not be empty", reference.isEmpty()); assertTrue("The reference must be longer that 7 chars", reference.length() > 7); } public PreprocessorContext assertExecution(final Value expectedResult, final String expression) throws Exception { final PreprocessorContext context = preparePreprocessorContext(getCurrentTestFolder()); assertEquals("The expression result must be equal to the expected one", expectedResult, Expression.evalExpression(expression, context)); return context; } public void assertPreprocessorException(final String expression) { try { assertExecution(Value.INT_ZERO, expression); fail("Must throw PE"); } catch (PreprocessorException expected) { } catch (Exception unexpected) { unexpected.printStackTrace(); fail("Unexpected exception detected, must be you have a program error"); } } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/operators/OperatorADDTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; import org.junit.Test; public class OperatorADDTest extends AbstractOperatorTest { private static final OperatorADD HANDLER = new OperatorADD(); @Override public void testExecution() throws Exception { assertExecution(Value.valueOf(Long.valueOf(11)), "3+8"); assertExecution(Value.valueOf("helloworld"), "\"hello\"+\"world\""); assertExecution(Value.valueOf(2.2f), "1.2+1"); assertExecution(Value.valueOf("1test"), "1+\"test\""); assertExecution(Value.valueOf("1.2test"), "1.2+\"test\""); } @Test public void testExecution_chain() throws Exception { assertExecution(Value.valueOf("1.2.3"), "1+\".\"+2+\".\"+3"); } @Override public void testExecution_PreprocessorException() throws Exception { assertPreprocessorException("+"); assertPreprocessorException("+1"); assertPreprocessorException("2+"); assertPreprocessorException("true+false"); assertPreprocessorException("1+true"); assertPreprocessorException("2.3+false"); } @Override public void testArity() { assertEquals(2, HANDLER.getArity()); } @Override public void testKeyword() { assertEquals("+", HANDLER.getKeyword()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testPriority() { assertEquals(ExpressionItemPriority.ARITHMETIC_ADD_SUB, HANDLER.getExpressionItemPriority()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/operators/OperatorANDTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; import org.junit.Test; public class OperatorANDTest extends AbstractOperatorTest { private static final OperatorAND HANDLER = new OperatorAND(); @Test public void testExecution() throws Exception { assertExecution(Value.valueOf(1L), "3 && 1"); assertExecution(Value.valueOf(0L), "1 && 0"); assertExecution(Value.valueOf(1L), "1 && 3"); assertExecution(Value.valueOf(Boolean.TRUE), "true && true"); assertExecution(Value.valueOf(Boolean.FALSE), "false && true"); assertExecution(Value.valueOf(Boolean.FALSE), "true && false"); assertExecution(Value.valueOf(Boolean.FALSE), "false && false"); assertExecution(Value.valueOf(Boolean.FALSE), "false && false && true"); assertExecution(Value.valueOf(Boolean.TRUE), "true && true && true"); } @Override public void testExecution_PreprocessorException() throws Exception { assertPreprocessorException("&&"); assertPreprocessorException("true &&"); assertPreprocessorException("&& false"); assertPreprocessorException("\"test\" && true"); assertPreprocessorException("false && 1.3"); } @Override public void testKeyword() { assertEquals("&&", HANDLER.getKeyword()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(2, HANDLER.getArity()); } @Override public void testPriority() { assertEquals(ExpressionItemPriority.LOGICAL, HANDLER.getExpressionItemPriority()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/operators/OperatorDIVTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; import org.junit.Test; public class OperatorDIVTest extends AbstractOperatorTest { private static final OperatorDIV HANDLER = new OperatorDIV(); @Override public void testExecution() throws Exception { assertExecution(Value.valueOf(5L), "10/2"); assertExecution(Value.valueOf(1.5f), "3.0/2"); assertExecution(Value.valueOf(1L), "3/2"); } @Test public void testExecution_chain() throws Exception { assertExecution(Value.valueOf(8L), "160/4/5"); } @Override public void testExecution_PreprocessorException() { assertPreprocessorException("/"); assertPreprocessorException("1/"); assertPreprocessorException("/2.2"); assertPreprocessorException("1/true"); assertPreprocessorException("false/3"); assertPreprocessorException("\"hello\"/2.2"); assertPreprocessorException("1/\"hello\""); } @Test(expected = ArithmeticException.class) public void testExecution_arithmeticException() throws Exception { assertExecution(Value.INT_ZERO, "1/0"); } @Override public void testKeyword() { assertEquals("/", HANDLER.getKeyword()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(2, HANDLER.getArity()); } @Override public void testPriority() { assertEquals(ExpressionItemPriority.ARITHMETIC_MUL_DIV_MOD, HANDLER.getExpressionItemPriority()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/operators/OperatorEQUTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; public class OperatorEQUTest extends AbstractOperatorTest { private static final OperatorEQU HANDLER = new OperatorEQU(); @Override public void testExecution() throws Exception { assertExecution(Value.BOOLEAN_TRUE, "true==true"); assertExecution(Value.BOOLEAN_FALSE, "false==true"); assertExecution(Value.BOOLEAN_FALSE, "true==false"); assertExecution(Value.BOOLEAN_FALSE, "1==0"); assertExecution(Value.BOOLEAN_TRUE, "2==2"); assertExecution(Value.BOOLEAN_TRUE, "2.4==2.4"); assertExecution(Value.BOOLEAN_TRUE, "0x443==1091"); assertExecution(Value.BOOLEAN_TRUE, "1091==0x443"); assertExecution(Value.BOOLEAN_TRUE, "\"test\"==\"test\""); assertExecution(Value.BOOLEAN_FALSE, "\"test\"==\"test2\""); assertExecution(Value.BOOLEAN_TRUE, "1==1.0"); } @Override public void testExecution_PreprocessorException() throws Exception { assertPreprocessorException("true==1"); assertPreprocessorException("=="); assertPreprocessorException("1=="); assertPreprocessorException("==1"); } @Override public void testKeyword() { assertEquals("==", HANDLER.getKeyword()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(2, HANDLER.getArity()); } @Override public void testPriority() { assertEquals(ExpressionItemPriority.COMPARISON, HANDLER.getExpressionItemPriority()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/operators/OperatorGREATEQUTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; public class OperatorGREATEQUTest extends AbstractOperatorTest { private static final OperatorGREATEQU HANDLER = new OperatorGREATEQU(); @Override public void testKeyword() { assertEquals(">=", HANDLER.getKeyword()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(2, HANDLER.getArity()); } @Override public void testPriority() { assertEquals(ExpressionItemPriority.COMPARISON, HANDLER.getExpressionItemPriority()); } @Override public void testExecution() throws Exception { assertExecution(Value.BOOLEAN_TRUE, "1>=0"); assertExecution(Value.BOOLEAN_TRUE, "0>=0"); assertExecution(Value.BOOLEAN_TRUE, "\"test\">=\"t\""); assertExecution(Value.BOOLEAN_TRUE, "\"test\">=\"test\""); assertExecution(Value.BOOLEAN_FALSE, "\"t\">=\"test\""); assertExecution(Value.BOOLEAN_TRUE, "1.2>=1.1"); assertExecution(Value.BOOLEAN_FALSE, "1.5>=2.3"); assertExecution(Value.BOOLEAN_TRUE, "1.5>=1.5"); } @Override public void testExecution_PreprocessorException() throws Exception { assertPreprocessorException(">="); assertPreprocessorException("1>="); assertPreprocessorException(">=0"); assertPreprocessorException("true>=\"test\""); assertPreprocessorException("true>=1"); assertPreprocessorException("2.3>=\"test\""); assertPreprocessorException("2.3>=false"); assertPreprocessorException("true>=false"); assertPreprocessorException("1>=false"); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/operators/OperatorGREATTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; public class OperatorGREATTest extends AbstractOperatorTest { private static final OperatorGREAT HANDLER = new OperatorGREAT(); @Override public void testKeyword() { assertEquals(">", HANDLER.getKeyword()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(2, HANDLER.getArity()); } @Override public void testPriority() { assertEquals(ExpressionItemPriority.COMPARISON, HANDLER.getExpressionItemPriority()); } @Override public void testExecution() throws Exception { assertExecution(Value.BOOLEAN_TRUE, "1>0"); assertExecution(Value.BOOLEAN_FALSE, "0>0"); assertExecution(Value.BOOLEAN_TRUE, "\"test\">\"t\""); assertExecution(Value.BOOLEAN_TRUE, "1.2>1.1"); assertExecution(Value.BOOLEAN_FALSE, "1.5>2.3"); } @Override public void testExecution_PreprocessorException() throws Exception { assertPreprocessorException(">"); assertPreprocessorException("1>"); assertPreprocessorException(">0"); assertPreprocessorException("true>\"test\""); assertPreprocessorException("true>1"); assertPreprocessorException("2.3>\"test\""); assertPreprocessorException("2.3>false"); assertPreprocessorException("true>false"); assertPreprocessorException("1>false"); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/operators/OperatorLESSEQUTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; public class OperatorLESSEQUTest extends AbstractOperatorTest { private static final OperatorLESSEQU HANDLER = new OperatorLESSEQU(); @Override public void testKeyword() { assertEquals("<=", HANDLER.getKeyword()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(2, HANDLER.getArity()); } @Override public void testPriority() { assertEquals(ExpressionItemPriority.COMPARISON, HANDLER.getExpressionItemPriority()); } @Override public void testExecution() throws Exception { assertExecution(Value.BOOLEAN_FALSE, "1<=0"); assertExecution(Value.BOOLEAN_TRUE, "0<=0"); assertExecution(Value.BOOLEAN_FALSE, "\"test\"<=\"t\""); assertExecution(Value.BOOLEAN_TRUE, "\"test\"<=\"test\""); assertExecution(Value.BOOLEAN_TRUE, "\"t\"<=\"test\""); assertExecution(Value.BOOLEAN_FALSE, "1.2<=1.1"); assertExecution(Value.BOOLEAN_TRUE, "1.5<=2.3"); assertExecution(Value.BOOLEAN_TRUE, "1.5<=1.5"); } @Override public void testExecution_PreprocessorException() throws Exception { assertPreprocessorException("<="); assertPreprocessorException("1<="); assertPreprocessorException("<=0"); assertPreprocessorException("true<=\"test\""); assertPreprocessorException("true<=1"); assertPreprocessorException("2.3<=\"test\""); assertPreprocessorException("2.3<=false"); assertPreprocessorException("true<=false"); assertPreprocessorException("1<=false"); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/expression/operators/OperatorLESSTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.expression.operators; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.expression.ExpressionItemPriority; import com.igormaznitsa.jcp.expression.Value; public class OperatorLESSTest extends AbstractOperatorTest { private static final OperatorLESS HANDLER = new OperatorLESS(); @Override public void testKeyword() { assertEquals("<", HANDLER.getKeyword()); } @Override public void testReference() { assertReference(HANDLER); } @Override public void testArity() { assertEquals(2, HANDLER.getArity()); } @Override public void testPriority() { assertEquals(ExpressionItemPriority.COMPARISON, HANDLER.getExpressionItemPriority()); } @Override public void testExecution() throws Exception { assertExecution(Value.BOOLEAN_FALSE, "1<0"); assertExecution(Value.BOOLEAN_FALSE, "0<0"); assertExecution(Value.BOOLEAN_FALSE, "\"test\"<\"t\""); assertExecution(Value.BOOLEAN_FALSE, "1.2<1.1"); assertExecution(Value.BOOLEAN_TRUE, "1.5<2.3"); } @Override public void testExecution_PreprocessorException() throws Exception { assertPreprocessorException("<"); assertPreprocessorException("1<"); assertPreprocessorException("<0"); assertPreprocessorException("true<\"test\""); assertPreprocessorException("true<1"); assertPreprocessorException("2.3<\"test\""); assertPreprocessorException("2.3 list1 = new ArrayList<>(Arrays.asList(array1)); final List list2 = new ArrayList<>(Arrays.asList(array2)); while (!list1.isEmpty() && !list2.isEmpty()) { final Object list1obj = list1.get(0); for (int i = 0; i < list2.size(); i++) { if (list2.get(i).equals(list1obj)) { list2.remove(i); break; } } list1.remove(0); } assertTrue("Different values in arrays", list1.isEmpty() && list2.isEmpty()); } @Before @Override protected void setUp() throws Exception { super.setUp(); } @After @Override protected void tearDown() throws Exception { super.tearDown(); } @Test public void testConfiguration() throws Exception { final File testPom = new File(this.getClass().getResource("test.pom.xml").toURI()); assertTrue("Must be existing", testPom.exists()); final PreprocessMojo mojo = (PreprocessMojo) lookupMojo("preprocess", testPom); assertNotNull("Must not be null", mojo); assertFalse(mojo.isSkip()); mojo.setSkip(true); assertTrue(mojo.isSkip()); final PreprocessorContext context = mojo.makePreprocessorContext(); final String[] sources = context.getSources() .stream() .map(PreprocessorContext.SourceFolder::getAsString) .toArray(String[]::new); assertArrayEqualsWithoutOrders(new String[] {"/", "/some", "/another/some"}, sources); assertEquals("destination_dir", context.getTarget().getName()); assertArrayEqualsWithoutOrders(new String[] {"xml", "html"}, context.getExcludeExtensions().toArray()); assertArrayEqualsWithoutOrders(new String[] {"java", "txt"}, context.getExtensions().toArray()); assertEquals(StandardCharsets.UTF_16, context.getSourceEncoding()); assertEquals(StandardCharsets.US_ASCII, context.getTargetEncoding()); assertEquals(CommentRemoverType.KEEP_ALL, context.getKeepComments()); assertTrue(context.isVerbose()); assertTrue(context.isDryRun()); assertTrue(context.isClearTarget()); assertTrue(context.isKeepLines()); assertTrue(context.isCareForLastEol()); assertTrue(context.isDontOverwriteSameContent()); assertTrue(context.isAllowWhitespaces()); assertTrue(context.isPreserveIndents()); assertTrue(context.isKeepAttributes()); assertTrue(context.isUnknownVariableAsFalse()); assertArrayEquals( Arrays.asList(".git", ".hg", "**/.cvs", "c:\\hello\\**\\world").toArray(new String[0]), context.getExcludeFolders().toArray(new String[0])); final List configFiles = context.getConfigFiles(); assertEquals("Must be two", 2, configFiles.size()); assertEquals("Must be test1.cfg", "test1.cfg", configFiles.get(0).getName()); assertEquals("Must be test2.cfg", "test2.cfg", configFiles.get(1).getName()); assertEquals("Must be 3", Value.INT_THREE, context.findVariableForName("globalvar1", true)); assertEquals("Must be 'hello world'", Value.valueOf("hello world"), context.findVariableForName("globalvar2", true)); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/removers/AbstractCommentRemoverTest.java ================================================ package com.igormaznitsa.jcp.removers; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import java.util.Arrays; import java.util.Collection; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @RunWith(Parameterized.class) public abstract class AbstractCommentRemoverTest { protected final boolean whiteSpaced; public AbstractCommentRemoverTest(final boolean whiteSpaced) { this.whiteSpaced = whiteSpaced; } @Parameterized.Parameters public static Collection data() { return Arrays.asList(Boolean.FALSE, Boolean.TRUE); } protected abstract AbstractCommentRemover makeCommentRemoverInstance(Reader reader, Writer writer, boolean whiteSpaceAllowed); public void assertCommentRemove(final String source, final String expected) { final Reader sourceReader = new StringReader(source); final Writer writer = new StringWriter(); final AbstractCommentRemover remover = this.makeCommentRemoverInstance(sourceReader, writer, this.whiteSpaced); try (Writer resultWriter = remover.process()) { assertEquals(expected, resultWriter.toString()); } catch (IOException ex) { fail("Unexpected error: " + ex.getMessage()); } } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/removers/CStyleCommentsRemoverTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.removers; import java.io.Reader; import java.io.Writer; import org.junit.Test; public class CStyleCommentsRemoverTest extends AbstractCommentRemoverTest { public CStyleCommentsRemoverTest(boolean whiteSpaced) { super(whiteSpaced); } @Override protected AbstractCommentRemover makeCommentRemoverInstance(final Reader reader, final Writer writer, final boolean whiteSpaceAllowed) { return new CStyleCommentRemover(reader, writer, whiteSpaceAllowed); } @Test public void testRemovingSingleStringComments() throws Exception { this.assertCommentRemove( "class main() {\n// hello world\nSystem.out.println(\"hello // world\");// a comment\n}", "class main() {\n\nSystem.out.println(\"hello // world\");\n}"); } @Test public void testMultilineStringComments() throws Exception { this.assertCommentRemove( "class main() {/**\ntest\n*/\n\n// hello world\nSystem.out.println(\"hello /*ooo*/ world\");/* a comment*/\n/* aslajdhkajhdkqwiueyoqiweuoqwueoqwiue}", "class main() {\n\n\nSystem.out.println(\"hello /*ooo*/ world\");\n"); } @Test public void testMultipleStarsAtComments() throws Exception { this.assertCommentRemove( "class main() {/**\ntest\n**/\n\n// hello world\nSystem.out.println(/**** some *** comment** ***/\"hello /*ooo*/ world\"/**** some *** comment*/);/* a comment*/\n/* aslajdhkajhdkqwiueyoqiweuoqwueoqwiue}", "class main() {\n\n\nSystem.out.println(\"hello /*ooo*/ world\");\n"); } @Test public void testTabulation() throws Exception { this.assertCommentRemove("\thello world();//test", "\thello world();"); } @Test public void testJcpDirectivesInComments() throws Exception { this.assertCommentRemove( "// hello world\n//#if DEBUG\nSystem.out.println(\"DEBUG\");\n//#else\nSystem.out.println(\"RELEASE\");\n//#endif\n// end", "\n\nSystem.out.println(\"DEBUG\");\n\nSystem.out.println(\"RELEASE\");\n\n" ); } @Test public void testLineCommentInTheEnd() throws Exception { this.assertCommentRemove("\thello world();//test\n// Hello", "\thello world();\n"); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/removers/JcpCommentLineRemoverTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.removers; import java.io.Reader; import java.io.Writer; import org.junit.Test; public class JcpCommentLineRemoverTest extends AbstractCommentRemoverTest { public JcpCommentLineRemoverTest(boolean whiteSpaced) { super(whiteSpaced); } @Override protected AbstractCommentRemover makeCommentRemoverInstance(final Reader reader, final Writer writer, final boolean whiteSpaceAllowed) { return new JcpCommentLineRemover(reader, writer, whiteSpaceAllowed); } @Test public void testRemovingSingleStringComments() throws Exception { this.assertCommentRemove( "class main() {\n// hello world\nSystem.out.println(\"hello // world\");// a comment\n}", "class main() {\n// hello world\nSystem.out.println(\"hello // world\");// a comment\n}" ); } @Test public void testMultilineStringComments() throws Exception { this.assertCommentRemove( "class main() {/**\ntest\n*/\n\n// hello world\nSystem.out.println(\"hello /*ooo*/ world\");/* a comment*/\n/* aslajdhkajhdkqwiueyoqiweuoqwueoqwiue}", "class main() {/**\ntest\n*/\n\n// hello world\nSystem.out.println(\"hello /*ooo*/ world\");/* a comment*/\n/* aslajdhkajhdkqwiueyoqiweuoqwueoqwiue}" ); } @Test public void testMultipleStarsAtComments() throws Exception { this.assertCommentRemove( "class main() {/**\ntest\n**/\n\n// hello world\nSystem.out.println(/**** some *** comment** ***/\"hello /*ooo*/ world\"/**** some *** comment*/);/* a comment*/\n/* aslajdhkajhdkqwiueyoqiweuoqwueoqwiue}", "class main() {/**\ntest\n**/\n\n// hello world\nSystem.out.println(/**** some *** comment** ***/\"hello /*ooo*/ world\"/**** some *** comment*/);/* a comment*/\n/* aslajdhkajhdkqwiueyoqiweuoqwueoqwiue}" ); } @Test public void testTabulation() throws Exception { this.assertCommentRemove( "\thello world();//test", "\thello world();//test" ); } @Test public void testJcpDirectivesInComments() throws Exception { this.assertCommentRemove( "// hello world\n//#if DEBUG\nSystem.out.println(\"DEBUG\");\n//#else\nSystem.out.println(\"RELEASE\");\n//#endif\n// end", "// hello world\n\nSystem.out.println(\"DEBUG\");\n\nSystem.out.println(\"RELEASE\");\n\n// end" ); } @Test public void testCommentedJcpDirective() throws Exception { this.assertCommentRemove( "/** some multiline //$ //# test\nwith jcp directives*/\n//$ some\n//$$$ some two\n// hello world\n////#if DEBUG\nSystem.out.println(\"DEBUG\");\n//#else\nSystem.out.println(\"RELEASE\");\n//#endif\n// end", "/** some multiline //$ //# test\nwith jcp directives*/\n\n\n// hello world\n////#if DEBUG\nSystem.out.println(\"DEBUG\");\n\nSystem.out.println(\"RELEASE\");\n\n// end" ); if (this.whiteSpaced) { this.assertCommentRemove( "/** some multiline //$ //# test\nwith jcp directives*/\n// $ some\n// $$$ some two\n// hello world\n//// #if DEBUG\nSystem.out.println(\"DEBUG\");\n// # else\nSystem.out.println(\"RELEASE\");\n// #endif\n// end", "/** some multiline //$ //# test\nwith jcp directives*/\n\n\n// hello world\n//// #if DEBUG\nSystem.out.println(\"DEBUG\");\n\nSystem.out.println(\"RELEASE\");\n\n// end" ); } } @Test public void testCommentedJcpDirectiveAndJcpMarkedLines() throws Exception { this.assertCommentRemove( "/\n//\n// JCP> test\n//JCP test\n//JCP! some jcp\n/** some multiline //$ //# test\nwith jcp directives*/\n//$ some\n//JCP> some line \n//$$$ some two\n// hello world\n////#if DEBUG\nSystem.out.println(\"DEBUG\");\n//#else\nSystem.out.println(\"RELEASE\");\n//#endif\n// end\n//JCP", "/\n//\n// JCP> test\n//JCP test\n\n/** some multiline //$ //# test\nwith jcp directives*/\n\n\n\n// hello world\n////#if DEBUG\nSystem.out.println(\"DEBUG\");\n\nSystem.out.println(\"RELEASE\");\n\n// end\n//JCP" ); if (this.whiteSpaced) { this.assertCommentRemove( "/\n//\n// JCP> test\n//JCP test\n//JCP! some jcp\n/** some multiline //$ //# test\nwith jcp directives*/\n// $ some\n//JCP> some line \n// $$$ some two\n// hello world\n//// #if DEBUG\nSystem.out.println(\"DEBUG\");\n// # else\nSystem.out.println(\"RELEASE\");\n// #endif\n// end\n//JCP", "/\n//\n// JCP> test\n//JCP test\n\n/** some multiline //$ //# test\nwith jcp directives*/\n\n\n\n// hello world\n//// #if DEBUG\nSystem.out.println(\"DEBUG\");\n\nSystem.out.println(\"RELEASE\");\n\n// end\n//JCP" ); } } @Test public void testLineCommentInTheEnd() throws Exception { this.assertCommentRemove( "\thello world();//test\n// Hello", "\thello world();//test\n// Hello" ); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/removers/JustCopyCommentsRemoverTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.removers; import java.io.Reader; import java.io.Writer; import org.junit.Test; public class JustCopyCommentsRemoverTest extends AbstractCommentRemoverTest { public JustCopyCommentsRemoverTest(boolean whiteSpaced) { super(whiteSpaced); } @Override protected AbstractCommentRemover makeCommentRemoverInstance(final Reader reader, final Writer writer, final boolean whiteSpaceAllowed) { return new JustCopyRemover(reader, writer, whiteSpaceAllowed); } @Test public void testRemovingSingleStringComments() throws Exception { this.assertCommentRemove( "class main() {\n// hello world\nSystem.out.println(\"hello // world\");// a comment\n}", "class main() {\n// hello world\nSystem.out.println(\"hello // world\");// a comment\n}" ); } @Test public void testMultilineStringComments() throws Exception { this.assertCommentRemove( "class main() {/**\ntest\n*/\n\n// hello world\nSystem.out.println(\"hello /*ooo*/ world\");/* a comment*/\n/* aslajdhkajhdkqwiueyoqiweuoqwueoqwiue}", "class main() {/**\ntest\n*/\n\n// hello world\nSystem.out.println(\"hello /*ooo*/ world\");/* a comment*/\n/* aslajdhkajhdkqwiueyoqiweuoqwueoqwiue}" ); } @Test public void testMultipleStarsAtComments() throws Exception { this.assertCommentRemove( "class main() {/**\ntest\n**/\n\n// hello world\nSystem.out.println(/**** some *** comment** ***/\"hello /*ooo*/ world\"/**** some *** comment*/);/* a comment*/\n/* aslajdhkajhdkqwiueyoqiweuoqwueoqwiue}", "class main() {/**\ntest\n**/\n\n// hello world\nSystem.out.println(/**** some *** comment** ***/\"hello /*ooo*/ world\"/**** some *** comment*/);/* a comment*/\n/* aslajdhkajhdkqwiueyoqiweuoqwueoqwiue}" ); } @Test public void testTabulation() throws Exception { this.assertCommentRemove( "\thello world();//test", "\thello world();//test" ); } @Test public void testJcpDirectivesInComments() throws Exception { this.assertCommentRemove( "// hello world\n//#if DEBUG\nSystem.out.println(\"DEBUG\");\n//#else\nSystem.out.println(\"RELEASE\");\n//#endif\n// end", "// hello world\n//#if DEBUG\nSystem.out.println(\"DEBUG\");\n//#else\nSystem.out.println(\"RELEASE\");\n//#endif\n// end" ); } @Test public void testLineCommentInTheEnd() throws Exception { this.assertCommentRemove( "\thello world();//test\n// Hello", "\thello world();//test\n// Hello" ); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/AbortTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class AbortTest extends AbstractUseCaseTest { @Override protected void tuneContext(PreprocessorContext context) { context.setCareForLastEol(true); } @Override public void check(PreprocessorContext context, JcpPreprocessor.Statistics stat) throws Exception { assertEquals(1, stat.getPreprocessed()); assertEquals(0, stat.getCopied()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/AbstractUseCaseTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static java.util.Objects.requireNonNull; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.io.File; import java.nio.charset.StandardCharsets; import java.util.Collections; import org.apache.commons.io.FileUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.rules.TemporaryFolder; public abstract class AbstractUseCaseTest { protected TemporaryFolder tmpResultFolder; protected File sourceFolder; protected File etalonFolder; @Before public void before() throws Exception { final File testDir = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI()); final File base = new File(testDir, this.getClass().getName().replace('.', File.separatorChar)); final File simulationFolder = new File(testDir.getParentFile(), "usecase_tests"); if (!simulationFolder.isDirectory()) { assertTrue("Can't make folders for simulation", simulationFolder.mkdirs()); } this.tmpResultFolder = new TemporaryFolder(simulationFolder); this.tmpResultFolder.create(); this.sourceFolder = new File(base, "src"); this.etalonFolder = new File(base, "etl"); } @After public void after() throws Exception { if (this.isDeleteTemporaryFolder()) { try { FileUtils.cleanDirectory(tmpResultFolder.getRoot()); } finally { this.tmpResultFolder.delete(); } } } public boolean isDeleteTemporaryFolder() { return true; } public abstract void check(PreprocessorContext context, JcpPreprocessor.Statistics stat) throws Exception; private void assertFolder(final File etalonFolder, final File checkFolder, final boolean ignoreEOL) throws Exception { assertTrue("Etalon folder must be a folder", etalonFolder.isDirectory()); assertTrue("Checked folder must be folder", checkFolder.isDirectory()); final File[] etalonFolderFiles = requireNonNull(etalonFolder.listFiles()); final File[] checkFolderFiles = requireNonNull(checkFolder.listFiles()); assertEquals("Must have the same number of files and folders", etalonFolderFiles.length, checkFolderFiles.length); for (final File etalonFile : etalonFolderFiles) { final File checkFile = new File(checkFolder, etalonFile.getName()); if (!checkFile.exists()) { fail("Can't find generated file :" + checkFile.getAbsolutePath()); } if (etalonFile.isFile() && !checkFile.isFile()) { fail("Expected file: " + checkFile.getAbsolutePath()); } else if (etalonFile.isDirectory()) { if (!checkFile.isDirectory()) { fail("Expected folder: " + checkFile.getAbsolutePath()); } else { assertFolder(etalonFile, checkFile, ignoreEOL); } } else { if (ignoreEOL) { final String[] etalonLines = FileUtils.readFileToString(etalonFile, StandardCharsets.UTF_8).split("\\R", -1); final String[] checkLines = FileUtils.readFileToString(checkFile, StandardCharsets.UTF_8).split("\\R", -1); if (etalonLines.length != checkLines.length) { System.err.println( "----Etalon----\n" + String.join(System.lineSeparator(), etalonLines)); System.err.println( "----Checking----\n" + String.join(System.lineSeparator(), checkLines)); fail("Different number of lines, expected " + etalonLines.length + " but read " + checkLines.length + " : " + checkFile.getAbsolutePath()); } for (int j = 0; j < etalonLines.length; j++) { final String etalon = etalonLines[j]; final String check = checkLines[j]; if (!etalon.equals(check)) { fail("Difference at line " + (j + 1) + ": etalon='" + etalon + "', check='" + check + '\''); } } } else { final long checksumEtalon = FileUtils.checksumCRC32(etalonFile); final long checksumTested = FileUtils.checksumCRC32(checkFile); if (checksumEtalon != checksumTested) { fail("Wrong checksum, etalon file = " + etalonFile.getAbsolutePath() + " , check file " + checkFile.getAbsolutePath()); } } } } } /** * Allows to tune preprocessor context. * * @param context preprocessor context */ protected void tuneContext(final PreprocessorContext context) { } protected void tuneDefaultContextOptions(final PreprocessorContext context) { context.setClearTarget(true); context.setSources(Collections.singletonList(this.sourceFolder.getAbsolutePath())); context.setTarget(tmpResultFolder.getRoot()); context.setExcludeExtensions(Collections.singletonList("xml")); context.setVerbose(true); } protected boolean isIgnoreEolInCheck() { return true; } protected PreprocessorContext createPreprocessorContext(final File baseFolder) { return new PreprocessorContext(baseFolder); } @Test public final void executeTest() throws Exception { final PreprocessorContext context = createPreprocessorContext(new File("some_impossible_folder_121212")); this.tuneDefaultContextOptions(context); this.tuneContext(context); System.setProperty("jcp.line.separator", "\n"); final JcpPreprocessor preprocessor = new JcpPreprocessor(context); final JcpPreprocessor.Statistics preprocessorStatistics = preprocessor.execute(); this.assertFolder(this.etalonFolder, this.tmpResultFolder.getRoot(), this.isIgnoreEolInCheck()); this.check(context, preprocessorStatistics); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/BinFileTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.util.Collections; public class BinFileTest extends AbstractUseCaseTest { @Override protected void tuneContext(final PreprocessorContext context) { context.setExcludeExtensions(Collections.singletonList("bin")); } @Override public void check(final PreprocessorContext context, final JcpPreprocessor.Statistics stat) throws Exception { assertEquals(1, stat.getPreprocessed()); assertEquals(0, stat.getCopied()); assertEquals(2, context.findAllInputFiles().size()); assertEquals(1, context.findAllProducedFiles().size()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/DefUndefTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class DefUndefTest extends AbstractUseCaseTest { @Override public void check(PreprocessorContext context, JcpPreprocessor.Statistics stat) throws Exception { assertEquals(0, stat.getCopied()); assertEquals(1, stat.getPreprocessed()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/EvalFileTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class EvalFileTest extends AbstractUseCaseTest { @Override protected void tuneContext(PreprocessorContext context) { context.setCareForLastEol(true); } @Override public void check(PreprocessorContext context, JcpPreprocessor.Statistics stat) throws Exception { assertEquals(1, stat.getPreprocessed()); assertEquals(0, stat.getCopied()); assertEquals(3, context.findAllInputFiles().size()); assertEquals(2, context.findAllProducedFiles().size()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/ExternalGlobalDefFileTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.io.File; public class ExternalGlobalDefFileTest extends AbstractUseCaseTest { @Override protected void tuneContext(PreprocessorContext context) { context.registerConfigFile(new File(sourceFolder.getParent(), "list.cfg")); } @Override public void check(final PreprocessorContext context, final JcpPreprocessor.Statistics stat) throws Exception { assertEquals(0, stat.getCopied()); assertEquals(1, stat.getPreprocessed()); assertEquals(2, context.findAllInputFiles().size()); assertEquals(1, context.findAllProducedFiles().size()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/GenerationTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class GenerationTest extends AbstractUseCaseTest { @Override public void check(PreprocessorContext context, JcpPreprocessor.Statistics stat) throws Exception { assertEquals(0, stat.getCopied()); assertEquals(1, stat.getPreprocessed()); assertEquals(1, context.findAllInputFiles().size()); assertEquals(3, context.findAllProducedFiles().size()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/IncludeAndExitTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class IncludeAndExitTest extends AbstractUseCaseTest { @Override public void check(final PreprocessorContext context, final JcpPreprocessor.Statistics stat) throws Exception { assertEquals(0, stat.getCopied()); assertEquals(1, stat.getPreprocessed()); assertEquals(3, context.findAllInputFiles().size()); assertEquals(1, context.findAllProducedFiles().size()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/InsidePreprocessingTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class InsidePreprocessingTest extends AbstractUseCaseTest { @Override public void check(PreprocessorContext context, JcpPreprocessor.Statistics stat) throws Exception { assertEquals(0, stat.getCopied()); assertEquals(1, stat.getPreprocessed()); assertEquals(2, context.findAllInputFiles().size()); assertEquals(1, context.findAllProducedFiles().size()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/PrefixPostfixTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class PrefixPostfixTest extends AbstractUseCaseTest { @Override public void check(PreprocessorContext context, JcpPreprocessor.Statistics stat) throws Exception { assertEquals(0, stat.getCopied()); assertEquals(1, stat.getPreprocessed()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/PreserveIndentOffTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class PreserveIndentOffTest extends AbstractUseCaseTest { @Override protected void tuneContext(final PreprocessorContext context) { context.setAllowWhitespaces(true); assertFalse(context.isPreserveIndents()); } @Override public void check(final PreprocessorContext context, final JcpPreprocessor.Statistics stat) throws Exception { assertEquals(1, stat.getPreprocessed()); assertEquals(0, stat.getCopied()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/PreserveIndentOnTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class PreserveIndentOnTest extends AbstractUseCaseTest { @Override protected void tuneContext(final PreprocessorContext context) { context.setAllowWhitespaces(true); context.setPreserveIndents(true); } @Override public void check(final PreprocessorContext context, final JcpPreprocessor.Statistics stat) throws Exception { assertEquals(1, stat.getPreprocessed()); assertEquals(0, stat.getCopied()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/SimpleTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class SimpleTest extends AbstractUseCaseTest { @Override public void check(final PreprocessorContext context, final JcpPreprocessor.Statistics stat) throws Exception { assertEquals(1, stat.getPreprocessed()); assertEquals(0, stat.getCopied()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/SpacesBeforeDirectivesNotAllowedTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.containers.FileInfoContainer; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.io.File; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class SpacesBeforeDirectivesNotAllowedTest extends AbstractUseCaseTest { @Override protected PreprocessorContext createPreprocessorContext(final File baseFolder) { return new WarnLogPreprocessorContext(baseFolder); } @Override protected void tuneContext(final PreprocessorContext context) { context.setAllowWhitespaces(false); } @Override public void check(final PreprocessorContext context, final JcpPreprocessor.Statistics stat) throws Exception { assertEquals(1, stat.getPreprocessed()); assertEquals(0, stat.getCopied()); final WarnLogPreprocessorContext warnContext = (WarnLogPreprocessorContext) context; assertEquals(3, warnContext.getWarnings().stream() .filter(x -> x != null && x.startsWith(FileInfoContainer.WARNING_SPACE_BEFORE_HASH)) .count()); } private static class WarnLogPreprocessorContext extends PreprocessorContext { private final List warnings = new CopyOnWriteArrayList<>(); public WarnLogPreprocessorContext(final File baseDir) { super(baseDir); } public List getWarnings() { return this.warnings; } @Override public void logWarning(String text) { this.warnings.add(text); super.logWarning(text); } } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/SpacesBeforeDirectivesTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.containers.FileInfoContainer; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.io.File; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class SpacesBeforeDirectivesTest extends AbstractUseCaseTest { @Override protected PreprocessorContext createPreprocessorContext(final File baseFolder) { return new WarnLogPreprocessorContext(baseFolder); } @Override protected void tuneContext(final PreprocessorContext context) { context.setAllowWhitespaces(true); } @Override public void check(final PreprocessorContext context, final JcpPreprocessor.Statistics stat) throws Exception { assertEquals(1, stat.getPreprocessed()); assertEquals(0, stat.getCopied()); final WarnLogPreprocessorContext warnContext = (WarnLogPreprocessorContext) context; assertEquals(0, warnContext.getWarnings().stream() .filter(x -> x != null && x.startsWith(FileInfoContainer.WARNING_SPACE_BEFORE_HASH)) .count()); } private static class WarnLogPreprocessorContext extends PreprocessorContext { private final List warnings = new CopyOnWriteArrayList<>(); public WarnLogPreprocessorContext(final File baseDir) { super(baseDir); } public List getWarnings() { return this.warnings; } @Override public void logWarning(String text) { this.warnings.add(text); super.logWarning(text); } } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/StaticSiteTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class StaticSiteTest extends AbstractUseCaseTest { @Override public void check(PreprocessorContext context, JcpPreprocessor.Statistics stat) throws Exception { assertEquals(10, stat.getPreprocessed()); assertEquals(205, stat.getCopied()); assertEquals(227, context.findAllInputFiles().size()); assertEquals(342, context.findAllProducedFiles().size()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/Str2JavaTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class Str2JavaTest extends AbstractUseCaseTest { @Override public void check(PreprocessorContext context, JcpPreprocessor.Statistics stat) throws Exception { assertEquals(0, stat.getCopied()); assertEquals(1, stat.getPreprocessed()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/StringDirectiveTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class StringDirectiveTest extends AbstractUseCaseTest { @Override public void check(PreprocessorContext context, JcpPreprocessor.Statistics stat) throws Exception { assertEquals(0, stat.getCopied()); assertEquals(1, stat.getPreprocessed()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/TextBufferVariablesTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; import java.util.Collections; public class TextBufferVariablesTest extends AbstractUseCaseTest { @Override protected void tuneContext(final PreprocessorContext context) { context.setExcludeExtensions(Collections.singletonList("bin")); } @Override public void check(final PreprocessorContext context, final JcpPreprocessor.Statistics stat) throws Exception { assertEquals(1, stat.getPreprocessed()); assertEquals(0, stat.getCopied()); assertEquals(1, context.findAllInputFiles().size()); assertEquals(1, context.findAllProducedFiles().size()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/UnknownVarAsFalseTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class UnknownVarAsFalseTest extends AbstractUseCaseTest { @Override protected void tuneContext(final PreprocessorContext context) { context.setUnknownVariableAsFalse(true); } @Override public void check(final PreprocessorContext context, final JcpPreprocessor.Statistics stat) throws Exception { assertEquals(0, stat.getCopied()); assertEquals(1, stat.getPreprocessed()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/UsePrefixAsMultilineTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; public class UsePrefixAsMultilineTest extends AbstractUseCaseTest { @Override public void check(PreprocessorContext context, JcpPreprocessor.Statistics stat) throws Exception { assertEquals(0, stat.getCopied()); assertEquals(1, stat.getPreprocessed()); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/usecases/UserFunctionTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.usecases; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import com.igormaznitsa.jcp.JcpPreprocessor; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.extension.PreprocessorExtension; import java.util.List; import java.util.Set; public class UserFunctionTest extends AbstractUseCaseTest implements PreprocessorExtension { int calledfunc; int calledaction; @Override protected void tuneContext(PreprocessorContext context) { context.addPreprocessorExtension(this); } @Override public void check(PreprocessorContext context, JcpPreprocessor.Statistics stat) throws Exception { assertEquals("User function must be called once", 1, calledfunc); assertEquals("User action must be called twice", 2, calledaction); assertEquals(0, stat.getCopied()); assertEquals(1, stat.getPreprocessed()); } @Override public boolean processAction(final PreprocessorContext context, final List parameters) { calledaction++; assertEquals(1000L, parameters.get(0).asLong().longValue()); assertEquals("hello", parameters.get(1).asString()); assertEquals(123L, parameters.get(2).asLong().longValue()); return true; } @Override public Value processUserFunction(final PreprocessorContext preprocessorContext, final String functionName, final List arguments) { if ("testfunc".equals(functionName) && arguments.size() == 3) { calledfunc++; assertEquals(1L, arguments.get(0).asLong().longValue()); assertEquals("hry", arguments.get(1).asString()); assertEquals(3L, arguments.get(2).asLong().longValue()); return Value.valueOf("yayaya"); } else { fail("Unexpected function '" + functionName + '\''); throw new RuntimeException("Error"); } } @Override public boolean hasAction(int arity) { return arity == 3; } @Override public boolean hasUserFunction(String name, Set arity) { if ("testfunc".equals(name)) { return arity.isEmpty() || arity.contains(3); } return false; } @Override public Set getUserFunctionArity(final String functionName) { return "testfunc".equals(functionName) ? Set.of(3) : Set.of(-1); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/utils/PreprocessorUtilsTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.utils; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import java.lang.reflect.Field; import java.nio.charset.Charset; import org.junit.Test; public class PreprocessorUtilsTest { @Test public void testReplaceStringPrefix() throws Exception { final String[] testData = new String[] {"--ae:123", "-homa-", "-hbd", "---Some", "-", "--"}; final String[] processed = PreprocessorUtils.replaceStringPrefix(new String[] {"-", "--"}, "/", testData); assertArrayEquals(new String[] {"/ae:123", "/homa-", "/hbd", "/-Some", "/", "/"}, processed); } @Test public void testGenerateStringForChar() throws Exception { assertEquals("", PreprocessorUtils.generateStringForChar(' ', -1)); assertEquals("", PreprocessorUtils.generateStringForChar(' ', 0)); assertEquals(" ", PreprocessorUtils.generateStringForChar(' ', 1)); assertEquals("aaa", PreprocessorUtils.generateStringForChar('a', 3)); } @Test public void testReplacePartByChar() throws Exception { assertEquals("", PreprocessorUtils.replacePartByChar("", ' ', 33, 44)); assertEquals("a de", PreprocessorUtils.replacePartByChar("abcde", ' ', 1, 2)); assertEquals("a ", PreprocessorUtils.replacePartByChar("abcde", ' ', 1, 8)); assertEquals("abc ", PreprocessorUtils.replacePartByChar("abcde", ' ', 3, 8)); } @Test public void testMakeFileReader_charsetAndBufferSizeChange() throws Exception { final Charset defaultCharset = Charset.defaultCharset(); final File testFile = new File(PreprocessorUtilsTest.class.getResource("somefile.txt").toURI()); Charset nonDefaultCharset = null; for (final Charset ch : Charset.availableCharsets().values()) { if (!defaultCharset.equals(ch)) { nonDefaultCharset = ch; break; } } assertNotNull( "We must have found a non default charset, system must have more than one available charset", nonDefaultCharset); // some hack to get access to the wrapped reader final Field inField = BufferedReader.class.getDeclaredField("in"); inField.setAccessible(true); final Field cbField = BufferedReader.class.getDeclaredField("cb"); cbField.setAccessible(true); final int BUFFER_SIZE = 0xCAFE; final BufferedReader reader = PreprocessorUtils.makeFileReader(testFile, nonDefaultCharset, BUFFER_SIZE); // check that we have selected the non standard charset final InputStreamReader wrappedReader = (InputStreamReader) inField.get(reader); assertNotNull("Must not be null", wrappedReader); assertEquals("The non default charset must be set", nonDefaultCharset.name(), wrappedReader.getEncoding()); // check that we have changed the buffer size final char[] insideCharBuffer = (char[]) cbField.get(reader); assertNotNull("Must not be null", insideCharBuffer); assertEquals("Must have our selected size", BUFFER_SIZE, insideCharBuffer.length); } } ================================================ FILE: jcp/src/test/java/com/igormaznitsa/jcp/utils/antpathmatcher/AntPathMatcherTest.java ================================================ /* * Copyright 2002-2019 Igor Maznitsa (http://www.igormaznitsa.com) * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.igormaznitsa.jcp.utils.antpathmatcher; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import com.igormaznitsa.jcp.utils.AntPathMatcher; import org.junit.Test; public class AntPathMatcherTest { @Test public void testMatching() { final AntPathMatcher matcher = new AntPathMatcher(); assertTrue(matcher.match("", "")); assertFalse(matcher.match("", "a")); assertFalse(matcher.match("a", "")); assertTrue(matcher.match("?", "a")); assertFalse(matcher.match("*", "")); assertFalse(matcher.match("?", "")); assertTrue(matcher.match("**/test", "test")); assertTrue(matcher.match("**/test?", "test1")); assertTrue(matcher.match("**/test*", "test111")); assertTrue(matcher.match("**/test", "some/test")); assertTrue(matcher.match("**/test", "some/help/test")); assertTrue(matcher.match("some/**/test", "some/help/test")); assertTrue(matcher.match("**/some/help/test", "some/help/test")); assertTrue(matcher.match("/**/help/test", "/some/help/test")); assertTrue(matcher.match("**/help/test", "some/help/test")); assertTrue(matcher.match("**\\help\\test", "some\\help\\test")); assertFalse(matcher.match("**\\help\\test", "some\\help\\test1")); assertFalse(matcher.match("some", "some1")); assertFalse(matcher.match("some/help", "some/help/ddd")); } } ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/cmdline/global_variable_def.txt ================================================ #some comment test="hello world" ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/context/spacedFile.txt ================================================ // #local VAR="hello" // $ /*$VAR$*/ // $$ /*$VAR$*/ Universe some test/* - */must be removed ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/context/standardFile.txt ================================================ //#local VAR="hello" //$ /*$VAR$*/ //$$ /*$VAR$*/ Universe some test/*-*/must be removed ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_abort.txt ================================================ 1 2 3 4 //#abort 5 6 ---START_ETALON--- 1 2 3 4 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_action.txt ================================================ test //#action 1,2,3+4,5+6,true,"hello," end //#if false //#action unexpected //#endif ---START_ETALON--- test end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_comment_next_line.txt ================================================ begin //#// hello //#// test ---START_ETALON--- begin // hello // test ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_define.txt ================================================ test //#define somevar //#define somenum 3*8 /*$somevar$*/ /*$somenum$*/ end ---START_ETALON--- test true 24 end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_definel.txt ================================================ test //#definel somevar // test //#definel somenum 3*8 /*$somevar$*/ /*$somenum$*/ end ---START_ETALON--- test true 24 end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_echo.txt ================================================ start //#local test=1 //#echo string /*$test+1$*/ ok end ---START_ETALON--- start end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_error.txt ================================================ start //#local test=1 //#error "string"+(test+1) end ---START_ETALON--- start end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_excludeif.txt ================================================ some text test //#excludeif true //#_if false //#excludeif false //#_endif //#excludeif hello+world test ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_exit.txt ================================================ test //#exit unexpected ---START_ETALON--- test ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_exitif.txt ================================================ test //#exitif false expected //#exitif true unexpected ---START_ETALON--- test expected ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_global.txt ================================================ //#global xxx=10 ttt ---START_ETALON--- ttt ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_globalifelseendif.txt ================================================ //#_if true //#if true hello //#else world //#endif //#global expected=true //#_else //#_if true //#global expected=false //#_else //#global expected=false //#_endif //#global unexpected=false //#if false unexp //#else exp //#endif //#_endif test ---START_ETALON--- hello exp test ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_globalifelseendif2.txt ================================================ //#if true a //#_if 0219384092384091 b //#_if true //#else c //#_endif d //#_else //#endif ---START_ETALON--- a b ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_if_else_endif.txt ================================================ hello //#if false //#local test = 111 // some comment1 nonprocessed /*$test$*/ //#endif //#local x=true //#local y=false //#local z=false //#if x // some comment2 //#if y unexpected1 //#else //#if z unexpected2 //#else //#if !z expected //#endif //#endif //#endif //#else //#if y must not be out //#else unexpected3 //#endif //#endif world ---START_ETALON--- hello // some comment2 expected world ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_if_else_endif_with_keptlines.txt ================================================ hello //#if false //#local test = 111 nonprocessed /*$test$*/ //#endif //#local x=true //#local y=false //#local z=false //#if x //#if y unexpected1 //#else //#if z unexpected2 //#else //#if !z expected //#endif //#endif //#endif //#else //#if y must not be out //#else unexpected3 //#endif //#endif world ---START_ETALON--- hello //JCP! if false //JCP! local test = 111 //JCP> nonprocessed /*$test$*/ //JCP! endif //JCP! local x=true //JCP! local y=false //JCP! local z=false //JCP! if x //JCP! if y //JCP> unexpected1 //JCP! else //JCP! if z //JCP> unexpected2 //JCP! else //JCP! if !z expected //JCP! endif //JCP! endif //JCP! endif //JCP! else //JCP! if y //JCP> must not be out //JCP! else //JCP> unexpected3 //JCP! endif //JCP! endif world ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_ifdef.txt ================================================ start //#ifdef test unexpected //#else expected1 //#endif //#define test //#if true //#ifdef test expected2 //#else unexpected //#endif //#endif //#ifdef BYTECODE somebytecode //#endif end ---START_ETALON--- start expected1 expected2 somebytecode end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_ifdefined.txt ================================================ start //#ifdefined test unexpected //#else expected1 //#endif //#define test //#if true //#ifdefined test expected2 //#else unexpected //#endif //#endif //#ifdefined BYTECODE somebytecode //#endif end ---START_ETALON--- start expected1 expected2 somebytecode end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_ifndef.txt ================================================ start //#ifndef test expected1 //#else unexpected //#endif //#define test //#if true //#ifndef test unexpected //#else expected2 //#endif //#endif //#ifndef BYTECODE somebytecode //#endif end ---START_ETALON--- start expected1 expected2 somebytecode end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_include.txt ================================================ start //#include "./directive_include2.txt" //#include __filefolder__+"/directive_include3.txt" end ---START_ETALON--- start This text must be included and this one too Absolute path end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_include2.txt ================================================ This text must be included and this one too ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_include3.txt ================================================ Absolute path ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_local.txt ================================================ //#local l_stringGamesNumber = "" //#local l_menuID = "hello" //#local l_menuName = "menu" /*$l_menuID+l_menuName+l_stringGamesNumber$*/ //#if false //#local x =1 //#endif hello //#local x = 5 world //#local y= 10 and me //#local z=x+y //#local test.var = z+"."+x+"."+y /*$test.var$*/ ---START_ETALON--- hellomenu hello world and me 15.5.10 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_msg.txt ================================================ start //#local test=1 //#msg string /*$test+1$*/ ok //#msg string /*$6*8$*/ ok end ---START_ETALON--- start end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_outdir.txt ================================================ //#local path="a/" //#outdir path+"expected" //#if false //#outdir path+"unexpected" //#endif /*$jcp.dst.dir$*/ ok ---START_ETALON--- a/expected ok ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_outdisabled.txt ================================================ hello world //#- //#if true unexpected text //#endif ---START_ETALON--- hello world ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_outenabled.txt ================================================ hello world //#- unexpected text //#+ expected text ---START_ETALON--- hello world expected text ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_outname.txt ================================================ //#outname "expected.java" //#if false //#outname "unexpected.html" //#endif /*$jcp.dst.name$*/ ok ---START_ETALON--- expected.java ok ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_prefixpostfix.txt ================================================ //#postfix+ This string must be in the postfix //#postfix- This string must be in the normal (1) //#prefix+ This string must be in the prefix //#prefix- This string must be in the normal (2) //#if false //#postfix+ //#endif This string must be in the normal (3) //#if false //#prefix+ //#endif This string must be in the normal (4) ok ---START_ETALON--- This string must be in the prefix This string must be in the normal (1) This string must be in the normal (2) This string must be in the normal (3) This string must be in the normal (4) ok This string must be in the postfix ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_special.txt ================================================ //$hello /*$111+112$*/ world //$$hello /*$111+112$*/ world //$"""hello /*$111+112$*/ world //$$"""hello /*$111+112$*/ world hello/*-*/world ---START_ETALON--- hello 223 world hello /*$111+112$*/ world """hello 223 world """hello /*$111+112$*/ world hello ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_special_block.txt ================================================ //$"""hello /*$111+112$*/ world //$"""next //$$"""hello /*$111+112$*/ world //$$"""next/*$111+112$*/ //$$"""hello /*$111+112$*/ world //$"""middle //$$"""next/*$111+112$*/ //$$"""hello /*$111+112$*/ world //$split //$$"""next/*$111+112$*/ //$"""hello /*$111+112$*/ world //$$split //$"""next/*$111+112$*/ //$"""line1 //#local a="" //$"""line2 //$"""hello //$"""world earth ---START_ETALON--- hello 223 world next hello /*$111+112$*/ world next/*$111+112$*/ hello /*$111+112$*/ world middle next/*$111+112$*/ hello /*$111+112$*/ world split next/*$111+112$*/ hello 223 world split next223 line1 line2 hello world earth ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_undef.txt ================================================ test //#definel localone /*$somevar$*/ /*$localone$*/ //#undef somevar //#undef localone end ---START_ETALON--- test true true end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_warning.txt ================================================ start //#local test=1 //#warning "string"+(test+1) end ---START_ETALON--- start end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/directive_while_continue_break_end.txt ================================================ begin //#local counter = 3 //#while counter>0 //#if counter == 2 //#local counter = counter-1 //#continue //#endif //#local counter2 = 3 //#while counter2>0 //#if counter2==1 //#break //#endif /*$counter$*/ /*$counter2$*/ //#local counter2=counter2-1 //#end //#local counter=counter-1 //#end end //#local c=4 //#while c>=0 //#local c=c-1 //#if c==1 break detected //#break //#else /*$c$*/ //#endif //#end //#if false //#while true 000 //#continue //#break 222 //#local unknown = unknown //#break 111 //#while false //#if true 333 //#endif //#continue 444 //#end //#end //#endif endall ---START_ETALON--- begin 3 3 3 2 1 3 1 2 end 3 2 break detected endall ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/only_spaces.txt ================================================ ---START_ETALON--- ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/directives/specvars_ro.txt ================================================ start //#outname "hello_world.jpg" line /*$__LINE__$*/ line /*$__LINE__$*/ line /*$__LINE__$*/ line /*$__LINE__$*/ line /*$__LINE__$*/ filesrc /*$__FILENAME__$*/ filesrc /*$jcp.src.name$*/ filedst /*$jcp.dst.name$*/ end ---START_ETALON--- start line 3 line 4 line 5 line 6 line 7 filesrc specvars_ro.txt filesrc specvars_ro.txt filedst hello_world.jpg end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/exceptions/wrong_bracket.txt ================================================ //#local test=10 //#while test>0 //#local test=test-1 //#end //#if false //#local hello = (1+2)/45*334) //#endif //#local hello = ( test ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/exceptions/wrong_bracket_closing.txt ================================================ //#local test=10 //#while test>0 //#local test=test-1 //#end //#if false //#local hello = (1+2)/45*334) //#endif //#local hello = xml_open("some.xml")) test ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/exceptions/wrong_bracket_include.txt ================================================ ufasd f dsasa dsa d sa d sa d sadli apodei qei pwqdsa d sad s ad sad sad s ad as d sad sad as d //#include "./wrong_bracket.txt" ijfda asd dasd as dsad ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/expression/functions/eval/TestBin.txt ================================================ Hello Preprocessor! ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/expression/functions/eval/TestBinLong.txt ================================================ какие то русские буквы Hello Preprocessor! it is very very very long line to fill the file! sometime it is useful for tests! als I decided to add one more line. ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/expression/functions/eval/TestEval.java ================================================ //#- package com.igormaznitsa.jcp; import com.igormaznitsa.jcp.context.PreprocessorContext; import com.igormaznitsa.jcp.exceptions.PreprocessorException; import com.igormaznitsa.jcp.expression.Value; import com.igormaznitsa.jcp.utils.PreprocessorUtils; import java.io.*; import static org.junit.Assert.*; import org.junit.Test; //#+ //#ifdefined includemeth public final class TestEval { public void main(String ... args){ //#endif System.out.println("/*$hello_world$*/"); //#ifdefined includemeth } } //#endif ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/expression/functions/eval/TestEvalWithIncluded.java ================================================ //#- public final class TestEvalWithIncluded { public void main(String ... args){ //#+ /*$evalfile("./TestEval.java")+__filename__$*/ //#- } } //#+ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/expression/functions/xml/noxml.txt ================================================ adslkj ql;d sd sad sadsa d as wqe sd sad sad ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/expression/functions/xml/test.xml ================================================ elem1 elem2 elem3 ]]> rustext gertext esttext fintext frtext ittext ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/global_error_at.txt ================================================ # error at the string 8 @yyejjw.txt var="h" ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/global_ok.txt ================================================ # this is a comment #@ #@@@@@ #@@@ /T:ISO-8859-1 globalVar1="hello world" #tttest globalVar2=1*2+1 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/maven/test.pom.xml ================================================ 4.0.0 com.igormaznitsa JCPreprocessor-test 1.0-SNAPSHOT jar Test of Preprocessor Mojo The pom is used for test purposes UTF-8 com.igormaznitsa jcp 7.3.0 preprocess / /some /another/some true destination_dir xml html java txt UTF-16 US-ASCII true true true true true true true true true true true> .git .hg **/.cvs c:\hello\**\world test1.cfg test2.cfg 3 hello world ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/removers/java/etalon.etl ================================================ public class test { public static void main(String ... args) { for(String a : args) { System.out.println("Arg: "+a); } System.out.println("//Hello /*World*/"); int a = 5+10; System.out.println("What a terrible comments/**aaaaa*/"); } } ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/removers/java/test_java.ppp ================================================ //#outname "w_o_comments.ttt" /** * Test file to check the remove comment preprocessor feature * //////////////////////////////////////////////// * @author Igor Maznitsa (igor.maznitsa@igormaznitsa.com) */ public class test { /* Some test method */ public static void main(String ... args) { // print each argument for(String a : args) { // to console System.out.println("Arg: "+a); } // ok, the loop is completed System.out.println("//Hello /*World*/"); // It's some test commented call /*It's a*/int a = /*It's the first arg*/5+/*It's the second one*/10;//Ha ha ha ha ha ha ha ha System.out.println("What a terrible comments/**aaaaa*/");// test /* float pi = 3.14f; // it's the most secret part of code, remove it after reading */ } } ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/AbortTest/etl/text.txt ================================================ 1 3 5 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/AbortTest/src/text.txt ================================================ //#if false //#abort unexpected //#endif //#include "text1.txt" end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/AbortTest/src/text1.txt ================================================ //#excludeif true 1 //#include "text2.txt" 2 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/AbortTest/src/text2.txt ================================================ //#excludeif true 3 //#include "text3.txt" 4 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/AbortTest/src/text3.txt ================================================ //#excludeif true 5 //#abort expected 6 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/BinFileTest/etl/body.txt ================================================ BASE64 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEpJREFUeNpi9K1d/Z+BTLCpKYSRBcTY3Bxqgk0B0PAz+ORANAuUfxaPRfjkGJgYKATDwADG0WgcjUZgNDICaWNyDfj///9ZgAADAHNfI01qaFVqAAAAAElFTkSuQmCC BASE64 splitted to lines iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFn ZVJlYWR5ccllPAAAAEpJREFUeNpi9K1d/Z+BTLCpKYSRBcTY3Bxqgk0B0PAz+ORANAuUfxaPRfjkGJgY KATDwADG0WgcjUZgNDICaWNyDfj///9ZgAADAHNfI01qaFVqAAAAAElFTkSuQmCC BYTE[] (byte)0x89,(byte)0x50,(byte)0x4E,(byte)0x47,(byte)0xD,(byte)0xA,(byte)0x1A,(byte)0xA,(byte)0x0,(byte)0x0,(byte)0x0,(byte)0xD,(byte)0x49,(byte)0x48,(byte)0x44,(byte)0x52,(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x10,(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x10,(byte)0x8,(byte)0x6,(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x1F,(byte)0xF3,(byte)0xFF,(byte)0x61,(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x19,(byte)0x74,(byte)0x45,(byte)0x58,(byte)0x74,(byte)0x53,(byte)0x6F,(byte)0x66,(byte)0x74,(byte)0x77,(byte)0x61,(byte)0x72,(byte)0x65,(byte)0x0,(byte)0x41,(byte)0x64,(byte)0x6F,(byte)0x62,(byte)0x65,(byte)0x20,(byte)0x49,(byte)0x6D,(byte)0x61,(byte)0x67,(byte)0x65,(byte)0x52,(byte)0x65,(byte)0x61,(byte)0x64,(byte)0x79,(byte)0x71,(byte)0xC9,(byte)0x65,(byte)0x3C,(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x4A,(byte)0x49,(byte)0x44,(byte)0x41,(byte)0x54,(byte)0x78,(byte)0xDA,(byte)0x62,(byte)0xF4,(byte)0xAD,(byte)0x5D,(byte)0xFD,(byte)0x9F,(byte)0x81,(byte)0x4C,(byte)0xB0,(byte)0xA9,(byte)0x29,(byte)0x84,(byte)0x91,(byte)0x5,(byte)0xC4,(byte)0xD8,(byte)0xDC,(byte)0x1C,(byte)0x6A,(byte)0x82,(byte)0x4D,(byte)0x1,(byte)0xD0,(byte)0xF0,(byte)0x33,(byte)0xF8,(byte)0xE4,(byte)0x40,(byte)0x34,(byte)0xB,(byte)0x94,(byte)0x7F,(byte)0x16,(byte)0x8F,(byte)0x45,(byte)0xF8,(byte)0xE4,(byte)0x18,(byte)0x98,(byte)0x18,(byte)0x28,(byte)0x4,(byte)0xC3,(byte)0xC0,(byte)0x0,(byte)0xC6,(byte)0xD1,(byte)0x68,(byte)0x1C,(byte)0x8D,(byte)0x46,(byte)0x60,(byte)0x34,(byte)0x32,(byte)0x2,(byte)0x69,(byte)0x63,(byte)0x72,(byte)0xD,(byte)0xF8,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x59,(byte)0x80,(byte)0x0,(byte)0x3,(byte)0x0,(byte)0x73,(byte)0x5F,(byte)0x23,(byte)0x4D,(byte)0x6A,(byte)0x68,(byte)0x55,(byte)0x6A,(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x49,(byte)0x45,(byte)0x4E,(byte)0x44,(byte)0xAE,(byte)0x42,(byte)0x60,(byte)0x82 BYTE[] splitted to lines (byte)0x89,(byte)0x50,(byte)0x4E,(byte)0x47,(byte)0xD,(byte)0xA,(byte)0x1A,(byte)0xA, (byte)0x0,(byte)0x0,(byte)0x0,(byte)0xD,(byte)0x49,(byte)0x48,(byte)0x44,(byte)0x52, (byte)0x0,(byte)0x0,(byte)0x0,(byte)0x10,(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x10, (byte)0x8,(byte)0x6,(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x1F,(byte)0xF3,(byte)0xFF, (byte)0x61,(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x19,(byte)0x74,(byte)0x45,(byte)0x58, (byte)0x74,(byte)0x53,(byte)0x6F,(byte)0x66,(byte)0x74,(byte)0x77,(byte)0x61,(byte)0x72, (byte)0x65,(byte)0x0,(byte)0x41,(byte)0x64,(byte)0x6F,(byte)0x62,(byte)0x65,(byte)0x20, (byte)0x49,(byte)0x6D,(byte)0x61,(byte)0x67,(byte)0x65,(byte)0x52,(byte)0x65,(byte)0x61, (byte)0x64,(byte)0x79,(byte)0x71,(byte)0xC9,(byte)0x65,(byte)0x3C,(byte)0x0,(byte)0x0, (byte)0x0,(byte)0x4A,(byte)0x49,(byte)0x44,(byte)0x41,(byte)0x54,(byte)0x78,(byte)0xDA, (byte)0x62,(byte)0xF4,(byte)0xAD,(byte)0x5D,(byte)0xFD,(byte)0x9F,(byte)0x81,(byte)0x4C, (byte)0xB0,(byte)0xA9,(byte)0x29,(byte)0x84,(byte)0x91,(byte)0x5,(byte)0xC4,(byte)0xD8, (byte)0xDC,(byte)0x1C,(byte)0x6A,(byte)0x82,(byte)0x4D,(byte)0x1,(byte)0xD0,(byte)0xF0, (byte)0x33,(byte)0xF8,(byte)0xE4,(byte)0x40,(byte)0x34,(byte)0xB,(byte)0x94,(byte)0x7F, (byte)0x16,(byte)0x8F,(byte)0x45,(byte)0xF8,(byte)0xE4,(byte)0x18,(byte)0x98,(byte)0x18, (byte)0x28,(byte)0x4,(byte)0xC3,(byte)0xC0,(byte)0x0,(byte)0xC6,(byte)0xD1,(byte)0x68, (byte)0x1C,(byte)0x8D,(byte)0x46,(byte)0x60,(byte)0x34,(byte)0x32,(byte)0x2,(byte)0x69, (byte)0x63,(byte)0x72,(byte)0xD,(byte)0xF8,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x59, (byte)0x80,(byte)0x0,(byte)0x3,(byte)0x0,(byte)0x73,(byte)0x5F,(byte)0x23,(byte)0x4D, (byte)0x6A,(byte)0x68,(byte)0x55,(byte)0x6A,(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0, (byte)0x49,(byte)0x45,(byte)0x4E,(byte)0x44,(byte)0xAE,(byte)0x42,(byte)0x60,(byte)0x82 --- ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/BinFileTest/src/body.txt ================================================ BASE64 /*$binfile("./file.bin","base64")$*/ BASE64 splitted to lines /*$binfile("./file.bin","base64s")$*/ BYTE[] /*$binfile("./file.bin","byte[]")$*/ BYTE[] splitted to lines /*$binfile("./file.bin","byte[]s")$*/ --- ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/DefUndefTest/etl/text.txt ================================================ expected1 expected2 expected3 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/DefUndefTest/src/text.txt ================================================ //#ifdef HELLO_WORLD unexpected1 //#else expected1 //#endif //#define HELLO_WORLD "hello world" //#ifndef HELLO_WORLD unexpected2 //#else expected2 //#endif //#undef HELLO_WORLD //#ifdef HELLO_WORLD unexpected3 //#else expected3 //#endif ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/EvalFileTest/etl/newfolder/file1.txt ================================================ File One ODYN end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/EvalFileTest/etl/newfolder/file2.txt ================================================ File Two DVA end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/EvalFileTest/src/_file1.txt ================================================ //#excludeif TRUE File One /*$SOME_TEXT$*/ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/EvalFileTest/src/_file2.txt ================================================ //#excludeif TRUE File Two /*$SOME_TEXT$*/ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/EvalFileTest/src/text.txt ================================================ //#noautoflush //#outdir "newfolder" //#definel SOME_TEXT "ODYN" /*$evalfile("_file1.txt")$*/ end //#outname "file1.txt" //#flush //#definel SOME_TEXT "DVA" /*$evalfile("_file2.txt")$*/ end //#outname "file2.txt" //#flush ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/ExternalGlobalDefFileTest/etl/test.txt ================================================ hello world see on Java Comment Preprocessor end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/ExternalGlobalDefFileTest/list.cfg ================================================ var1="world" var2="Java "+"Comment "+"Preprocessor" ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/ExternalGlobalDefFileTest/src/test.txt ================================================ hello /*$var1$*/ see on /*$var2$*/ end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/GenerationTest/etl/file1.ttt ================================================ file 1 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/GenerationTest/etl/file2.ttt ================================================ file 2 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/GenerationTest/etl/file3.ttt ================================================ file 3 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/GenerationTest/src/text.txt ================================================ //#noautoflush //#define COUNTER 1 //#while COUNTER<=3 file /*$COUNTER$*/ //#outname "file"+COUNTER+".ttt" //#define COUNTER COUNTER+1 //#msg "Counter is "+COUNTER //#flush //#end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/IncludeAndExitTest/etl/text.txt ================================================ start 1 2 3 4 5 true end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/IncludeAndExitTest/src/text.txt ================================================ start //#include "text1.txt" //#definel HELLO //#include "text2.txt" //#if false //#exit //#else end //#endif //#exit unsuspected text ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/IncludeAndExitTest/src/text1.txt ================================================ //#excludeif true 1 2 3 //#exitif false 4 5 //#exitif true 6 7 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/IncludeAndExitTest/src/text2.txt ================================================ //#excludeif true /*$HELLO$*/ //#exit World ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/InsidePreprocessingTest/etl/text.txt ================================================ start the prefix the middle the postfix end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/InsidePreprocessingTest/src/some.txt ================================================ //#excludeif true //#postfix+ the postfix //#postfix- //#prefix+ the prefix //#prefix- the middle ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/InsidePreprocessingTest/src/text.txt ================================================ start /*$evalfile("./some.txt")$*/end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/PrefixPostfixTest/etl/text.txt ================================================ the most first start start middle middle2 the first line in postfix the end ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/PrefixPostfixTest/src/text.txt ================================================ start //#postfix+ the first line in postfix //#postfix- //#- ignored section at all oh my god! //#+ //#prefix+ the most first start //#prefix- middle //#postfix+ the end //#postfix- middle2 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/PreserveIndentOffTest/etl/text.txt ================================================ test var has HUZZAAA! value test var has HUZZAAA! value test var has /*$TEST_VAR$*/ value test var has /*$TEST_VAR$*/ value ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/PreserveIndentOffTest/src/text.txt ================================================ //#local TEST_VAR="HUZZAAA!" //$ test var has /*$TEST_VAR$*/ value // $ test var has /*$TEST_VAR$*/ value //$$ test var has /*$TEST_VAR$*/ value // $$ test var has /*$TEST_VAR$*/ value ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/PreserveIndentOnTest/etl/text.txt ================================================ test var has HUZZAAA! value test var has HUZZAAA! value test var has /*$TEST_VAR$*/ value test var has /*$TEST_VAR$*/ value ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/PreserveIndentOnTest/src/text.txt ================================================ //#local TEST_VAR="HUZZAAA!" //$ test var has /*$TEST_VAR$*/ value // $ test var has /*$TEST_VAR$*/ value //$$ test var has /*$TEST_VAR$*/ value // $$ test var has /*$TEST_VAR$*/ value ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/SimpleTest/etl/text.txt ================================================ 1.Hello World at line 7 2.Hello World at line 7 3.Hello World at line 7 4.Hello World at line 7 5.Hello World at line 7 6.Hello World at line 7 7.Hello World at line 7 8.Hello World at line 7 9.Hello World at line 7 10.Hello World at line 7 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/SimpleTest/src/text.txt ================================================ //#define MESSAGE "Hello World" //#define MSG_NUMBER 10 //#define SHOW true //#if SHOW //#definel COUNTER 1 //#while COUNTER<=MSG_NUMBER /*$COUNTER$*/./*$MESSAGE$*/ at line /*$__LINE__$*/ //#definel COUNTER COUNTER+1 //#end //#endif ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/SpacesBeforeDirectivesNotAllowedTest/etl/body.txt ================================================ // #if SOME text1 // #else text2 // #endif ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/SpacesBeforeDirectivesNotAllowedTest/src/body.txt ================================================ //#local SOME=true // #if SOME text1 // #else text2 // #endif ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/SpacesBeforeDirectivesTest/etl/body.txt ================================================ all ok helloworldhelloworld line1 line2 hurraaa+HELLO hry hry +/* $SOME_VAR$ */ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/SpacesBeforeDirectivesTest/src/body.txt ================================================ // #global SOME_VAR = "HELLO" // #_if SOME_VAR=="HELLO" all ok // #local hello="hello" //#_endif // #local LOC = HELLO+"world" /* $LOC$*//*$LOC$*/ // #ifdef LOC line1/*-*/give up line2/* - */give up // #else must not be //#endif // $ hurraaa+/* $SOME_VAR$ */ // $$ hry hry +/* $SOME_VAR$ */ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/cmn/sendfeedback.phtml ================================================ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/cmn/styles.css ================================================ body { margin-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; background-color: #FFFFFF; } .menuheader { FONT-WEIGHT: normal; FONT-SIZE: 14px; COLOR: #BFBFFF; FONT-FAMILY: "Small Fonts", "Arial Black", Arial, Helvetica, sans-serif} .menu { FONT-WEIGHT: bold; FONT-SIZE: 11px; COLOR: white; FONT-FAMILY: Arial, Helvetica, sans-serif; TEXT-DECORATION: none; } .alltext { FONT-WEIGHT: normal; FONT-FAMILY: "Times New Roman", Times, serif; COLOR: black; TEXT-DECORATION: none; font-size: 12px; font-style: normal; } .newdata { FONT-WEIGHT: bold; FONT-SIZE: 11px; COLOR: #000000; FONT-FAMILY: Arial, Helvetica, sans-serif} .footer { font-size: x-small; font-family: Arial, Helvetica, sans-serif; color: #999999; } .langtxt { font-family: Arial, Helvetica, sans-serif; font-size: 11px; font-style: normal; font-weight: bold; } .rightnews { font-family: Arial, Helvetica, sans-serif; font-size: 9px; } .rightnewsHdr { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; } a:link { text-decoration: none; color: #00BBFF; } a:visited { text-decoration: none; color: #00BBFF; } a:hover { text-decoration: none; color: #00FF00; } a:active { text-decoration: none; color: #00BBFF; } .catalogheader { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000066; text-decoration: none; } .gameinfoheader { font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: #000066; text-decoration: none; } .gameinfoheadermin { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000066; text-decoration: none; } ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/cmn/styles2.css ================================================ body { margin-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; background-color: #FFFFFF; } .menuheader { FONT-WEIGHT: normal; FONT-SIZE: 14px; COLOR: #BFBFFF; FONT-FAMILY: "Small Fonts", "Arial Black", Arial, Helvetica, sans-serif} .menu { FONT-WEIGHT: bold; FONT-SIZE: 11px; COLOR: white; FONT-FAMILY: Arial, Helvetica, sans-serif; TEXT-DECORATION: none; } .alltext { FONT-WEIGHT: normal; FONT-FAMILY: "Times New Roman", Times, serif; COLOR: black; TEXT-DECORATION: none; font-size: 12px; font-style: normal; } .newdata { FONT-WEIGHT: bold; FONT-SIZE: 11px; COLOR: #000000; FONT-FAMILY: Arial, Helvetica, sans-serif} .footer { font-size: x-small; font-family: Arial, Helvetica, sans-serif; color: #999999; } .langtxt { font-family: Arial, Helvetica, sans-serif; font-size: 11px; font-style: normal; font-weight: bold; } .rightnews { font-family: Arial, Helvetica, sans-serif; font-size: 9px; } .rightnewsHdr { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; } a:link { text-decoration: none; color: #000000; } a:visited { text-decoration: none; color: #000000; } a:hover { text-decoration: none; color: #000000; } a:active { text-decoration: none; color: #000000; } .catalogheader { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000066; text-decoration: none; } .gameinfoheader { font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: #000066; text-decoration: none; } .gameinfoheadermin { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000066; text-decoration: none; } .devicename { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000066; text-decoration: none; } .devicelist { font-family: Arial, Helvetica, sans-serif; font-size: 10px; font-weight: normal; color: #000066; text-decoration: none; } .sendformref { font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; color: #000066; text-decoration: none; } .sendformhdr { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000066; text-decoration: none; } .sendformtxt { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: normal; color: #000066; text-decoration: none; } .sendformfield { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000066; text-decoration: none; } ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/end.txt ================================================ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_airaggression.htm ================================================ ColdCore(TM)/AIR AGGRESSION

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Nokia
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

AIR AGGRESSION

Eight alien monsters took control over all Earth's war-planes to enslave our planet. You were able to keep one plane from being captured and now you have got a chance to keep mankind free.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_airboil.htm ================================================ ColdCore(TM)/AIR BOIL

OWNER:

PUBLICATION DATE:
2005

DEVICES:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

AIR BOIL

In 2050, the remote planet with very low gravitation had been found. Inhabitants of the planet have been enslaved by four huge machine like aliens. The democratic Earth couldn’t reconcile with such state and a space shuttle had delivered to this planet a super agent John Petroff who had been dumped on a surface of the planet together with a bicycle and a rocket mount for prompting democracy and bridges of friendship. So, the task of a player is to pass 20 game levels and to destroy all flying objects on levels.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 

2.5$
 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_aneks_ny2006.htm ================================================ ColdCore(TM)/The collection 'New Year's jokes'

OWNER:

PUBLICATION DATE:
2005

DEVICES:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
6230i, 8800
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
6600, 6620
6630
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
D108, S100, S105, X400, X426, X427, X430
E400, S200, S208
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608
E105, E315, E316, E317, E710, E715, P400, P510, P518, X427M, X450, X458, X475
E217, E335, E635, X640
C200, C207, C208, C225, E600, E608, X105
D410, D415, D418, P207, P777
E300, E310, E810, X480
X120, X140
E610, E618, P730, P735
D500, D508, E730
E530, E620, E720, E880
D600
Z105, Z107
Z110
Z130
Z140, Z300, Z500

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

The collection 'New Year's jokes'

The application is a collection of jokes, the jokes are sorted on themes. The collection included 60 jokes.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 

2.5$
 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_blazinggears.htm ================================================ ColdCore(TM)/BLAZING GEARS

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

BLAZING GEARS

You are a driver of a sport car and your task is to pass loops for a limited time. You have to avoid collisions with other cars on the road.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_caspianmonster.htm ================================================ ColdCore(TM)/CASPIAN MONSTER

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Nokia
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

CASPIAN MONSTER

You are a pilot of a secret soviet airfoil boat, which is armed with missiles and a quick-firer. Your main objective is to leave the enemy base destroying as much military equipment as possible.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_castleassault.htm ================================================ ColdCore(TM)/CASTLE ASSAULT

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

CASTLE ASSAULT

You are the commander of a catapult crew and your task is to destroy two vertical neighbor parts of the castle wall with a missile. The wall can be destroyed top-down only. Left altimeter shows current altitude of the missile. You have to be careful because the enemy throws its missiles over the wall. You can't fire until the catapult has been charged.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_cockroach.htm ================================================ ColdCore(TM)/COCKROACH

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

COCKROACH

You are driving a running cockroach in the maze and your task is as soon as possible to find a way out of the maze. There are a lot of scattered eatable things in the maze they increase and decrease game scores, so the game scores are decreased with time.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_coconutsfall.htm ================================================ ColdCore(TM)/COCONUTS FALL

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

COCONUTS FALL

You are a monkey and hunters want to catch you. Your task is to save own freedom as long as possible. You can use coconuts to knock men and you have to be careful because a helicopter tries to catch you with a net.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_conecone.htm ================================================ ColdCore(TM)/CONE! CONE!

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

CONE! CONE!

You are a squirrel defending your supplies against crows. You can throw cones at them but be careful because you should keep a distance from a crow.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_copterbomber.htm ================================================ ColdCore(TM)/COPTER BOMBER

OWNER:

PUBLICATION DATE:
2006

DEVICES:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

COPTER BOMBER

You are a pilot of a top secret copter-bomber and your task is to destroy all enemy ground targets. You must avoid collisions with flying enemies.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_drunkman.htm ================================================ ColdCore(TM)/TIPPLER

OWNER:

PUBLICATION DATE:
2006

DEVICES:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

TIPPLER

A mobile version of the TIPPLER card game. You can select one from three opponents and to play with it for undressing.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_firingline.htm ================================================ ColdCore(TM)/FIRING LINE

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

FIRING LINE

You are the defender of the docking tunnel of your spaceship from space creatures. Don’t allow them to approach to you! Fire! Fire!

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_fisher.htm ================================================ ColdCore(TM)/FISHER

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

FISHER

You are a fisher and have to catch as many as possible fishes. Take care of big predatory fishes, they break your fishing-line.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_fruitmania.htm ================================================ ColdCore(TM)/FRUITMANIA

OWNER:

PUBLICATION DATE:
2005

DEVICES:
Nokia
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
v300, v500, v600, v535, v550, v620, E398, E375, v3

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

FRUITMANIA

A mobile version of well-known casino game enables to make bet from real casino account and to play via internet from your mobile devices. You can win real money with the game.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_hardday.htm ================================================ ColdCore(TM)/HARD DAY

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

HARD DAY

You are a courier in a big company and your task is to deliver documents inside of an office. All white folders must be delivered to recipients as soon as possible. Remember, your manager will be very angry if meet you without a folder.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_hunt.htm ================================================ ColdCore(TM)/HUNT

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

HUNT

You are a brave hunter and your task is to kill as many as possible animals by 20 bullets. If you have missed 20 animals, one your bullet will be removed.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_icegifts.htm ================================================ ColdCore(TM)/ICE GIFTS

OWNER:

PUBLICATION DATE:
2006

DEVICES:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

ICE GIFTS

Help Santa to send all XMas gifts. Combine their identical parties and do not suppose absence of empty ice-holes for new gifts.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_ironstream.htm ================================================ ColdCore(TM)/IRON STREAM

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

IRON STREAM

Warning! Warning! The enemy has dashed our protection line and marching into a populated area! Your tank is our only hope in the area and your duty is to defend it. You have to destroy as many enemy tanks as possible but keep buildings untouched.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_kalah.htm ================================================ ColdCore(TM)/KALAH

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Nokia
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

KALAH

A mobile version of the well known KALAH game. The object of the game is to move as many stones as possible into your KALAH (right bowl).

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_kickkick.htm ================================================ ColdCore(TM)/KICK! KICK!

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

KICK! KICK!

You drive footballers fixed on a pivot. Your task is to defend own goal and to kick as many balls as possible into the opponent’s goal.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_lifesaver.htm ================================================ ColdCore(TM)/LIFESAVER

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LIFESAVER

Fire! Fire! Fire has occupied the ground level! You are the chief of a fire brigade and must not let the fire to occupy all building; you can use a water cannon. Hopeless men jump from windows and you have to catch them.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_livebridge.htm ================================================ ColdCore(TM)/LIVE BRIDGE

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LIVE BRIDGE

You are a porter and your task is to carry cargo from the left riverside to the right riverside but there is not any bridge on the river so you use turtles as a live bridge. Unfortunately it is dangerous to use turtles as a bridge because they catch fishes and dive in the depth from time to time.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_mobilechase.htm ================================================ ColdCore(TM)/MOBILE CHASE

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Nokia
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

MOBILE CHASE

You are a brave policeman who has received the message about a bank robbery. Your have to overtake the gangsters and stop their van.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_mobilesheriff.htm ================================================ ColdCore(TM)/MOBILE SHERIFF

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

MOBILE SHERIFF

You are a brave sheriff of Wild West who is releasing a small town from a band. The number of the bandits is known but you don’t know their faces so you must be careful because there are a lot of inhabitants in the town and you must not kill them (we recommend you to wait an unkind action and don’t shoot before).

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_mtvpaparazzo.htm ================================================ ColdCore(TM)/PAPARAZZO

OWNER:

PUBLICATION DATE:
2005

DEVICES:
Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

PAPARAZZO

You are a paparazzo and your task to get as many photos of celebrities as possible.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_mtvpillow.htm ================================================ ColdCore(TM)/PILLOW

OWNER:

PUBLICATION DATE:
2005

DEVICES:
Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

PILLOW

You're a visitor of MTV office and your task is to belabour music stars by a pillow.You can find new pillows in rooms.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_mtvpuzzle.htm ================================================ ColdCore(TM)/MTV PUZZLE

OWNER:

PUBLICATION DATE:
2005

DEVICES:
Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

MTV PUZZLE

Your task is to collect a full image with moved squares.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_mtvstage.htm ================================================ ColdCore(TM)/HOLD OUT ON THE STAGE

OWNER:

PUBLICATION DATE:
2005

DEVICES:
Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

HOLD OUT ON THE STAGE

You are a rock-star and your worshipper throw different things on your stage.You have to avoid collision with bad things and catch flowers.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_nimble.htm ================================================ ColdCore(TM)/NIMBLE

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

NIMBLE

You are an airport loader and your task is to sort baggage. You have to take color bags and place them on the conveyer having the same color as the bag. Bags should not overload conveyers.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_opthunderclap.htm ================================================ ColdCore(TM)/OPERATION THUNDERCLAP

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

OPERATION THUNDERCLAP

You are a pilot of a military copter and your task is to kill as many as possible enemy copters.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_oysterbank.htm ================================================ ColdCore(TM)/OYSTER BANK

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

OYSTER BANK

You are a diver gathering pearls. You should collect as many pearls as possible. You have to avoid collisions with a shark. The oxygen cylinder is limited so you have to look after its level.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_papaninsquest.htm ================================================ ColdCore(TM)/PAPANIN'S QUEST

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Nokia
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

PAPANIN'S QUEST

Ivan Papanin, the well-known Polar researcher, discovered an ancient Egyptian pyramid lost in the Antarctic ice. When examining the pyramid, he fell down and found himself inside of it. You have to help Papanin to find the way out of this terrible maze. The object of the game is to collect all magic stones in the maze to get the key that opens the door to the next level. You can use a pick to make holes in the floor. Swords scattered on the level will help you to fight with monsters. Be careful, after some period of time the destroyed monsters reappear. If you need to restore your life power, drink some water from a jar. But all these items can be used only once.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_ravenscheese.htm ================================================ ColdCore(TM)/RAVEN'S CHEESE

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

RAVEN'S CHEESE

You drive a fox and your task to catch cheeses that throwed by ravens.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_searoad.htm ================================================ ColdCore(TM)/SEA ROAD

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

SEA ROAD

You are a driver of a speedboat and your task is to pass as many gates as possible during limited time. You should avoid collisions with other ships.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_searovers.htm ================================================ ColdCore(TM)/SEA ROVERS

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

SEA ROVERS

You are a pirate hunting for cargo ships. When you have damaged a cargo ship (it has three-cornered sail), you should stop own ship near it to enable your crew to rob the ship. You have to avoid collisions with battleships. Good luck, captain!

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_slider_alpop.htm ================================================ ColdCore(TM)/Slider 'Aleosha Popovich'

OWNER:

PUBLICATION DATE:
2005

DEVICES:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
6230i, 8800
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
X100, X108, X600, X608
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

Slider 'Aleosha Popovich'

The slide-show contains 10 frames (with texts) from the cartoon film "Aleosha Popovich and Toogarin Zmey". You can view the frames in both automatic and manual modes as well you can magnify selected frame and consider it.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_smashingkick.htm ================================================ ColdCore(TM)/SMASHING KICK

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

SMASHING KICK

You are a training footballer and your task is to kick as many as possible balls into the goal. You have to keep the ball in the air with your foots and head.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_smscat.htm ================================================ ColdCore(TM)/SMS Catalog

OWNER:

PUBLICATION DATE:
2005

DEVICES:
Nokia
3410
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
6230i, 8800
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M(T)50, C55, C56, CT56, 6688i, M46, 3118
SL45i
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

SMS Catalog

The mobile catalog enables to a user to look through contents of a mobile content provider's base and to order liked content with automatically generated SMS (if the device is supporting). The application supports three SMS schemes: Siemens, Samsung and WMA. The application enables to organize complicated tree-structured catalogs. It can be started on any device supports MIDP-1.0 or older.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_spiders.htm ================================================ ColdCore(TM)/SPIDERS

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

SPIDERS

You are an ant bringing twigs into own anthill. You should bring as many twigs as possible and to avoid clutches of spiders.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_starharbor.htm ================================================ ColdCore(TM)/STAR HARBOR

OWNER:

PUBLICATION DATE:
2005

DEVICES:
Nokia
3410
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M(T)50, C55, C56, CT56, 6688i, M46, 3118
SL45i
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

STAR HARBOR

A terrible invasion threatens the Earth.A player is a gunner of a star cruiser gun and your task is to stop the invasion.You have to destroy both cruisers and fighters.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 

2.5$
 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_strangehunt.htm ================================================ ColdCore(TM)/STRANGE HUNT

OWNER:

PUBLICATION DATE:
2006

DEVICES:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

STRANGE HUNT

You have come on military range but do not surrender! Shoot as many as possible ducks and wild boars!

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_tastydish.htm ================================================ ColdCore(TM)/TASTY DISH

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

TASTY DISH

You are a crocodile living in a river. Your task is to catch as many animals on the beach as possible. Time to time the hunter visits the beach and attempts to kill you with a gun.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_vineyard.htm ================================================ ColdCore(TM)/VINEYARD

OWNER:

PUBLICATION DATE:
2006

DEVICES:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

VINEYARD

Gather grapes and put its into mollies, you must collect all grapes to pass a game level. You must avoid collisions with snails!

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_waterway.htm ================================================ ColdCore(TM)/WATER WAY

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

WATER WAY

You are an ant collecting dew for its ant heap. Your task is to catch drops with a leaf and pour out it in the flower of your workmate. Remember, the leaf can contain one drop only.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_wildballs.htm ================================================ ColdCore(TM)/WILD BALLS

OWNER:

PUBLICATION DATE:
2004

DEVICES:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

WILD BALLS

You should clear as many as possible pins with own balls. You must use a rolling ball to clear pins; you have to direct the ball at a pin with your ball. If you miss, your ball will be lost.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/gpage_wildroad.htm ================================================ ColdCore(TM)/WILD ROAD

OWNER:

PUBLICATION DATE:
2006

DEVICES:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

WILD ROAD

Break away from persecutors, do not allow them to destroy your car or to jump on it. Pick up jerricans because fuel constantly drips out through the raked tanks.

The form enables you to send us your opinion, wish or problem description for the application. It's very important for us!
Name:

E-mail:
Message:

 PURCHASE 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu1_about.htm ================================================ ColdCore/ABOUT
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu1_contacts.htm ================================================ ColdCore/CONTACTS
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu1_job.htm ================================================ ColdCore/JOB
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu1_news.htm ================================================ ColdCore/NEWS
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu1_partnership.htm ================================================ ColdCore/PARTNERSHIP
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu2_all.htm ================================================ ColdCore/GAMES/ALL
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu2_arcade.htm ================================================ ColdCore/GAMES/ARCADE
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu2_clientserver.htm ================================================ ColdCore/GAMES/CLIENT-SERVER
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu2_erotic.htm ================================================ ColdCore/GAMES/EROTIC
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu2_fighting.htm ================================================ ColdCore/GAMES/FIGHTING
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu2_gambling.htm ================================================ ColdCore/GAMES/GAMBLING
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu2_logic.htm ================================================ ColdCore/GAMES/PUZZLE
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu2_multiplayer.htm ================================================ ColdCore/GAMES/MULTIPLAYER
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu2_quest.htm ================================================ ColdCore/GAMES/QUEST
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu2_racing.htm ================================================ ColdCore/GAMES/RACING
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu2_shooter.htm ================================================ ColdCore/GAMES/SHOOTER
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu2_sport.htm ================================================ ColdCore/GAMES/SPORT
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/menu3_appsall.htm ================================================ ColdCore/APPLICATIONS/ALL
ColdCore(R)
 
Buy a bit of Game(TM)

ENG

 
Papanin's quest
The Papanin's quest game for Nokia Series 60 has been available on Playmobile.
read more...
Mobile chase
Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile.
read more...
Air aggression
The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile.
read more...
Caspian monster
The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile.
read more...
Kalah
The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile
read more...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/send_error.html ================================================ I can't deliver the message.

I can't deliver the message. May be the server has troubles, if it is possible resend the message later. Thank you.
 
================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/eng/send_ok.html ================================================ Your message has been delivered successfully.

Your message has been delivered successfully. Thank you very much!
 
================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/games/games2003_2006.html ================================================ Old mobile games (august 2003-march 2006)

Old mobile games (august 2003 - march 2006)

Summary team at the period

Producing: Arteom Litvinov, Igor Maznitsa
Project management: Igor Maznitsa
Project coordination: Aleksey Goryachev
Game design: Aleksey Goryachev, Igor Maznitsa
Level design: Aleksey Goryachev
Programming: Alexander Vasiliev, Denis Parinov, Sergey Kuligin, Denis Rozhnev, Igor Maznitsa
Art: Svetlana Semenova, Andrey Diakov, Dmitriy Semenov, Igor Maznitsa
Sound: Igor Maznitsa
Testing: Aleksey Goryachev


-----------------------------

1. Papanin's quest

-----------------------------

2. Air Aggression

-----------------------------

3. Kalah

-----------------------------

4. Mobile chase

-----------------------------

5. Caspian monster

-----------------------------

6. Hunt

-----------------------------

7. Raven's cheese

-----------------------------

8. Sea road

-----------------------------

9. Blazing gears

-----------------------------

10. Castle assault

-----------------------------

11. Cockroach

-----------------------------

12. Coconuts fall

-----------------------------

13. Cone! Cone!

-----------------------------

14. Firing line

-----------------------------

15. Fruit mania

-----------------------------

16. Hard day

-----------------------------

17. Ice gifts

-----------------------------

18. Iron stream

-----------------------------

19. Kick Kick

-----------------------------

20. Lifesaver

-----------------------------

21. Live bridge

-----------------------------

22. Mobile sheriff

-----------------------------

23. Paparazzo

-----------------------------

24. Pillow war

-----------------------------

25. MTV Puzzle

-----------------------------

26. Scene

-----------------------------

27. Nimble

-----------------------------

28. Operation "Thunderclap"

-----------------------------

29. Oyster bank

-----------------------------

30. Sea rovers

-----------------------------

31. Smashing kick

-----------------------------

32. Spiders

-----------------------------

33. Star harbor

-----------------------------

34. Strange Hunt

-----------------------------

35. Tasty dish

-----------------------------

36. Vineyard

-----------------------------

37. Waterway

-----------------------------

38. Wild balls

-----------------------------

39. Wild road

-----------------------------

40. Copter bomber

-----------------------------

41. Drunkman

-----------------------------

42. Fisher

-----------------------------

43. Air boil

 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/index.htm ================================================ ColdCore� official site
Cold Core�
================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/loadpages/muzon_AirBoil.htm ================================================ Java-����: Air Boil
Air Boil



���
5008485
��� ��������?

�������� ����� SMS-���������.

� ������ ��������� ������� 5008485

��������� SMS-��������� � ����� �� ��������� ����� ������ ���������:
�������� ������ � ������� ��������� �����
������-����� 9998
��������, �������, ������, �����, ��������, ������, ������, ������ ��������, �����������, ��������, �����, �����, ������, �������, ��������, ������, �����, ����, ������, ���������, ��������� 9998
������-����� 9998
������ � ���������� �������, ������, ��������, �������, ������, ��������, ������, ��������, �����, ����, ���������, ��������, �������, �����, ������, ����, ������, �����-���������, �������� ������ ��������, �������, ���, ���������, ������, ���������, ������, �����, ������-���, ������� ���������, ���������, ���������, ������ �� ����, ������ �������, �������, ��������� �����������, �������, ��������, ����������, ��������, ����, �����, �����-������� ������������, ���������, ������ 9998

��������� �������� SMS-��������� �� ��������� ����� ��������� ���������� $2,50 ��� ����� �������.

����� ��������� ������ �� �������� WAP-������,
������� ���������� ��������������
(�������� ���������� � ������ ��������).

�������������� ��������:
Motorola: C380, C650, v220, v180, v300, v500, v600, v535, v550, v620, E398, E375, v3
Nokia: 3510i, 7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i, 6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270, 3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD, 7610, 6260, 6670, 3230
Samsung: C100, C108T, C110, S300, S300M, S307, E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468, X100, X108, X600, X608
Siemens: M55, C60, MC60, S55, SL55, S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65, C65, SL65
LG: G1600
Sony Ericsson: T610, T616, T618, T628, T630, T637, Z600, Z608


================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/loadpages/muzon_StarHarbor.htm ================================================ Java-����: Star Harbor
Star Harbor



���
5006971
��� ��������?

�������� ����� SMS-���������.

� ������ ��������� ������� 5006971

��������� SMS-��������� � ����� �� ��������� ����� ������ ���������:
�������� ������ � ������� ��������� �����
������-����� 4012
��������, �������, ������, �����, ��������, ������, ������, ������ ��������, �����������, ��������, �����, �����, ������, �������, ��������, ������, �����, ����, ������, ���������, ��������� 4012
������-����� 4012
������ � ���������� �������, ������, ��������, �������, ������, ��������, ������, ��������, �����, ����, ���������, ��������, �������, �����, ������, ����, ������, �����-���������, �������� ������ ��������, �������, ���, ���������, ������, ���������, ������, �����, ������-���, ������� ���������, ���������, ���������, ������ �� ����, ������ �������, �������, ��������� �����������, �������, ��������, ����������, ��������, ����, �����, �����-������� ������������, ���������, ������ 4012

��������� �������� SMS-��������� �� ��������� ����� ��������� ���������� $2,50 ��� ����� �������.

����� ��������� ������ �� �������� WAP-������,
������� ���������� ��������������
(�������� ���������� � ������ ��������).

�������������� ��������:
Motorola: C380, C650, v220, v180, v300, v500, v600, v535, v550, v620, E398, E375, v3
Nokia: 3410, 3510i, 7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i, 6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270, 3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD, 7610, 6260, 6670, 3230
Samsung: C100, C108T, C110, S300, S300M, S307, E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468, X100, X108, X600, X608
Siemens: M(T)50, C55, C56, CT56, 6688i, M46, 3118, SL45i, M55, C60, MC60, S55, SL55, S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65, C65, SL65
LG: G1600
Sony Ericsson: T610, T616, T618, T628, T630, T637, Z600, Z608


================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_airaggression.htm ================================================ ColdCore(TM)/AIR AGGRESSION

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Nokia
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

AIR AGGRESSION

У землян очередная напасть — 8 инопланетных монстров захватили власть над всеми самолетами планеты и только ваш самолет чудом избежал их влияния. Ваша задача уничтожить всех восьмерых монстров, принявших образы гигантских самолетов, и вернуть планете мир и спокойствие. Управляя маленьким самолетиком на экране, следует избегать столкновения с другими самолетами, избегать попаданий и брать бонусы и оружие, которое доставляется вертолетом поддержки.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_airboil.htm ================================================ ColdCore(TM)/AIR BOIL

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2005

УСТРОЙСТВА:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

AIR BOIL

В 2050 году, была обнаружена отдаленная планета с очень низкой гравитацией. Жители этой планеты оказались порабощены четырьмя огромными машиноподобными пришельцами. Демократическая Земля не смогла смириться с таким состояниейм дел и космический шаттл доставил на эту планету суперспецназовца Джона Петрова, который и был сброшен на поверхность планеты вместе с велосипедом и ракетной установкой для наведения демократии и мостов дружбы. Итак, задача играющего - пройти 20 уровней уничтожая различную летающую нечисть и уклоняясь от метеоритных дождей, весьма частых на этой планете. Игровые попытки можно пополнять, подбирая падающие пропеллеры, а патроны прилетают на воздушных шарах.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 

2.5$
 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_aneks_ny2006.htm ================================================ ColdCore(TM)/The collection 'New Year's jokes'

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2005

УСТРОЙСТВА:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
6230i, 8800
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
6600, 6620
6630
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
D108, S100, S105, X400, X426, X427, X430
E400, S200, S208
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608
E105, E315, E316, E317, E710, E715, P400, P510, P518, X427M, X450, X458, X475
E217, E335, E635, X640
C200, C207, C208, C225, E600, E608, X105
D410, D415, D418, P207, P777
E300, E310, E810, X480
X120, X140
E610, E618, P730, P735
D500, D508, E730
E530, E620, E720, E880
D600
Z105, Z107
Z110
Z130
Z140, Z300, Z500

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

The collection 'New Year's jokes'

Приложение является сборником новогодних анекдотов, рассортированных по темам. В сборник вошло 60 анекдотов.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 

2.5$
 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_blazinggears.htm ================================================ ColdCore(TM)/BLAZING GEARS

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

BLAZING GEARS

Вы водитель автомашины, участвующей в гонках без правил. На прохождение каждого этапа гонок вам дается ограниченное время. Двигайтесь на максимальной скорости, но постарайтесь не сталкиваться с другими машинами!

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_caspianmonster.htm ================================================ ColdCore(TM)/CASPIAN MONSTER

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Nokia
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

CASPIAN MONSTER

Террористы похитили секретный экраноплан «Каспийский монстр», вооруженный самым современным оружием, но вам удалось проникнуть на их базу и угнать экраноплан. Ваша задача пройти три участка от базы к открытому морю, нашпигованных вражеской техникой и минами.Вооружение состоит из автоматической пушки и двух видов ракет, самонаводящихся и неуправляемых. Самонаводящиеся ракеты автоматически выбирают цель и рассчитывают свою траекторию, а неуправляемые летят по курсу экраноплана и очень полезны для разрушения мостов.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_castleassault.htm ================================================ ColdCore(TM)/CASTLE ASSAULT

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

CASTLE ASSAULT

Вы управляете катапультой и должны разрушить два соседних участка стены осажденного замка. Дождитесь зарядки катапульты и следите за указателем высоты прицеливания. Стену можно разрушить только сверху вниз. Но берегитесь вражеских камней летящих из-за стены!

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_cockroach.htm ================================================ ColdCore(TM)/COCKROACH

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

COCKROACH

Игрок управляет тараканом, ползающим в лабиринте из труб и его задача найти выход из лабиринта. В лабиринте разбросаны различные съедобные предметы, некоторые таракан может есть безболезненно, некоторые отнимают очки и время.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_coconutsfall.htm ================================================ ColdCore(TM)/COCONUTS FALL

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

COCONUTS FALL

Игрок управляет обезьяной, спасающейся на верхушках пальм от карабкающихся по ним человечков. Обезьяна может бросать в человечков собранные на пальмах кокосы и должна прятаться от пролетающего над пальмами вертолета.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_conecone.htm ================================================ ColdCore(TM)/CONE! CONE!

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

CONE! CONE!

Игрок управляет белкой, защищающей от ворон спрятанные в дуплах дерева запасы. Белка прыгает по ветвям, собирает шишки и бросает их по воронам, садящимся на ветви.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_copterbomber.htm ================================================ ColdCore(TM)/COPTER BOMBER

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2006

УСТРОЙСТВА:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

COPTER BOMBER

Вы пилот секретного вертолета-бомбардировщика, уничтожьте все вражеские цели и не сталкивайтесь с воздушным противником.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_drunkman.htm ================================================ ColdCore(TM)/TIPPLER

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2006

УСТРОЙСТВА:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

TIPPLER

Мобильная версия карточной игры ПЬЯНИЦА. Игра на раздевание с тремя противниками.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_firingline.htm ================================================ ColdCore(TM)/FIRING LINE

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

FIRING LINE

Игрок - защитник стыковочного шлюза, в который лезут инопланетные твари. Задача - настрелять как можно больше тварей, прежде чем их поток захлестнет станцию.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_fisher.htm ================================================ ColdCore(TM)/FISHER

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

FISHER

Игрок выступает в роли рыбака и его задача наловить как можно больше рыбы при ограниченном количестве крючков (игровых попыток). В воде плавают рыбы, которых можно ловить и хищники, которые могут перекусывать леску, при этом игрок теряет одну попытку. Игрок может управлять глубиной погружения крючка, разматывая леску или поднимая удочку.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_fruitmania.htm ================================================ ColdCore(TM)/FRUITMANIA

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2005

УСТРОЙСТВА:
Nokia
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
v300, v500, v600, v535, v550, v620, E398, E375, v3

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

FRUITMANIA

Мобильная версия известного автомата "Однорукий бандит", позволяющая делать ставку с реального счета в казино и осуществлять игру через интернет с мобильного телефона, выигрывая реальные деньги.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_hardday.htm ================================================ ColdCore(TM)/HARD DAY

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

HARD DAY

Вы управляете курьером, который должен доставлять документы внутри офиса. Все белые папки должны быть доставлены нетерпеливым получателям как можно быстрее. Помните, ваш директор будет очень зол, если встретит вас шатающимся без дела!

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_hunt.htm ================================================ ColdCore(TM)/HUNT

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

HUNT

Игрок выступает в роли охотника и в начале игры ему дается 20 патронов. Он должен настрелять как можно больше животных. При пропуске без единого выстрела 20 животных, у игрока снимается один патрон. Частота появления зверей на экране возрастает с течением игрового процесса. За каждое убитое животное, игроку начисляется определенное количество игровых очков. При наведении прицела на бегущее животное, оно останавливается (кроме вороны) и отрабатывается анимация страха, животное стоит под прицелом, пока игрок не выстрелит или не уберет прицел.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_icegifts.htm ================================================ ColdCore(TM)/ICE GIFTS

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2006

УСТРОЙСТВА:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

ICE GIFTS

Помоги деду Морозу отправить все Новогодние подарки. Совмещай их одинаковыми сторонами и не допускай отсутствия пустых прорубей для новых подарков.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_ironstream.htm ================================================ ColdCore(TM)/IRON STREAM

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

IRON STREAM

Внимание! Внимание! Враг прорвал нашу оборону и входит в населенный район! Ваш танк единственная наша надежда в этом районе и Ваша святая обязанность защитить его. Вы должны уничтожить, как можно больше вражеских танков, но при этом сохранить в целости постройки.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_kalah.htm ================================================ ColdCore(TM)/KALAH

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Nokia
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

KALAH

Мобильная версия известной логической игры Kalah. Задача игрока собрать как можно больше камней в свой калах (правая ложбинка на игровом поле). При очередном ходе играющий снимает с одного из своих полей все камни и распределяет их по одному на последующие поля в порядке возрастания их номеров; полем, следующим за шестым, считается свой калах. Далее камни распределяются по чужим полям (опять-таки в порядке возрастания их номеров), затем вновь по своим (чужой калах пропускается) и так далее, как бы совершая обход полей против часовой стрелки. Если последний из распределяемых камней попал в «свой» калах, то игрок делает еще один ход. Во всех остальных случаях очередь хода передается противнику. Если последний камень попал на пустое поле игрока, совершавшего ход, а на противоположном поле соперника есть хотя бы один камень, то содержимое обоих полей переносится в КАЛАХ игрока, совершавшего ход (после чего, ход переходит к его противнику). Если на полях игрока, сделавшего ход, не остается ни одного камня, то все камни, находящиеся на полях противника, переносятся в калах противника, и игра заканчивается. Игра заканчивается, когда одному из противников нечем ходить. Выигрывает тот, у кого по окончании игры в калахе оказалось больше камней. Если в обоих калахах находится по 36 камней, фиксируется ничья.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_kickkick.htm ================================================ ColdCore(TM)/KICK! KICK!

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

KICK! KICK!

Игра по мотивам настольной игры. Игрок управляет тремя футболистами, закрепленными на одном вращающемся стержне. Необходимо пробить защиту соперника и забить мяч в его ворота.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_lifesaver.htm ================================================ ColdCore(TM)/LIFESAVER

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LIFESAVER

Игрок выступает в роли руководителя пожарной команды и его задача спасти как можно больше жителей из горящего дома. Изначально горит первый этаж дома, с течением времени огонь охватывает следующие этажи здания, управляя пожарниками, игрок может тушить этажи, исключая первый. С последнего этажа прыгают люди и игрок должен, управляя пожарными, успевать ловить их на брезент. При смерти одного прыгнувшего, снимается одна попытка играющего, так же попытка снимается при полном сгорании здания.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_livebridge.htm ================================================ ColdCore(TM)/LIVE BRIDGE

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LIVE BRIDGE

Игрок управляет носильщиком, переправляющим через реку грузы. Через реку можно переправиться только по плавающим в ней черепахам, ныряющим время от времени за рыбками, всплывающими со дна.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_mobilechase.htm ================================================ ColdCore(TM)/MOBILE CHASE

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Nokia
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

MOBILE CHASE

Игрок должен нагнать фургон преступников и стреляя в него, заставить его остановиться. При этом надо объезжать препятствия на дороге и избегать столкновения с другими участниками дорожного движения. Так же следует избегать луж, так как они делают автомобиль неуправляемым.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_mobilesheriff.htm ================================================ ColdCore(TM)/MOBILE SHERIFF

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

MOBILE SHERIFF

Игрок управляет шерифом, освобождающим маленький техасский город от банды. Число бандитов известно, но в лицо их никто не знает. Игрок должен отличить бандитов от мирных горожан и уничтожить бандитов. В проемах окон и дверей периодически появляются и прячутся человечки. Человечки могут быть мирными горожанами или бандитами. Бандит внешне отличается только тем, что начинает стрелять в шерифа. Игрок может стрелять первым, рискуя убить горожанина или ждать пока по нему не начнут стрелять бандиты. Бандит делает разное число выстрелов, но убить шерифа может только третьим выстрелом подряд. Игрок должен успеть за это время прицелиться и выстрелить. Убив мирного горожанина, игрок теряет одну игровую попытку. Убив бандита, игрок получает очки.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_mtvpaparazzo.htm ================================================ ColdCore(TM)/PAPARAZZO

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2005

УСТРОЙСТВА:
Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

PAPARAZZO

Вы должны фотографировать лица знаменитостей шоу-бизнеса,имеющих знак 'звезды' и избегать охранников в окнах. Ваше время и число кадров-ограничены.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_mtvpillow.htm ================================================ ColdCore(TM)/PILLOW

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2005

УСТРОЙСТВА:
Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

PILLOW

Ты ходишь по офису MTV и дубасишь всех подушкой.Опасайся охранников с дубинками.Заходи в двери,там могут быть подушки.Лови сердца-это жизни.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_mtvpuzzle.htm ================================================ ColdCore(TM)/MTV PUZZLE

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2005

УСТРОЙСТВА:
Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

MTV PUZZLE

Ваша задача-передвигая квадратики,собрать изначальную картинку за минимальное количество ходов. Имеется три уровня сложности поля: 3х3,4х4 и 5х5.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_mtvstage.htm ================================================ ColdCore(TM)/HOLD OUT ON THE STAGE

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2005

УСТРОЙСТВА:
Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

HOLD OUT ON THE STAGE

Вы должны продержаться на сцене определенное время,уворачиваясь от града опасных предметов,летящих из зала.Ловите только цветы ваших фанатов и зарабатывайте этим очки.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_nimble.htm ================================================ ColdCore(TM)/NIMBLE

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

NIMBLE

Игрок управляет рабочим в аэропорту, который должен разобрать перепутанный багаж на лентах транспортера до того как транспортеры переполнятся.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_opthunderclap.htm ================================================ ColdCore(TM)/OPERATION THUNDERCLAP

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

OPERATION THUNDERCLAP

Игрок выступает в роли пилота боевого вертолета, в задачу которого входит уничтожение как можно большего количества вертолетов противника. Вертолеты противника случайным образом появляются на экране и перемещаются по различным траекториям. Уничтожение вертолета противника осуществляется путем наведения на него прицела и нажатия на гашетку (кнопка «Огонь»). Некоторые противники так же могут вести огонь по игроку, вертолет игрока уничтожается, если стреляющий противник не будет своевременно уничтожен. За каждого уничтоженного противника начисляются 10 игровых очков.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_oysterbank.htm ================================================ ColdCore(TM)/OYSTER BANK

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

OYSTER BANK

Игрок управляет ныряльщиком, охотящимся за жемчужинами на морском дне. Игрок должен направлять ловца к тем раковинам, которые открыты, следить за его запасом кислорода и беречь от акул

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_papaninsquest.htm ================================================ ColdCore(TM)/PAPANIN'S QUEST

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Nokia
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

PAPANIN'S QUEST

Путешественник Папанин обнаружил египетскую пирамиду, затерянную во льдах Антарктики. При осмотре он провалился в расщелину и оказался внутри. Задача игрока — помочь Папанину выбраться наружу, преодолев 10 игровых уровней. Чтобы пройти игровой уровень, требуется собрать все бриллианты, расположенные в лабиринте, после чего появляется ключ, которым можно открыть дверь на следующий уровень. В прохождении лабиринтов, игроку мешают различного вида монстры, с которыми игрок может бороться при помощи мечей, разбросанных по уровню. Жизни можно восстановить при помощи кувшина с водой, а некоторые участки пола можно пробивать при помощи кирки.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_ravenscheese.htm ================================================ ColdCore(TM)/RAVEN'S CHEESE

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

RAVEN'S CHEESE

Игрок выступает в роли лисы, ловящей куски сыра, бросаемого воронами. Задача игрока наловить как можно больше кусков сыра. Игра не имеет ограничения по времени, но имеет ограничение по максимальному количеству пропущенных сыров. На ветвях деревьев появляются вороны с сыром в клюве, игрок должен угадать момент броска сыра и поставить лису в позицию, при которой сыр будет брошен ей в пасть. Всего имеется четыре положения лисы. Игроку следует учитывать, что лиса не может постоянно стоять на задних лапах и через какое то время опускается. Если ворона доходит до края ветки, а лиса не готова поймать сыр, то раздается карканье и сыр падает на землю. С края экрана выбегает мышь и уносит кусок сыра, при этом у игрока забирается одна попытка. Скорость появления ворон со временем увеличивается, но при достижении игроком количества очков кратного 50, количество попыток игрока восстанавливается. Выигрышная картинка будет показана игроку при набранном количестве сыров не меньше 100. При достижении количества очков кратного 50, скорость появления ворон уменьшается.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_searoad.htm ================================================ ColdCore(TM)/SEA ROAD

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

SEA ROAD

Игрок управляет спортивным катером, принимающим участие в слаломе на оживленном морском пути. Двигаясь по дистанции, игрок должен проходить через встречные ворота, время прохождения которых влияет на зарабатываемые очки.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_searovers.htm ================================================ ColdCore(TM)/SEA ROVERS

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

SEA ROVERS

Игрок управляет пиратским парусным кораблем и должен захватывать торговые корабли, избегая встречи с военными кораблями. Все корабли вооружены и делятся на торговые, военные и прочие (боты). Корабли отличаются также количеством энергии и, соответственно, числом бортовых залпов, необходимых для их потопления. Игрок должен нападать на торговые корабли и опасаться военных, которые могут дать отпор. Прочие корабли также могут быть мишенью для пушек пиратского корабля, но это не принесет игроку много очков.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_slider_alpop.htm ================================================ ColdCore(TM)/Slider 'Aleosha Popovich'

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2005

УСТРОЙСТВА:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
6230i, 8800
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
X100, X108, X600, X608
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

Slider 'Aleosha Popovich'

Слайдер содержит 10 кадров мультфильма с текстом к каждому кадру. Есть возможность просмотра кадров как в ручном так и в автоматическом режиме. Можно увеличивать выбранный кадр и рассматривать отдельные детали изображения.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_smashingkick.htm ================================================ ColdCore(TM)/SMASHING KICK

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

SMASHING KICK

Игрок управляет тренирующимся футболистом и его задача довести как можно больше мячей до ворот, не роняя их на землю. Тренер с уменьшающимся интервалом подает мячи и игрок, удерживая мяч в воздухе при помощи ног и головы, доводит его до ворот и забивает, попытка снимается если мяч касается земли. После 10 забитых мячей игроку восстанавливается 1 игровая попытка.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_smscat.htm ================================================ ColdCore(TM)/SMS Catalog

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2005

УСТРОЙСТВА:
Nokia
3410
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
6230i, 8800
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M(T)50, C55, C56, CT56, 6688i, M46, 3118
SL45i
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

SMS Catalog

Мобильный каталог контента, позволяющий пользователю ознакомиться с составом мобильного контента в базе контент провайдера и, если телефон имеет возможность, осуществить отправку SMS на номер провайдера с целью заказа понравившегося контента. Приложение позволяет организовывать сложную древовидную структуру каталога с включением изображений для предпросмотра, изображения могут храниться как с каталогом так и быть загруженными через сеть. Поддерживается три схемы отправки SMS: Siemens, WMA и Samsung. Язык приложения русский, при ином языке, установленном на аппарате пользователя, приложение автоматически отображает текст транслитом. Приложение динамически подстраивается под возможности аппарата и может работать на любом аппарате с платформой не ниже MIDP-1.0. Список возможностей оболочки превышает 20 пунктов.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_spiders.htm ================================================ ColdCore(TM)/SPIDERS

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

SPIDERS

Игрок управляет муравьем, который должен носить в муравейник веточки из лежащей невдалеке кучи и не стать добычей пауков, спускающихся сверху на паутине. Игрок может перемещать муравья влево/вправо. Подбежав к куче веточек, муравей взваливает одну себе на спину. Вернувшись к муравейнику, он бросает свой груз в проем и бежит за следующим. За каждую доставленную веточку игроку начисляются очки. Между муравейником и кучей веток висят на своих паутинах пауки, поджидающие добычу. Пауки быстро опускаются и медленно поднимаются по паутине. Кроме того, они передвигаются с остановками, иногда меняя после такой паузы направление движения. Если паук схватит муравья, то игрок теряет одну игровую попытку.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_starharbor.htm ================================================ ColdCore(TM)/STAR HARBOR

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2005

УСТРОЙСТВА:
Nokia
3410
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M(T)50, C55, C56, CT56, 6688i, M46, 3118
SL45i
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

STAR HARBOR

В очередной раз гадкие инопланетяне собираются попрать своими щупальцами нашу голубую планету, но они не учли того, что ,несмотря на все усилия по уклонению от воинской повинности, любитель компьютерных игр Иван Копченый был забрит в космический флот и находился среди ноющих о родном доме призывников на борту космического крейсера "Червона Украина", готовящегося к отправлению на границы солнечной системы с орбиты Земли. Неожиданное нападение пришельцев так поразило командный состав крейсера, что оно немедленно ушло в запой лечить нервы и Иван остался единственным дееспособным членом экипажа. Итак, задача игрока отразить нападение, путем тотального уничтожения атакующих сил. Игра от первого лица из разряда "Убей их всех", имеет три уровня сложности, различающиеся активностью и количеством противника.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 

2.5$
 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_strangehunt.htm ================================================ ColdCore(TM)/STRANGE HUNT

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2006

УСТРОЙСТВА:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

STRANGE HUNT

Тебя занесло на военный полигон, но не сдавайся! Несмотря на трудности, настреляй как можно больше уток и кабанов!

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_tastydish.htm ================================================ ColdCore(TM)/TASTY DISH

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

TASTY DISH

Игрок управляет крокодилом, охотящимся в реке у берега. Крокодил должен поймать свою добычу и не попасть на мушку охотника. Крокодил движется к берегу, пересекая реку, с постоянной скоростью. Игрок может только поворачивать крокодила влево/вправо, выбирая на какой участок берега напасть. Подплыв к берегу, крокодил хватает добычу, если на этом участке есть какое-либо животное, пьющее воду из реки. Игроку начисляются очки, в зависимости от ценности добычи. На месте животного может оказаться охотник, который, появившись на берегу, стреляет в крокодила, если тот находится напротив него. В этом случае крокодил погибает, а игрок теряет игровую попытку. Если на участке берега, к которому был направлен крокодил, нет добычи, то крокодил остается ни с чем и погружается обратно в воду. Для следующей попытки придется снова переплывать реку, подкрадываясь издалека. Игрок может промахнуться только 20 раз, после чего он теряет игровую попытку.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_vineyard.htm ================================================ ColdCore(TM)/VINEYARD

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2006

УСТРОЙСТВА:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

VINEYARD

Собирайте виноград и раскладывайте его в корзины, переход на следующий уровень когда все корзины заполнены. Не попадайтесь улиткам!

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_waterway.htm ================================================ ColdCore(TM)/WATER WAY

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

WATER WAY

Вы управляете муравьем, собирающим воду для муравейников. Ваша задача ловить по одной капле воды в листок и выливать ее в цветок вашего напарника-муравья. Листок может выдержать только одну каплю!

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_wildballs.htm ================================================ ColdCore(TM)/WILD BALLS

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2004

УСТРОЙСТВА:
Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

WILD BALLS

Игрок осуществляет игру в футуристические кегли и его задача выбить как можно больше кеглей, зарабатывая очки при ограниченном количестве шаров. Но кегли нельзя сбивать напрямую своим шаром, поэтому периодически случайным образом, экран пересекают шары, которые игрок должен направить на кегли, посредством удара своим шаром и изменения траектории катящегося шара. Если игрок промахнется мимо катящегося шара, то его шар разобьется о поднявшуюся стенку и одна игровая попытка будет снята.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/gpage_wildroad.htm ================================================ ColdCore(TM)/WILD ROAD

ВЛАДЕЛЕЦ:

ГОД ВЫПУСКА:
2006

УСТРОЙСТВА:
Nokia
3510i
7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i
6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270
3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD
7610, 6260, 6670, 3230

Siemens
M55, C60, MC60
S55, SL55
S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65
C65, SL65

Motorola
C380, C650, v220, v180
v300, v500, v600, v535, v550, v620, E398, E375, v3

Samsung
C100, C108T, C110, S300, S300M, S307
E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468
X100, X108, X600, X608

LG
G1600

SonyEricsson
T610, T616, T618, T628, T630, T637, Z600, Z608

WILD ROAD

Оторвись от преследователей, не дай им подорвать твою машину или прыгнуть на неё. Подбирай канистры, так как топливо постоянно вытекает через прострелянные баки.

При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас!
Имя:

E-mail:
Сообщение:

 КУПИТЬ ИГРУ 


 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu1_about.htm ================================================ ColdCore/О НАС
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu1_contacts.htm ================================================ ColdCore/КОНТАКТЫ
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu1_job.htm ================================================ ColdCore/ВАКАНСИИ
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu1_news.htm ================================================ ColdCore/НОВОСТИ
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu1_partnership.htm ================================================ ColdCore/ПАРТНЕРСТВО
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu2_all.htm ================================================ ColdCore/ИГРЫ/ВСЕ
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu2_arcade.htm ================================================ ColdCore/ИГРЫ/АРКАДЫ
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu2_clientserver.htm ================================================ ColdCore/ИГРЫ/КЛИЕНТ-СЕРВЕР
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu2_erotic.htm ================================================ ColdCore/ИГРЫ/ЭРОТИЧЕСКИЕ
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu2_fighting.htm ================================================ ColdCore/ИГРЫ/ДРАКИ
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu2_gambling.htm ================================================ ColdCore/ИГРЫ/АЗАРТНЫЕ
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu2_logic.htm ================================================ ColdCore/ИГРЫ/ЛОГИЧЕСКИЕ
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu2_multiplayer.htm ================================================ ColdCore/ИГРЫ/МУЛЬТИПЛЕЕР
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu2_quest.htm ================================================ ColdCore/ИГРЫ/КВЕСТЫ
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu2_racing.htm ================================================ ColdCore/ИГРЫ/ГОНКИ
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu2_shooter.htm ================================================ ColdCore/ИГРЫ/СТРЕЛЯЛКИ
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu2_sport.htm ================================================ ColdCore/ИГРЫ/СПОРТ
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/menu3_appsall.htm ================================================ ColdCore/ПРИЛОЖЕНИЯ/ВСЕ
ColdCore(R)
 
Buy a bit of Game(TM)

RUS

 
Papanin's quest
Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile.
������ ������...
Mobile chase
Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile.
������ ������...
Air aggression
Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile.
������ ������...
Caspian monster
Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile.
������ ������...
Kalah
Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile.
������ ������...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/send_error.html ================================================ �� ���� ��������� ���������.

�� ���� ��������� ���������, �������� �������� �� �������. ���������� ���������� �����.
 
================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/rus/send_ok.html ================================================ ��������� ���������� �������.

���� ��������� ������� ����������. �������!
 
================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/etl/wap/index.wml ================================================

ColdCore(R)

Sorry, under construction...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/about.htm ================================================ //#- //#excludeif true Sorry, the page is still under construction //#+ //#if curLangID=="rus"
   ColdCore - Java2ME , . . , , 100 . - Java2ME , - , .
, :
  • .
  • .
//#else
  ColdCore is a leader in Java2ME content development. We have unique skills and technologies that enable us to develop hi-end production under time. Our production is published under leading worldwide trademarks and our portfolio contains more than 100 games and applications for mobile devices. Our mission is to become a global leader in mobile Java2ME game content development through development the best technologies, the best workflows and the best products that meet requirements of the market.
We not only develop mobile applications for own sales but also we implement outside orders like:
  • Development of mobile games and mobile applications to order.
  • Development of parts for customer's systems.
//#endif //#- //#+ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/channels.xml ================================================ СИМОНА SIMONE Контент-провайдер A content provider http://www.simona.ru http://www.simona.ru ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/cmn/sendfeedback.phtml ================================================ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/cmn/styles.css ================================================ body { margin-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; background-color: #FFFFFF; } .menuheader { FONT-WEIGHT: normal; FONT-SIZE: 14px; COLOR: #BFBFFF; FONT-FAMILY: "Small Fonts", "Arial Black", Arial, Helvetica, sans-serif} .menu { FONT-WEIGHT: bold; FONT-SIZE: 11px; COLOR: white; FONT-FAMILY: Arial, Helvetica, sans-serif; TEXT-DECORATION: none; } .alltext { FONT-WEIGHT: normal; FONT-FAMILY: "Times New Roman", Times, serif; COLOR: black; TEXT-DECORATION: none; font-size: 12px; font-style: normal; } .newdata { FONT-WEIGHT: bold; FONT-SIZE: 11px; COLOR: #000000; FONT-FAMILY: Arial, Helvetica, sans-serif} .footer { font-size: x-small; font-family: Arial, Helvetica, sans-serif; color: #999999; } .langtxt { font-family: Arial, Helvetica, sans-serif; font-size: 11px; font-style: normal; font-weight: bold; } .rightnews { font-family: Arial, Helvetica, sans-serif; font-size: 9px; } .rightnewsHdr { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; } a:link { text-decoration: none; color: #00BBFF; } a:visited { text-decoration: none; color: #00BBFF; } a:hover { text-decoration: none; color: #00FF00; } a:active { text-decoration: none; color: #00BBFF; } .catalogheader { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000066; text-decoration: none; } .gameinfoheader { font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: #000066; text-decoration: none; } .gameinfoheadermin { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000066; text-decoration: none; } ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/cmn/styles2.css ================================================ body { margin-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; background-color: #FFFFFF; } .menuheader { FONT-WEIGHT: normal; FONT-SIZE: 14px; COLOR: #BFBFFF; FONT-FAMILY: "Small Fonts", "Arial Black", Arial, Helvetica, sans-serif} .menu { FONT-WEIGHT: bold; FONT-SIZE: 11px; COLOR: white; FONT-FAMILY: Arial, Helvetica, sans-serif; TEXT-DECORATION: none; } .alltext { FONT-WEIGHT: normal; FONT-FAMILY: "Times New Roman", Times, serif; COLOR: black; TEXT-DECORATION: none; font-size: 12px; font-style: normal; } .newdata { FONT-WEIGHT: bold; FONT-SIZE: 11px; COLOR: #000000; FONT-FAMILY: Arial, Helvetica, sans-serif} .footer { font-size: x-small; font-family: Arial, Helvetica, sans-serif; color: #999999; } .langtxt { font-family: Arial, Helvetica, sans-serif; font-size: 11px; font-style: normal; font-weight: bold; } .rightnews { font-family: Arial, Helvetica, sans-serif; font-size: 9px; } .rightnewsHdr { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; } a:link { text-decoration: none; color: #000000; } a:visited { text-decoration: none; color: #000000; } a:hover { text-decoration: none; color: #000000; } a:active { text-decoration: none; color: #000000; } .catalogheader { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000066; text-decoration: none; } .gameinfoheader { font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: #000066; text-decoration: none; } .gameinfoheadermin { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000066; text-decoration: none; } .devicename { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000066; text-decoration: none; } .devicelist { font-family: Arial, Helvetica, sans-serif; font-size: 10px; font-weight: normal; color: #000066; text-decoration: none; } .sendformref { font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; color: #000066; text-decoration: none; } .sendformhdr { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000066; text-decoration: none; } .sendformtxt { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: normal; color: #000066; text-decoration: none; } .sendformfield { font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: #000066; text-decoration: none; } ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/contacts.htm ================================================ //#- //#excludeif true Sorry, the page is still under construction //#+

//#if curLangID=="rus" : support@coldcore.ru
: webmaster@coldcore.ru
: sales@coldcore.ru
//#else Information: support@coldcore.ru
Website: webmaster@coldcore.ru
Marketing: sales@coldcore.ru
//#endif
//#- //#+ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/devices.xml ================================================ 3410 3510i 7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i 6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270 6230i, 8800 3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD 6600, 6620 7610, 6260, 6670, 3230 6630 M(T)50, C55, C56, CT56, 6688i, M46, 3118 SL45i M55, C60, MC60 S55, SL55 S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65 C65, SL65 C380, C650, v220, v180 Accompli 008 v300, v500, v600, v535, v550, v620, E398, E375, v3 D108, S100, S105, X400, X426, X427, X430 E400, S200, S208 C100, C108T, C110, S300, S300M, S307 E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468 X100, X108, X600, X608 E105, E315, E316, E317, E710, E715, P400, P510, P518, X427M, X450, X458, X475 E217, E335, E635, X640 C200, C207, C208, C225, E600, E608, X105 D410, D415, D418, P207, P777 E300, E310, E810, X480 X120, X140 E610, E618, P730, P735 D500, D508, E730 E530, E620, E720, E880 D600 Z105, Z107 Z110 Z130 Z140, Z300, Z500 G1600 T610, T616, T618, T628, T630, T637, Z600, Z608 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/eng/send_error.html ================================================ I can't deliver the message.

I can't deliver the message. May be the server has troubles, if it is possible resend the message later. Thank you.
 
================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/eng/send_ok.html ================================================ Your message has been delivered successfully.

Your message has been delivered successfully. Thank you very much!
 
================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/gamelist.htm ================================================ //#- //#excludeif true Sorry, the page is still under construction //#+
//#local gl_curGameIndex = 0 //#local gl_counterOutGames = 0 //#while gl_curGameIndex0 //#local gl_gameID = xml_attr(gl_currentGameElement,"id") //#local gl_gamePageLink = "gpage_"+gl_gameID+".htm" //#local gl_gameReference = xml_get(xml_list(gl_currentGameElement,"shortreference"),0) //#local gl_gameReferenceName = str2web(xml_attr(gl_currentGameElement,"title")) //#local gl_gameReferenceText = xml_text(xml_get(xml_list(gl_gameReference,curLangID),0)) //#if gl_counterOutGames!=0
//#endif //#local gl_counterOutGames = gl_counterOutGames + 1 //#else read more... //#endif
/*$gl_gameReferenceName$*/

/*$gl_gameReferenceText$*/
//#if curLangID=="rus" ...

//#endif //#local gl_curGameIndex = gl_curGameIndex + 1 //#end //#- //#+ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/gameref.htm ================================================ //#noautoflush //#local gref_langs = xml_root(xml_open("site.xml")) //#local gref_devices = xml_root(xml_open("devices.xml")) //#local gref_footer = xml_get(xml_list(xml_root(xml_open("site.xml")),"footer"),0) //#local gref_langs = xml_list(xml_get(xml_list(gref_langs,"languages"),0),"lang") //#local gref_docRoot = xml_root(xml_open("games.xml")) //#local gref_gamesList = xml_list(xml_get(xml_list(gref_docRoot,"games"),0),"game") //#local gref_channelsList = xml_get(xml_list(gref_docRoot,"channels"),0) //#local gref_ownersList = xml_get(xml_list(gref_docRoot,"owners"),0) //#local gref_langIndex = 0 //#while gref_langIndex ColdCore(TM)//*$gref_currentGameTitle$*/

//#if gref_curLangID=="rus"
ВЛАДЕЛЕЦ:
//#else
OWNER:
//#endif
//#if gref_curLangID=="rus"
ГОД ВЫПУСКА:
//#else
PUBLICATION DATE:
//#endif
/*$gref_currentGameYear$*/

//#if gref_curLangID=="rus" УСТРОЙСТВА: //#else DEVICES: //#endif
//#local gref_curDeviceIndex = 0 //#local gref_curDeviceName = "" //#while gref_curDeviceIndex //#endif
/*$str2web(gref_curDeviceName)$*/
//#endif
/*$gref_curDeviceFamily$*/
//#local gref_curDeviceIndex = gref_curDeviceIndex+1 //#end

/*$gref_currentGameTitle$*/
//#if strlen(gref_currentGameScreens)>0 //#local gref_curScreenLimit = str2int(gref_currentGameScreens) //#else //#local gref_curScreenLimit = 3 //#endif //#local gref_curScreenIndex = 1 //#while gref_curScreenIndex<=gref_curScreenLimit //#local gref_curScreenIndex = gref_curScreenIndex+1 //#end

/*$gref_currentGameReference$*/

//#if gref_curLangID=="rus" При помощи этой формы, Вы можете послать нам свое мнение, пожелание или описание проблемы по этому приложению. Это очень важно для нас! //#else The form enables you to send us your opinion, wish or problem description for the application. It's very important for us! //#endif
//#if gref_curLangID=="rus" Имя: //#else Name: //#endif

E-mail:
//#if gref_curLangID=="rus" Сообщение: //#else Message: //#endif
//#if gref_curLangID=="rus" //#else //#endif
//#if gref_curLangID=="rus" //#else //#endif
//#if gref_curLangID=="rus"  КУПИТЬ ИГРУ  //#else  PURCHASE  //#endif

//#local gref_curSalesIndex=0 //#while gref_curSalesIndex /*$gref_curSalesCost$*/ //#local gref_curSalesIndex=gref_curSalesIndex+1 //#end
 

//#flush //#local gref_curGameIndex = gref_curGameIndex+1 //#end //#local gref_langIndex = gref_langIndex+1 //#end //#outname "null.txt" ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/games/games2003_2006.html ================================================ Old mobile games (august 2003-march 2006)

Old mobile games (august 2003 - march 2006)

Summary team at the period

Producing: Arteom Litvinov, Igor Maznitsa
Project management: Igor Maznitsa
Project coordination: Aleksey Goryachev
Game design: Aleksey Goryachev, Igor Maznitsa
Level design: Aleksey Goryachev
Programming: Alexander Vasiliev, Denis Parinov, Sergey Kuligin, Denis Rozhnev, Igor Maznitsa
Art: Svetlana Semenova, Andrey Diakov, Dmitriy Semenov, Igor Maznitsa
Sound: Igor Maznitsa
Testing: Aleksey Goryachev


-----------------------------

1. Papanin's quest

-----------------------------

2. Air Aggression

-----------------------------

3. Kalah

-----------------------------

4. Mobile chase

-----------------------------

5. Caspian monster

-----------------------------

6. Hunt

-----------------------------

7. Raven's cheese

-----------------------------

8. Sea road

-----------------------------

9. Blazing gears

-----------------------------

10. Castle assault

-----------------------------

11. Cockroach

-----------------------------

12. Coconuts fall

-----------------------------

13. Cone! Cone!

-----------------------------

14. Firing line

-----------------------------

15. Fruit mania

-----------------------------

16. Hard day

-----------------------------

17. Ice gifts

-----------------------------

18. Iron stream

-----------------------------

19. Kick Kick

-----------------------------

20. Lifesaver

-----------------------------

21. Live bridge

-----------------------------

22. Mobile sheriff

-----------------------------

23. Paparazzo

-----------------------------

24. Pillow war

-----------------------------

25. MTV Puzzle

-----------------------------

26. Scene

-----------------------------

27. Nimble

-----------------------------

28. Operation "Thunderclap"

-----------------------------

29. Oyster bank

-----------------------------

30. Sea rovers

-----------------------------

31. Smashing kick

-----------------------------

32. Spiders

-----------------------------

33. Star harbor

-----------------------------

34. Strange Hunt

-----------------------------

35. Tasty dish

-----------------------------

36. Vineyard

-----------------------------

37. Waterway

-----------------------------

38. Wild balls

-----------------------------

39. Wild road

-----------------------------

40. Copter bomber

-----------------------------

41. Drunkman

-----------------------------

42. Fisher

-----------------------------

43. Air boil

 

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/games.htm ================================================ //#- //#excludeif true Sorry, the page is still under construction //#+

Sorry, but the page is still under construction....

Visit us later, please...

//#- //#+ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/games.xml ================================================ Контент-провайдер A content provider http://www.simone.ru http://wap.simone.ru Мелодии, игры и логотипы для мобильных телефонов. Ringtones, games and logos for mobile phones. http://www.muzon.ru http://wap.muzon.ru Мелодии, игры и логотипы для мобильных телефонов. Ringtones, games and logos for mobile phones. http://www.ringtime.ru http://wap.muzon.ru Азартные игры на мобильном телефоне, на реальные деньги. Gambling games on cell phones on real money. http://www.cellcasino.ru NIKITA Контент-провайдер A content provider http://www.nikita.ru http://wap.nikita.ru Контент-провайдер A content provider http://www.infon.ru http://wap.infon.ru Контент-провайдер A content provider http://www.playmobile.ru http://wap.playmobile.ru ColdCore(R) Siemens mobile SAMSUNG FunClub MTV Akumiitti Oy INFON Gamefederation CellCasino Ringtime(R) Сборник "НОВОГОДНИЕ АНЕКДОТЫ", содержит 60 отборных Новогодних историй. The collection "New Year's jokes" contains 60 jokes. Приложение является сборником новогодних анекдотов, рассортированных по темам. В сборник вошло 60 анекдотов. The application is a collection of jokes, the jokes are sorted on themes. The collection included 60 jokes. Слайдер по известному мультфильму "Алеша Попович и Тугарин Змей" A slide-show of the cartoon film "Aleosha Popovich and Toogarin Zmey" Слайдер содержит 10 кадров мультфильма с текстом к каждому кадру. Есть возможность просмотра кадров как в ручном так и в автоматическом режиме. Можно увеличивать выбранный кадр и рассматривать отдельные детали изображения. The slide-show contains 10 frames (with texts) from the cartoon film "Aleosha Popovich and Toogarin Zmey". You can view the frames in both automatic and manual modes as well you can magnify selected frame and consider it. Электронный каталог мобильного контента с возможностью заказа и обновления через WAP. A mobile catalog of mobile content enables to send SMS for order and can be upgraded via WAP. Мобильный каталог контента, позволяющий пользователю ознакомиться с составом мобильного контента в базе контент провайдера и, если телефон имеет возможность, осуществить отправку SMS на номер провайдера с целью заказа понравившегося контента. Приложение позволяет организовывать сложную древовидную структуру каталога с включением изображений для предпросмотра, изображения могут храниться как с каталогом так и быть загруженными через сеть. Поддерживается три схемы отправки SMS: Siemens, WMA и Samsung. Язык приложения русский, при ином языке, установленном на аппарате пользователя, приложение автоматически отображает текст транслитом. Приложение динамически подстраивается под возможности аппарата и может работать на любом аппарате с платформой не ниже MIDP-1.0. Список возможностей оболочки превышает 20 пунктов. The mobile catalog enables to a user to look through contents of a mobile content provider's base and to order liked content with automatically generated SMS (if the device is supporting). The application supports three SMS schemes: Siemens, Samsung and WMA. The application enables to organize complicated tree-structured catalogs. It can be started on any device supports MIDP-1.0 or older. Мобильная версия "Однорукого бандита", позволяющая играть на реальные деньги. Mobile version of the "Fruitmania" casino game enables to play on real money. Мобильная версия известного автомата "Однорукий бандит", позволяющая делать ставку с реального счета в казино и осуществлять игру через интернет с мобильного телефона, выигрывая реальные деньги. A mobile version of well-known casino game enables to make bet from real casino account and to play via internet from your mobile devices. You can win real money with the game. Тебя занесло на военный полигон, но не сдавайся! You have come on military range but do not surrender! Тебя занесло на военный полигон, но не сдавайся! Несмотря на трудности, настреляй как можно больше уток и кабанов! You have come on military range but do not surrender! Shoot as many as possible ducks and wild boars! Помоги деду Морозу отправить все Новогодние подарки. Help Santa to send all XMas gifts. Помоги деду Морозу отправить все Новогодние подарки. Совмещай их одинаковыми сторонами и не допускай отсутствия пустых прорубей для новых подарков. Help Santa to send all XMas gifts. Combine their identical parties and do not suppose absence of empty ice-holes for new gifts. Игра в стиле Безумный Макс. Уйди от погони и собирай канистры. Break away from persecutors, do not allow them to destroy your car. Оторвись от преследователей, не дай им подорвать твою машину или прыгнуть на неё. Подбирай канистры, так как топливо постоянно вытекает через прострелянные баки. Break away from persecutors, do not allow them to destroy your car or to jump on it. Pick up jerricans because fuel constantly drips out through the raked tanks. Пришла пора собирать виноград, но злобные улитки-мутанты не спят. It is the time to collect grapes but evil snails can prevent it. Собирайте виноград и раскладывайте его в корзины, переход на следующий уровень когда все корзины заполнены. Не попадайтесь улиткам! Gather grapes and put its into mollies, you must collect all grapes to pass a game level. You must avoid collisions with snails! Уничтожь противника при помощи нового супервертолета. Destroy all enemy tanks and buildings with new supercoter. Вы пилот секретного вертолета-бомбардировщика, уничтожьте все вражеские цели и не сталкивайтесь с воздушным противником. You are a pilot of a top secret copter-bomber and your task is to destroy all enemy ground targets. You must avoid collisions with flying enemies. Мобильная версия карточной игры ПЬЯНИЦА на раздевание. A mobile version of the card game TIPPLER. Мобильная версия карточной игры ПЬЯНИЦА. Игра на раздевание с тремя противниками. A mobile version of the TIPPLER card game. You can select one from three opponents and to play with it for undressing. Освободи жителей далекой планеты от господства машин. Release a distant planet from machines' domination. В 2050 году, была обнаружена отдаленная планета с очень низкой гравитацией. Жители этой планеты оказались порабощены четырьмя огромными машиноподобными пришельцами. Демократическая Земля не смогла смириться с таким состояниейм дел и космический шаттл доставил на эту планету суперспецназовца Джона Петрова, который и был сброшен на поверхность планеты вместе с велосипедом и ракетной установкой для наведения демократии и мостов дружбы. Итак, задача играющего - пройти 20 уровней уничтожая различную летающую нечисть и уклоняясь от метеоритных дождей, весьма частых на этой планете. Игровые попытки можно пополнять, подбирая падающие пропеллеры, а патроны прилетают на воздушных шарах. In 2050, the remote planet with very low gravitation had been found. Inhabitants of the planet have been enslaved by four huge machine like aliens. The democratic Earth couldn’t reconcile with such state and a space shuttle had delivered to this planet a super agent John Petroff who had been dumped on a surface of the planet together with a bicycle and a rocket mount for prompting democracy and bridges of friendship. So, the task of a player is to pass 20 game levels and to destroy all flying objects on levels. Ужасное вторжение грозит Земле. Игрок управляет орудием космического крейсера и должен отбить атаку, уничтожив все крейсеры и истребители. A terrible invasion threatens the Earth.A player is a gunner of a star cruiser gun and your task is to stop the invasion.You have to destroy both cruisers and fighters. В очередной раз гадкие инопланетяне собираются попрать своими щупальцами нашу голубую планету, но они не учли того, что ,несмотря на все усилия по уклонению от воинской повинности, любитель компьютерных игр Иван Копченый был забрит в космический флот и находился среди ноющих о родном доме призывников на борту космического крейсера "Червона Украина", готовящегося к отправлению на границы солнечной системы с орбиты Земли. Неожиданное нападение пришельцев так поразило командный состав крейсера, что оно немедленно ушло в запой лечить нервы и Иван остался единственным дееспособным членом экипажа. Итак, задача игрока отразить нападение, путем тотального уничтожения атакующих сил. Игра от первого лица из разряда "Убей их всех", имеет три уровня сложности, различающиеся активностью и количеством противника. A terrible invasion threatens the Earth.A player is a gunner of a star cruiser gun and your task is to stop the invasion.You have to destroy both cruisers and fighters. Мобильная версия известной настольной игры КАЛАХ. Цель игры - взять как можно больше камней. A mobile version of the well known KALAH game. The object of the game is to move as many stones as possible into your KALAH (right bowl). Мобильная версия известной логической игры Kalah. Задача игрока собрать как можно больше камней в свой калах (правая ложбинка на игровом поле). При очередном ходе играющий снимает с одного из своих полей все камни и распределяет их по одному на последующие поля в порядке возрастания их номеров; полем, следующим за шестым, считается свой калах. Далее камни распределяются по чужим полям (опять-таки в порядке возрастания их номеров), затем вновь по своим (чужой калах пропускается) и так далее, как бы совершая обход полей против часовой стрелки. Если последний из распределяемых камней попал в «свой» калах, то игрок делает еще один ход. Во всех остальных случаях очередь хода передается противнику. Если последний камень попал на пустое поле игрока, совершавшего ход, а на противоположном поле соперника есть хотя бы один камень, то содержимое обоих полей переносится в КАЛАХ игрока, совершавшего ход (после чего, ход переходит к его противнику). Если на полях игрока, сделавшего ход, не остается ни одного камня, то все камни, находящиеся на полях противника, переносятся в калах противника, и игра заканчивается. Игра заканчивается, когда одному из противников нечем ходить. Выигрывает тот, у кого по окончании игры в калахе оказалось больше камней. Если в обоих калахах находится по 36 камней, фиксируется ничья. A mobile version of the well known KALAH game. The object of the game is to move as many stones as possible into your KALAH (right bowl). Игрок играет за путешественника Папанина, провалившегося в ужасную пирамиду на Южном полюсе и ищущего путь домой. You have to help Papanin to find the way out of the terrible maze. The object of the game is to collect all magic stones in the maze. Путешественник Папанин обнаружил египетскую пирамиду, затерянную во льдах Антарктики. При осмотре он провалился в расщелину и оказался внутри. Задача игрока — помочь Папанину выбраться наружу, преодолев 10 игровых уровней. Чтобы пройти игровой уровень, требуется собрать все бриллианты, расположенные в лабиринте, после чего появляется ключ, которым можно открыть дверь на следующий уровень. В прохождении лабиринтов, игроку мешают различного вида монстры, с которыми игрок может бороться при помощи мечей, разбросанных по уровню. Жизни можно восстановить при помощи кувшина с водой, а некоторые участки пола можно пробивать при помощи кирки. Ivan Papanin, the well-known Polar researcher, discovered an ancient Egyptian pyramid lost in the Antarctic ice. When examining the pyramid, he fell down and found himself inside of it. You have to help Papanin to find the way out of this terrible maze. The object of the game is to collect all magic stones in the maze to get the key that opens the door to the next level. You can use a pick to make holes in the floor. Swords scattered on the level will help you to fight with monsters. Be careful, after some period of time the destroyed monsters reappear. If you need to restore your life power, drink some water from a jar. But all these items can be used only once. Вы мирно отдыхали на обочине, сидя в своей полицейской машине, когда поступило сообщение об ограблении банка. В погоню! You are a brave policeman who has received the message about a bank robbery. Your have to overtake the gangsters and stop their van. Игрок должен нагнать фургон преступников и стреляя в него, заставить его остановиться. При этом надо объезжать препятствия на дороге и избегать столкновения с другими участниками дорожного движения. Так же следует избегать луж, так как они делают автомобиль неуправляемым. You are a brave policeman who has received the message about a bank robbery. Your have to overtake the gangsters and stop their van. Управляя секретным советским экранопланом, уничтожь противника и найди выход с базы. You are a pilot of a secret soviet airfoil boat, which is armed with missiles and a quick-firer. Террористы похитили секретный экраноплан «Каспийский монстр», вооруженный самым современным оружием, но вам удалось проникнуть на их базу и угнать экраноплан. Ваша задача пройти три участка от базы к открытому морю, нашпигованных вражеской техникой и минами.Вооружение состоит из автоматической пушки и двух видов ракет, самонаводящихся и неуправляемых. Самонаводящиеся ракеты автоматически выбирают цель и рассчитывают свою траекторию, а неуправляемые летят по курсу экраноплана и очень полезны для разрушения мостов. You are a pilot of a secret soviet airfoil boat, which is armed with missiles and a quick-firer. Your main objective is to leave the enemy base destroying as much military equipment as possible. Инопланетные монстры взяли контроль над земными самолетами, спаси мир! Eight alien monsters took control over all Earth's war-planes to enslave our planet. У землян очередная напасть — 8 инопланетных монстров захватили власть над всеми самолетами планеты и только ваш самолет чудом избежал их влияния. Ваша задача уничтожить всех восьмерых монстров, принявших образы гигантских самолетов, и вернуть планете мир и спокойствие. Управляя маленьким самолетиком на экране, следует избегать столкновения с другими самолетами, избегать попаданий и брать бонусы и оружие, которое доставляется вертолетом поддержки. Eight alien monsters took control over all Earth's war-planes to enslave our planet. You were able to keep one plane from being captured and now you have got a chance to keep mankind free. Управляя гоночной машиной, надо показать лучшее время. You are a driver of a sport car and your task is to pass loops for a limited time. You have to avoid collisions with other cars on the road. Вы водитель автомашины, участвующей в гонках без правил. На прохождение каждого этапа гонок вам дается ограниченное время. Двигайтесь на максимальной скорости, но постарайтесь не сталкиваться с другими машинами! You are a driver of a sport car and your task is to pass loops for a limited time. You have to avoid collisions with other cars on the road. Надо разбить крепостную стену, что бы захватить замок. To break a castle wall by a catapult. Вы управляете катапультой и должны разрушить два соседних участка стены осажденного замка. Дождитесь зарядки катапульты и следите за указателем высоты прицеливания. Стену можно разрушить только сверху вниз. Но берегитесь вражеских камней летящих из-за стены! You are the commander of a catapult crew and your task is to destroy two vertical neighbor parts of the castle wall with a missile. The wall can be destroyed top-down only. Left altimeter shows current altitude of the missile. You have to be careful because the enemy throws its missiles over the wall. You can't fire until the catapult has been charged. Управляя тараканом и подбирая разные съедобные и несъедобные предметы, надо найти выход из лабиринта. A cockroach have to find a way out of the maze Игрок управляет тараканом, ползающим в лабиринте из труб и его задача найти выход из лабиринта. В лабиринте разбросаны различные съедобные предметы, некоторые таракан может есть безболезненно, некоторые отнимают очки и время. You are driving a running cockroach in the maze and your task is as soon as possible to find a way out of the maze. There are a lot of scattered eatable things in the maze they increase and decrease game scores, so the game scores are decreased with time. Обезьяна должна отбиться от преследователей орехами. Save own freedom with coconuts. Игрок управляет обезьяной, спасающейся на верхушках пальм от карабкающихся по ним человечков. Обезьяна может бросать в человечков собранные на пальмах кокосы и должна прятаться от пролетающего над пальмами вертолета. You are a monkey and hunters want to catch you. Your task is to save own freedom as long as possible. You can use coconuts to knock men and you have to be careful because a helicopter tries to catch you with a net. Управляя белкой, собери как можно больше орехов и отбейся от ворон. You are a squirrel defending your supplies against crows. Игрок управляет белкой, защищающей от ворон спрятанные в дуплах дерева запасы. Белка прыгает по ветвям, собирает шишки и бросает их по воронам, садящимся на ветви. You are a squirrel defending your supplies against crows. You can throw cones at them but be careful because you should keep a distance from a crow. Они приходят прямо из открытого космоса, а у тебя только бластер... You are the defender of the docking tunnel of your spaceship from space creatures. Игрок - защитник стыковочного шлюза, в который лезут инопланетные твари. Задача - настрелять как можно больше тварей, прежде чем их поток захлестнет станцию. You are the defender of the docking tunnel of your spaceship from space creatures. Don’t allow them to approach to you! Fire! Fire! Победи в чемпионате по рыболовству, но помни что крючков мало, а акул много... You are a fisher and have to catch as many as possible fishes. Игрок выступает в роли рыбака и его задача наловить как можно больше рыбы при ограниченном количестве крючков (игровых попыток). В воде плавают рыбы, которых можно ловить и хищники, которые могут перекусывать леску, при этом игрок теряет одну попытку. Игрок может управлять глубиной погружения крючка, разматывая леску или поднимая удочку. You are a fisher and have to catch as many as possible fishes. Take care of big predatory fishes, they break your fishing-line. Тяжела работа курьера в офисе, но Вы не боитесь тяжелой работы... You are a courier in a big company and your task is to deliver documents inside of an office. Вы управляете курьером, который должен доставлять документы внутри офиса. Все белые папки должны быть доставлены нетерпеливым получателям как можно быстрее. Помните, ваш директор будет очень зол, если встретит вас шатающимся без дела! You are a courier in a big company and your task is to deliver documents inside of an office. All white folders must be delivered to recipients as soon as possible. Remember, your manager will be very angry if meet you without a folder. Зверей в лесу много, а патронов мало.. трать их с толком. You are a brave hunter and your task is to kill as many as possible animals by 20 bullets. Игрок выступает в роли охотника и в начале игры ему дается 20 патронов. Он должен настрелять как можно больше животных. При пропуске без единого выстрела 20 животных, у игрока снимается один патрон. Частота появления зверей на экране возрастает с течением игрового процесса. За каждое убитое животное, игроку начисляется определенное количество игровых очков. При наведении прицела на бегущее животное, оно останавливается (кроме вороны) и отрабатывается анимация страха, животное стоит под прицелом, пока игрок не выстрелит или не уберет прицел. You are a brave hunter and your task is to kill as many as possible animals by 20 bullets. If you have missed 20 animals, one your bullet will be removed. Внимание! Внимание! Враг прорвал нашу оборону и входит в населенный район! Ваш танк - единственная наша надежда! Warning! Warning! The enemy has dashed our protection line and marching into a populated area! Внимание! Внимание! Враг прорвал нашу оборону и входит в населенный район! Ваш танк единственная наша надежда в этом районе и Ваша святая обязанность защитить его. Вы должны уничтожить, как можно больше вражеских танков, но при этом сохранить в целости постройки. Warning! Warning! The enemy has dashed our protection line and marching into a populated area! Your tank is our only hope in the area and your duty is to defend it. You have to destroy as many enemy tanks as possible but keep buildings untouched. Игрок управляет тремя футболистами, закрепленными на одном вращающемся стержне. You drive footballers fixed on a pivot. Игра по мотивам настольной игры. Игрок управляет тремя футболистами, закрепленными на одном вращающемся стержне. Необходимо пробить защиту соперника и забить мяч в его ворота. You drive footballers fixed on a pivot. Your task is to defend own goal and to kick as many balls as possible into the opponent’s goal. Огонь перекрыл выходы и жители прыгают из горящих окон, спаси их! Fire! Fire! Fire has occupied the ground level! Игрок выступает в роли руководителя пожарной команды и его задача спасти как можно больше жителей из горящего дома. Изначально горит первый этаж дома, с течением времени огонь охватывает следующие этажи здания, управляя пожарниками, игрок может тушить этажи, исключая первый. С последнего этажа прыгают люди и игрок должен, управляя пожарными, успевать ловить их на брезент. При смерти одного прыгнувшего, снимается одна попытка играющего, так же попытка снимается при полном сгорании здания. Fire! Fire! Fire has occupied the ground level! You are the chief of a fire brigade and must not let the fire to occupy all building; you can use a water cannon. Hopeless men jump from windows and you have to catch them. Срочная посылка, но мост уже вторую пятилетку в ремонте. Придется воспользоваться черепахами... You are a porter and your task is to carry cargo from the left riverside to the right riverside. Игрок управляет носильщиком, переправляющим через реку грузы. Через реку можно переправиться только по плавающим в ней черепахам, ныряющим время от времени за рыбками, всплывающими со дна. You are a porter and your task is to carry cargo from the left riverside to the right riverside but there is not any bridge on the river so you use turtles as a live bridge. Unfortunately it is dangerous to use turtles as a bridge because they catch fishes and dive in the depth from time to time. Игрок управляет рабочим в аэропорту, который должен разобрать перепутанный багаж на лентах транспортера. You are an airport loader and your task is to sort baggage. Игрок управляет рабочим в аэропорту, который должен разобрать перепутанный багаж на лентах транспортера до того как транспортеры переполнятся. You are an airport loader and your task is to sort baggage. You have to take color bags and place them on the conveyer having the same color as the bag. Bags should not overload conveyers. Игрок выступает в роли пилота боевого вертолета, в задачу которого входит уничтожение как можно большего количества вертолетов противника. You are a pilot of a military copter and your task is to kill as many as possible enemy copters. Игрок выступает в роли пилота боевого вертолета, в задачу которого входит уничтожение как можно большего количества вертолетов противника. Вертолеты противника случайным образом появляются на экране и перемещаются по различным траекториям. Уничтожение вертолета противника осуществляется путем наведения на него прицела и нажатия на гашетку (кнопка «Огонь»). Некоторые противники так же могут вести огонь по игроку, вертолет игрока уничтожается, если стреляющий противник не будет своевременно уничтожен. За каждого уничтоженного противника начисляются 10 игровых очков. You are a pilot of a military copter and your task is to kill as many as possible enemy copters. Игрок управляет ныряльщиком, охотящимся за жемчужинами на морском дне. You are a diver gathering pearls. Игрок управляет ныряльщиком, охотящимся за жемчужинами на морском дне. Игрок должен направлять ловца к тем раковинам, которые открыты, следить за его запасом кислорода и беречь от акул You are a diver gathering pearls. You should collect as many pearls as possible. You have to avoid collisions with a shark. The oxygen cylinder is limited so you have to look after its level. Вороне Бог послал кусочек сыра, но трудно будет лисе если целая стая ворон бомбит её сыром... You drive a fox and your task to catch cheeses that throwed by ravens. Игрок выступает в роли лисы, ловящей куски сыра, бросаемого воронами. Задача игрока наловить как можно больше кусков сыра. Игра не имеет ограничения по времени, но имеет ограничение по максимальному количеству пропущенных сыров. На ветвях деревьев появляются вороны с сыром в клюве, игрок должен угадать момент броска сыра и поставить лису в позицию, при которой сыр будет брошен ей в пасть. Всего имеется четыре положения лисы. Игроку следует учитывать, что лиса не может постоянно стоять на задних лапах и через какое то время опускается. Если ворона доходит до края ветки, а лиса не готова поймать сыр, то раздается карканье и сыр падает на землю. С края экрана выбегает мышь и уносит кусок сыра, при этом у игрока забирается одна попытка. Скорость появления ворон со временем увеличивается, но при достижении игроком количества очков кратного 50, количество попыток игрока восстанавливается. Выигрышная картинка будет показана игроку при набранном количестве сыров не меньше 100. При достижении количества очков кратного 50, скорость появления ворон уменьшается. You drive a fox and your task to catch cheeses that throwed by ravens. А не поохотиться ли со скуки на торговые корабли в открытом море? А почему бы и нет? You are a pirate hunting for cargo ships. Игрок управляет пиратским парусным кораблем и должен захватывать торговые корабли, избегая встречи с военными кораблями. Все корабли вооружены и делятся на торговые, военные и прочие (боты). Корабли отличаются также количеством энергии и, соответственно, числом бортовых залпов, необходимых для их потопления. Игрок должен нападать на торговые корабли и опасаться военных, которые могут дать отпор. Прочие корабли также могут быть мишенью для пушек пиратского корабля, но это не принесет игроку много очков. You are a pirate hunting for cargo ships. When you have damaged a cargo ship (it has three-cornered sail), you should stop own ship near it to enable your crew to rob the ship. You have to avoid collisions with battleships. Good luck, captain! Игрок управляет спортивным катером, принимающим участие в слаломе на оживленном морском пути. You are a driver of a speedboat. Игрок управляет спортивным катером, принимающим участие в слаломе на оживленном морском пути. Двигаясь по дистанции, игрок должен проходить через встречные ворота, время прохождения которых влияет на зарабатываемые очки. You are a driver of a speedboat and your task is to pass as many gates as possible during limited time. You should avoid collisions with other ships. Игрок управляет шерифом, освобождающим маленький техасский город от банды. You are a brave sheriff of Wild West who is releasing a small town from a band. Игрок управляет шерифом, освобождающим маленький техасский город от банды. Число бандитов известно, но в лицо их никто не знает. Игрок должен отличить бандитов от мирных горожан и уничтожить бандитов. В проемах окон и дверей периодически появляются и прячутся человечки. Человечки могут быть мирными горожанами или бандитами. Бандит внешне отличается только тем, что начинает стрелять в шерифа. Игрок может стрелять первым, рискуя убить горожанина или ждать пока по нему не начнут стрелять бандиты. Бандит делает разное число выстрелов, но убить шерифа может только третьим выстрелом подряд. Игрок должен успеть за это время прицелиться и выстрелить. Убив мирного горожанина, игрок теряет одну игровую попытку. Убив бандита, игрок получает очки. You are a brave sheriff of Wild West who is releasing a small town from a band. The number of the bandits is known but you don’t know their faces so you must be careful because there are a lot of inhabitants in the town and you must not kill them (we recommend you to wait an unkind action and don’t shoot before). Игрок управляет тренирующимся футболистом и его задача довести как можно больше мячей до ворот, не роняя их на землю. You are a training footballer and your task is to kick as many as possible balls into the goal. Игрок управляет тренирующимся футболистом и его задача довести как можно больше мячей до ворот, не роняя их на землю. Тренер с уменьшающимся интервалом подает мячи и игрок, удерживая мяч в воздухе при помощи ног и головы, доводит его до ворот и забивает, попытка снимается если мяч касается земли. После 10 забитых мячей игроку восстанавливается 1 игровая попытка. You are a training footballer and your task is to kick as many as possible balls into the goal. You have to keep the ball in the air with your foots and head. Игрок управляет муравьем, который должен носить в муравейник веточки из лежащей невдалеке кучи и не стать добычей пауков, спускающихся сверху на паутине. You are an ant bringing twigs into own anthill. Игрок управляет муравьем, который должен носить в муравейник веточки из лежащей невдалеке кучи и не стать добычей пауков, спускающихся сверху на паутине. Игрок может перемещать муравья влево/вправо. Подбежав к куче веточек, муравей взваливает одну себе на спину. Вернувшись к муравейнику, он бросает свой груз в проем и бежит за следующим. За каждую доставленную веточку игроку начисляются очки. Между муравейником и кучей веток висят на своих паутинах пауки, поджидающие добычу. Пауки быстро опускаются и медленно поднимаются по паутине. Кроме того, они передвигаются с остановками, иногда меняя после такой паузы направление движения. Если паук схватит муравья, то игрок теряет одну игровую попытку. You are an ant bringing twigs into own anthill. You should bring as many twigs as possible and to avoid clutches of spiders. Игрок управляет крокодилом, охотящимся в реке у берега. You are a crocodile living in a river. Игрок управляет крокодилом, охотящимся в реке у берега. Крокодил должен поймать свою добычу и не попасть на мушку охотника. Крокодил движется к берегу, пересекая реку, с постоянной скоростью. Игрок может только поворачивать крокодила влево/вправо, выбирая на какой участок берега напасть. Подплыв к берегу, крокодил хватает добычу, если на этом участке есть какое-либо животное, пьющее воду из реки. Игроку начисляются очки, в зависимости от ценности добычи. На месте животного может оказаться охотник, который, появившись на берегу, стреляет в крокодила, если тот находится напротив него. В этом случае крокодил погибает, а игрок теряет игровую попытку. Если на участке берега, к которому был направлен крокодил, нет добычи, то крокодил остается ни с чем и погружается обратно в воду. Для следующей попытки придется снова переплывать реку, подкрадываясь издалека. Игрок может промахнуться только 20 раз, после чего он теряет игровую попытку. You are a crocodile living in a river. Your task is to catch as many animals on the beach as possible. Time to time the hunter visits the beach and attempts to kill you with a gun. Вы управляете муравьем, собирающим воду для муравейников. You are an ant collecting dew for its ant heap. Вы управляете муравьем, собирающим воду для муравейников. Ваша задача ловить по одной капле воды в листок и выливать ее в цветок вашего напарника-муравья. Листок может выдержать только одну каплю! You are an ant collecting dew for its ant heap. Your task is to catch drops with a leaf and pour out it in the flower of your workmate. Remember, the leaf can contain one drop only. Игрок осуществляет игру в футуристические кегли и его задача выбить как можно больше кеглей, зарабатывая очки при ограниченном количестве шаров. You should clear as many as possible pins with own balls. Игрок осуществляет игру в футуристические кегли и его задача выбить как можно больше кеглей, зарабатывая очки при ограниченном количестве шаров. Но кегли нельзя сбивать напрямую своим шаром, поэтому периодически случайным образом, экран пересекают шары, которые игрок должен направить на кегли, посредством удара своим шаром и изменения траектории катящегося шара. Если игрок промахнется мимо катящегося шара, то его шар разобьется о поднявшуюся стенку и одна игровая попытка будет снята. You should clear as many as possible pins with own balls. You must use a rolling ball to clear pins; you have to direct the ball at a pin with your ball. If you miss, your ball will be lost. Известная игра 15 на тему MTV. A puzzle game. Ваша задача-передвигая квадратики,собрать изначальную картинку за минимальное количество ходов. Имеется три уровня сложности поля: 3х3,4х4 и 5х5. Your task is to collect a full image with moved squares. Нащелкай как можно больше звезд на свой фотик... You are a paparazzo and your task to get as many photos of celebrities as possible. Вы должны фотографировать лица знаменитостей шоу-бизнеса,имеющих знак 'звезды' и избегать охранников в окнах. Ваше время и число кадров-ограничены. You are a paparazzo and your task to get as many photos of celebrities as possible. Не любишь виджеев? Ну тогда подушку в руки и пошли отрываться в офисе МТВ... You're a visitor of MTV office and your task is to belabour music stars by a pillow. Ты ходишь по офису MTV и дубасишь всех подушкой.Опасайся охранников с дубинками.Заходи в двери,там могут быть подушки.Лови сердца-это жизни. You're a visitor of MTV office and your task is to belabour music stars by a pillow.You can find new pillows in rooms. Петь мы все любим, но не у всех есть слух. Главное - уворачиваться от тяжелых предметов... You are a rock-star and your worshipper throw different things on your stage. Вы должны продержаться на сцене определенное время,уворачиваясь от града опасных предметов,летящих из зала.Ловите только цветы ваших фанатов и зарабатывайте этим очки. You are a rock-star and your worshipper throw different things on your stage.You have to avoid collision with bad things and catch flowers. ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/hotnews.htm ================================================ //#- //#excludeif true NEWS //#+ //#local l_cnewsNewsFile = xml_root(xml_open("hotnews.xml")) //#local l_cnewsNewsList = xml_list(l_cnewsNewsFile,"news") //#local l_cnewsIndex = 0 //#while l_cnewsIndex //#else read more... //#endif //#local l_cnewsIndex = l_cnewsIndex + 1 //#end
/*$l_cnewsName$*/
/*$l_cnewsContent$*/
//#if curLangID=="rus" ...
//#- //#+ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/hotnews.xml ================================================ Papanin's quest Увлекательная игра "Papanin's quest" для Nokia Series 60, доступна на Playmobile. http://www.playmobile.ru/games/arcade/Papanins_Quest Papanin's quest The Papanin's quest game for Nokia Series 60 has been available on Playmobile. http://www.playmobile.ru/games/arcade/Papanins_Quest Mobile chase Увлекательнейшая гонка с элементами шутера "Mobile Chase" для Nokia Series 60, доступна на Playmobile. http://www.playmobile.ru/games/race/Mobile_Chase Mobile chase Super racing game "Mobile Chase" (contains elements of shooter) for Nokia Series 60 has been available on Playmobile. http://www.playmobile.ru/games/race/Mobile_Chase Air aggression Аркада "Air aggression" для Nokia Series 60, доступна на Playmobile. http://www.playmobile.ru/games/shooter/Air_Aggression Air aggression The arcade game "Air aggression" for Nokia Series 60 has been available on Playmobile. http://www.playmobile.ru/games/shooter/Air_Aggression Caspian monster Очень красочный скроллшутер "Caspian monster" для Nokia Series 60, доступен на Playmobile. http://www.playmobile.ru/games/shooter/Caspian_monster Caspian monster The scrollshooter "Caspian monster" for Nokia Series 60 has been available on Playmobile. http://www.playmobile.ru/games/shooter/Caspian_monster Kalah Восточная игра Калах, теперь имеет свою уникальную интерпретацию на мобильных телефонах Nokia Series 60 и доступна на Playmobile. http://www.playmobile.ru/games/logic/Kalah Kalah The east game Kalah has excellent mobile verison for Nokia Series 60 what has been available on Playmobile http://www.playmobile.ru/games/logic/Kalah ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/index.htm ================================================ ColdCore official site
Cold Core
================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/job.htm ================================================ //#- //#excludeif true Sorry, the page is still under construction //#+

Sorry, but the page is still under construction....

Visit us later, please...

//#- //#+ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/loadpages/muzon_AirBoil.htm ================================================ Java-: Air Boil
Air Boil




5008485
?

SMS-.

5008485

SMS- :
- 9998
, , , , , , , , , , , , , , , , , , , , 9998
- 9998
, , , , , , , , , , , , , , , , , -, , , , , , , , , -, , , , , , , , , , , , , , - , , 9998

SMS- $2,50 .

WAP-,

( ).

:
Motorola: C380, C650, v220, v180, v300, v500, v600, v535, v550, v620, E398, E375, v3
Nokia: 3510i, 7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i, 6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270, 3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD, 7610, 6260, 6670, 3230
Samsung: C100, C108T, C110, S300, S300M, S307, E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468, X100, X108, X600, X608
Siemens: M55, C60, MC60, S55, SL55, S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65, C65, SL65
LG: G1600
Sony Ericsson: T610, T616, T618, T628, T630, T637, Z600, Z608


================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/loadpages/muzon_StarHarbor.htm ================================================ Java-: Star Harbor
Star Harbor




5006971
?

SMS-.

5006971

SMS- :
- 4012
, , , , , , , , , , , , , , , , , , , , 4012
- 4012
, , , , , , , , , , , , , , , , , -, , , , , , , , , -, , , , , , , , , , , , , , - , , 4012

SMS- $2,50 .

WAP-,

( ).

:
Motorola: C380, C650, v220, v180, v300, v500, v600, v535, v550, v620, E398, E375, v3
Nokia: 3410, 3510i, 7210, 3100, 3105, 3108, 3120, 3125, 3200, 3205, 3300, 5100, 6100, 6108, 6200, 6220, 6225, 6585, 6610, 6610i, 6800, 7200, 7250,7250i, 6230, 5140, 5140, 6170, 6255, 6020, 7260, 7270, 3650, 3600, 3620, 3660, 7650, N-Gage, N-GageQD, 7610, 6260, 6670, 3230
Samsung: C100, C108T, C110, S300, S300M, S307, E100, E108, E330, E338, E630, E638, E700, E708, E800, E808, E820, X460, X468, X100, X108, X600, X608
Siemens: M(T)50, C55, C56, CT56, 6688i, M46, 3118, SL45i, M55, C60, MC60, S55, SL55, S65, CX65, CXT65, CXV65, CX66, CX70, M65, M6V, M6C, S6V, S6C, S66, SK65, C65, SL65
LG: G1600
Sony Ericsson: T610, T616, T618, T628, T630, T637, Z600, Z608


================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/main.htm ================================================ //#local site_file = xml_root(xml_open("site.xml")) //#local games_file = xml_root(xml_open("games.xml")) //#local games_list = xml_list(xml_get(xml_list(games_file,"games"),0),"game") //#local languages= xml_list(xml_get(xml_list(site_file,"languages"),0),"lang") //#local langsNumber = xml_size(languages) //#local langIndex = 0 //#while langIndex0 //#local menuList = xml_list(site_file,"menu"+menuMainIndex) //#if xml_size(menuList)==0 //#local menuList=-1 //#local menuMainIndex = -1 //#continue //#endif //#local menuList = xml_get(menuList,0) //#local menuSubIndex = 0 //#local submenuList = xml_list(menuList,"item") //#local rootMenuNameText = xml_list(menuList,"textname") //#local rootMenuNameID = "menu"+menuMainIndex //#if xml_size(rootMenuNameText)==0 //#local rootMenuNameText="" //#else //#local rootMenuNameText = xml_get(rootMenuNameText,0) //#local rootMenuNameText=str2web(xml_text(xml_get(xml_list(rootMenuNameText,curLangID),0))) //#endif //#local submenuItemsNumber = xml_size(submenuList) //#echo SUBITEMS: /*$submenuItemsNumber$*/ //#while menuSubIndex //#local pageHeader = str2web(xml_text(xml_get(xml_list(xml_get(xml_list(site_file,"header"),0),curLangID),0))) //#if strlen(rootMenuNameText)==0 //#local rootMenuNameText2="/" //#else //#local rootMenuNameText2="/"+rootMenuNameText+"/" //#endif /*$pageHeader+rootMenuNameText2+currentItemText$*/
ColdCore(R)
 
Buy a bit of Game(TM)
//#else //#if curLangID=="rus"
НАВИГАЦИЯ
//#endif //#endif

//#local li = 0 //#while li
/*$locLangText$*/
//#else
//#endif //#local li = li +1 //#end

 
//#include "./"+"hotnews.htm"

//#local footer = xml_text(xml_get(xml_list(xml_get(xml_list(site_file,"footer"),0),curLangID),0))
//#flush //#local menuSubIndex = menuSubIndex + 1 //#end //#local menuMainIndex = menuMainIndex +1 //#end //#local langIndex = langIndex+1 //#end //#outname "end.txt" ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/news.htm ================================================ //#- //#excludeif true NEWS //#+ //#local l_newsList = xml_list(xml_root(xml_open("news.xml")),"news") //#local l_newsIndex = 0 //#while l_newsIndex
/*$l_newsDate$*/
  //#local l_newsScreen=1 //#while true //#local l_newsCurScreen = xml_list(l_newsCurrentNews,"scr"+l_newsScreen) //#if xml_size(l_newsCurScreen)==0 //#break //#endif //#local l_newsScreenHREF = xml_text(xml_get(l_newsCurScreen,0)) /*$ //#local l_newsScreen = l_newsScreen + 1 //#end
/*$l_newsCurrentNewsContent$*/
//#if strlen(l_newsCurrentLink)>0
//#if curLangID=="rus" ... //#else read more... //#endif
//#endif
//#local l_newsIndex = l_newsIndex + 1 //#end //#- //#+ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/news.xml ================================================ ../games/aneks_ny2006_scr1.gif ../games/aneks_ny2006_scr3.gif Выпущен сборник из серии "Анекдоты" на Новогоднюю тему. В сборник вошло 60 анекдотов. Приложение поддерживает практически все мобильные телефоны с платформой MIDP-1.0 The collection "Ney Year's jokes" has been completed. The collection includes 60 jokes. It supports all MIDP-1.0 Java2ME mobile devices. ../games/slider_alpop_scr1.gif Вышел слайдер по мультфильму "Алеша Попович и Тугарин Змей". Слайдер содержит 10 красочных кадров из мультфильма и текст. The slide-show "Aleosha Popovich and Toogarin Zmey" has been completed. The slide-show includes 10 frames from the cartoon film and texts. ../games/smscat_scr2.gif ../games/smscat_scr3.gif Закончена разработка приложения "SMS Catalog". Приложение позволяет потенциальным клиентам ознакамливаться с содержимым базы контент-провайдера, организованной в удобном древовидном представлении и (если телефон позволяет) формировать SMS с заказом понравившегося контента. The "SMS Catalog" application has been developed. It enables for user to look through a content provider base and order liked content with automatically generated SMS (if the device is supporting). ../games/airboil_scr1.gif ../games/airboil_scr3.gif Вышла игра "Air Boil". Игра является аркадой выполненной в классическом стиле. Игроку требуется проходить игровые уровни с нарастающей сложностью, каждая группа уровней заканчивается встречей с "боссом". The game "Air Boil" has been completed. The game is a classic style arcade game. A player should pass game stages. Game stages have different difficult of the gameplay, every group of game stages has a game "boss" what must be destroyed by the player. ../games/starharbor_scr1.gif ../games/starharbor_scr2.gif Ушла в продажу игра "Star Harbor". Игра является псевдотрехмерным шутером от первого лица. Игрок играет за стрелка турели космического крейсера и его задача - отразить вторжение инопланетных сил на Землю. Игра имеет три уровня сложности и входит в разряд timekiller приложений. Поддерживает более 100 моделей телефонов, в том числе несколько черно-белых моделей Nokia и Siemens. The "Star Harbor" game has come into the market. The game is a pseudo 3d shooter. A player is a brawe star cruiser gunner and the task is to destroy both enemy cruisers and fighters that are attacking the Earth. It is a timekiller game and it has three levels of complexity. The game supports more than 100 models of mobile devices including a few black white devices of Nokia and Siemens. Альфа-версия сайта выложена в интернет. К сожалению не все разделы еще функционируют, но как говорится "..это большой шаг для всего человечества". The alpha version of the site has been placed in the net. Unfortunately a few pages of the site are not working but we're working for it. ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/partnership.htm ================================================ //#- //#excludeif true Sorry, the page is still under construction //#+

Sorry, but the page is still under construction....

Visit us later, please...

//#- //#+ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/rus/send_error.html ================================================ .

, . .
 
================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/rus/send_ok.html ================================================ .

. !
 
================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/site.xml ================================================
ColdCore ColdCore
НОВОСТИ NEWS О НАС ABOUT ПАРТНЕРСТВО PARTNERSHIP ВАКАНСИИ JOB КОНТАКТЫ CONTACTS ИГРЫ GAMES ВСЕ ALL АРКАДЫ ARCADE ЭРОТИЧЕСКИЕ EROTIC ДРАКИ FIGHTING АЗАРТНЫЕ GAMBLING ЛОГИЧЕСКИЕ PUZZLE МУЛЬТИПЛЕЕР MULTIPLAYER КЛИЕНТ-СЕРВЕР CLIENT-SERVER КВЕСТЫ QUEST ГОНКИ RACING СТРЕЛЯЛКИ SHOOTER СПОРТ SPORT ПРИЛОЖЕНИЯ APPLICATIONS ВСЕ ALL
Copyright © ColdCore® 2005-2007. Символы "™" и "®" показывают торговые марки и зарегистрированные торговые марки их полноправных владельцев. © 2005-2007 ColdCore®. All rights reserved. "™" and "®" indicate trademarks or registered trademarks of their respective owners.
================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StaticSiteTest/src/wap/index.wml ================================================

ColdCore(R)

Sorry, under construction...

================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/Str2JavaTest/etl/text.txt ================================================ public class Hello { public void say() { System.out.println("Hello"); } } public class Test { public static void main(String[] args) throws Exception { ClassPool cp = ClassPool.getDefault(); CtClass cc = cp.get("Hello"); CtMethod m = cc.getDeclaredMethod("say"); m.insertBefore( "System.out.println(\"Hello World\");\n" +"System.out.println(\"Hello World2\");\n" ); System.out.println("Just some string"); Class c = cc.toClass(); Hello h = (Hello)c.newInstance(); h.say(); } } ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/Str2JavaTest/src/body.txt ================================================ //#excludeif true //#- import some.package; public class Body { public void main(){ //#+ System.out.println("Hello World"); System.out.println("Hello World2"); //#- } } //#+ ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/Str2JavaTest/src/str.txt ================================================ //#excludeif true Just some string ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/Str2JavaTest/src/text.txt ================================================ public class Hello { public void say() { System.out.println("Hello"); } } public class Test { public static void main(String[] args) throws Exception { ClassPool cp = ClassPool.getDefault(); CtClass cc = cp.get("Hello"); CtMethod m = cc.getDeclaredMethod("say"); m.insertBefore( /*$str2java(evalfile("body.txt"),true)$*//*-*/"" ); System.out.println("/*$str2java(evalfile("str.txt"),false)$*/"); Class c = cc.toClass(); Hello h = (Hello)c.newInstance(); h.say(); } } ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StringDirectiveTest/etl/text.txt ================================================ expected world expected /*$HELLO$*/ test ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/StringDirectiveTest/src/text.txt ================================================ //#define HELLO "world" //#if false //$ unexpected /*$HELLO$*/ //#else //$ expected /*$HELLO$*/ //#endif //#if false //$$ unexpected /*$HELLO$*/ //#else //$$ expected /*$HELLO$*/ //#endif //#if false test /*-*/unexpected //#else test /*-*/expected //#endif ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/TextBufferVariablesTest/etl/text.txt ================================================ set prefix--- Some block text which will be placed into a variable as multiline text and prefix buffer is used to accumulate it === --- Some block text which will be placed into a variable as multiline text and prefix buffer is used to accumulate it === ... set postfix ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/TextBufferVariablesTest/src/text.txt ================================================ //#postfix+ defined postfix //#postfix- //#prefix+ Some block text which will be placed into a variable as multiline text and prefix buffer is used to accumulate it //#prefix- //#local multiline_prefix = jcp.text.buffer.prefix //#local jcp.text.buffer.prefix="set prefix" //#local jcp.text.buffer.postfix="set postfix" --- //$/*$multiline_prefix$*/ === //$/*$jcp.text.buffer.middle$*/ ... ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/UnknownVarAsFalseTest/etl/body.txt ================================================ false 123false must be huzzaaaaa! --- ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/UnknownVarAsFalseTest/src/body.txt ================================================ /*$UNKNOWN_VAR$*/ /*$"123"+UGUMS$*/ //#if !ANOTHER_UNKNWOWN must be //#else must not be //#endif //#ifndef HUZZAA huzzaaaaa! //#endif //#ifdefined SOMEUNKNOWN hmmmmmm //#endif //#ifdef HMMML noooooo!!!!! //#endif --- ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/UsePrefixAsMultilineTest/etl/text.txt ================================================ package test; public class Main { public static final int mul(int a, b) { return a * b; } public static final int div(int a, b) { return a / b; } } ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/UsePrefixAsMultilineTest/src/text.txt ================================================ //#prefix+ //$ public static final int mul(int a, b) { //$ return a * b; //$ } //#prefix- //#postfix+ //$ public static final int div(int a, b) { //$ return a / b; //$ } //#postfix- //#local mul_func = jcp.text.buffer.prefix //#local div_func = jcp.text.buffer.postfix //#local jcp.text.buffer.prefix = "" //#local jcp.text.buffer.postfix = "" package test; public class Main { /*$mul_func$*/ /*$div_func$*/ } ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/UserFunctionTest/etl/text.txt ================================================ hello test:yayaya ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/usecases/UserFunctionTest/src/text.txt ================================================ //#action 1000,"hello",123 hello /*$"test:"+$testfunc(1,"hry",3)$*/ //#action 1000,"hello",123 ================================================ FILE: jcp/src/test/resources/com/igormaznitsa/jcp/utils/somefile.txt ================================================ it's just a some file ================================================ FILE: jcp-tests/jcp-test-android/app/build.gradle ================================================ // section for preprocessor buildscript { repositories { flatDir dirs: "../../../jcp/target" } dependencies { classpath "com.igormaznitsa:jcp:" + project.getProperty("jcp_plugin_version") } } apply plugin: 'com.igormaznitsa.jcp' // end section for preprocessor apply plugin: 'com.android.application' android { compileSdkVersion 28 defaultConfig { applicationId "android.it.igormaznitsa.com.jcpandroid" minSdkVersion 15 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'com.android.support:design:28.0.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } preprocess { sources = android.sourceSets.main.java.srcDirs keepComments = false actionPreprocessorExtensions = ["com.igormaznitsa.jcp.extension.LogPreprocessorExtension"] vars = [ 'action.text' : 'Non-secret action!', 'remove.secret': 'true' ] } task(changeSourceFolder) { android.sourceSets.main.java.srcDirs = [preprocess.target] }.dependsOn preprocess preBuild.dependsOn preprocess ================================================ FILE: jcp-tests/jcp-test-android/app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the # proguardFiles setting in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} # Uncomment this to preserve the line number information for # debugging stack traces. #-keepattributes SourceFile,LineNumberTable # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile ================================================ FILE: jcp-tests/jcp-test-android/app/src/androidTest/java/android/it/igormaznitsa/com/jcpandroid/ExampleInstrumentedTest.java ================================================ package android.it.igormaznitsa.com.jcpandroid; import android.content.Context; import android.it.igormaznitsa.com.jcpandroid.utils.Utils; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.*; @RunWith(AndroidJUnit4.class) public class ExampleInstrumentedTest { @Test public void useAppContext() { Context appContext = InstrumentationRegistry.getTargetContext(); assertEquals("android.it.igormaznitsa.com.jcpandroid", appContext.getPackageName()); } } ================================================ FILE: jcp-tests/jcp-test-android/app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: jcp-tests/jcp-test-android/app/src/main/java/android/it/igormaznitsa/com/jcpandroid/MainActivity.java ================================================ package android.it.igormaznitsa.com.jcpandroid; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //#if remove.secret //$ Snackbar.make(view, "/*$action.text$*/", Snackbar.LENGTH_LONG).setAction("Action", null).show(); //#else Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG).setAction("Action", null).show(); //#endif } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } } ================================================ FILE: jcp-tests/jcp-test-android/app/src/main/java/android/it/igormaznitsa/com/jcpandroid/utils/Utils.java ================================================ package android.it.igormaznitsa.com.jcpandroid.utils; public final class Utils { private Utils(){ } //#if remove.secret //$public static String makeSecretPassword() { //$ return "testPassword"; //$} //#else public static String makeSecretPassword() { return "122sdsferSSADSD123232"; } //#endif } ================================================ FILE: jcp-tests/jcp-test-android/app/src/main/res/drawable/ic_launcher_background.xml ================================================ ================================================ FILE: jcp-tests/jcp-test-android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml ================================================ ================================================ FILE: jcp-tests/jcp-test-android/app/src/main/res/layout/activity_main.xml ================================================ ================================================ FILE: jcp-tests/jcp-test-android/app/src/main/res/layout/content_main.xml ================================================ ================================================ FILE: jcp-tests/jcp-test-android/app/src/main/res/menu/menu_main.xml ================================================ ================================================ FILE: jcp-tests/jcp-test-android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml ================================================ ================================================ FILE: jcp-tests/jcp-test-android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml ================================================ ================================================ FILE: jcp-tests/jcp-test-android/app/src/main/res/values/colors.xml ================================================ #008577 #00574B #D81B60 ================================================ FILE: jcp-tests/jcp-test-android/app/src/main/res/values/dimens.xml ================================================ 16dp ================================================ FILE: jcp-tests/jcp-test-android/app/src/main/res/values/strings.xml ================================================ JcpAndroid Settings ================================================ FILE: jcp-tests/jcp-test-android/app/src/main/res/values/styles.xml ================================================