├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── build.gradle ├── gradle ├── bintray.gradle ├── jacoco.gradle ├── jtwig-version.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── main └── java │ └── org │ └── jtwig │ ├── JtwigModel.java │ ├── JtwigTemplate.java │ ├── environment │ ├── DefaultEnvironmentConfiguration.java │ ├── Environment.java │ ├── EnvironmentConfiguration.java │ ├── EnvironmentConfigurationBuilder.java │ ├── EnvironmentFactory.java │ ├── EnvironmentHolder.java │ ├── and │ │ ├── AndBuilder.java │ │ ├── AndEscapeEngineConfigurationBuilder.java │ │ ├── AndJtwigParserConfigurationBuilder.java │ │ ├── AndPropertyResolverConfigurationBuilder.java │ │ ├── AndRenderConfigurationBuilder.java │ │ ├── AndResourceConfigurationBuilder.java │ │ └── AndValueConfigurationBuilder.java │ └── initializer │ │ └── EnvironmentInitializer.java │ ├── escape │ ├── EscapeEngine.java │ ├── EscapeEngineSelector.java │ ├── HtmlEscapeEngine.java │ ├── JavascriptEscapeEngine.java │ ├── NoneEscapeEngine.java │ ├── config │ │ ├── DefaultEscapeEngineConfiguration.java │ │ ├── EscapeEngineConfiguration.java │ │ └── EscapeEngineConfigurationBuilder.java │ └── environment │ │ ├── EscapeEnvironment.java │ │ └── EscapeEnvironmentFactory.java │ ├── exceptions │ ├── CalculationException.java │ ├── InvalidFunctionNameException.java │ ├── JtwigException.java │ └── ResolveValueException.java │ ├── extension │ └── Extension.java │ ├── functions │ ├── EmptyExpressionResolver.java │ ├── ExpressionResolver.java │ ├── FunctionArguments.java │ ├── FunctionRequest.java │ ├── FunctionRequestFactory.java │ ├── JtwigFunction.java │ ├── SimpleJtwigFunction.java │ ├── annotations │ │ ├── JtwigFunction.java │ │ └── Parameter.java │ ├── config │ │ └── DefaultJtwigFunctionList.java │ ├── environment │ │ └── FunctionResolverFactory.java │ ├── impl │ │ ├── control │ │ │ ├── EscapeFunction.java │ │ │ └── RawFunction.java │ │ ├── date │ │ │ └── DateFormatFunction.java │ │ ├── java │ │ │ ├── ClassFunction.java │ │ │ └── ConstantFunction.java │ │ ├── list │ │ │ ├── BatchFunction.java │ │ │ ├── ConcatenateFunction.java │ │ │ ├── JoinFunction.java │ │ │ ├── MergeFunction.java │ │ │ ├── SliceFunction.java │ │ │ └── SortFunction.java │ │ ├── logical │ │ │ ├── DefinedFunction.java │ │ │ ├── EmptyFunction.java │ │ │ ├── EvenFunction.java │ │ │ ├── IterableFunction.java │ │ │ └── OddFunction.java │ │ ├── map │ │ │ └── KeysFunction.java │ │ ├── math │ │ │ ├── AbsFunction.java │ │ │ └── RoundFunction.java │ │ ├── mixed │ │ │ ├── DefaultFunction.java │ │ │ ├── DumpFunction.java │ │ │ ├── FirstFunction.java │ │ │ ├── LastFunction.java │ │ │ ├── LengthFunction.java │ │ │ ├── ReverseFunction.java │ │ │ └── UrlEncodeFunction.java │ │ ├── string │ │ │ ├── CapitalizeFunction.java │ │ │ ├── ConvertEncodingFunction.java │ │ │ ├── FormatFunction.java │ │ │ ├── LowerFunction.java │ │ │ ├── NlToBrFunction.java │ │ │ ├── NumberFormatFunction.java │ │ │ ├── ReplaceFunction.java │ │ │ ├── SplitFunction.java │ │ │ ├── StripTagsFunction.java │ │ │ ├── TitleFunction.java │ │ │ ├── TrimFunction.java │ │ │ └── UpperFunction.java │ │ └── structural │ │ │ ├── BlockFunction.java │ │ │ ├── NodeRenderHelper.java │ │ │ ├── ParentFunction.java │ │ │ └── exceptions │ │ │ ├── ParentFunctionOutsideBlockException.java │ │ │ └── ParentFunctionWithoutExtending.java │ └── resolver │ │ ├── CoreFunctionResolver.java │ │ ├── FunctionResolver.java │ │ ├── FunctionValueSupplier.java │ │ └── FunctionValueSupplierFactory.java │ ├── macro │ ├── ImportedMacros.java │ ├── Macro.java │ └── render │ │ ├── ImportRender.java │ │ └── MacroRender.java │ ├── model │ ├── expression │ │ ├── BinaryOperationExpression.java │ │ ├── ComprehensionListExpression.java │ │ ├── ConstantExpression.java │ │ ├── EnumeratedListExpression.java │ │ ├── Expression.java │ │ ├── FunctionExpression.java │ │ ├── InjectableExpression.java │ │ ├── MapExpression.java │ │ ├── MapSelectionExpression.java │ │ ├── TernaryOperationExpression.java │ │ ├── TestOperationExpression.java │ │ ├── UnaryOperationExpression.java │ │ ├── VariableExpression.java │ │ └── test │ │ │ ├── DefinedTestExpression.java │ │ │ ├── DivisibleByTestExpression.java │ │ │ ├── FunctionTestExpression.java │ │ │ ├── IsFunctionTestExpression.java │ │ │ ├── NotTestExpression.java │ │ │ ├── NullTestExpression.java │ │ │ ├── SameAsTestExpression.java │ │ │ └── TestExpression.java │ ├── position │ │ ├── Position.java │ │ └── Traceable.java │ └── tree │ │ ├── AutoEscapeNode.java │ │ ├── BlockNode.java │ │ ├── CompositeNode.java │ │ ├── ContentEscapeNode.java │ │ ├── ContentNode.java │ │ ├── DoNode.java │ │ ├── EmbedNode.java │ │ ├── ExtendsNode.java │ │ ├── FilterNode.java │ │ ├── FlushNode.java │ │ ├── ForLoopNode.java │ │ ├── IfNode.java │ │ ├── ImportNode.java │ │ ├── ImportSelfNode.java │ │ ├── IncludeNode.java │ │ ├── MacroNode.java │ │ ├── Node.java │ │ ├── OutputNode.java │ │ ├── OverrideBlockNode.java │ │ ├── SetNode.java │ │ ├── TextNode.java │ │ ├── VerbatimNode.java │ │ ├── include │ │ └── IncludeConfiguration.java │ │ └── visitor │ │ └── NodeVisitor.java │ ├── parser │ ├── CachedJtwigParser.java │ ├── JtwigParser.java │ ├── JtwigParserFactory.java │ ├── ParseException.java │ ├── addon │ │ └── AddonParserProvider.java │ ├── cache │ │ ├── InMemoryConcurrentPersistentTemplateCache.java │ │ ├── RetrieveFuture.java │ │ └── TemplateCache.java │ ├── config │ │ ├── AndSyntaxConfigurationBuilder.java │ │ ├── DefaultJtwigParserConfiguration.java │ │ ├── DefaultSyntaxConfiguration.java │ │ ├── JtwigParserConfiguration.java │ │ ├── JtwigParserConfigurationBuilder.java │ │ ├── SyntaxConfiguration.java │ │ └── SyntaxConfigurationBuilder.java │ ├── parboiled │ │ ├── DocumentParser.java │ │ ├── ParboiledJtwigParser.java │ │ ├── ParserContext.java │ │ ├── base │ │ │ ├── BasicParser.java │ │ │ ├── BooleanParser.java │ │ │ ├── LexicParser.java │ │ │ ├── LimitsParser.java │ │ │ ├── PositionTrackerParser.java │ │ │ └── SpacingParser.java │ │ ├── expression │ │ │ ├── AnyExpressionParser.java │ │ │ ├── BinaryOperationExpressionParser.java │ │ │ ├── BinaryOperationSuffixExpressionParser.java │ │ │ ├── BinaryOrPrimaryExpressionParser.java │ │ │ ├── BooleanExpressionParser.java │ │ │ ├── ComprehensionListExpressionParser.java │ │ │ ├── ConstantExpressionParser.java │ │ │ ├── EnumerationListExpressionParser.java │ │ │ ├── ExpressionParser.java │ │ │ ├── FunctionExpressionParser.java │ │ │ ├── MapExpressionParser.java │ │ │ ├── MapSelectionExpressionParser.java │ │ │ ├── NullExpressionParser.java │ │ │ ├── NumberExpressionParser.java │ │ │ ├── PrimaryExpressionParser.java │ │ │ ├── SimpleExpressionParser.java │ │ │ ├── StringExpressionParser.java │ │ │ ├── TernaryOperationExpressionParser.java │ │ │ ├── TestOperationExpressionParser.java │ │ │ ├── UnaryOperationExpressionParser.java │ │ │ ├── VariableExpressionParser.java │ │ │ ├── operator │ │ │ │ ├── BinaryOperatorParser.java │ │ │ │ └── UnaryOperatorParser.java │ │ │ └── test │ │ │ │ ├── AnyTestExpressionParser.java │ │ │ │ ├── DefinedTestExpressionParser.java │ │ │ │ ├── DivisibleByTestExpressionParser.java │ │ │ │ ├── FunctionTestExpressionParser.java │ │ │ │ ├── IsFunctionTestExpressionParser.java │ │ │ │ ├── NullTestExpressionParser.java │ │ │ │ ├── SameAsTestExpressionParser.java │ │ │ │ └── TestExpressionParser.java │ │ ├── model │ │ │ ├── Keyword.java │ │ │ └── LimitProperties.java │ │ └── node │ │ │ ├── AddonParser.java │ │ │ ├── AutoEscapeNodeParser.java │ │ │ ├── BlockNodeParser.java │ │ │ ├── CommentParser.java │ │ │ ├── CompositeNodeParser.java │ │ │ ├── ContentEscapeNodeParser.java │ │ │ ├── DoNodeParser.java │ │ │ ├── EmbedNodeParser.java │ │ │ ├── ExtendsNodeParser.java │ │ │ ├── FilterNodeParser.java │ │ │ ├── FlushNodeParser.java │ │ │ ├── ForLoopNodeParser.java │ │ │ ├── IfNodeParser.java │ │ │ ├── ImportNodeParser.java │ │ │ ├── ImportSelfNodeParser.java │ │ │ ├── IncludeNodeParser.java │ │ │ ├── MacroNodeParser.java │ │ │ ├── NodeParser.java │ │ │ ├── OutputNodeParser.java │ │ │ ├── OverrideBlockNodeParser.java │ │ │ ├── SetNodeParser.java │ │ │ ├── TextNodeParser.java │ │ │ └── VerbatimNodeParser.java │ └── util │ │ └── ParboiledExceptionMessageExtractor.java │ ├── property │ ├── configuration │ │ ├── DefaultPropertyResolverConfiguration.java │ │ ├── PropertyResolverConfiguration.java │ │ └── PropertyResolverConfigurationBuilder.java │ ├── environment │ │ ├── PropertyResolverEnvironment.java │ │ └── PropertyResolverEnvironmentFactory.java │ ├── resolver │ │ ├── CallMethodPropertyResolver.java │ │ ├── EmptyPropertyResolver.java │ │ ├── FieldPropertyResolver.java │ │ ├── MacroPropertyResolver.java │ │ ├── MapPropertyResolver.java │ │ ├── MethodPropertyResolver.java │ │ ├── PropertyResolver.java │ │ ├── ValueContextPropertyResolver.java │ │ └── request │ │ │ ├── ArgumentsExtractor.java │ │ │ ├── PropertyNameExtractor.java │ │ │ ├── PropertyResolveRequest.java │ │ │ └── PropertyResolveRequestFactory.java │ ├── selection │ │ ├── BaseSelectionPropertyResolver.java │ │ ├── CachedSelectionPropertyResolver.java │ │ ├── SelectionPropertyResolveService.java │ │ ├── SelectionPropertyResolver.java │ │ ├── SelectionRequest.java │ │ ├── SelectionResult.java │ │ └── cache │ │ │ ├── NoSelectionPropertyResolverCache.java │ │ │ ├── SelectionPropertyResolverCache.java │ │ │ ├── SelectionPropertyResolverCacheKey.java │ │ │ └── SelectionPropertyResolverPersistentCache.java │ └── strategy │ │ ├── FieldPropertyResolverStrategy.java │ │ ├── FunctionMethodPropertyResolverStrategy.java │ │ ├── GetMethodPropertyResolverStrategy.java │ │ ├── MacroPropertyResolverStrategy.java │ │ ├── MapPropertyResolverStrategy.java │ │ ├── PropertyResolverStrategy.java │ │ ├── ValueContextPropertyResolverStrategy.java │ │ ├── VariableMethodPropertyResolverStrategy.java │ │ └── method │ │ ├── ArgumentsConverter.java │ │ ├── FunctionArgumentCalculator.java │ │ ├── MethodArgumentsMatcher.java │ │ ├── MethodPropertyResolverFactory.java │ │ ├── argument │ │ ├── AssignableTypes.java │ │ ├── IsNativeType.java │ │ └── group │ │ │ ├── ArgumentGroup.java │ │ │ ├── GroupingArgumentsService.java │ │ │ ├── SingleArgumentGroup.java │ │ │ └── VarArgumentGroup.java │ │ ├── convert │ │ ├── Converter.java │ │ └── NativeTypeConverter.java │ │ └── finder │ │ ├── CompositePropertyMethodFinder.java │ │ ├── ExactMethodNamePropertyMethodFinder.java │ │ ├── PrefixedMethodNamePropertyMethodFinder.java │ │ └── PropertyMethodFinder.java │ ├── render │ ├── RenderRequest.java │ ├── RenderResourceRequest.java │ ├── RenderResourceService.java │ ├── config │ │ ├── DefaultRenderConfiguration.java │ │ ├── RenderConfiguration.java │ │ └── RenderConfigurationBuilder.java │ ├── context │ │ ├── Context.java │ │ ├── RenderContext.java │ │ ├── RenderContextHolder.java │ │ └── model │ │ │ ├── BlockContext.java │ │ │ ├── BlockDefinition.java │ │ │ ├── BlockReference.java │ │ │ └── PropertiesContext.java │ ├── environment │ │ ├── RenderEnvironment.java │ │ └── RenderEnvironmentFactory.java │ ├── expression │ │ ├── CalculateExpressionService.java │ │ ├── ExpressionCalculatorSelector.java │ │ ├── calculator │ │ │ ├── BinaryOperationExpressionCalculator.java │ │ │ ├── ComprehensionListExpressionCalculator.java │ │ │ ├── ConstantExpressionCalculator.java │ │ │ ├── EnumeratedListExpressionCalculator.java │ │ │ ├── ExpressionCalculator.java │ │ │ ├── FunctionArgumentsFactory.java │ │ │ ├── FunctionExpressionCalculator.java │ │ │ ├── MapExpressionCalculator.java │ │ │ ├── MapSelectionExpressionCalculator.java │ │ │ ├── TernaryExpressionCalculator.java │ │ │ ├── TestOperationExpressionCalculator.java │ │ │ ├── UnaryOperationExpressionCalculator.java │ │ │ ├── VariableExpressionCalculator.java │ │ │ ├── enumerated │ │ │ │ ├── CharAscendingOrderEnumerationListStrategy.java │ │ │ │ ├── CharDescendingOrderEnumerationListStrategy.java │ │ │ │ ├── CompositeEnumerationListStrategy.java │ │ │ │ ├── EnumerationListStrategy.java │ │ │ │ ├── IntegerAscendingOrderEnumerationListStrategy.java │ │ │ │ ├── IntegerDescendingOrderEnumerationListStrategy.java │ │ │ │ ├── config │ │ │ │ │ └── DefaultEnumerationListStrategyList.java │ │ │ │ └── environment │ │ │ │ │ └── EnumerationListStrategyFactory.java │ │ │ └── operation │ │ │ │ ├── binary │ │ │ │ ├── BinaryOperationCalculatorSelector.java │ │ │ │ ├── BinaryOperationService.java │ │ │ │ ├── BinaryOperator.java │ │ │ │ ├── calculators │ │ │ │ │ ├── AndOperationCalculator.java │ │ │ │ │ ├── BinaryOperationCalculator.java │ │ │ │ │ ├── BooleanOperationCalculator.java │ │ │ │ │ ├── CompositionOperationCalculator.java │ │ │ │ │ ├── ConcatOperationCalculator.java │ │ │ │ │ ├── DifferentOperationCalculator.java │ │ │ │ │ ├── DivideOperationCalculator.java │ │ │ │ │ ├── EquivalentOperationCalculator.java │ │ │ │ │ ├── GreaterOperationCalculator.java │ │ │ │ │ ├── GreaterOrEqualOperationCalculator.java │ │ │ │ │ ├── InOperationCalculator.java │ │ │ │ │ ├── IntegerDivideOperationCalculator.java │ │ │ │ │ ├── IntegerMultiplyOperationCalculator.java │ │ │ │ │ ├── LessOperationCalculator.java │ │ │ │ │ ├── LessOrEqualOperationCalculator.java │ │ │ │ │ ├── MatchesOperationCalculator.java │ │ │ │ │ ├── MathOperationCalculator.java │ │ │ │ │ ├── ModOperationCalculator.java │ │ │ │ │ ├── MultiplyOperationCalculator.java │ │ │ │ │ ├── OrOperationCalculator.java │ │ │ │ │ ├── SimpleBinaryBooleanCalculator.java │ │ │ │ │ ├── SimpleBinaryMathCalculator.java │ │ │ │ │ ├── SimpleBinaryOperationCalculator.java │ │ │ │ │ ├── SimpleOperationCalculator.java │ │ │ │ │ ├── SubtractOperationCalculator.java │ │ │ │ │ ├── SumOperationCalculator.java │ │ │ │ │ └── selection │ │ │ │ │ │ ├── SelectionErrorMessageGenerator.java │ │ │ │ │ │ └── SelectionOperationCalculator.java │ │ │ │ └── impl │ │ │ │ │ ├── AndOperator.java │ │ │ │ │ ├── CompositionOperator.java │ │ │ │ │ ├── ConcatOperator.java │ │ │ │ │ ├── DifferentOperator.java │ │ │ │ │ ├── DivideOperator.java │ │ │ │ │ ├── EquivalentOperator.java │ │ │ │ │ ├── GreaterOperator.java │ │ │ │ │ ├── GreaterOrEqualOperator.java │ │ │ │ │ ├── InOperator.java │ │ │ │ │ ├── IntDivideOperator.java │ │ │ │ │ ├── IntMultiplyOperator.java │ │ │ │ │ ├── LessOperator.java │ │ │ │ │ ├── LessOrEqualOperator.java │ │ │ │ │ ├── MatchesOperator.java │ │ │ │ │ ├── ModOperator.java │ │ │ │ │ ├── MultiplyOperator.java │ │ │ │ │ ├── OrOperator.java │ │ │ │ │ ├── SelectionOperator.java │ │ │ │ │ ├── SubtractOperator.java │ │ │ │ │ └── SumOperator.java │ │ │ │ └── unary │ │ │ │ ├── UnaryOperationCalculatorSelector.java │ │ │ │ ├── UnaryOperationService.java │ │ │ │ ├── UnaryOperator.java │ │ │ │ ├── calculators │ │ │ │ ├── NegativeOperationCalculator.java │ │ │ │ ├── NotOperationCalculator.java │ │ │ │ └── UnaryOperationCalculator.java │ │ │ │ └── impl │ │ │ │ ├── NegativeUnaryOperator.java │ │ │ │ └── NotUnaryOperator.java │ │ └── test │ │ │ ├── CalculateTestExpressionService.java │ │ │ ├── TestExpressionCalculatorSelector.java │ │ │ └── calculator │ │ │ ├── DefinedTestExpressionCalculator.java │ │ │ ├── DivisibleByTestExpressionCalculator.java │ │ │ ├── FunctionTestExpressionCalculator.java │ │ │ ├── IsFunctionTestExpressionCalculator.java │ │ │ ├── NotTestExpressionCalculator.java │ │ │ ├── NullTestExpressionCalculator.java │ │ │ ├── SameAsTestExpressionCalculator.java │ │ │ └── TestExpressionCalculator.java │ ├── listeners │ │ ├── RenderListener.java │ │ ├── RenderListenerRegistry.java │ │ ├── RenderStage.java │ │ └── StagedRenderListener.java │ └── node │ │ ├── NodeRenderSelector.java │ │ ├── RenderNodeService.java │ │ └── renderer │ │ ├── AutoEscapeNodeRender.java │ │ ├── BlockNodeRender.java │ │ ├── CompositeNodeRender.java │ │ ├── ContentEscapeNodeRender.java │ │ ├── DoNodeRender.java │ │ ├── EmbedNodeRender.java │ │ ├── ExtendsNodeRender.java │ │ ├── FilterNodeRender.java │ │ ├── FlushNodeRender.java │ │ ├── ForLoopNodeRender.java │ │ ├── IfNodeRender.java │ │ ├── ImportNodeRender.java │ │ ├── ImportSelfNodeRender.java │ │ ├── IncludeNodeRender.java │ │ ├── MacroNodeRender.java │ │ ├── NodeRender.java │ │ ├── OutputNodeRender.java │ │ ├── OverrideBlockNodeRender.java │ │ ├── SetNodeRender.java │ │ ├── TextNodeRender.java │ │ └── VerbatimNodeRender.java │ ├── renderable │ ├── RenderException.java │ ├── RenderResult.java │ ├── Renderable.java │ ├── StreamRenderResult.java │ ├── StringBuilderRenderResult.java │ └── impl │ │ ├── CompositeRenderable.java │ │ ├── EmptyRenderable.java │ │ ├── FlushRenderable.java │ │ ├── FutureRenderable.java │ │ ├── OverrideRenderable.java │ │ └── StringRenderable.java │ ├── resource │ ├── ResourceService.java │ ├── config │ │ ├── DefaultResourceConfiguration.java │ │ ├── ResourceConfiguration.java │ │ └── ResourceConfigurationBuilder.java │ ├── environment │ │ ├── ResourceEnvironment.java │ │ └── ResourceEnvironmentFactory.java │ ├── exceptions │ │ ├── ResourceException.java │ │ └── ResourceNotFoundException.java │ ├── loader │ │ ├── ClasspathResourceLoader.java │ │ ├── CompositeResourceLoader.java │ │ ├── FileResourceLoader.java │ │ ├── InMemoryResourceLoader.java │ │ ├── ResourceLoader.java │ │ ├── StringResourceLoader.java │ │ └── TypedResourceLoader.java │ ├── metadata │ │ ├── EmptyResourceMetadata.java │ │ ├── ResourceMetadata.java │ │ └── ResourceResourceMetadata.java │ ├── reference │ │ ├── DefaultResourceReferenceExtractor.java │ │ ├── PosixResourceReferenceExtractor.java │ │ ├── ResourceReference.java │ │ ├── ResourceReferenceExtractor.java │ │ ├── UncResourceReferenceExtractor.java │ │ └── path │ │ │ ├── PathType.java │ │ │ └── PathTypeSupplier.java │ └── resolver │ │ ├── ReferenceRelativeResourceResolver.java │ │ ├── RelativeResourceResolver.java │ │ └── path │ │ ├── RelativeFilePathResolver.java │ │ ├── RelativePathResolver.java │ │ └── RelativeReferenceResolver.java │ ├── util │ ├── ClasspathFinder.java │ ├── ErrorMessageFormatter.java │ ├── EscapeUtils.java │ ├── FunctionValueUtils.java │ ├── HtmlUtils.java │ ├── LoopCursor.java │ ├── UrlEncodingUtils.java │ └── builder │ │ ├── ListBuilder.java │ │ └── MapBuilder.java │ └── value │ ├── Undefined.java │ ├── WrappedCollection.java │ ├── compare │ ├── DefaultValueComparator.java │ └── ValueComparator.java │ ├── config │ ├── DefaultValueConfiguration.java │ ├── ValueConfiguration.java │ └── ValueConfigurationBuilder.java │ ├── context │ ├── IsolateParentValueContext.java │ ├── JtwigModelValueContext.java │ ├── MapValueContext.java │ ├── StaticVariableValueContext.java │ └── ValueContext.java │ ├── convert │ ├── CompositeConverter.java │ ├── Converter.java │ ├── NullConverter.java │ ├── bool │ │ └── BooleanConverter.java │ ├── character │ │ └── CharConverter.java │ ├── collection │ │ ├── ArrayToCollectionConverter.java │ │ ├── IterableToCollectionConverter.java │ │ └── MapToCollectionConverter.java │ ├── number │ │ └── BigDecimalConverter.java │ └── string │ │ ├── DefaultStringConverter.java │ │ └── StringConverter.java │ └── environment │ ├── ValueEnvironment.java │ └── ValueEnvironmentFactory.java └── test ├── java └── org │ └── jtwig │ ├── JtwigModelTest.java │ ├── JtwigTemplateTest.java │ ├── TestUtils.java │ ├── cache │ └── SelectionPropertyResolverPersistentCacheTest.java │ ├── environment │ ├── EnvironmentConfigurationBuilderTest.java │ ├── EnvironmentFactoryTest.java │ └── EnvironmentTest.java │ ├── escape │ └── config │ │ └── EscapeEngineConfigurationBuilderTest.java │ ├── functions │ ├── EmptyExpressionResolverTest.java │ ├── FunctionArgumentsTest.java │ ├── FunctionRequestTest.java │ ├── impl │ │ ├── AbstractFunctionTest.java │ │ ├── ParentFunctionTest.java │ │ ├── java │ │ │ └── ConstantFunctionTest.java │ │ ├── map │ │ │ └── KeysFunctionTest.java │ │ ├── mixed │ │ │ └── DumpFunctionTest.java │ │ └── structural │ │ │ └── ParentFunctionExceptionTest.java │ └── resolver │ │ └── FunctionResolverFactoryTest.java │ ├── integration │ ├── AbstractIntegrationTest.java │ ├── WhiteSpaceControlTest.java │ ├── addon │ │ └── AddOnParserTest.java │ ├── configuration │ │ ├── CacheConfigurationTest.java │ │ └── StrictModeTest.java │ ├── expression │ │ ├── CompositionTest.java │ │ ├── ConstantExpressionTest.java │ │ ├── ContentEscapeTest.java │ │ ├── FunctionTest.java │ │ ├── InTest.java │ │ ├── IsTest.java │ │ ├── ListTest.java │ │ ├── MapSelectionTest.java │ │ ├── MapTest.java │ │ ├── OperatorPrecedenceTest.java │ │ ├── PolymorphicVariableTest.java │ │ ├── PrintingBooleanTest.java │ │ ├── RelationalOperatorsTest.java │ │ ├── SelectionTest.java │ │ ├── TernaryOperatorTest.java │ │ ├── TestExpressionTest.java │ │ ├── VariableNestedAccessTest.java │ │ ├── VariableTest.java │ │ └── binary │ │ │ ├── ComparisonOperatorsTest.java │ │ │ ├── LogicOperatorsTest.java │ │ │ ├── MatchesComparatorTest.java │ │ │ └── MathOperatorsTest.java │ ├── function │ │ ├── AbsFunctionTest.java │ │ ├── BatchFunctionTest.java │ │ ├── BlockFunctionTest.java │ │ ├── CapitalizeFunctionTest.java │ │ ├── ClassFunctionTest.java │ │ ├── ConcatFunctionTest.java │ │ ├── ConstantFunctionTest.java │ │ ├── ConvertEncodingFunctionTest.java │ │ ├── DateFunctionTest.java │ │ ├── DefaultFunctionTest.java │ │ ├── DefinedFunctionTest.java │ │ ├── EmptyFunctionTest.java │ │ ├── EscapeRawTest.java │ │ ├── FirstFunctionTest.java │ │ ├── FormatFunctionTest.java │ │ ├── IterableFunctionTest.java │ │ ├── JoinFunctionTest.java │ │ ├── LastFunctionTest.java │ │ ├── LengthFunctionTest.java │ │ ├── MergeFunctionTest.java │ │ ├── Nl2BrFunctionTest.java │ │ ├── NonExistingFunctionTest.java │ │ ├── NumberFormatFunctionTest.java │ │ ├── OddEvenFunctionTest.java │ │ ├── ReplaceFunctionTest.java │ │ ├── ReverseFunctionTest.java │ │ ├── RoundFunctionTest.java │ │ ├── SliceFunctionTest.java │ │ ├── SortFunctionTest.java │ │ ├── SplitFunctionTest.java │ │ ├── StripTagsFunctionTest.java │ │ ├── TitleFunctionTest.java │ │ ├── TrimFunctionTest.java │ │ ├── UpperFunctionTest.java │ │ └── UrlEncodeFunctionTest.java │ ├── issues │ │ ├── Issue061Test.java │ │ ├── Issue075Test.java │ │ ├── Issue076Test.java │ │ ├── Issue079Test.java │ │ ├── Issue082Test.java │ │ ├── Issue086Test.java │ │ ├── Issue092Test.java │ │ ├── Issue112Test.java │ │ ├── Issue140Test.java │ │ ├── Issue142Test.java │ │ ├── Issue210Test.java │ │ ├── Issue238Test.java │ │ ├── Issue246Test.java │ │ ├── Issue250Test.java │ │ ├── Issue288Test.java │ │ ├── Issue294Test.java │ │ ├── Issue296Test.java │ │ ├── Issue297Test.java │ │ ├── Issue303Test.java │ │ ├── Issue304Test.java │ │ ├── Issue310Test.java │ │ ├── Issue313Test.java │ │ ├── Issue328Test.java │ │ ├── Issue332Test.java │ │ ├── Issue333Test.java │ │ └── Issue336Test.java │ ├── node │ │ ├── AutoEscapeTest.java │ │ ├── BlockTest.java │ │ ├── DoTest.java │ │ ├── EmbedTest.java │ │ ├── ExtendsTest.java │ │ ├── FilterTest.java │ │ ├── FlushNodeTest.java │ │ ├── ForTest.java │ │ ├── IfConditionTest.java │ │ ├── ImportTest.java │ │ ├── IncludeTest.java │ │ ├── MacroTest.java │ │ ├── OutputTest.java │ │ ├── SetTest.java │ │ ├── TextTest.java │ │ └── VerbatimTest.java │ ├── property │ │ └── MapPropertySelectionTest.java │ ├── render │ │ └── RenderListenersTest.java │ ├── resources │ │ ├── MultipleFileLoaderTest.java │ │ ├── RelativePathResourceTest.java │ │ └── RetrieveNonexistentResourceMultipleTimesTest.java │ ├── stackoverflow │ │ └── JtwigGlobalFieldFilterTest.java │ └── structured │ │ └── BlockValueContextTest.java │ ├── model │ ├── expression │ │ └── BinaryOperationExpressionTest.java │ └── tree │ │ ├── EmbedNodeTest.java │ │ └── ExtendsNodeTest.java │ ├── parser │ ├── CachedJtwigParserTest.java │ ├── cache │ │ ├── InMemoryConcurrentPersistentTemplateCacheTest.java │ │ └── RetrieveFutureTest.java │ └── parboiled │ │ ├── AbstractParserTest.java │ │ ├── base │ │ ├── ArgumentsParserTest.java │ │ ├── LexicParserTest.java │ │ ├── LimitsParserTest.java │ │ └── TextBuilderParserTest.java │ │ ├── expression │ │ ├── AnyExpressionParserTest.java │ │ ├── ComprehensionListExpressionParserTest.java │ │ ├── ConstantExpressionParserTest.java │ │ ├── FunctionExpressionParserTest.java │ │ ├── MapSelectionExpressionParserTest.java │ │ └── VariableExpressionParserTest.java │ │ ├── model │ │ └── KeywordTest.java │ │ └── node │ │ ├── BlockNodeParserTest.java │ │ ├── DoNodeParserTest.java │ │ ├── EmbedNodeParserTest.java │ │ ├── ExtendsNodeParserTest.java │ │ ├── ForLoopNodeParserTest.java │ │ ├── IfNodeParserTest.java │ │ ├── ImportNodeParserTest.java │ │ ├── IncludeNodeParserTest.java │ │ ├── MacroNodeParserTest.java │ │ ├── OutputNodeParserTest.java │ │ ├── SetNodeParserTest.java │ │ └── TextNodeParserTest.java │ ├── performance │ └── SelectionOperatorPerformanceTest.java │ ├── property │ ├── resolver │ │ ├── CallMethodPropertyResolverTest.java │ │ ├── EmptyPropertyResolverTest.java │ │ ├── FieldPropertyResolverTest.java │ │ ├── MacroPropertyResolverTest.java │ │ ├── MapPropertyResolverTest.java │ │ ├── MethodPropertyResolverTest.java │ │ ├── ValueContextPropertyResolverTest.java │ │ └── request │ │ │ └── PropertyNameExtractorTest.java │ ├── selection │ │ ├── SelectionPropertyResolveServiceTest.java │ │ └── cache │ │ │ └── SelectionPropertyResolverCacheKeyTest.java │ └── strategy │ │ ├── VariableMethodPropertyResolverStrategyTest.java │ │ └── method │ │ ├── ArgumentsConverterTest.java │ │ ├── argument │ │ ├── AssignableTypesTest.java │ │ └── group │ │ │ ├── GroupingArgumentsServiceTest.java │ │ │ └── VarArgumentGroupTest.java │ │ ├── convert │ │ └── NativeTypeConverterTest.java │ │ └── finder │ │ └── ExactMethodNamePropertyMethodFinderTest.java │ ├── render │ ├── RenderResourceServiceTest.java │ ├── context │ │ ├── ContextTest.java │ │ ├── RenderContextTest.java │ │ └── model │ │ │ ├── BlockContextTest.java │ │ │ └── PropertiesContextTest.java │ ├── expression │ │ ├── CalculateExpressionServiceTest.java │ │ ├── ExpressionCalculatorSelectorTest.java │ │ ├── calculator │ │ │ ├── BinaryOperationExpressionCalculatorTest.java │ │ │ ├── ComprehensionListExpressionCalculatorTest.java │ │ │ ├── ConstantExpressionCalculatorTest.java │ │ │ ├── EnumeratedListExpressionCalculatorTest.java │ │ │ ├── FunctionExpressionCalculatorTest.java │ │ │ ├── MapExpressionCalculatorTest.java │ │ │ ├── MapSelectionExpressionCalculatorTest.java │ │ │ ├── TernaryExpressionCalculatorTest.java │ │ │ ├── TestOperationExpressionCalculatorTest.java │ │ │ ├── UnaryOperationExpressionCalculatorTest.java │ │ │ ├── VariableExpressionCalculatorTest.java │ │ │ ├── enumerated │ │ │ │ ├── CharAscendingOrderEnumerationListStrategyTest.java │ │ │ │ ├── CharDescendingOrderEnumerationListStrategyTest.java │ │ │ │ ├── CompositeEnumerationListStrategyTest.java │ │ │ │ ├── IntegerAscendingOrderEnumerationListStrategyTest.java │ │ │ │ ├── IntegerDescendingOrderEnumerationListStrategyTest.java │ │ │ │ └── environment │ │ │ │ │ └── EnumerationListStrategyFactoryTest.java │ │ │ └── operation │ │ │ │ ├── binary │ │ │ │ ├── BinaryOperationCalculatorSelectorTest.java │ │ │ │ ├── BinaryOperationServiceTest.java │ │ │ │ └── calculators │ │ │ │ │ ├── AndOperationCalculatorTest.java │ │ │ │ │ ├── BooleanOperationCalculatorTest.java │ │ │ │ │ ├── CompositionOperationCalculatorTest.java │ │ │ │ │ ├── ConcatOperationCalculatorTest.java │ │ │ │ │ ├── DifferentOperationCalculatorTest.java │ │ │ │ │ ├── DivideOperationCalculatorTest.java │ │ │ │ │ ├── EquivalentOperationCalculatorTest.java │ │ │ │ │ ├── GreaterOperationCalculatorTest.java │ │ │ │ │ ├── GreaterOrEqualOperationCalculatorTest.java │ │ │ │ │ ├── InOperationCalculatorTest.java │ │ │ │ │ ├── IntegerDivideOperationCalculatorTest.java │ │ │ │ │ ├── IntegerMultiplyOperationCalculatorTest.java │ │ │ │ │ ├── LessOperationCalculatorTest.java │ │ │ │ │ ├── LessOrEqualOperationCalculatorTest.java │ │ │ │ │ ├── MathOperationCalculatorTest.java │ │ │ │ │ ├── ModOperationCalculatorTest.java │ │ │ │ │ ├── MultiplyOperationCalculatorTest.java │ │ │ │ │ ├── OrOperationCalculatorTest.java │ │ │ │ │ ├── SimpleOperationCalculatorTest.java │ │ │ │ │ ├── SubtractOperationCalculatorTest.java │ │ │ │ │ ├── SumOperationCalculatorTest.java │ │ │ │ │ └── selection │ │ │ │ │ └── SelectionErrorMessageGeneratorTest.java │ │ │ │ └── unary │ │ │ │ ├── UnaryOperationCalculatorSelectorTest.java │ │ │ │ ├── UnaryOperationServiceTest.java │ │ │ │ └── calculators │ │ │ │ ├── NegativeOperationCalculatorTest.java │ │ │ │ └── NotOperationCalculatorTest.java │ │ └── test │ │ │ ├── CalculateTestExpressionServiceTest.java │ │ │ ├── TestExpressionCalculatorSelectorTest.java │ │ │ └── calculator │ │ │ ├── DivisibleByTestExpressionCalculatorTest.java │ │ │ ├── FunctionTestExpressionCalculatorTest.java │ │ │ ├── IsFunctionTestExpressionCalculatorTest.java │ │ │ ├── NotTestExpressionCalculatorTest.java │ │ │ ├── NullTestExpressionCalculatorTest.java │ │ │ └── SameAsTestExpressionCalculatorTest.java │ └── node │ │ ├── NodeRenderSelectorTest.java │ │ ├── RenderNodeServiceTest.java │ │ └── renderer │ │ ├── AutoEscapeNodeRenderTest.java │ │ ├── BlockNodeRenderTest.java │ │ ├── CompositeNodeRenderTest.java │ │ ├── ContentEscapeNodeRenderTest.java │ │ ├── DoNodeRenderTest.java │ │ ├── EmbedNodeRenderTest.java │ │ ├── ExtendsNodeRenderTest.java │ │ ├── FilterNodeRenderTest.java │ │ ├── FlushNodeRenderTest.java │ │ ├── ForLoopNodeRenderTest.java │ │ ├── IfNodeRenderTest.java │ │ ├── ImportNodeRenderTest.java │ │ ├── IncludeNodeRenderTest.java │ │ ├── MacroNodeRenderTest.java │ │ ├── OutputNodeRenderTest.java │ │ ├── OverrideBlockNodeRenderTest.java │ │ ├── SetNodeRenderTest.java │ │ ├── TextNodeRenderTest.java │ │ └── VerbatimNodeRenderTest.java │ ├── renderable │ ├── StreamRenderResultTest.java │ ├── StringBuilderRenderResultTest.java │ └── impl │ │ ├── CompositeRenderableTest.java │ │ ├── FutureRenderableTest.java │ │ ├── OverrideRenderableTest.java │ │ └── StringRenderableTest.java │ ├── resource │ ├── ResourceServiceTest.java │ ├── environment │ │ └── ResourceEnvironmentTest.java │ ├── exceptions │ │ └── ResourceExceptionTest.java │ ├── loader │ │ ├── ClasspathResourceLoaderIntegrationTest.java │ │ ├── ClasspathResourceLoaderTest.java │ │ ├── CompositeResourceLoaderTest.java │ │ ├── FileResourceLoaderTest.java │ │ ├── InMemoryResourceLoaderTest.java │ │ └── StringResourceLoaderTest.java │ ├── metadata │ │ ├── EmptyResourceMetadataTest.java │ │ └── ResourceResourceMetadataTest.java │ ├── reference │ │ ├── DefaultResourceReferenceExtractorTest.java │ │ ├── PosixResourceReferenceExtractorTest.java │ │ ├── ResourceReferenceTest.java │ │ ├── UncResourceReferenceExtractorTest.java │ │ └── path │ │ │ └── PathTypeSupplierTest.java │ └── resolver │ │ ├── ReferenceRelativeResourceResolverTest.java │ │ └── path │ │ ├── RelativeFilePathResolverTest.java │ │ └── RelativePathResolverTest.java │ ├── support │ ├── IsOptional.java │ └── MatcherUtils.java │ ├── util │ ├── ClasspathFinderTest.java │ ├── EscapeUtilsTest.java │ ├── FunctionValueUtilsTest.java │ ├── HtmlUtilsTest.java │ ├── LoopCursorTest.java │ ├── UrlEncodingUtilsTest.java │ └── builder │ │ ├── ListBuilderTest.java │ │ └── MapBuilderTest.java │ └── value │ ├── compare │ └── DefaultValueComparatorTest.java │ ├── context │ ├── IsolateParentValueContextTest.java │ ├── JtwigModelValueContextTest.java │ ├── MapValueContextTest.java │ └── StaticVariableValueContextTest.java │ └── convert │ ├── NullConverterTest.java │ ├── bool │ └── BooleanConverterTest.java │ ├── character │ └── CharConverterTest.java │ ├── collection │ ├── ArrayToCollectionConverterTest.java │ ├── IterableToCollectionConverterTest.java │ └── MapToCollectionConverterTest.java │ ├── number │ └── BigDecimalConverterTest.java │ └── string │ └── DefaultStringConverterTest.java └── resources ├── example ├── base │ ├── base.twig │ └── nested │ │ └── file.twig ├── classpath-error.twig ├── classpath-extends-include-in-block.twig ├── classpath-include.twig ├── classpath-template.twig ├── extends │ ├── extendable-template.twig │ └── nested-extendable-template.twig ├── macros │ ├── macro-example.twig │ ├── macro-self-example.twig │ ├── mixed-imports-example.twig │ ├── nested-macro-child-example.twig │ └── nested-macro-example.twig └── structure │ ├── base-layout.twig │ └── index-jtwig.twig └── issues └── 333.twig /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE 2 | .idea 3 | *.iml 4 | 5 | # Gradle 6 | .gradle 7 | build/ 8 | 9 | # Compiled files 10 | *.class 11 | 12 | # Package Files # 13 | *.war 14 | *.ear 15 | 16 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 17 | hs_err_pid* 18 | 19 | # Maven 20 | pom.xml -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | 5 | env: 6 | TERM: dumb 7 | 8 | before_script: 9 | - chmod +x gradlew 10 | 11 | script: 12 | - ./gradlew check 13 | - ./gradlew test jacoco 14 | 15 | after_success: 16 | - bash <(curl -s https://codecov.io/bash) 17 | - if [[ ( "$TRAVIS_BRANCH" == "master" ) && ( "$TRAVIS_PULL_REQUEST" == "false" ) && ( -z "$TRAVIS_TAG" ) ]]; then ./gradlew bintrayUpload; fi 18 | - if [ ! -z "$TRAVIS_TAG" ]; then ./gradlew bintrayUpload -PjtwigVersion="$TRAVIS_TAG"; fi 19 | 20 | notifications: 21 | webhooks: http://jtwig.org/rest/travis 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jtwig Core : Core Library 2 | 3 | 4 | **Build Stats** 5 | 6 | [![Build Status](https://travis-ci.org/jtwig/jtwig-core.svg?branch=master)](https://travis-ci.org/jtwig/jtwig-core) 7 | [![codecov](https://codecov.io/gh/jtwig/jtwig-core/branch/master/graph/badge.svg)](https://codecov.io/gh/jtwig/jtwig-core) 8 | [![Codacy Badge](https://api.codacy.com/project/badge/grade/3002724fc73f4cf1933e8fd349b12acb)](https://www.codacy.com/app/jmelo_3328/jtwig-core) 9 | [![Download](https://api.bintray.com/packages/jtwig/maven/jtwig-core/images/download.svg) ](https://bintray.com/jtwig/maven/jtwig-core/_latestVersion) 10 | 11 | **Licensing** 12 | 13 | [![Apache License](https://img.shields.io/hexpm/l/plug.svg?maxAge=2592000)]() 14 | 15 | **Requirements** 16 | 17 | - Java 7 18 | 19 | -------------------------------------------------------------------------------- /gradle/jacoco.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'jacoco' 2 | 3 | test { 4 | jacoco { 5 | excludes = ["org.jtwig.parser.parboiled.*"] 6 | } 7 | } 8 | 9 | jacocoTestReport { 10 | afterEvaluate { 11 | classDirectories = files(classDirectories.files.collect { 12 | fileTree(dir: it, exclude: 'org/jtwig/parser/**') 13 | }) 14 | } 15 | reports { 16 | xml.enabled true 17 | xml.destination "${buildDir}/reports/jacoco/report.xml" 18 | html.enabled false 19 | csv.enabled false 20 | } 21 | } -------------------------------------------------------------------------------- /gradle/jtwig-version.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | jtwigVersion = project.hasProperty('jtwigVersion') ? project.getProperty('jtwigVersion') : '5.CURRENT' 3 | } 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jtwig/jtwig-core/4ec125756e2883ce51114747b9beef93b8a1b15b/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Sep 09 02:32:01 BST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip 7 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'jtwig-core' 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/environment/EnvironmentHolder.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.environment; 2 | 3 | public class EnvironmentHolder { 4 | private static ThreadLocal instance = new InheritableThreadLocal<>(); 5 | 6 | public static Environment get () { 7 | return instance.get(); 8 | } 9 | 10 | public static Environment set (Environment environment) { 11 | instance.set(environment); 12 | return environment; 13 | } 14 | 15 | public static void remove () { 16 | instance.remove(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/environment/and/AndBuilder.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.environment.and; 2 | 3 | public interface AndBuilder { 4 | public Parent and (); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/environment/initializer/EnvironmentInitializer.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.environment.initializer; 2 | 3 | import org.jtwig.environment.Environment; 4 | 5 | public interface EnvironmentInitializer { 6 | void initialize (Environment environment); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/escape/EscapeEngine.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.escape; 2 | 3 | public interface EscapeEngine { 4 | String escape (String input); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/escape/HtmlEscapeEngine.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.escape; 2 | 3 | import org.apache.commons.lang3.StringEscapeUtils; 4 | 5 | public class HtmlEscapeEngine implements EscapeEngine { 6 | private static final HtmlEscapeEngine instance = new HtmlEscapeEngine(); 7 | 8 | public static HtmlEscapeEngine instance () { 9 | return instance; 10 | } 11 | 12 | private HtmlEscapeEngine () {} 13 | 14 | @Override 15 | public String escape(String input) { 16 | return StringEscapeUtils.escapeHtml4(input); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/escape/JavascriptEscapeEngine.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.escape; 2 | 3 | import org.apache.commons.lang3.StringEscapeUtils; 4 | 5 | public class JavascriptEscapeEngine implements EscapeEngine { 6 | private static final JavascriptEscapeEngine instance = new JavascriptEscapeEngine(); 7 | 8 | public static JavascriptEscapeEngine instance () { 9 | return instance; 10 | } 11 | 12 | private JavascriptEscapeEngine () {} 13 | 14 | @Override 15 | public String escape(String input) { 16 | return StringEscapeUtils.escapeEcmaScript(input); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/escape/NoneEscapeEngine.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.escape; 2 | 3 | public class NoneEscapeEngine implements EscapeEngine { 4 | private static final NoneEscapeEngine instance = new NoneEscapeEngine(); 5 | 6 | public static NoneEscapeEngine instance () { 7 | return instance; 8 | } 9 | 10 | private NoneEscapeEngine () {} 11 | 12 | @Override 13 | public String escape(String input) { 14 | return input; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/escape/config/DefaultEscapeEngineConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.escape.config; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import org.jtwig.escape.EscapeEngine; 5 | import org.jtwig.escape.HtmlEscapeEngine; 6 | import org.jtwig.escape.JavascriptEscapeEngine; 7 | import org.jtwig.escape.NoneEscapeEngine; 8 | 9 | public class DefaultEscapeEngineConfiguration extends EscapeEngineConfiguration { 10 | public DefaultEscapeEngineConfiguration() { 11 | super( 12 | "none", 13 | "html", 14 | ImmutableMap.builder() 15 | .put("none", NoneEscapeEngine.instance()) 16 | .put("html", HtmlEscapeEngine.instance()) 17 | .put("js", JavascriptEscapeEngine.instance()) 18 | .put("javascript", JavascriptEscapeEngine.instance()) 19 | .build()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/exceptions/CalculationException.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.exceptions; 2 | 3 | public class CalculationException extends JtwigException { 4 | public CalculationException(String message) { 5 | super(message); 6 | } 7 | 8 | public CalculationException(String message, Throwable cause) { 9 | super(message, cause); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/exceptions/InvalidFunctionNameException.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.exceptions; 2 | 3 | public class InvalidFunctionNameException extends RuntimeException { 4 | public InvalidFunctionNameException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/exceptions/JtwigException.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.exceptions; 2 | 3 | public class JtwigException extends RuntimeException { 4 | public JtwigException(String message) { 5 | super(message); 6 | } 7 | 8 | public JtwigException(Throwable cause) { 9 | super(cause); 10 | } 11 | 12 | public JtwigException(String message, Throwable cause) { 13 | super(message, cause); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/exceptions/ResolveValueException.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.exceptions; 2 | 3 | public class ResolveValueException extends RuntimeException { 4 | public ResolveValueException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/extension/Extension.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.extension; 2 | 3 | import org.jtwig.environment.EnvironmentConfigurationBuilder; 4 | 5 | public interface Extension { 6 | void configure (EnvironmentConfigurationBuilder configurationBuilder); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/EmptyExpressionResolver.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions; 2 | 3 | import com.google.common.base.Function; 4 | import org.jtwig.model.expression.Expression; 5 | 6 | public class EmptyExpressionResolver implements Function { 7 | public static EmptyExpressionResolver INSTANCE = new EmptyExpressionResolver(); 8 | 9 | public static EmptyExpressionResolver instance () { 10 | return INSTANCE; 11 | } 12 | 13 | private EmptyExpressionResolver() {} 14 | 15 | @Override 16 | public Object apply(Expression input) { 17 | return null; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/ExpressionResolver.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions; 2 | 3 | import com.google.common.base.Function; 4 | import org.jtwig.model.expression.Expression; 5 | import org.jtwig.render.RenderRequest; 6 | 7 | public class ExpressionResolver implements Function { 8 | private final RenderRequest renderRequest; 9 | 10 | public ExpressionResolver(RenderRequest renderRequest) { 11 | this.renderRequest = renderRequest; 12 | } 13 | 14 | @Override 15 | public Object apply(Expression input) { 16 | return renderRequest.getEnvironment().getRenderEnvironment().getCalculateExpressionService().calculate(renderRequest, input); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/FunctionRequestFactory.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.render.RenderRequest; 5 | 6 | public class FunctionRequestFactory { 7 | public FunctionRequest create (RenderRequest request, Position position, String functionName, FunctionArguments arguments) { 8 | return new FunctionRequest( 9 | request, position, functionName, 10 | arguments 11 | ); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/JtwigFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions; 2 | 3 | import java.util.Collection; 4 | 5 | public interface JtwigFunction { 6 | String name (); 7 | Collection aliases (); 8 | Object execute (FunctionRequest request); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/SimpleJtwigFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions; 2 | 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | 6 | public abstract class SimpleJtwigFunction implements JtwigFunction { 7 | @Override 8 | public Collection aliases() { 9 | return Collections.emptyList(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/annotations/JtwigFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.annotations; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(value = RetentionPolicy.RUNTIME) 9 | @Target(value = ElementType.METHOD) 10 | public @interface JtwigFunction { 11 | String value () default ""; 12 | String[] aliases () default ""; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/annotations/Parameter.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.annotations; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(value = RetentionPolicy.RUNTIME) 9 | @Target(value = ElementType.PARAMETER) 10 | public @interface Parameter { 11 | String value() default ""; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/java/ClassFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.java; 2 | 3 | import org.jtwig.functions.FunctionRequest; 4 | import org.jtwig.functions.SimpleJtwigFunction; 5 | import org.jtwig.value.Undefined; 6 | 7 | public class ClassFunction extends SimpleJtwigFunction { 8 | @Override 9 | public String name() { 10 | return "class"; 11 | } 12 | 13 | @Override 14 | public Object execute(FunctionRequest request) { 15 | request.maximumNumberOfArguments(1).minimumNumberOfArguments(1); 16 | 17 | if (request.get(0) == null || request.get(0) == Undefined.UNDEFINED) { 18 | return Undefined.UNDEFINED; 19 | } else { 20 | return request.get(0).getClass(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/logical/EvenFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.logical; 2 | 3 | import org.jtwig.functions.FunctionRequest; 4 | import org.jtwig.functions.SimpleJtwigFunction; 5 | import org.jtwig.util.FunctionValueUtils; 6 | 7 | import java.math.BigDecimal; 8 | 9 | public class EvenFunction extends SimpleJtwigFunction { 10 | public static final BigDecimal TWO = new BigDecimal(2); 11 | 12 | @Override 13 | public String name() { 14 | return "even"; 15 | } 16 | 17 | @Override 18 | public Object execute(FunctionRequest request) { 19 | request.minimumNumberOfArguments(1); 20 | request.maximumNumberOfArguments(1); 21 | 22 | BigDecimal conversionResult = FunctionValueUtils.getNumber(request, 0); 23 | return BigDecimal.ZERO.equals(conversionResult.remainder(TWO)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/logical/IterableFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.logical; 2 | 3 | import org.jtwig.functions.FunctionRequest; 4 | import org.jtwig.functions.SimpleJtwigFunction; 5 | 6 | public class IterableFunction extends SimpleJtwigFunction { 7 | @Override 8 | public String name() { 9 | return "iterable"; 10 | } 11 | 12 | @Override 13 | public Boolean execute(FunctionRequest request) { 14 | Object input = request.maximumNumberOfArguments(1) 15 | .minimumNumberOfArguments(1) 16 | .get(0); 17 | 18 | return request.getEnvironment().getValueEnvironment() 19 | .getCollectionConverter().convert(input) 20 | .isDefined(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/logical/OddFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.logical; 2 | 3 | import org.jtwig.functions.FunctionRequest; 4 | import org.jtwig.functions.SimpleJtwigFunction; 5 | import org.jtwig.util.FunctionValueUtils; 6 | 7 | import java.math.BigDecimal; 8 | 9 | public class OddFunction extends SimpleJtwigFunction { 10 | public static final BigDecimal TWO = new BigDecimal(2); 11 | @Override 12 | public String name() { 13 | return "odd"; 14 | } 15 | 16 | @Override 17 | public Object execute(FunctionRequest request) { 18 | request.minimumNumberOfArguments(1).maximumNumberOfArguments(1); 19 | 20 | BigDecimal conversionResult = FunctionValueUtils.getNumber(request, 0); 21 | return BigDecimal.ONE.equals(conversionResult.remainder(TWO)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/map/KeysFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.map; 2 | 3 | import org.jtwig.functions.FunctionRequest; 4 | import org.jtwig.functions.SimpleJtwigFunction; 5 | import org.jtwig.value.WrappedCollection; 6 | 7 | public class KeysFunction extends SimpleJtwigFunction { 8 | @Override 9 | public String name() { 10 | return "keys"; 11 | } 12 | 13 | @Override 14 | public Object execute(FunctionRequest request) { 15 | request.maximumNumberOfArguments(1).minimumNumberOfArguments(1); 16 | 17 | WrappedCollection wrappedCollection = request.getEnvironment().getValueEnvironment().getCollectionConverter().convert(request.get(0)) 18 | .or(WrappedCollection.empty()); 19 | 20 | return wrappedCollection.keys(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/math/AbsFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.math; 2 | 3 | import org.jtwig.functions.FunctionRequest; 4 | import org.jtwig.functions.SimpleJtwigFunction; 5 | import org.jtwig.util.FunctionValueUtils; 6 | 7 | import java.math.BigDecimal; 8 | 9 | public class AbsFunction extends SimpleJtwigFunction { 10 | @Override 11 | public String name() { 12 | return "abs"; 13 | } 14 | 15 | @Override 16 | public Object execute(FunctionRequest request) { 17 | request.maximumNumberOfArguments(1).minimumNumberOfArguments(1); 18 | 19 | BigDecimal conversionResult = FunctionValueUtils.getNumber(request, 0); 20 | return conversionResult.abs(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/string/CapitalizeFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.string; 2 | 3 | import org.jtwig.functions.FunctionRequest; 4 | import org.jtwig.functions.SimpleJtwigFunction; 5 | 6 | public class CapitalizeFunction extends SimpleJtwigFunction { 7 | @Override 8 | public String name() { 9 | return "capitalize"; 10 | } 11 | 12 | @Override 13 | public Object execute(FunctionRequest request) { 14 | request.minimumNumberOfArguments(1).maximumNumberOfArguments(1); 15 | String input = getString(request, 0); 16 | if (input.length() > 0) 17 | return input.substring(0, 1).toUpperCase() + input.substring(1); 18 | else 19 | return input; 20 | } 21 | 22 | 23 | private String getString(FunctionRequest request, int index) { 24 | return request.getEnvironment().getValueEnvironment().getStringConverter().convert(request.get(index)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/string/FormatFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.string; 2 | 3 | import org.jtwig.functions.FunctionRequest; 4 | import org.jtwig.functions.SimpleJtwigFunction; 5 | 6 | public class FormatFunction extends SimpleJtwigFunction { 7 | @Override 8 | public String name() { 9 | return "format"; 10 | } 11 | 12 | @Override 13 | public Object execute(FunctionRequest request) { 14 | request.minimumNumberOfArguments(1); 15 | String input = getString(request, 0); 16 | return String.format(input, request.getRemainingArguments(1)); 17 | } 18 | 19 | 20 | private String getString(FunctionRequest request, int index) { 21 | return request.getEnvironment().getValueEnvironment() 22 | .getStringConverter().convert(request.get(index)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/string/LowerFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.string; 2 | 3 | import org.jtwig.functions.FunctionRequest; 4 | import org.jtwig.functions.SimpleJtwigFunction; 5 | 6 | public class LowerFunction extends SimpleJtwigFunction { 7 | @Override 8 | public String name() { 9 | return "lower"; 10 | } 11 | 12 | @Override 13 | public Object execute(FunctionRequest request) { 14 | request.minimumNumberOfArguments(1).maximumNumberOfArguments(1); 15 | String input = request.getEnvironment().getValueEnvironment().getStringConverter().convert(request.get(0)); 16 | return input.toLowerCase(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/string/NlToBrFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.string; 2 | 3 | import org.jtwig.functions.FunctionRequest; 4 | import org.jtwig.functions.SimpleJtwigFunction; 5 | 6 | public class NlToBrFunction extends SimpleJtwigFunction { 7 | @Override 8 | public String name() { 9 | return "nl2br"; 10 | } 11 | 12 | @Override 13 | public Object execute(FunctionRequest request) { 14 | request.minimumNumberOfArguments(1).maximumNumberOfArguments(1); 15 | String input = getString(request, 0); 16 | return input.replace("\n", "
"); 17 | } 18 | 19 | private String getString(FunctionRequest request, int index) { 20 | return request.getEnvironment().getValueEnvironment().getStringConverter().convert(request.get(index)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/string/SplitFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.string; 2 | 3 | import org.jtwig.functions.FunctionRequest; 4 | import org.jtwig.functions.SimpleJtwigFunction; 5 | 6 | import static java.util.Arrays.asList; 7 | 8 | public class SplitFunction extends SimpleJtwigFunction { 9 | @Override 10 | public String name() { 11 | return "split"; 12 | } 13 | 14 | @Override 15 | public Object execute(FunctionRequest request) { 16 | request.minimumNumberOfArguments(2).maximumNumberOfArguments(2); 17 | String input = getString(request, 0); 18 | String separator = getString(request, 1); 19 | return asList(input.split(separator)); 20 | } 21 | 22 | private String getString(FunctionRequest request, int index) { 23 | return request.getEnvironment().getValueEnvironment().getStringConverter().convert(request.get(index)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/string/TitleFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.string; 2 | 3 | import org.apache.commons.lang3.text.WordUtils; 4 | import org.jtwig.functions.FunctionRequest; 5 | import org.jtwig.functions.SimpleJtwigFunction; 6 | 7 | public class TitleFunction extends SimpleJtwigFunction { 8 | @Override 9 | public String name() { 10 | return "title"; 11 | } 12 | 13 | @Override 14 | public Object execute(FunctionRequest request) { 15 | request.minimumNumberOfArguments(1).maximumNumberOfArguments(1); 16 | String input = request.getEnvironment().getValueEnvironment() 17 | .getStringConverter() 18 | .convert(request.get(0)); 19 | return WordUtils.capitalize(input); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/string/TrimFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.string; 2 | 3 | import org.jtwig.functions.FunctionRequest; 4 | import org.jtwig.functions.SimpleJtwigFunction; 5 | 6 | public class TrimFunction extends SimpleJtwigFunction { 7 | @Override 8 | public String name() { 9 | return "trim"; 10 | } 11 | 12 | @Override 13 | public Object execute(FunctionRequest request) { 14 | request.minimumNumberOfArguments(1).maximumNumberOfArguments(1); 15 | String input = getString(request, 0); 16 | return input.trim(); 17 | } 18 | 19 | 20 | private String getString(FunctionRequest request, int index) { 21 | return request.getEnvironment().getValueEnvironment().getStringConverter().convert(request.get(index)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/string/UpperFunction.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.string; 2 | 3 | import org.jtwig.functions.FunctionRequest; 4 | import org.jtwig.functions.SimpleJtwigFunction; 5 | 6 | public class UpperFunction extends SimpleJtwigFunction { 7 | @Override 8 | public String name() { 9 | return "upper"; 10 | } 11 | 12 | @Override 13 | public Object execute(FunctionRequest request) { 14 | request.minimumNumberOfArguments(1).maximumNumberOfArguments(1); 15 | String input = request.getEnvironment().getValueEnvironment().getStringConverter().convert(request.get(0)); 16 | return input.toUpperCase(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/structural/exceptions/ParentFunctionOutsideBlockException.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.structural.exceptions; 2 | 3 | public class ParentFunctionOutsideBlockException extends IllegalStateException { 4 | public ParentFunctionOutsideBlockException() { 5 | super("Call to parent() when not in a block."); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/impl/structural/exceptions/ParentFunctionWithoutExtending.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.structural.exceptions; 2 | 3 | public class ParentFunctionWithoutExtending extends IllegalStateException { 4 | public ParentFunctionWithoutExtending() { 5 | super("Call to parent() in a template that does not extend another template."); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/resolver/FunctionResolver.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.resolver; 2 | 3 | import com.google.common.base.Optional; 4 | import com.google.common.base.Supplier; 5 | import org.jtwig.functions.FunctionArguments; 6 | import org.jtwig.model.position.Position; 7 | import org.jtwig.render.RenderRequest; 8 | 9 | public interface FunctionResolver { 10 | Optional> resolve (RenderRequest request, Position position, String functionName, FunctionArguments arguments); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/resolver/FunctionValueSupplier.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.resolver; 2 | 3 | import com.google.common.base.Supplier; 4 | import org.jtwig.functions.FunctionRequest; 5 | import org.jtwig.functions.JtwigFunction; 6 | 7 | public class FunctionValueSupplier implements Supplier { 8 | private final JtwigFunction jtwigFunction; 9 | private final FunctionRequest request; 10 | 11 | public FunctionValueSupplier(JtwigFunction jtwigFunction, FunctionRequest request) { 12 | this.jtwigFunction = jtwigFunction; 13 | this.request = request; 14 | } 15 | 16 | @Override 17 | public Object get() { 18 | return jtwigFunction.execute(request); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/functions/resolver/FunctionValueSupplierFactory.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.resolver; 2 | 3 | import com.google.common.base.Supplier; 4 | import org.jtwig.functions.FunctionRequest; 5 | import org.jtwig.functions.JtwigFunction; 6 | 7 | public class FunctionValueSupplierFactory { 8 | public Supplier create (JtwigFunction function, FunctionRequest request) { 9 | return new FunctionValueSupplier(function, request); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/macro/ImportedMacros.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.macro; 2 | 3 | import com.google.common.base.Optional; 4 | 5 | import java.util.Map; 6 | 7 | public class ImportedMacros { 8 | private final Map macros; 9 | 10 | public ImportedMacros(Map macros) { 11 | this.macros = macros; 12 | } 13 | 14 | public Optional resolve(String name) { 15 | return Optional.fromNullable(macros.get(name)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/macro/Macro.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.macro; 2 | 3 | import org.jtwig.model.tree.Node; 4 | import org.jtwig.resource.reference.ResourceReference; 5 | 6 | import java.util.List; 7 | 8 | public class Macro { 9 | private final ResourceReference resourceReference; 10 | private final Node content; 11 | private final List argumentNames; 12 | 13 | public Macro(ResourceReference resourceReference, Node content, List argumentNames) { 14 | this.resourceReference = resourceReference; 15 | this.content = content; 16 | this.argumentNames = argumentNames; 17 | } 18 | 19 | public ResourceReference getResourceReference() { 20 | return resourceReference; 21 | } 22 | 23 | public Node getContent() { 24 | return content; 25 | } 26 | 27 | public List getArgumentNames() { 28 | return argumentNames; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/ConstantExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression; 2 | 3 | import org.jtwig.model.position.Position; 4 | 5 | public class ConstantExpression extends Expression { 6 | private final Object value; 7 | 8 | public ConstantExpression(Position position, Object value) { 9 | super(position); 10 | this.value = value; 11 | } 12 | 13 | public Object getConstantValue() { 14 | return value; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/EnumeratedListExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression; 2 | 3 | import org.jtwig.model.position.Position; 4 | 5 | import java.util.Collection; 6 | 7 | public class EnumeratedListExpression extends Expression { 8 | private final Collection expressions; 9 | 10 | public EnumeratedListExpression(Position position, Collection expressions) { 11 | super(position); 12 | this.expressions = expressions; 13 | } 14 | 15 | public Collection getExpressions() { 16 | return expressions; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/Expression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.model.position.Traceable; 5 | 6 | public abstract class Expression implements Traceable { 7 | private final Position position; 8 | 9 | protected Expression(Position position) { 10 | this.position = position; 11 | } 12 | 13 | @Override 14 | public Position getPosition() { 15 | return position; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/InjectableExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression; 2 | 3 | import org.jtwig.model.position.Position; 4 | 5 | public abstract class InjectableExpression extends Expression { 6 | protected InjectableExpression(Position position) { 7 | super(position); 8 | } 9 | 10 | public abstract Expression inject (Expression expression); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/MapExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression; 2 | 3 | import org.jtwig.model.position.Position; 4 | 5 | import java.util.Map; 6 | 7 | public class MapExpression extends Expression { 8 | private final Map expressions; 9 | 10 | public MapExpression(Position position, Map expressions) { 11 | super(position); 12 | this.expressions = expressions; 13 | } 14 | 15 | public Map getExpressions() { 16 | return expressions; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/MapSelectionExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression; 2 | 3 | import org.jtwig.model.position.Position; 4 | 5 | public class MapSelectionExpression extends Expression { 6 | private final Expression mapExpression; 7 | private final Expression selectValue; 8 | 9 | public MapSelectionExpression(Position position, Expression mapExpression, Expression selectValue) { 10 | super(position); 11 | this.mapExpression = mapExpression; 12 | this.selectValue = selectValue; 13 | } 14 | 15 | public Expression getMapExpression() { 16 | return mapExpression; 17 | } 18 | 19 | public Expression getSelectValue() { 20 | return selectValue; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/TestOperationExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression; 2 | 3 | import org.jtwig.model.expression.test.TestExpression; 4 | import org.jtwig.model.position.Position; 5 | 6 | public class TestOperationExpression extends Expression { 7 | private final Expression argument; 8 | private final TestExpression testExpression; 9 | 10 | public TestOperationExpression(Position position, Expression argument, TestExpression testExpression) { 11 | super(position); 12 | this.argument = argument; 13 | this.testExpression = testExpression; 14 | } 15 | 16 | public Expression getArgument() { 17 | return argument; 18 | } 19 | 20 | public TestExpression getTestExpression() { 21 | return testExpression; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/UnaryOperationExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.render.expression.calculator.operation.unary.UnaryOperator; 5 | 6 | public class UnaryOperationExpression extends Expression { 7 | private final UnaryOperator calculator; 8 | private final Expression operand; 9 | 10 | public UnaryOperationExpression(Position position, UnaryOperator calculator, Expression operand) { 11 | super(position); 12 | this.calculator = calculator; 13 | this.operand = operand; 14 | } 15 | 16 | public UnaryOperator getOperator() { 17 | return calculator; 18 | } 19 | 20 | public Expression getOperand() { 21 | return operand; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/VariableExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression; 2 | 3 | import org.jtwig.model.position.Position; 4 | 5 | import java.util.Collections; 6 | 7 | public class VariableExpression extends InjectableExpression { 8 | private final String identifier; 9 | 10 | public VariableExpression(Position position, String identifier) { 11 | super(position); 12 | this.identifier = identifier; 13 | } 14 | 15 | public String getIdentifier() { 16 | return identifier; 17 | } 18 | 19 | @Override 20 | public Expression inject(Expression expression) { 21 | return new FunctionExpression(getPosition(), identifier, Collections.singletonList(expression)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/test/DefinedTestExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression.test; 2 | 3 | public class DefinedTestExpression extends TestExpression { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/test/DivisibleByTestExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression.test; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | 5 | public class DivisibleByTestExpression extends TestExpression { 6 | private final Expression expression; 7 | 8 | public DivisibleByTestExpression(Expression expression) { 9 | this.expression = expression; 10 | } 11 | 12 | public Expression getExpression() { 13 | return expression; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/test/FunctionTestExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression.test; 2 | 3 | import org.jtwig.model.expression.InjectableExpression; 4 | 5 | public class FunctionTestExpression extends TestExpression { 6 | private final InjectableExpression injectableExpression; 7 | 8 | public FunctionTestExpression(InjectableExpression injectableExpression) { 9 | this.injectableExpression = injectableExpression; 10 | } 11 | 12 | public InjectableExpression getInjectableExpression() { 13 | return injectableExpression; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/test/IsFunctionTestExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression.test; 2 | 3 | public class IsFunctionTestExpression extends TestExpression { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/test/NotTestExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression.test; 2 | 3 | public class NotTestExpression extends TestExpression { 4 | public static TestExpression create(Boolean isNot, TestExpression nested) { 5 | if (isNot) { 6 | return new NotTestExpression(nested); 7 | } 8 | return nested; 9 | } 10 | 11 | private final TestExpression testExpression; 12 | 13 | public NotTestExpression(TestExpression testExpression) { 14 | this.testExpression = testExpression; 15 | } 16 | 17 | public TestExpression getTestExpression() { 18 | return testExpression; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/test/NullTestExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression.test; 2 | 3 | public class NullTestExpression extends TestExpression { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/test/SameAsTestExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression.test; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | 5 | public class SameAsTestExpression extends TestExpression { 6 | private final Expression expression; 7 | 8 | public SameAsTestExpression(Expression expression) { 9 | this.expression = expression; 10 | } 11 | 12 | public Expression getExpression() { 13 | return expression; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/expression/test/TestExpression.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.expression.test; 2 | 3 | public abstract class TestExpression { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/position/Position.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.position; 2 | 3 | import org.jtwig.resource.reference.ResourceReference; 4 | 5 | public class Position { 6 | private final ResourceReference resource; 7 | private final int line; 8 | private final int column; 9 | 10 | public Position(ResourceReference resource, int line, int column) { 11 | this.resource = resource; 12 | this.line = line; 13 | this.column = column; 14 | } 15 | 16 | public int getLine() { 17 | return line; 18 | } 19 | 20 | public int getColumn() { 21 | return column; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return String.format("%s (Line: %d, Column: %d)", resource, line, column); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/position/Traceable.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.position; 2 | 3 | public interface Traceable { 4 | Position getPosition (); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/AutoEscapeNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.model.position.Position; 5 | 6 | public class AutoEscapeNode extends ContentNode { 7 | private final Optional escapeEngineName; 8 | 9 | public AutoEscapeNode(Position position, Node content, Optional escapeEngineName) { 10 | super(position, content); 11 | this.escapeEngineName = escapeEngineName; 12 | } 13 | 14 | public Optional getEscapeEngineName() { 15 | return escapeEngineName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/BlockNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.expression.VariableExpression; 4 | import org.jtwig.model.position.Position; 5 | 6 | public class BlockNode extends ContentNode { 7 | private final VariableExpression blockIdentifier; 8 | 9 | public BlockNode(Position position, VariableExpression blockIdentifier, Node content) { 10 | super(position, content); 11 | this.blockIdentifier = blockIdentifier; 12 | } 13 | 14 | public VariableExpression getBlockIdentifier() { 15 | return blockIdentifier; 16 | } 17 | 18 | public String getIdentifier() { 19 | return blockIdentifier.getIdentifier(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/CompositeNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.model.tree.visitor.NodeVisitor; 5 | 6 | import java.util.Collection; 7 | 8 | public class CompositeNode extends Node { 9 | private final Collection nodes; 10 | 11 | public CompositeNode(Position position, Collection nodes) { 12 | super(position); 13 | this.nodes = nodes; 14 | } 15 | 16 | public Collection getNodes() { 17 | return nodes; 18 | } 19 | 20 | @Override 21 | public void visit(NodeVisitor nodeConsumer) { 22 | super.visit(nodeConsumer); 23 | for (Node node : nodes) { 24 | node.visit(nodeConsumer); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/ContentEscapeNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.model.position.Position; 5 | 6 | public class ContentEscapeNode extends ContentNode { 7 | private final Optional escapeEngineName; 8 | 9 | public ContentEscapeNode(Position position, Node content, Optional escapeEngineName) { 10 | super(position, content); 11 | this.escapeEngineName = escapeEngineName; 12 | } 13 | 14 | public Optional getEscapeEngineName() { 15 | return escapeEngineName; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/ContentNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.model.tree.visitor.NodeVisitor; 5 | 6 | public class ContentNode extends Node { 7 | private final Node content; 8 | 9 | protected ContentNode(Position position, Node content) { 10 | super(position); 11 | this.content = content; 12 | } 13 | 14 | public Node getContent() { 15 | return content; 16 | } 17 | 18 | @Override 19 | public void visit(NodeVisitor nodeConsumer) { 20 | super.visit(nodeConsumer); 21 | content.visit(nodeConsumer); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/DoNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.model.position.Position; 5 | 6 | public class DoNode extends Node { 7 | private final Expression expression; 8 | 9 | public DoNode(Position position, Expression expression) { 10 | super(position); 11 | this.expression = expression; 12 | } 13 | 14 | public Expression getExpression() { 15 | return expression; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/FilterNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.expression.InjectableExpression; 4 | import org.jtwig.model.position.Position; 5 | 6 | public class FilterNode extends ContentNode { 7 | private final InjectableExpression filterExpression; 8 | 9 | public FilterNode(Position position, Node content, InjectableExpression filterExpression) { 10 | super(position, content); 11 | this.filterExpression = filterExpression; 12 | } 13 | 14 | public InjectableExpression getFilterExpression() { 15 | return filterExpression; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/FlushNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.position.Position; 4 | 5 | public class FlushNode extends Node { 6 | public FlushNode(Position position) { 7 | super(position); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/ImportNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.model.expression.VariableExpression; 5 | import org.jtwig.model.position.Position; 6 | 7 | public class ImportNode extends Node { 8 | private final Expression importExpression; 9 | private final VariableExpression aliasIdentifier; 10 | 11 | public ImportNode(Position position, Expression importExpression, VariableExpression aliasIdentifier) { 12 | super(position); 13 | this.importExpression = importExpression; 14 | this.aliasIdentifier = aliasIdentifier; 15 | } 16 | 17 | public Expression getImportExpression() { 18 | return importExpression; 19 | } 20 | 21 | public VariableExpression getAliasIdentifier() { 22 | return aliasIdentifier; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/ImportSelfNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.expression.VariableExpression; 4 | import org.jtwig.model.position.Position; 5 | 6 | public class ImportSelfNode extends Node { 7 | private final VariableExpression aliasIdentifier; 8 | 9 | public ImportSelfNode(Position position, VariableExpression aliasIdentifier) { 10 | super(position); 11 | this.aliasIdentifier = aliasIdentifier; 12 | } 13 | 14 | public VariableExpression getAliasIdentifier() { 15 | return aliasIdentifier; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/IncludeNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.model.position.Position; 5 | import org.jtwig.model.tree.include.IncludeConfiguration; 6 | 7 | public class IncludeNode extends Node { 8 | private final IncludeConfiguration configuration; 9 | 10 | public IncludeNode(Position position, IncludeConfiguration configuration) { 11 | super(position); 12 | this.configuration = configuration; 13 | } 14 | 15 | public Expression getMapExpression() { 16 | return configuration.getMap(); 17 | } 18 | 19 | public boolean isInheritModel() { 20 | return configuration.isInheritModel(); 21 | } 22 | 23 | public boolean isIgnoreMissing() { 24 | return configuration.isIgnoreMissing(); 25 | } 26 | 27 | public Expression getResourceExpression () { 28 | return configuration.getInclude(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/Node.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.model.position.Traceable; 5 | import org.jtwig.model.tree.visitor.NodeVisitor; 6 | 7 | public abstract class Node implements Traceable { 8 | private final Position position; 9 | 10 | protected Node(Position position) { 11 | this.position = position; 12 | } 13 | 14 | @Override 15 | public Position getPosition() { 16 | return position; 17 | } 18 | 19 | public void visit (NodeVisitor nodeConsumer) { 20 | nodeConsumer.consume(this); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/OutputNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.model.position.Position; 5 | 6 | public class OutputNode extends Node { 7 | private final Expression expression; 8 | 9 | public OutputNode(Position position, Expression expression) { 10 | super(position); 11 | this.expression = expression; 12 | } 13 | 14 | public Expression getExpression() { 15 | return expression; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/OverrideBlockNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.expression.VariableExpression; 4 | import org.jtwig.model.position.Position; 5 | 6 | public class OverrideBlockNode extends BlockNode { 7 | public OverrideBlockNode(Position position, VariableExpression blockIdentifier, Node content) { 8 | super(position, blockIdentifier, content); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/SetNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.model.expression.VariableExpression; 5 | import org.jtwig.model.position.Position; 6 | 7 | public class SetNode extends Node { 8 | private final VariableExpression variableExpression; 9 | private final Expression expression; 10 | 11 | public SetNode(Position position, VariableExpression variableExpression, Expression expression) { 12 | super(position); 13 | this.variableExpression = variableExpression; 14 | this.expression = expression; 15 | } 16 | 17 | public VariableExpression getVariableExpression() { 18 | return variableExpression; 19 | } 20 | 21 | public Expression getExpression() { 22 | return expression; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/VerbatimNode.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.position.Position; 4 | 5 | public class VerbatimNode extends Node { 6 | private final String content; 7 | 8 | public VerbatimNode(Position position, String content) { 9 | super(position); 10 | this.content = content; 11 | } 12 | 13 | public String getContent() { 14 | return content; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/model/tree/visitor/NodeVisitor.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree.visitor; 2 | 3 | import org.jtwig.model.tree.Node; 4 | 5 | public interface NodeVisitor { 6 | void consume(Node node); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/CachedJtwigParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser; 2 | 3 | import org.jtwig.environment.Environment; 4 | import org.jtwig.model.tree.Node; 5 | import org.jtwig.parser.cache.TemplateCache; 6 | import org.jtwig.resource.reference.ResourceReference; 7 | 8 | public class CachedJtwigParser implements JtwigParser { 9 | private final TemplateCache cache; 10 | private final JtwigParser jtwigParser; 11 | 12 | public CachedJtwigParser(TemplateCache cache, JtwigParser jtwigParser) { 13 | this.cache = cache; 14 | this.jtwigParser = jtwigParser; 15 | } 16 | 17 | @Override 18 | public Node parse(Environment environment, ResourceReference resource) { 19 | return cache.get(jtwigParser, environment, resource); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/JtwigParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser; 2 | 3 | import org.jtwig.environment.Environment; 4 | import org.jtwig.model.tree.Node; 5 | import org.jtwig.resource.reference.ResourceReference; 6 | 7 | public interface JtwigParser { 8 | Node parse (Environment environment, ResourceReference resource); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/JtwigParserFactory.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.parser.cache.TemplateCache; 5 | import org.jtwig.parser.config.JtwigParserConfiguration; 6 | import org.jtwig.parser.parboiled.ParboiledJtwigParser; 7 | 8 | public class JtwigParserFactory { 9 | public JtwigParser create (JtwigParserConfiguration configuration) { 10 | ParboiledJtwigParser parboiledJtwigParser = new ParboiledJtwigParser(configuration); 11 | Optional templateCache = configuration.getTemplateCache(); 12 | if (templateCache.isPresent()) { 13 | return new CachedJtwigParser(templateCache.get(), parboiledJtwigParser); 14 | } else { 15 | return parboiledJtwigParser; 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/ParseException.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser; 2 | 3 | public class ParseException extends RuntimeException { 4 | 5 | public ParseException(String message) { 6 | super(message); 7 | } 8 | 9 | public ParseException(Throwable cause) { 10 | super(cause); 11 | } 12 | 13 | public ParseException(String message, Throwable cause) { 14 | super(message, cause); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/addon/AddonParserProvider.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.addon; 2 | 3 | import org.jtwig.parser.parboiled.node.AddonParser; 4 | 5 | import java.util.Collection; 6 | 7 | public interface AddonParserProvider { 8 | Class parser (); 9 | Collection keywords (); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/cache/RetrieveFuture.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.cache; 2 | 3 | import com.google.common.base.Function; 4 | import org.jtwig.renderable.RenderException; 5 | 6 | import java.util.concurrent.ExecutionException; 7 | import java.util.concurrent.Future; 8 | 9 | public class RetrieveFuture implements Function, T> { 10 | @Override 11 | public T apply(Future input) { 12 | try { 13 | return input.get(); 14 | } catch (InterruptedException | ExecutionException e) { 15 | throw new RenderException(e); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/cache/TemplateCache.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.cache; 2 | 3 | import org.jtwig.environment.Environment; 4 | import org.jtwig.model.tree.Node; 5 | import org.jtwig.parser.JtwigParser; 6 | import org.jtwig.resource.reference.ResourceReference; 7 | 8 | public interface TemplateCache { 9 | Node get (JtwigParser parser, Environment environment, ResourceReference resource); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/config/AndSyntaxConfigurationBuilder.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.config; 2 | 3 | import org.jtwig.environment.and.AndBuilder; 4 | 5 | public class AndSyntaxConfigurationBuilder extends SyntaxConfigurationBuilder> implements AndBuilder { 6 | private final Parent parent; 7 | 8 | public AndSyntaxConfigurationBuilder(Parent parserConfigurationBuilder) { 9 | this.parent = parserConfigurationBuilder; 10 | } 11 | 12 | public AndSyntaxConfigurationBuilder(Parent parent, SyntaxConfiguration prototype) { 13 | super(prototype); 14 | this.parent = parent; 15 | } 16 | 17 | @Override 18 | public Parent and() { 19 | return parent; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/config/DefaultSyntaxConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.config; 2 | 3 | public class DefaultSyntaxConfiguration extends SyntaxConfiguration { 4 | public DefaultSyntaxConfiguration() { 5 | super("{#", "#}", "{{", "}}", "{%", "%}"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/parboiled/base/BooleanParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.base; 2 | 3 | import org.jtwig.parser.parboiled.ParserContext; 4 | 5 | public class BooleanParser extends BasicParser { 6 | public BooleanParser(ParserContext context) { 7 | super(BooleanParser.class, context); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/parboiled/base/PositionTrackerParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.base; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.parser.parboiled.ParserContext; 5 | 6 | public class PositionTrackerParser extends BasicParser { 7 | public PositionTrackerParser(ParserContext context) { 8 | super(PositionTrackerParser.class, context); 9 | } 10 | 11 | public boolean PushPosition() { 12 | push(new Position(parserContext().resource(), getContext().getPosition().line, getContext().getPosition().column)); 13 | return true; 14 | } 15 | 16 | public Position currentPosition() { 17 | return new Position(parserContext().resource(), super.getContext().getPosition().line, super.getContext().getPosition().column); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/parboiled/expression/AnyExpressionParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.expression; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.parser.parboiled.ParserContext; 5 | import org.parboiled.Rule; 6 | import org.parboiled.annotations.Label; 7 | 8 | public class AnyExpressionParser extends ExpressionParser { 9 | public AnyExpressionParser(ParserContext context) { 10 | super(AnyExpressionParser.class, context); 11 | } 12 | 13 | @Label("Any Expression") 14 | public Rule ExpressionRule() { 15 | return FirstOf( 16 | parserContext().parser(TestOperationExpressionParser.class).ExpressionRule(), 17 | parserContext().parser(SimpleExpressionParser.class).ExpressionRule() 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/parboiled/expression/BinaryOperationExpressionParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.expression; 2 | 3 | import org.jtwig.model.expression.BinaryOperationExpression; 4 | import org.jtwig.parser.parboiled.ParserContext; 5 | import org.parboiled.Rule; 6 | 7 | public class BinaryOperationExpressionParser extends ExpressionParser { 8 | public BinaryOperationExpressionParser(ParserContext context) { 9 | super(BinaryOperationExpressionParser.class, context); 10 | } 11 | 12 | @Override 13 | public Rule ExpressionRule() { 14 | return Sequence( 15 | parserContext().parser(PrimaryExpressionParser.class).ExpressionRule(), 16 | parserContext().parser(BinaryOperationSuffixExpressionParser.class).ExpressionRule() 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/parboiled/expression/BinaryOrPrimaryExpressionParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.expression; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.parser.parboiled.ParserContext; 5 | import org.parboiled.Rule; 6 | 7 | public class BinaryOrPrimaryExpressionParser extends ExpressionParser { 8 | public BinaryOrPrimaryExpressionParser(ParserContext context) { 9 | super(BinaryOrPrimaryExpressionParser.class, context); 10 | } 11 | 12 | @Override 13 | public Rule ExpressionRule() { 14 | return FirstOf( 15 | parserContext().parser(BinaryOperationExpressionParser.class).ExpressionRule(), 16 | parserContext().parser(PrimaryExpressionParser.class).ExpressionRule() 17 | ); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/parboiled/expression/ExpressionParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.expression; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.parser.parboiled.ParserContext; 5 | import org.jtwig.parser.parboiled.base.BasicParser; 6 | import org.parboiled.Rule; 7 | 8 | public abstract class ExpressionParser extends BasicParser { 9 | public ExpressionParser(Class type, ParserContext context) { 10 | super(type, context); 11 | } 12 | 13 | public abstract Rule ExpressionRule (); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/parboiled/expression/test/DefinedTestExpressionParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.expression.test; 2 | 3 | import org.jtwig.model.expression.test.DefinedTestExpression; 4 | import org.jtwig.parser.parboiled.ParserContext; 5 | import org.jtwig.parser.parboiled.base.SpacingParser; 6 | import org.parboiled.Rule; 7 | 8 | public class DefinedTestExpressionParser extends TestExpressionParser { 9 | public DefinedTestExpressionParser(ParserContext context) { 10 | super(DefinedTestExpressionParser.class, context); 11 | } 12 | 13 | @Override 14 | public Rule Test() { 15 | SpacingParser spacingParser = parserContext().parser(SpacingParser.class); 16 | 17 | return Sequence( 18 | String("defined"), 19 | spacingParser.Spacing(), 20 | push(new DefinedTestExpression()) 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/parboiled/expression/test/IsFunctionTestExpressionParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.expression.test; 2 | 3 | import org.jtwig.model.expression.test.IsFunctionTestExpression; 4 | import org.jtwig.parser.parboiled.ParserContext; 5 | import org.jtwig.parser.parboiled.base.SpacingParser; 6 | import org.parboiled.Rule; 7 | 8 | public class IsFunctionTestExpressionParser extends TestExpressionParser { 9 | public IsFunctionTestExpressionParser(ParserContext context) { 10 | super(IsFunctionTestExpressionParser.class, context); 11 | } 12 | 13 | @Override 14 | public Rule Test() { 15 | SpacingParser spacingParser = parserContext().parser(SpacingParser.class); 16 | 17 | return Sequence( 18 | String("function"), 19 | spacingParser.Spacing(), 20 | push(new IsFunctionTestExpression()) 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/parboiled/expression/test/NullTestExpressionParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.expression.test; 2 | 3 | import org.jtwig.model.expression.test.NullTestExpression; 4 | import org.jtwig.parser.parboiled.ParserContext; 5 | import org.jtwig.parser.parboiled.base.LexicParser; 6 | import org.jtwig.parser.parboiled.model.Keyword; 7 | import org.parboiled.Rule; 8 | 9 | public class NullTestExpressionParser extends TestExpressionParser { 10 | public NullTestExpressionParser(ParserContext context) { 11 | super(NullTestExpressionParser.class, context); 12 | } 13 | 14 | @Override 15 | public Rule Test() { 16 | return Sequence( 17 | parserContext().parser(LexicParser.class).Keyword(Keyword.NULL), 18 | push(new NullTestExpression()) 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/parboiled/expression/test/TestExpressionParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.expression.test; 2 | 3 | import org.jtwig.model.expression.test.TestExpression; 4 | import org.jtwig.parser.parboiled.ParserContext; 5 | import org.jtwig.parser.parboiled.base.BasicParser; 6 | import org.parboiled.Rule; 7 | 8 | public abstract class TestExpressionParser extends BasicParser { 9 | public TestExpressionParser(Class type, ParserContext context) { 10 | super(type, context); 11 | } 12 | 13 | public abstract Rule Test (); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/parboiled/model/LimitProperties.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.model; 2 | 3 | public class LimitProperties { 4 | private final boolean whiteSpaceControl; 5 | 6 | public LimitProperties(boolean whiteSpaceControl) { 7 | this.whiteSpaceControl = whiteSpaceControl; 8 | } 9 | 10 | public boolean isWhiteSpaceControl() { 11 | return whiteSpaceControl; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/parboiled/node/AddonParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.node; 2 | 3 | import org.jtwig.model.tree.Node; 4 | import org.jtwig.parser.parboiled.ParserContext; 5 | 6 | public abstract class AddonParser extends NodeParser { 7 | 8 | public AddonParser(Class type, ParserContext context) { 9 | super(type, context); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/parboiled/node/CommentParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.node; 2 | 3 | import org.jtwig.parser.parboiled.ParserContext; 4 | import org.jtwig.parser.parboiled.base.BasicParser; 5 | import org.jtwig.parser.parboiled.base.LimitsParser; 6 | import org.parboiled.Rule; 7 | 8 | public class CommentParser extends BasicParser { 9 | public CommentParser(ParserContext context) { 10 | super(CommentParser.class, context); 11 | } 12 | 13 | public Rule Comment() { 14 | LimitsParser limitsParser = parserContext().parser(LimitsParser.class); 15 | return Sequence( 16 | limitsParser.startComment(), 17 | ZeroOrMore( 18 | TestNot(limitsParser.endComment()), 19 | ANY 20 | ), 21 | limitsParser.endComment() 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/parboiled/node/NodeParser.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.node; 2 | 3 | import org.jtwig.model.tree.Node; 4 | import org.jtwig.parser.parboiled.ParserContext; 5 | import org.jtwig.parser.parboiled.base.BasicParser; 6 | import org.parboiled.Rule; 7 | 8 | public abstract class NodeParser extends BasicParser { 9 | public NodeParser(Class type, ParserContext context) { 10 | super(type, context); 11 | } 12 | 13 | public abstract Rule NodeRule (); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/parser/util/ParboiledExceptionMessageExtractor.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.util; 2 | 3 | import org.parboiled.errors.ParserRuntimeException; 4 | 5 | public class ParboiledExceptionMessageExtractor { 6 | public String extract (ParserRuntimeException exception) { 7 | String[] split = exception.getMessage().split("\n"); 8 | return split[1] + "\n" + split[2]; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/environment/PropertyResolverEnvironment.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.environment; 2 | 3 | import org.jtwig.property.selection.SelectionPropertyResolver; 4 | 5 | public class PropertyResolverEnvironment { 6 | private final SelectionPropertyResolver selectionPropertyResolver; 7 | 8 | public PropertyResolverEnvironment(SelectionPropertyResolver selectionPropertyResolver) { 9 | this.selectionPropertyResolver = selectionPropertyResolver; 10 | } 11 | 12 | public SelectionPropertyResolver getSelectionPropertyResolver() { 13 | return selectionPropertyResolver; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/resolver/EmptyPropertyResolver.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.resolver; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.property.resolver.request.PropertyResolveRequest; 5 | import org.jtwig.reflection.model.Value; 6 | 7 | public class EmptyPropertyResolver implements PropertyResolver { 8 | private static final EmptyPropertyResolver INSTANCE = new EmptyPropertyResolver(); 9 | 10 | public static EmptyPropertyResolver instance () { 11 | return INSTANCE; 12 | } 13 | 14 | private EmptyPropertyResolver () {} 15 | 16 | @Override 17 | public Optional resolve(PropertyResolveRequest request) { 18 | return Optional.absent(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/resolver/MapPropertyResolver.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.resolver; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.property.resolver.request.PropertyResolveRequest; 5 | import org.jtwig.reflection.model.Value; 6 | 7 | import java.util.Map; 8 | 9 | public class MapPropertyResolver implements PropertyResolver { 10 | @Override 11 | public Optional resolve(PropertyResolveRequest request) { 12 | if (request.getContext() == null) return Optional.absent(); 13 | if (!(request.getContext() instanceof Map)) return Optional.absent(); 14 | 15 | if(((Map) request.getContext()).containsKey(request.getPropertyName().get())){ 16 | return Optional.of(new Value(((Map) request.getContext()).get(request.getPropertyName().get()))); 17 | }else{ 18 | return Optional.absent(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/resolver/PropertyResolver.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.resolver; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.property.resolver.request.PropertyResolveRequest; 5 | import org.jtwig.reflection.model.Value; 6 | 7 | public interface PropertyResolver { 8 | Optional resolve (PropertyResolveRequest request); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/resolver/ValueContextPropertyResolver.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.resolver; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.property.resolver.request.PropertyResolveRequest; 5 | import org.jtwig.reflection.model.Value; 6 | import org.jtwig.value.context.ValueContext; 7 | 8 | public class ValueContextPropertyResolver implements PropertyResolver { 9 | @Override 10 | public Optional resolve(PropertyResolveRequest request) { 11 | if (request.getContext() == null) return Optional.absent(); 12 | if (!(request.getContext() instanceof ValueContext)) return Optional.absent(); 13 | 14 | return Optional.of(new Value(((ValueContext) request.getContext()).resolve(request.getPropertyName().get()))); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/resolver/request/ArgumentsExtractor.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.resolver.request; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.model.expression.FunctionExpression; 5 | import org.jtwig.render.RenderRequest; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class ArgumentsExtractor { 11 | public List extract (RenderRequest request, Expression expression) { 12 | ArrayList arguments = new ArrayList<>(); 13 | if (expression instanceof FunctionExpression) { 14 | for (Expression argument : ((FunctionExpression) expression).getArguments()) { 15 | Object argumentValue = request.getEnvironment().getRenderEnvironment().getCalculateExpressionService().calculate(request, argument); 16 | arguments.add(argumentValue); 17 | } 18 | } 19 | return arguments; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/resolver/request/PropertyNameExtractor.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.resolver.request; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.model.expression.Expression; 5 | import org.jtwig.model.expression.FunctionExpression; 6 | import org.jtwig.model.expression.VariableExpression; 7 | 8 | public class PropertyNameExtractor { 9 | public Optional extract (Expression expression) { 10 | if (expression instanceof VariableExpression) { 11 | return Optional.of(((VariableExpression) expression).getIdentifier()); 12 | } 13 | 14 | if (expression instanceof FunctionExpression) { 15 | return Optional.of(((FunctionExpression) expression).getFunctionIdentifier()); 16 | } 17 | 18 | return Optional.absent(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/selection/SelectionPropertyResolver.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.selection; 2 | 3 | public interface SelectionPropertyResolver { 4 | SelectionResult resolve (SelectionRequest request); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/selection/SelectionRequest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.selection; 2 | 3 | import org.jtwig.environment.Environment; 4 | import org.jtwig.model.expression.Expression; 5 | import org.jtwig.render.RenderRequest; 6 | import org.jtwig.render.context.RenderContext; 7 | 8 | public class SelectionRequest extends RenderRequest { 9 | private final Expression leftExpression; 10 | private final Expression rightExpression; 11 | 12 | public SelectionRequest(RenderContext renderContext, Environment environment, Expression leftExpression, Expression rightExpression) { 13 | super(renderContext, environment); 14 | this.leftExpression = leftExpression; 15 | this.rightExpression = rightExpression; 16 | } 17 | 18 | public Expression getLeftExpression() { 19 | return leftExpression; 20 | } 21 | 22 | public Expression getRightExpression() { 23 | return rightExpression; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/selection/SelectionResult.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.selection; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.property.resolver.PropertyResolver; 5 | import org.jtwig.reflection.model.Value; 6 | 7 | public class SelectionResult { 8 | private final Optional propertyResolver; 9 | private final Optional resolvedValue; 10 | 11 | public SelectionResult(Optional propertyResolver, Optional resolvedValue) { 12 | this.propertyResolver = propertyResolver; 13 | this.resolvedValue = resolvedValue; 14 | } 15 | 16 | public Optional getPropertyResolver() { 17 | return propertyResolver; 18 | } 19 | 20 | public Optional getResolvedValue() { 21 | return resolvedValue; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/selection/cache/SelectionPropertyResolverCache.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.selection.cache; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.property.resolver.PropertyResolver; 5 | 6 | public interface SelectionPropertyResolverCache { 7 | Optional getCachedResolver(SelectionPropertyResolverCacheKey cacheKey); 8 | 9 | void cacheResolver(SelectionPropertyResolverCacheKey cacheKey, PropertyResolver propertyResolver); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/strategy/MapPropertyResolverStrategy.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.strategy; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.model.expression.VariableExpression; 5 | import org.jtwig.property.resolver.MapPropertyResolver; 6 | import org.jtwig.property.resolver.PropertyResolver; 7 | 8 | import java.util.Map; 9 | 10 | public class MapPropertyResolverStrategy implements PropertyResolverStrategy { 11 | @Override 12 | public Optional select(Request request) { 13 | if (request.getLeftValue() instanceof Map) { 14 | if (request.getRightExpression() instanceof VariableExpression) { 15 | PropertyResolver propertyResolver = new MapPropertyResolver(); 16 | return Optional.of(propertyResolver); 17 | } 18 | } 19 | 20 | return Optional.absent(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/strategy/ValueContextPropertyResolverStrategy.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.strategy; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.model.expression.VariableExpression; 5 | import org.jtwig.property.resolver.PropertyResolver; 6 | import org.jtwig.property.resolver.ValueContextPropertyResolver; 7 | import org.jtwig.value.context.ValueContext; 8 | 9 | public class ValueContextPropertyResolverStrategy implements PropertyResolverStrategy { 10 | @Override 11 | public Optional select(Request request) { 12 | if (request.getLeftValue() instanceof ValueContext) { 13 | if (request.getRightExpression() instanceof VariableExpression) { 14 | PropertyResolver propertyResolver = new ValueContextPropertyResolver(); 15 | return Optional.of(propertyResolver); 16 | } 17 | } 18 | return Optional.absent(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/strategy/method/FunctionArgumentCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.strategy.method; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.render.RenderRequest; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class FunctionArgumentCalculator { 10 | public List calculate (RenderRequest request, List arguments) { 11 | List result = new ArrayList<>(); 12 | for (Expression argument : arguments) { 13 | result.add(request.getEnvironment().getRenderEnvironment().getCalculateExpressionService().calculate(request, argument)); 14 | } 15 | return result; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/strategy/method/MethodArgumentsMatcher.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.strategy.method; 2 | 3 | import org.jtwig.reflection.model.java.JavaMethod; 4 | 5 | import java.util.List; 6 | 7 | public class MethodArgumentsMatcher { 8 | private final ArgumentsConverter argumentsConverter; 9 | 10 | public MethodArgumentsMatcher(ArgumentsConverter argumentsConverter) { 11 | this.argumentsConverter = argumentsConverter; 12 | } 13 | 14 | public boolean matches(JavaMethod method, List arguments) { 15 | return argumentsConverter.convert(method, arguments.toArray()).isPresent(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/strategy/method/argument/IsNativeType.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.strategy.method.argument; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | import static java.util.Arrays.asList; 7 | 8 | public class IsNativeType { 9 | private static final IsNativeType INSTANCE = new IsNativeType(); 10 | private static final List> NATIVE_TYPES = asList(Integer.TYPE, Float.TYPE, Double.TYPE, Long.TYPE, Boolean.TYPE, Character.TYPE); 11 | 12 | public static IsNativeType instance () { 13 | return INSTANCE; 14 | } 15 | 16 | private IsNativeType() { 17 | } 18 | 19 | public boolean isNative(Class type) { 20 | return NATIVE_TYPES.contains(type); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/strategy/method/argument/group/ArgumentGroup.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.strategy.method.argument.group; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.property.strategy.method.convert.Converter; 5 | import org.jtwig.reflection.model.Value; 6 | 7 | public interface ArgumentGroup { 8 | Optional toArgument (Converter converter); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/strategy/method/argument/group/SingleArgumentGroup.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.strategy.method.argument.group; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.property.strategy.method.convert.Converter; 5 | import org.jtwig.reflection.model.Value; 6 | import org.jtwig.reflection.model.java.JavaMethodArgument; 7 | 8 | public class SingleArgumentGroup implements ArgumentGroup { 9 | private final JavaMethodArgument javaMethodArgument; 10 | private final Object value; 11 | 12 | public SingleArgumentGroup(JavaMethodArgument javaMethodArgument, Object value) { 13 | this.javaMethodArgument = javaMethodArgument; 14 | this.value = value; 15 | } 16 | 17 | @Override 18 | public Optional toArgument(Converter converter) { 19 | return converter.convert(value, javaMethodArgument.type()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/strategy/method/convert/Converter.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.strategy.method.convert; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.reflection.model.Value; 5 | 6 | public interface Converter { 7 | Optional convert (Object value, Class type); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/property/strategy/method/finder/PropertyMethodFinder.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.strategy.method.finder; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.reflection.model.java.JavaClass; 5 | import org.jtwig.reflection.model.java.JavaMethod; 6 | 7 | import java.util.List; 8 | 9 | public interface PropertyMethodFinder { 10 | Optional find(JavaClass type, String identifier, List arguments); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/RenderRequest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render; 2 | 3 | import org.jtwig.environment.Environment; 4 | import org.jtwig.render.context.RenderContext; 5 | 6 | public class RenderRequest { 7 | private final RenderContext renderContext; 8 | private final Environment environment; 9 | 10 | public RenderRequest(RenderContext renderContext, Environment environment) { 11 | this.renderContext = renderContext; 12 | this.environment = environment; 13 | } 14 | 15 | public RenderContext getRenderContext() { 16 | return renderContext; 17 | } 18 | 19 | public Environment getEnvironment() { 20 | return environment; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/context/RenderContextHolder.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.context; 2 | 3 | public class RenderContextHolder { 4 | private static final ThreadLocal current = new ThreadLocal<>(); 5 | 6 | private RenderContextHolder () {} 7 | 8 | public static RenderContext set (RenderContext context) { 9 | current.set(context); 10 | return context; 11 | } 12 | 13 | public static RenderContext get () { 14 | return current.get(); 15 | } 16 | 17 | public static void remove () { 18 | current.remove(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/context/model/BlockDefinition.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.context.model; 2 | 3 | import org.jtwig.model.tree.Node; 4 | import org.jtwig.resource.reference.ResourceReference; 5 | 6 | public class BlockDefinition { 7 | private final Node node; 8 | private final ResourceReference origin; 9 | 10 | public BlockDefinition(Node node, ResourceReference origin) { 11 | this.node = node; 12 | this.origin = origin; 13 | } 14 | 15 | public Node getNode() { 16 | return node; 17 | } 18 | 19 | public ResourceReference getSource() { 20 | return origin; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/context/model/BlockReference.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.context.model; 2 | 3 | public class BlockReference { 4 | private String identifier; 5 | 6 | public BlockReference(String identifier) { 7 | this.identifier = identifier; 8 | } 9 | 10 | public String getIdentifier() { 11 | return identifier; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/context/model/PropertiesContext.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.context.model; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class PropertiesContext { 7 | public static PropertiesContext newContext () { 8 | return new PropertiesContext(new HashMap()); 9 | } 10 | 11 | private final Map properties; 12 | 13 | public PropertiesContext(Map properties) { 14 | this.properties = properties; 15 | } 16 | 17 | public void set (String key, Object value) { 18 | properties.put(key, value); 19 | } 20 | 21 | public T get (String key) { 22 | return (T) properties.get(key); 23 | } 24 | 25 | public boolean has (String key) { 26 | return properties.containsKey(key); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/CalculateExpressionService.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.render.RenderRequest; 5 | 6 | public class CalculateExpressionService { 7 | private final ExpressionCalculatorSelector calculatorSelector; 8 | 9 | public CalculateExpressionService(ExpressionCalculatorSelector calculatorSelector) { 10 | this.calculatorSelector = calculatorSelector; 11 | } 12 | 13 | public Object calculate (RenderRequest request, Expression expression) { 14 | return calculatorSelector.calculatorFor(expression) 15 | .calculate(request, expression); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/BinaryOperationExpressionCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator; 2 | 3 | import org.jtwig.model.expression.BinaryOperationExpression; 4 | import org.jtwig.render.RenderRequest; 5 | 6 | public class BinaryOperationExpressionCalculator implements ExpressionCalculator { 7 | @Override 8 | public Object calculate(RenderRequest request, BinaryOperationExpression expression) { 9 | return request.getEnvironment().getRenderEnvironment().getBinaryOperationService() 10 | .calculate(request, expression); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/ConstantExpressionCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator; 2 | 3 | import org.jtwig.model.expression.ConstantExpression; 4 | import org.jtwig.render.RenderRequest; 5 | 6 | public class ConstantExpressionCalculator implements ExpressionCalculator { 7 | @Override 8 | public Object calculate(RenderRequest request, ConstantExpression expression) { 9 | return expression.getConstantValue(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/ExpressionCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.render.RenderRequest; 5 | 6 | public interface ExpressionCalculator { 7 | Object calculate (RenderRequest request, T expression); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/FunctionArgumentsFactory.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator; 2 | 3 | import org.jtwig.functions.ExpressionResolver; 4 | import org.jtwig.functions.FunctionArguments; 5 | import org.jtwig.model.expression.Expression; 6 | import org.jtwig.render.RenderRequest; 7 | 8 | import java.util.List; 9 | 10 | public class FunctionArgumentsFactory { 11 | public FunctionArguments create (RenderRequest request, List expressions) { 12 | ExpressionResolver expressionResolver = new ExpressionResolver(request); 13 | return new FunctionArguments(expressionResolver, expressions); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/TestOperationExpressionCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator; 2 | 3 | import org.jtwig.model.expression.TestOperationExpression; 4 | import org.jtwig.render.RenderRequest; 5 | import org.jtwig.render.expression.test.CalculateTestExpressionService; 6 | 7 | public class TestOperationExpressionCalculator implements ExpressionCalculator { 8 | @Override 9 | public Object calculate(RenderRequest request, TestOperationExpression expression) { 10 | CalculateTestExpressionService calculateTestExpressionService = request.getEnvironment().getRenderEnvironment().getCalculateTestExpressionService(); 11 | 12 | return calculateTestExpressionService.calculate(request, expression.getPosition(), expression.getTestExpression(), expression.getArgument()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/UnaryOperationExpressionCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator; 2 | 3 | import org.jtwig.model.expression.UnaryOperationExpression; 4 | import org.jtwig.render.RenderRequest; 5 | 6 | public class UnaryOperationExpressionCalculator implements ExpressionCalculator { 7 | @Override 8 | public Object calculate(RenderRequest request, UnaryOperationExpression expression) { 9 | return request.getEnvironment().getRenderEnvironment().getUnaryOperationService() 10 | .calculate(request, expression); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/enumerated/EnumerationListStrategy.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.enumerated; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.render.RenderRequest; 5 | 6 | import java.util.List; 7 | 8 | public interface EnumerationListStrategy { 9 | Optional> enumerate(RenderRequest request, Object left, Object right); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/enumerated/config/DefaultEnumerationListStrategyList.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.enumerated.config; 2 | 3 | import org.jtwig.render.expression.calculator.enumerated.*; 4 | 5 | import java.util.ArrayList; 6 | 7 | import static java.util.Arrays.asList; 8 | 9 | public class DefaultEnumerationListStrategyList extends ArrayList { 10 | public DefaultEnumerationListStrategyList() { 11 | super(asList( 12 | new IntegerAscendingOrderEnumerationListStrategy(), 13 | new IntegerDescendingOrderEnumerationListStrategy(), 14 | new CharAscendingOrderEnumerationListStrategy(), 15 | new CharDescendingOrderEnumerationListStrategy() 16 | )); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/enumerated/environment/EnumerationListStrategyFactory.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.enumerated.environment; 2 | 3 | import org.jtwig.render.expression.calculator.enumerated.CompositeEnumerationListStrategy; 4 | import org.jtwig.render.expression.calculator.enumerated.EnumerationListStrategy; 5 | 6 | import java.util.Collection; 7 | 8 | public class EnumerationListStrategyFactory { 9 | public EnumerationListStrategy create (Collection listStrategies) { 10 | return new CompositeEnumerationListStrategy(listStrategies); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/BinaryOperationCalculatorSelector.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.render.expression.calculator.operation.binary.calculators.BinaryOperationCalculator; 5 | 6 | import java.util.Map; 7 | 8 | public class BinaryOperationCalculatorSelector { 9 | private final Map, BinaryOperationCalculator> calculatorMap; 10 | 11 | public BinaryOperationCalculatorSelector(Map, BinaryOperationCalculator> calculatorMap) { 12 | this.calculatorMap = calculatorMap; 13 | } 14 | 15 | public Optional calculatorFor (BinaryOperator operator) { 16 | return Optional.fromNullable(calculatorMap.get(operator.getClass())); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/BinaryOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary; 2 | 3 | public interface BinaryOperator { 4 | String symbol (); 5 | int precedence (); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/AndOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | public class AndOperationCalculator implements SimpleBinaryBooleanCalculator { 4 | @Override 5 | public boolean calculate(boolean leftBoolean, boolean rightBoolean) { 6 | return leftBoolean && rightBoolean; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/ConcatOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.render.RenderRequest; 5 | 6 | public class ConcatOperationCalculator implements SimpleBinaryOperationCalculator { 7 | @Override 8 | public Object calculate(RenderRequest request, Position position, Object left, Object right) { 9 | return getString(request, left) + getString(request, right); 10 | } 11 | 12 | 13 | private String getString(RenderRequest request, Object input) { 14 | return request.getEnvironment().getValueEnvironment().getStringConverter().convert(input); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/DifferentOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.render.RenderRequest; 5 | 6 | public class DifferentOperationCalculator implements SimpleBinaryOperationCalculator { 7 | @Override 8 | public Object calculate(RenderRequest request, Position position, Object left, Object right) { 9 | return request.getEnvironment().getValueEnvironment().getValueComparator().compare(request, left, right) != 0; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/DivideOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.render.RenderRequest; 4 | 5 | import java.math.BigDecimal; 6 | import java.math.MathContext; 7 | 8 | public class DivideOperationCalculator implements SimpleBinaryMathCalculator { 9 | @Override 10 | public BigDecimal calculate(RenderRequest request, BigDecimal left, BigDecimal right) { 11 | MathContext mathContext = request.getEnvironment().getValueEnvironment().getMathContext(); 12 | return left.divide(right, mathContext); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/EquivalentOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.render.RenderRequest; 5 | import org.jtwig.value.compare.ValueComparator; 6 | 7 | public class EquivalentOperationCalculator implements SimpleBinaryOperationCalculator { 8 | @Override 9 | public Object calculate(RenderRequest request, Position position, Object left, Object right) { 10 | ValueComparator valueComparator = request.getEnvironment().getValueEnvironment().getValueComparator(); 11 | return valueComparator.compare(request, left, right) == 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/GreaterOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.render.RenderRequest; 5 | import org.jtwig.value.compare.ValueComparator; 6 | 7 | public class GreaterOperationCalculator implements SimpleBinaryOperationCalculator { 8 | 9 | @Override 10 | public Object calculate(RenderRequest request, Position position, Object left, Object right) { 11 | ValueComparator valueComparator = request.getEnvironment().getValueEnvironment().getValueComparator(); 12 | return valueComparator.compare(request, left, right) > 0; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/GreaterOrEqualOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.render.RenderRequest; 5 | import org.jtwig.value.compare.ValueComparator; 6 | 7 | public class GreaterOrEqualOperationCalculator implements SimpleBinaryOperationCalculator { 8 | @Override 9 | public Object calculate(RenderRequest request, Position position, Object left, Object right) { 10 | ValueComparator valueComparator = request.getEnvironment().getValueEnvironment().getValueComparator(); 11 | return valueComparator.compare(request, left, right) >= 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/IntegerDivideOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.render.RenderRequest; 4 | 5 | import java.math.BigDecimal; 6 | import java.math.MathContext; 7 | import java.math.RoundingMode; 8 | 9 | public class IntegerDivideOperationCalculator implements SimpleBinaryMathCalculator { 10 | @Override 11 | public BigDecimal calculate(RenderRequest request, BigDecimal left, BigDecimal right) { 12 | RoundingMode roundingMode = request.getEnvironment().getValueEnvironment().getRoundingMode(); 13 | MathContext mathContext = request.getEnvironment().getValueEnvironment().getMathContext(); 14 | return left.setScale(0, roundingMode).divide(right.setScale(0, roundingMode), mathContext).setScale(0, roundingMode); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/IntegerMultiplyOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.render.RenderRequest; 4 | 5 | import java.math.BigDecimal; 6 | import java.math.RoundingMode; 7 | 8 | public class IntegerMultiplyOperationCalculator implements SimpleBinaryMathCalculator { 9 | @Override 10 | public BigDecimal calculate(RenderRequest request, BigDecimal left, BigDecimal right) { 11 | RoundingMode roundingMode = request.getEnvironment().getValueEnvironment().getRoundingMode(); 12 | return left.setScale(0, roundingMode).multiply(right.setScale(0, roundingMode)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/LessOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.render.RenderRequest; 5 | import org.jtwig.value.compare.ValueComparator; 6 | 7 | public class LessOperationCalculator implements SimpleBinaryOperationCalculator { 8 | @Override 9 | public Object calculate(RenderRequest request, Position position, Object left, Object right) { 10 | ValueComparator valueComparator = request.getEnvironment().getValueEnvironment().getValueComparator(); 11 | return valueComparator.compare(request, left, right) < 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/LessOrEqualOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.render.RenderRequest; 5 | import org.jtwig.value.compare.ValueComparator; 6 | 7 | public class LessOrEqualOperationCalculator implements SimpleBinaryOperationCalculator { 8 | @Override 9 | public Object calculate(RenderRequest request, Position position, Object left, Object right) { 10 | ValueComparator valueComparator = request.getEnvironment().getValueEnvironment().getValueComparator(); 11 | return valueComparator.compare(request, left, right) <= 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/MatchesOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.render.RenderRequest; 5 | 6 | public class MatchesOperationCalculator implements SimpleBinaryOperationCalculator { 7 | @Override 8 | public Object calculate(RenderRequest request, Position position, Object left, Object right) { 9 | String leftOperand = request.getEnvironment().getValueEnvironment().getStringConverter().convert(left); 10 | String rightOperand = request.getEnvironment().getValueEnvironment().getStringConverter().convert(right); 11 | 12 | return leftOperand.matches(rightOperand); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/ModOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.render.RenderRequest; 4 | 5 | import java.math.BigDecimal; 6 | 7 | public class ModOperationCalculator implements SimpleBinaryMathCalculator { 8 | @Override 9 | public BigDecimal calculate(RenderRequest request, BigDecimal left, BigDecimal right) { 10 | return left.remainder(right, request.getEnvironment().getValueEnvironment().getMathContext()); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/MultiplyOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.render.RenderRequest; 4 | 5 | import java.math.BigDecimal; 6 | 7 | public class MultiplyOperationCalculator implements SimpleBinaryMathCalculator { 8 | @Override 9 | public BigDecimal calculate(RenderRequest request, BigDecimal left, BigDecimal right) { 10 | return left.multiply(right); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/OrOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | public class OrOperationCalculator implements SimpleBinaryBooleanCalculator { 4 | @Override 5 | public boolean calculate(boolean leftBoolean, boolean rightBoolean) { 6 | return leftBoolean || rightBoolean; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/SimpleBinaryBooleanCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | public interface SimpleBinaryBooleanCalculator { 4 | boolean calculate(boolean leftBoolean, boolean rightBoolean); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/SimpleBinaryMathCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.render.RenderRequest; 4 | 5 | import java.math.BigDecimal; 6 | 7 | public interface SimpleBinaryMathCalculator { 8 | BigDecimal calculate(RenderRequest request, BigDecimal left, BigDecimal right); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/SimpleBinaryOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.render.RenderRequest; 5 | 6 | public interface SimpleBinaryOperationCalculator { 7 | Object calculate(RenderRequest request, Position position, Object left, Object right); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/SubtractOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.render.RenderRequest; 4 | 5 | import java.math.BigDecimal; 6 | 7 | public class SubtractOperationCalculator implements SimpleBinaryMathCalculator { 8 | @Override 9 | public BigDecimal calculate(RenderRequest request, BigDecimal left, BigDecimal right) { 10 | return left.subtract(right); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/calculators/SumOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.jtwig.render.RenderRequest; 4 | 5 | import java.math.BigDecimal; 6 | 7 | public class SumOperationCalculator implements SimpleBinaryMathCalculator { 8 | @Override 9 | public BigDecimal calculate(RenderRequest request, BigDecimal left, BigDecimal right) { 10 | return left.add(right); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/AndOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class AndOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "and"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 25; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/CompositionOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class CompositionOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "|"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 30; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/ConcatOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class ConcatOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "~"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 12; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/DifferentOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class DifferentOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "!="; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 20; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/DivideOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class DivideOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "/"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 5; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/EquivalentOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class EquivalentOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "=="; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 20; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/GreaterOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class GreaterOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return ">"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 15; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/GreaterOrEqualOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class GreaterOrEqualOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return ">="; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 15; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/InOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class InOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "in"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 15; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/IntDivideOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class IntDivideOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "//"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 5; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/IntMultiplyOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class IntMultiplyOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "**"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 5; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/LessOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class LessOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "<"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 15; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/LessOrEqualOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class LessOrEqualOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "<="; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 15; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/MatchesOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class MatchesOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "matches"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 25; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/ModOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class ModOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "%"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 5; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/MultiplyOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class MultiplyOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "*"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 5; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/OrOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class OrOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "or"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 25; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/SelectionOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class SelectionOperator implements BinaryOperator { 6 | public static final String OPERATOR = "."; 7 | 8 | @Override 9 | public String symbol() { 10 | return OPERATOR; 11 | } 12 | 13 | @Override 14 | public int precedence() { 15 | return 1; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/SubtractOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class SubtractOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "-"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 10; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/binary/impl/SumOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.binary.BinaryOperator; 4 | 5 | public class SumOperator implements BinaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "+"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 10; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/unary/UnaryOperationCalculatorSelector.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.unary; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.render.expression.calculator.operation.unary.calculators.UnaryOperationCalculator; 5 | 6 | import java.util.Map; 7 | 8 | public class UnaryOperationCalculatorSelector { 9 | private final Map, UnaryOperationCalculator> operationCalculatorMap; 10 | 11 | public UnaryOperationCalculatorSelector(Map, UnaryOperationCalculator> operationCalculatorMap) { 12 | this.operationCalculatorMap = operationCalculatorMap; 13 | } 14 | 15 | public Optional calculatorFor (UnaryOperator operator) { 16 | return Optional.fromNullable(operationCalculatorMap.get(operator.getClass())); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/unary/UnaryOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.unary; 2 | 3 | public interface UnaryOperator { 4 | int precedence (); 5 | String symbol (); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/unary/calculators/UnaryOperationCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.unary.calculators; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.model.position.Position; 5 | import org.jtwig.render.RenderRequest; 6 | 7 | public interface UnaryOperationCalculator { 8 | Object calculate(RenderRequest request, Position position, Expression operand); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/unary/impl/NegativeUnaryOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.unary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.unary.UnaryOperator; 4 | 5 | public class NegativeUnaryOperator implements UnaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "-"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 5; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/calculator/operation/unary/impl/NotUnaryOperator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.unary.impl; 2 | 3 | import org.jtwig.render.expression.calculator.operation.unary.UnaryOperator; 4 | 5 | public class NotUnaryOperator implements UnaryOperator { 6 | @Override 7 | public String symbol() { 8 | return "not"; 9 | } 10 | 11 | @Override 12 | public int precedence() { 13 | return 10; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/test/TestExpressionCalculatorSelector.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.test; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.model.expression.test.TestExpression; 5 | import org.jtwig.render.expression.test.calculator.TestExpressionCalculator; 6 | 7 | import java.util.Map; 8 | 9 | public class TestExpressionCalculatorSelector { 10 | private final Map, TestExpressionCalculator> calculatorMap; 11 | 12 | public TestExpressionCalculatorSelector(Map, TestExpressionCalculator> calculatorMap) { 13 | this.calculatorMap = calculatorMap; 14 | } 15 | 16 | public Optional calculatorFor (TestExpression expression) { 17 | return Optional.fromNullable(calculatorMap.get(expression.getClass())); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/expression/test/calculator/TestExpressionCalculator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.test.calculator; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.model.expression.test.TestExpression; 5 | import org.jtwig.model.position.Position; 6 | import org.jtwig.render.RenderRequest; 7 | 8 | public interface TestExpressionCalculator { 9 | Object calculate (RenderRequest request, Position position, T test, Expression argument); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/listeners/RenderListener.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.listeners; 2 | 3 | import org.jtwig.render.RenderRequest; 4 | 5 | public interface RenderListener { 6 | void listen (RenderRequest request); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/listeners/RenderListenerRegistry.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.listeners; 2 | 3 | import org.jtwig.render.RenderRequest; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | public class RenderListenerRegistry { 9 | private final Map> listeners; 10 | 11 | public RenderListenerRegistry(Map> listeners) { 12 | this.listeners = listeners; 13 | } 14 | 15 | public void trigger (RenderStage stage, RenderRequest request) { 16 | if (listeners.containsKey(stage)) { 17 | for (RenderListener listener : listeners.get(stage)) { 18 | listener.listen(request); 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/listeners/RenderStage.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.listeners; 2 | 3 | public enum RenderStage { 4 | PRE_TEMPLATE_RENDER, 5 | POST_TEMPLATE_RENDER, 6 | PRE_RESOURCE_RENDER, 7 | POST_RESOURCE_RENDER, 8 | PRE_NODE_RENDER, 9 | POST_NODE_RENDER 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/listeners/StagedRenderListener.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.listeners; 2 | 3 | public class StagedRenderListener { 4 | private final RenderStage stage; 5 | private final RenderListener listener; 6 | 7 | public StagedRenderListener(RenderStage stage, RenderListener listener) { 8 | this.stage = stage; 9 | this.listener = listener; 10 | } 11 | 12 | public RenderStage getStage() { 13 | return stage; 14 | } 15 | 16 | public RenderListener getListener() { 17 | return listener; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/node/NodeRenderSelector.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.node; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.model.tree.Node; 5 | import org.jtwig.render.node.renderer.NodeRender; 6 | 7 | import java.util.Map; 8 | 9 | public class NodeRenderSelector { 10 | private final Map, NodeRender> nodeRenderMap; 11 | 12 | public NodeRenderSelector(Map, NodeRender> nodeRenderMap) { 13 | this.nodeRenderMap = nodeRenderMap; 14 | } 15 | 16 | public Optional renderFor(Node node) { 17 | return Optional.fromNullable(nodeRenderMap.get(node.getClass())); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/node/renderer/DoNodeRender.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.node.renderer; 2 | 3 | import org.jtwig.model.tree.DoNode; 4 | import org.jtwig.render.RenderRequest; 5 | import org.jtwig.renderable.Renderable; 6 | import org.jtwig.renderable.impl.EmptyRenderable; 7 | 8 | public class DoNodeRender implements NodeRender { 9 | @Override 10 | public Renderable render(RenderRequest renderRequest, DoNode node) { 11 | renderRequest.getEnvironment().getRenderEnvironment().getCalculateExpressionService().calculate(renderRequest, node.getExpression()); 12 | return EmptyRenderable.instance(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/node/renderer/FlushNodeRender.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.node.renderer; 2 | 3 | import org.jtwig.model.tree.FlushNode; 4 | import org.jtwig.render.RenderRequest; 5 | import org.jtwig.renderable.Renderable; 6 | import org.jtwig.renderable.impl.FlushRenderable; 7 | 8 | public class FlushNodeRender implements NodeRender { 9 | @Override 10 | public Renderable render(RenderRequest renderRequest, FlushNode node) { 11 | return FlushRenderable.instance(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/node/renderer/MacroNodeRender.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.node.renderer; 2 | 3 | import org.jtwig.model.tree.MacroNode; 4 | import org.jtwig.render.RenderRequest; 5 | import org.jtwig.renderable.Renderable; 6 | import org.jtwig.renderable.impl.EmptyRenderable; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | public class MacroNodeRender implements NodeRender { 11 | private final static Logger log = LoggerFactory.getLogger(MacroNodeRender.class); 12 | 13 | @Override 14 | public Renderable render(RenderRequest request, MacroNode node) { 15 | return EmptyRenderable.instance(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/node/renderer/NodeRender.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.node.renderer; 2 | 3 | import org.jtwig.model.tree.Node; 4 | import org.jtwig.render.RenderRequest; 5 | import org.jtwig.renderable.Renderable; 6 | 7 | public interface NodeRender { 8 | Renderable render (RenderRequest renderRequest, T node); 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/node/renderer/OverrideBlockNodeRender.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.node.renderer; 2 | 3 | import org.jtwig.model.tree.OverrideBlockNode; 4 | import org.jtwig.render.RenderRequest; 5 | import org.jtwig.render.context.model.BlockContext; 6 | import org.jtwig.renderable.Renderable; 7 | import org.jtwig.renderable.impl.EmptyRenderable; 8 | import org.jtwig.resource.reference.ResourceReference; 9 | 10 | public class OverrideBlockNodeRender implements NodeRender { 11 | @Override 12 | public Renderable render(RenderRequest renderRequest, OverrideBlockNode node) { 13 | ResourceReference current = renderRequest.getRenderContext().getCurrent(ResourceReference.class); 14 | renderRequest.getRenderContext().getCurrent(BlockContext.class).addLast(node, current); 15 | return EmptyRenderable.instance(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/render/node/renderer/VerbatimNodeRender.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.node.renderer; 2 | 3 | import org.jtwig.model.tree.VerbatimNode; 4 | import org.jtwig.render.RenderRequest; 5 | import org.jtwig.renderable.Renderable; 6 | import org.jtwig.renderable.impl.StringRenderable; 7 | 8 | public class VerbatimNodeRender implements NodeRender { 9 | @Override 10 | public Renderable render(RenderRequest renderRequest, VerbatimNode node) { 11 | return new StringRenderable(node.getContent()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/renderable/RenderException.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.renderable; 2 | 3 | import org.jtwig.exceptions.JtwigException; 4 | 5 | public class RenderException extends JtwigException { 6 | public RenderException(Throwable cause) { 7 | super(cause); 8 | } 9 | 10 | public RenderException(String message) { 11 | super(message); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/renderable/RenderResult.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.renderable; 2 | 3 | public interface RenderResult { 4 | RenderResult append(String content); 5 | RenderResult flush (); 6 | String content (); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/renderable/Renderable.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.renderable; 2 | 3 | public interface Renderable { 4 | RenderResult appendTo (RenderResult result); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/renderable/StringBuilderRenderResult.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.renderable; 2 | 3 | public class StringBuilderRenderResult implements RenderResult { 4 | private final StringBuilder builder = new StringBuilder(); 5 | 6 | @Override 7 | public RenderResult append(String content) { 8 | builder.append(content); 9 | return this; 10 | } 11 | 12 | @Override 13 | public RenderResult flush() { 14 | return this; 15 | } 16 | 17 | @Override 18 | public String content() { 19 | return builder.toString(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/renderable/impl/CompositeRenderable.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.renderable.impl; 2 | 3 | import org.jtwig.renderable.RenderResult; 4 | import org.jtwig.renderable.Renderable; 5 | 6 | import java.util.Collection; 7 | 8 | public class CompositeRenderable implements Renderable { 9 | private final Collection renderableCollection; 10 | 11 | public CompositeRenderable(Collection renderableCollection) { 12 | this.renderableCollection = renderableCollection; 13 | } 14 | 15 | @Override 16 | public RenderResult appendTo(RenderResult result) { 17 | for (Renderable renderable : renderableCollection) { 18 | renderable.appendTo(result); 19 | } 20 | return result; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/renderable/impl/EmptyRenderable.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.renderable.impl; 2 | 3 | import org.jtwig.renderable.RenderResult; 4 | import org.jtwig.renderable.Renderable; 5 | 6 | public class EmptyRenderable implements Renderable { 7 | private static final EmptyRenderable instance = new EmptyRenderable(); 8 | public static EmptyRenderable instance () { 9 | return instance; 10 | } 11 | 12 | private EmptyRenderable () {} 13 | 14 | @Override 15 | public RenderResult appendTo(RenderResult result) { 16 | return result; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/renderable/impl/FlushRenderable.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.renderable.impl; 2 | 3 | import org.jtwig.renderable.RenderResult; 4 | import org.jtwig.renderable.Renderable; 5 | 6 | public class FlushRenderable implements Renderable { 7 | private static final FlushRenderable INSTANCE = new FlushRenderable(); 8 | 9 | public static FlushRenderable instance() { 10 | return INSTANCE; 11 | } 12 | 13 | private FlushRenderable () {} 14 | 15 | @Override 16 | public RenderResult appendTo(RenderResult result) { 17 | result.flush(); 18 | return result; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/renderable/impl/FutureRenderable.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.renderable.impl; 2 | 3 | import org.jtwig.renderable.RenderResult; 4 | import org.jtwig.renderable.Renderable; 5 | 6 | public class FutureRenderable implements Renderable { 7 | private Renderable renderable; 8 | 9 | public FutureRenderable complete(Renderable renderable) { 10 | if (this.renderable != null) throw new IllegalStateException("Future Renderable already completed"); 11 | this.renderable = renderable; 12 | return this; 13 | } 14 | 15 | @Override 16 | public RenderResult appendTo(RenderResult result) { 17 | if (renderable != null) { 18 | renderable.appendTo(result); 19 | return result; 20 | } else { 21 | throw new IllegalStateException("Current renderable is in invalid state, it must be completed first"); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/renderable/impl/StringRenderable.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.renderable.impl; 2 | 3 | import org.jtwig.escape.EscapeEngine; 4 | import org.jtwig.escape.NoneEscapeEngine; 5 | import org.jtwig.renderable.RenderResult; 6 | import org.jtwig.renderable.Renderable; 7 | 8 | public class StringRenderable implements Renderable { 9 | private final String content; 10 | private final EscapeEngine escapeEngine; 11 | 12 | public StringRenderable(String content) { 13 | this(content, NoneEscapeEngine.instance()); 14 | } 15 | 16 | public StringRenderable(String content, EscapeEngine escapeEngine) { 17 | this.content = content; 18 | this.escapeEngine = escapeEngine; 19 | } 20 | 21 | @Override 22 | public RenderResult appendTo(RenderResult result) { 23 | result.append(escapeEngine.escape(content)); 24 | return result; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/resource/exceptions/ResourceException.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.exceptions; 2 | 3 | import org.jtwig.exceptions.JtwigException; 4 | 5 | public class ResourceException extends JtwigException { 6 | 7 | public ResourceException(String message, Throwable cause) { 8 | super(message, cause); 9 | } 10 | 11 | public ResourceException(String message) { 12 | super(message); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/resource/exceptions/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.exceptions; 2 | 3 | import org.jtwig.exceptions.JtwigException; 4 | 5 | public class ResourceNotFoundException extends JtwigException { 6 | public ResourceNotFoundException(String message) { 7 | super(message); 8 | } 9 | 10 | public ResourceNotFoundException(Throwable e) { 11 | super(e); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/resource/loader/ResourceLoader.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.loader; 2 | 3 | import com.google.common.base.Optional; 4 | 5 | import java.io.InputStream; 6 | import java.net.URL; 7 | import java.nio.charset.Charset; 8 | 9 | public interface ResourceLoader { 10 | Optional getCharset(String path); 11 | InputStream load (String path); 12 | boolean exists (String path); 13 | Optional toUrl (String path); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/resource/loader/TypedResourceLoader.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.loader; 2 | 3 | public class TypedResourceLoader { 4 | private final String type; 5 | private final ResourceLoader resourceLoader; 6 | 7 | public TypedResourceLoader(String type, ResourceLoader resourceLoader) { 8 | this.type = type; 9 | this.resourceLoader = resourceLoader; 10 | } 11 | 12 | public String getType() { 13 | return type; 14 | } 15 | 16 | public ResourceLoader getResourceLoader() { 17 | return resourceLoader; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/resource/metadata/ResourceMetadata.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.metadata; 2 | 3 | import com.google.common.base.Optional; 4 | 5 | import java.io.InputStream; 6 | import java.net.URL; 7 | import java.nio.charset.Charset; 8 | 9 | public interface ResourceMetadata { 10 | boolean exists (); 11 | InputStream load(); 12 | Optional getCharset (); 13 | Optional toUrl (); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/resource/reference/PosixResourceReferenceExtractor.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.reference; 2 | 3 | public class PosixResourceReferenceExtractor implements ResourceReferenceExtractor { 4 | @Override 5 | public ResourceReference extract(String spec) { 6 | int indexOf = spec.indexOf(":"); 7 | if (indexOf == -1) { 8 | return new ResourceReference(ResourceReference.ANY_TYPE, spec); 9 | } else { 10 | return new ResourceReference(spec.substring(0, indexOf), spec.substring(indexOf + 1)); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/resource/reference/ResourceReferenceExtractor.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.reference; 2 | 3 | public interface ResourceReferenceExtractor { 4 | ResourceReference extract (String spec); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/resource/reference/UncResourceReferenceExtractor.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.reference; 2 | 3 | public class UncResourceReferenceExtractor implements ResourceReferenceExtractor { 4 | @Override 5 | public ResourceReference extract(String spec) { 6 | if (isAbsolute(spec)) { 7 | return new ResourceReference(ResourceReference.ANY_TYPE, spec); 8 | } else { 9 | int indexOf = spec.indexOf(":"); 10 | if (indexOf == -1) { 11 | return new ResourceReference(ResourceReference.ANY_TYPE, spec); 12 | } else { 13 | return new ResourceReference(spec.substring(0, indexOf), spec.substring(indexOf + 1)); 14 | } 15 | } 16 | } 17 | 18 | private boolean isAbsolute(String spec) { 19 | return spec.length() > 2 && spec.charAt(1) == ':' && spec.charAt(2) == '\\'; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/resource/reference/path/PathType.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.reference.path; 2 | 3 | public enum PathType { 4 | UNC, POSIX 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/resource/resolver/RelativeResourceResolver.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.resolver; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.resource.reference.ResourceReference; 5 | 6 | public interface RelativeResourceResolver { 7 | Optional resolve(ResourceReference parentReference, ResourceReference newPath); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/resource/resolver/path/RelativeFilePathResolver.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.resolver.path; 2 | 3 | import java.io.File; 4 | 5 | public class RelativeFilePathResolver implements RelativeReferenceResolver { 6 | private static final RelativeFilePathResolver INSTANCE = new RelativeFilePathResolver(); 7 | 8 | public static RelativeFilePathResolver instance () { 9 | return INSTANCE; 10 | } 11 | 12 | private RelativeFilePathResolver() {} 13 | 14 | @Override 15 | public boolean isRelative(String path) { 16 | return !new File(path).isAbsolute(); 17 | } 18 | 19 | @Override 20 | public String resolve(String parent, String child) { 21 | return new File(new File(parent).getParentFile(), child).getPath(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/resource/resolver/path/RelativeReferenceResolver.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.resolver.path; 2 | 3 | public interface RelativeReferenceResolver { 4 | boolean isRelative(String path); 5 | String resolve(String parent, String child); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/util/ErrorMessageFormatter.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.util; 2 | 3 | import org.jtwig.model.position.Position; 4 | 5 | public class ErrorMessageFormatter { 6 | public static String errorMessage (Position position, String message) { 7 | return String.format("%s -> %s", position, message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/util/EscapeUtils.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.util; 2 | 3 | public class EscapeUtils { 4 | public static String escapeJtwig (String input) { 5 | return input.replace("\\", "\\\\"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/util/UrlEncodingUtils.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.util; 2 | 3 | import org.jtwig.model.position.Position; 4 | 5 | import java.io.UnsupportedEncodingException; 6 | import java.net.URLEncoder; 7 | 8 | public class UrlEncodingUtils { 9 | public static String encode (String content, String encoding, Position position) { 10 | try { 11 | return URLEncoder.encode(content, encoding); 12 | } catch (UnsupportedEncodingException e) { 13 | throw new IllegalArgumentException(ErrorMessageFormatter.errorMessage(position, String.format("Invalid encoding '%s'", encoding)), e); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/value/Undefined.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value; 2 | 3 | public final class Undefined { 4 | public static final Undefined UNDEFINED = new Undefined(); 5 | 6 | private Undefined() {} 7 | 8 | @Override 9 | public String toString() { 10 | return ""; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/value/compare/ValueComparator.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.compare; 2 | 3 | import org.jtwig.render.RenderRequest; 4 | 5 | public interface ValueComparator { 6 | int compare(RenderRequest renderRequest, Object left, Object right); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/value/context/IsolateParentValueContext.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.context; 2 | 3 | import org.jtwig.value.Undefined; 4 | 5 | public class IsolateParentValueContext implements ValueContext { 6 | private final ValueContext parent; 7 | private final ValueContext current; 8 | 9 | public IsolateParentValueContext(ValueContext parent, ValueContext current) { 10 | this.parent = parent; 11 | this.current = current; 12 | } 13 | 14 | @Override 15 | public Object resolve(String key) { 16 | Object value = current.resolve(key); 17 | if (value == Undefined.UNDEFINED) { 18 | return parent.resolve(key); 19 | } else { 20 | return value; 21 | } 22 | } 23 | 24 | @Override 25 | public ValueContext with(String key, Object value) { 26 | current.with(key, value); 27 | return this; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/value/context/StaticVariableValueContext.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.context; 2 | 3 | public class StaticVariableValueContext implements ValueContext { 4 | private final ValueContext parent; 5 | private final String staticKey; 6 | private final Object staticValue; 7 | 8 | public StaticVariableValueContext(ValueContext parent, String staticKey, Object staticValue) { 9 | this.parent = parent; 10 | this.staticKey = staticKey; 11 | this.staticValue = staticValue; 12 | } 13 | 14 | @Override 15 | public Object resolve(String key) { 16 | if (staticKey.equals(key)) { 17 | return staticValue; 18 | } else { 19 | return parent.resolve(key); 20 | } 21 | } 22 | 23 | @Override 24 | public ValueContext with(String key, Object value) { 25 | parent.with(key, value); 26 | return this; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/value/context/ValueContext.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.context; 2 | 3 | public interface ValueContext { 4 | Object resolve (String key); 5 | ValueContext with (String key, Object value); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/value/convert/CompositeConverter.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.convert; 2 | 3 | import java.util.Collection; 4 | 5 | public class CompositeConverter implements Converter { 6 | private final Collection> converters; 7 | 8 | public CompositeConverter(Collection> converters) { 9 | this.converters = converters; 10 | } 11 | 12 | @Override 13 | public Result convert(Object value) { 14 | for (Converter converter : converters) { 15 | Result convert = converter.convert(value); 16 | if (convert.isDefined()) return convert; 17 | } 18 | return Result.undefined(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/value/convert/NullConverter.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.convert; 2 | 3 | public class NullConverter implements Converter { 4 | @Override 5 | public Result convert(Object object) { 6 | if (object == null) return Result.defined(null); 7 | 8 | return Result.undefined(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/value/convert/character/CharConverter.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.convert.character; 2 | 3 | import org.jtwig.value.convert.Converter; 4 | 5 | public class CharConverter implements Converter { 6 | @Override 7 | public Result convert(Object object) { 8 | String string = object.toString(); 9 | 10 | if (string.length() == 1) { 11 | return Result.defined(string.charAt(0)); 12 | } 13 | 14 | return Result.undefined(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/value/convert/collection/ArrayToCollectionConverter.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.convert.collection; 2 | 3 | import org.jtwig.value.WrappedCollection; 4 | import org.jtwig.value.convert.Converter; 5 | 6 | public class ArrayToCollectionConverter implements Converter { 7 | @Override 8 | public Result convert(Object object) { 9 | if (object.getClass().isArray()) { 10 | WrappedCollection result = new WrappedCollection(); 11 | Object[] array = (Object[]) object; 12 | 13 | for (int i = 0; i < array.length; i++) { 14 | result.add(String.valueOf(i), array[i]); 15 | } 16 | 17 | return Result.defined(result); 18 | } 19 | return Result.undefined(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/value/convert/collection/IterableToCollectionConverter.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.convert.collection; 2 | 3 | import org.jtwig.value.WrappedCollection; 4 | import org.jtwig.value.convert.Converter; 5 | 6 | import java.util.Iterator; 7 | 8 | public class IterableToCollectionConverter implements Converter { 9 | @Override 10 | public Result convert(Object object) { 11 | if (object instanceof Iterable) { 12 | WrappedCollection result = new WrappedCollection(); 13 | Iterator iterator = ((Iterable) object).iterator(); 14 | int i = 0; 15 | while (iterator.hasNext()) { 16 | Object next = iterator.next(); 17 | result.add(String.valueOf(i++), next); 18 | } 19 | return Result.defined(result); 20 | } 21 | return Result.undefined(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/value/convert/collection/MapToCollectionConverter.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.convert.collection; 2 | 3 | import org.jtwig.value.WrappedCollection; 4 | import org.jtwig.value.convert.Converter; 5 | 6 | import java.util.Map; 7 | 8 | public class MapToCollectionConverter implements Converter { 9 | @Override 10 | public Result convert(Object object) { 11 | if (object instanceof Map) { 12 | Map input = (Map) object; 13 | WrappedCollection result = new WrappedCollection(); 14 | for (Map.Entry entry : input.entrySet()) { 15 | result.add(entry.getKey().toString(), entry.getValue()); 16 | } 17 | return Result.defined(result); 18 | } 19 | return Result.undefined(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/value/convert/string/DefaultStringConverter.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.convert.string; 2 | 3 | public class DefaultStringConverter implements StringConverter { 4 | @Override 5 | public String convert(Object input) { 6 | return input == null ? "" : input.toString(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/value/convert/string/StringConverter.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.convert.string; 2 | 3 | public interface StringConverter { 4 | String convert(Object input); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/jtwig/value/environment/ValueEnvironmentFactory.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.environment; 2 | 3 | import org.jtwig.value.config.ValueConfiguration; 4 | import org.jtwig.value.convert.CompositeConverter; 5 | 6 | public class ValueEnvironmentFactory { 7 | public ValueEnvironment create (ValueConfiguration configuration) { 8 | return new ValueEnvironment( 9 | configuration.getMathContext(), 10 | configuration.getRoundingMode(), 11 | new CompositeConverter<>(configuration.getNumberConverters()), 12 | new CompositeConverter<>(configuration.getBooleanConverters()), 13 | new CompositeConverter<>(configuration.getCollectionConverters()), 14 | new CompositeConverter<>(configuration.getCharConverters()), 15 | configuration.getValueComparator(), configuration.getStringConverter()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/JtwigModelTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig; 2 | 3 | import com.google.common.base.Optional; 4 | import com.google.common.collect.ImmutableMap; 5 | import org.jtwig.reflection.model.Value; 6 | import org.junit.Test; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | 10 | public class JtwigModelTest { 11 | @Test 12 | public void newModelFromMap() throws Exception { 13 | 14 | JtwigModel underTest = JtwigModel.newModel(ImmutableMap.builder() 15 | .put("test", "hello") 16 | .build()); 17 | 18 | Optional result = underTest.get("test"); 19 | 20 | assertEquals("hello", result.get().getValue()); 21 | } 22 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/TestUtils.java: -------------------------------------------------------------------------------- 1 | package org.jtwig; 2 | 3 | import org.apache.commons.lang.StringUtils; 4 | 5 | import java.io.File; 6 | import java.util.regex.Pattern; 7 | 8 | import static java.util.Arrays.asList; 9 | 10 | public class TestUtils { 11 | public static String universalPath (String path) { 12 | try { 13 | StringBuilder stringBuilder = new StringBuilder(); 14 | stringBuilder.append(StringUtils.join(asList(path.split(Pattern.quote("/"))), File.separator)); 15 | File file = new File(stringBuilder.toString()); 16 | return new File(file.getParentFile(), file.getName()).getCanonicalPath(); 17 | } catch (Exception e) { 18 | return path; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/escape/config/EscapeEngineConfigurationBuilderTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.escape.config; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.jtwig.support.MatcherUtils.theSameBean; 6 | import static org.junit.Assert.assertThat; 7 | 8 | public class EscapeEngineConfigurationBuilderTest { 9 | @Test 10 | public void cloneConstructor() throws Exception { 11 | EscapeEngineConfiguration prototype = new DefaultEscapeEngineConfiguration(); 12 | 13 | EscapeEngineConfiguration result = new EscapeEngineConfigurationBuilder<>(prototype) 14 | .build(); 15 | 16 | assertThat(result, theSameBean(prototype)); 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/functions/EmptyExpressionResolverTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.junit.Test; 5 | 6 | import static org.hamcrest.core.Is.is; 7 | import static org.hamcrest.core.IsNull.nullValue; 8 | import static org.junit.Assert.assertThat; 9 | import static org.mockito.Mockito.mock; 10 | 11 | public class EmptyExpressionResolverTest { 12 | 13 | @Test 14 | public void apply() throws Exception { 15 | Object result = EmptyExpressionResolver.instance().apply(mock(Expression.class)); 16 | 17 | assertThat(result, is(nullValue())); 18 | } 19 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/functions/impl/AbstractFunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl; 2 | 3 | public abstract class AbstractFunctionTest { 4 | } 5 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/functions/impl/map/KeysFunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.functions.impl.map; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.core.Is.is; 8 | import static org.junit.Assert.assertThat; 9 | 10 | public class KeysFunctionTest { 11 | @Test 12 | public void keysSimple() throws Exception { 13 | String result = JtwigTemplate.inlineTemplate("{{ keys({'1':'one', '2':'two'}) }}").render(JtwigModel.newModel()); 14 | 15 | assertThat(result, is("[1, 2]")); 16 | } 17 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/AbstractIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration; 2 | 3 | public abstract class AbstractIntegrationTest { 4 | } 5 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/expression/ContentEscapeTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.expression; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class ContentEscapeTest { 11 | @Test 12 | public void example() throws Exception { 13 | String result = JtwigTemplate.inlineTemplate("{% contentescape %}&{% endcontentescape %}") 14 | .render(JtwigModel.newModel()); 15 | 16 | assertThat(result, is("&")); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/expression/FunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.expression; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class FunctionTest { 11 | @Test 12 | public void functionCallWithOneArgumentOnly() throws Exception { 13 | String result = JtwigTemplate.inlineTemplate("{{ trim ' word ' }}") 14 | .render(JtwigModel.newModel()); 15 | 16 | assertThat(result, is("word")); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/expression/MapTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.expression; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.jtwig.integration.AbstractIntegrationTest; 6 | import org.junit.Test; 7 | 8 | import static org.hamcrest.MatcherAssert.assertThat; 9 | import static org.hamcrest.core.Is.is; 10 | 11 | public class MapTest extends AbstractIntegrationTest { 12 | @Test 13 | public void map() throws Exception { 14 | String result = JtwigTemplate.inlineTemplate("{{ { one: 'two' } }}") 15 | .render(JtwigModel.newModel()); 16 | 17 | assertThat(result, is("{one=two}")); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/expression/OperatorPrecedenceTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.expression; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.core.Is.is; 8 | import static org.junit.Assert.assertThat; 9 | 10 | public class OperatorPrecedenceTest { 11 | @Test 12 | public void multiplyOverSum() throws Exception { 13 | String result = JtwigTemplate.inlineTemplate("{{ 2 + 5 * 3 }}") 14 | .render(JtwigModel.newModel()); 15 | 16 | assertThat(result, is("17")); 17 | } 18 | @Test 19 | public void multiplyOverSum2() throws Exception { 20 | String result = JtwigTemplate.inlineTemplate("{{ 2 * 5 + 3 }}") 21 | .render(JtwigModel.newModel()); 22 | 23 | assertThat(result, is("13")); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/expression/PrintingBooleanTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.expression; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.jtwig.integration.AbstractIntegrationTest; 6 | import org.junit.Test; 7 | 8 | import static org.hamcrest.MatcherAssert.assertThat; 9 | import static org.hamcrest.core.Is.is; 10 | 11 | public class PrintingBooleanTest extends AbstractIntegrationTest { 12 | @Test 13 | public void printTrue() throws Exception { 14 | String result = JtwigTemplate.inlineTemplate("{{ true }}").render(JtwigModel.newModel()); 15 | 16 | assertThat(result, is("true")); 17 | } 18 | 19 | @Test 20 | public void printFalse() throws Exception { 21 | String result = JtwigTemplate.inlineTemplate("{{ false }}").render(JtwigModel.newModel()); 22 | 23 | assertThat(result, is("false")); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/expression/binary/MatchesComparatorTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.expression.binary; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class MatchesComparatorTest { 11 | @Test 12 | public void matchesUnhappy() throws Exception { 13 | String result = JtwigTemplate.inlineTemplate("{{ 'one' matches '[a-z]{2}' }}") 14 | .render(JtwigModel.newModel()); 15 | 16 | assertThat(result, is("false")); 17 | } 18 | 19 | @Test 20 | public void matchesHappy() throws Exception { 21 | String result = JtwigTemplate.inlineTemplate("{{ 'one' matches '[a-z]{3}' }}") 22 | .render(JtwigModel.newModel()); 23 | 24 | assertThat(result, is("true")); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/expression/binary/MathOperatorsTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.expression.binary; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class MathOperatorsTest { 11 | @Test 12 | public void modSimple() throws Exception { 13 | String result = JtwigTemplate.inlineTemplate("{{ 4 % 2 }}").render(JtwigModel.newModel()); 14 | 15 | assertThat(result, is("0")); 16 | } 17 | @Test 18 | public void addSimple() throws Exception { 19 | String result = JtwigTemplate.inlineTemplate("{{ 4 + 2 }}").render(JtwigModel.newModel()); 20 | 21 | assertThat(result, is("6")); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/function/ConcatFunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.function; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class ConcatFunctionTest { 11 | @Test 12 | public void simpleConcat() throws Exception { 13 | String result = JtwigTemplate.inlineTemplate("{{ concat('hello', ' world') }}").render(JtwigModel.newModel()); 14 | 15 | assertThat(result, is("hello world")); 16 | } 17 | @Test 18 | public void concatWithNulls() throws Exception { 19 | String result = JtwigTemplate.inlineTemplate("{{ concat('hello', null, ' world') }}").render(JtwigModel.newModel()); 20 | 21 | assertThat(result, is("hello world")); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/function/ConvertEncodingFunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.function; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class ConvertEncodingFunctionTest { 11 | @Test 12 | public void simpleConvertEncoding() throws Exception { 13 | String result = JtwigTemplate.inlineTemplate("{{ convert_encoding('hello', 'ASCII', 'UTF-8') }}").render(JtwigModel.newModel()); 14 | 15 | assertThat(result, is("hello")); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/function/FormatFunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.function; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class FormatFunctionTest { 11 | @Test 12 | public void simpleFormat() throws Exception { 13 | 14 | String result = JtwigTemplate.inlineTemplate("{{ format('Hello %s', 'World') }}").render(JtwigModel.newModel()); 15 | 16 | assertThat(result, is("Hello World")); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/function/MergeFunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.function; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class MergeFunctionTest { 11 | @Test 12 | public void simpleMerge() throws Exception { 13 | String result = JtwigTemplate.inlineTemplate("{{ [1, 2, 3] | merge([4,5]) }}").render(JtwigModel.newModel()); 14 | 15 | assertThat(result, is("[1, 2, 3, 4, 5]")); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/function/Nl2BrFunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.function; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class Nl2BrFunctionTest { 11 | @Test 12 | public void nl2brSimple() throws Exception { 13 | 14 | String result = JtwigTemplate.inlineTemplate("{{ nl2br(var) }}").render(JtwigModel.newModel().with("var", "\n")); 15 | 16 | assertThat(result, is("
")); 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/function/ReplaceFunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.function; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class ReplaceFunctionTest { 11 | @Test 12 | public void simpleReplace() throws Exception { 13 | String result = JtwigTemplate.inlineTemplate("{{ replace('Hello %name%', { '%name%': 'world' }) }}").render(JtwigModel.newModel()); 14 | 15 | assertThat(result, is("Hello world")); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/function/SplitFunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.function; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class SplitFunctionTest { 11 | @Test 12 | public void simpleSplit() throws Exception { 13 | 14 | String result = JtwigTemplate.inlineTemplate("{{ split('jtwig-2','-') }}").render(JtwigModel.newModel()); 15 | 16 | assertThat(result, is("[jtwig, 2]")); 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/function/StripTagsFunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.function; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class StripTagsFunctionTest { 11 | @Test 12 | public void simpleStripTags() throws Exception { 13 | String result = JtwigTemplate.inlineTemplate("{{ striptags('jtwig') }}").render(JtwigModel.newModel()); 14 | 15 | assertThat(result, is("jtwig")); 16 | } 17 | @Test 18 | public void simpleStripTagsWithIgnore() throws Exception { 19 | String result = JtwigTemplate.inlineTemplate("{{ striptags('jtwig', '') }}").render(JtwigModel.newModel()); 20 | 21 | assertThat(result, is("jtwigSubmit")); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/function/TitleFunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.function; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class TitleFunctionTest { 11 | @Test 12 | public void simpleTitle() throws Exception { 13 | 14 | String result = JtwigTemplate.inlineTemplate("{{ title('hello world') }}").render(JtwigModel.newModel()); 15 | 16 | assertThat(result, is("Hello World")); 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/function/TrimFunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.function; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class TrimFunctionTest { 11 | @Test 12 | public void simpleTrim() throws Exception { 13 | 14 | String result = JtwigTemplate.inlineTemplate("{{ trim(' jtwig ') }}").render(JtwigModel.newModel()); 15 | 16 | assertThat(result, is("jtwig")); 17 | 18 | } 19 | 20 | @Test 21 | public void trimNull() throws Exception { 22 | 23 | String result = JtwigTemplate.inlineTemplate("{{ trim(null) }}").render(JtwigModel.newModel()); 24 | 25 | assertThat(result, is("")); 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/function/UpperFunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.function; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class UpperFunctionTest { 11 | @Test 12 | public void simpleUpper() throws Exception { 13 | 14 | String result = JtwigTemplate.inlineTemplate("{{ upper('jtwig') }}").render(JtwigModel.newModel()); 15 | 16 | assertThat(result, is("JTWIG")); 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/function/UrlEncodeFunctionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.function; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.Matchers.equalTo; 9 | import static org.hamcrest.core.Is.is; 10 | 11 | public class UrlEncodeFunctionTest { 12 | @Test 13 | public void simpleUrl() throws Exception { 14 | String result = JtwigTemplate.inlineTemplate("{{ url_encode({id: 1, special: '&'}) }}").render(JtwigModel.newModel()); 15 | 16 | assertThat(result, equalTo("id=1&special=%26")); 17 | } 18 | @Test 19 | public void urlString() throws Exception { 20 | String result = JtwigTemplate.inlineTemplate("{{ url_encode('one&two') }}").render(JtwigModel.newModel()); 21 | 22 | assertThat(result, is("one%26two")); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/issues/Issue061Test.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.issues; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.StringContains.containsString; 9 | 10 | public class Issue061Test { 11 | 12 | @Test 13 | public void issue61() throws Exception { 14 | JtwigModel model = JtwigModel.newModel(); 15 | 16 | String result = JtwigTemplate 17 | .classpathTemplate("/example/classpath-template.twig") 18 | .render(model); 19 | 20 | assertThat(result, containsString("Hello")); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/issues/Issue082Test.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.issues; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | import static org.hamcrest.core.IsEqual.equalTo; 10 | 11 | public class Issue082Test { 12 | @Test 13 | public void issue82() throws Exception { 14 | JtwigModel model = new JtwigModel(); 15 | 16 | String result = JtwigTemplate 17 | .inlineTemplate("{{ notice }}") 18 | .render(model); 19 | 20 | assertThat(result, is(equalTo(""))); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/issues/Issue250Test.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.issues; 2 | 3 | import org.hamcrest.MatcherAssert; 4 | import org.jtwig.JtwigModel; 5 | import org.jtwig.JtwigTemplate; 6 | import org.jtwig.integration.AbstractIntegrationTest; 7 | import org.junit.Test; 8 | 9 | import static org.hamcrest.core.Is.is; 10 | import static org.hamcrest.core.IsEqual.equalTo; 11 | 12 | public class Issue250Test extends AbstractIntegrationTest { 13 | @Test 14 | public void numberFormatShouldHandleNullAsZero() throws Exception { 15 | JtwigModel model = new JtwigModel(); 16 | 17 | String result = JtwigTemplate 18 | .inlineTemplate("{{ null | number_format(2, ',', '.') }}") 19 | .render(model); 20 | 21 | MatcherAssert.assertThat(result, is(equalTo("0,00"))); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/issues/Issue288Test.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.issues; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class Issue288Test { 11 | @Test 12 | public void valueAccessTest() throws Exception { 13 | String result = JtwigTemplate.inlineTemplate("{{ [1,2,3][0] }}").render(JtwigModel.newModel()); 14 | 15 | assertThat(result, is("1")); 16 | } 17 | 18 | @Test 19 | public void valueAccessSplitTest() throws Exception { 20 | String result = JtwigTemplate.inlineTemplate("{{ ('te st'|split(' '))[0] }}").render(JtwigModel.newModel()); 21 | 22 | assertThat(result, is("te")); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/issues/Issue332Test.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.issues; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.CoreMatchers.is; 8 | import static org.hamcrest.MatcherAssert.assertThat; 9 | 10 | public class Issue332Test { 11 | @Test 12 | public void reproduceIssue() throws Exception { 13 | 14 | String result = JtwigTemplate.inlineTemplate("{% autoescape 'html' %}&{{ '&' }}{% endautoescape %}") 15 | .render(JtwigModel.newModel()); 16 | 17 | assertThat(result, is("&&")); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/issues/Issue333Test.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.issues; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | import static org.jtwig.environment.EnvironmentConfigurationBuilder.configuration; 10 | 11 | public class Issue333Test { 12 | @Test 13 | public void reproduceIssue() throws Exception { 14 | String result = JtwigTemplate.classpathTemplate("issues/333.twig", configuration() 15 | .render().withStrictMode(true).and() 16 | .build()) 17 | .render(JtwigModel.newModel()); 18 | 19 | assertThat(result.trim(), is("Hello world!")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/node/DoTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.node; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.jtwig.integration.AbstractIntegrationTest; 6 | import org.junit.Test; 7 | 8 | import static org.hamcrest.MatcherAssert.assertThat; 9 | import static org.hamcrest.core.Is.is; 10 | 11 | public class DoTest extends AbstractIntegrationTest { 12 | @Test 13 | public void simpleDo() throws Exception { 14 | JtwigTemplate template = JtwigTemplate.inlineTemplate("{% do 1 + 2 %}"); 15 | String result = template.render(JtwigModel.newModel()); 16 | assertThat(result, is("")); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/node/FlushNodeTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.node; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.jtwig.integration.AbstractIntegrationTest; 6 | import org.junit.Test; 7 | 8 | import java.io.OutputStream; 9 | 10 | import static org.mockito.Mockito.mock; 11 | import static org.mockito.Mockito.verify; 12 | 13 | public class FlushNodeTest extends AbstractIntegrationTest { 14 | @Test 15 | public void simpleFlush() throws Exception { 16 | OutputStream outputStream = mock(OutputStream.class); 17 | 18 | JtwigTemplate result = JtwigTemplate.inlineTemplate("{% flush %}"); 19 | result.render(JtwigModel.newModel(), outputStream); 20 | 21 | verify(outputStream).flush(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/node/VerbatimTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.node; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.jtwig.integration.AbstractIntegrationTest; 6 | import org.junit.Test; 7 | 8 | import static org.hamcrest.MatcherAssert.assertThat; 9 | import static org.hamcrest.core.Is.is; 10 | 11 | public class VerbatimTest extends AbstractIntegrationTest { 12 | @Test 13 | public void simpleVerbatim() throws Exception { 14 | JtwigTemplate template = JtwigTemplate.inlineTemplate("{% verbatim %}{% if (hello) %}{% endverbatim %}"); 15 | String result = template.render(JtwigModel.newModel()); 16 | assertThat(result, is("{% if (hello) %}")); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/integration/resources/RelativePathResourceTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.integration.resources; 2 | 3 | import org.jtwig.JtwigModel; 4 | import org.jtwig.JtwigTemplate; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.core.Is.is; 9 | 10 | public class RelativePathResourceTest { 11 | @Test 12 | public void relativePath() throws Exception { 13 | 14 | String result = JtwigTemplate.classpathTemplate("/example/base/nested/file.twig") 15 | .render(JtwigModel.newModel()); 16 | 17 | assertThat(result, is("Hello")); 18 | } 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/org/jtwig/model/tree/EmbedNodeTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.position.Position; 4 | import org.jtwig.model.tree.include.IncludeConfiguration; 5 | import org.jtwig.model.tree.visitor.NodeVisitor; 6 | import org.junit.Test; 7 | 8 | import static java.util.Arrays.asList; 9 | import static org.mockito.Mockito.mock; 10 | import static org.mockito.Mockito.verify; 11 | 12 | public class EmbedNodeTest { 13 | private final OverrideBlockNode overrideBlockNode = mock(OverrideBlockNode.class); 14 | private EmbedNode underTest = new EmbedNode(mock(Position.class), asList(overrideBlockNode), mock(IncludeConfiguration.class)); 15 | 16 | @Test 17 | public void testVisit() throws Exception { 18 | NodeVisitor nodeVisitor = mock(NodeVisitor.class); 19 | 20 | underTest.visit(nodeVisitor); 21 | 22 | verify(overrideBlockNode).visit(nodeVisitor); 23 | } 24 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/model/tree/ExtendsNodeTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.model.tree; 2 | 3 | import org.jtwig.model.expression.Expression; 4 | import org.jtwig.model.position.Position; 5 | import org.jtwig.model.tree.visitor.NodeVisitor; 6 | import org.junit.Test; 7 | 8 | import static java.util.Arrays.asList; 9 | import static org.mockito.Mockito.mock; 10 | import static org.mockito.Mockito.verify; 11 | 12 | public class ExtendsNodeTest { 13 | Node node = mock(Node.class); 14 | ExtendsNode underTest = new ExtendsNode(mock(Position.class), mock(Expression.class), asList(node)); 15 | 16 | @Test 17 | public void visitTest() throws Exception { 18 | NodeVisitor nodeConsumer = mock(NodeVisitor.class); 19 | 20 | underTest.visit(nodeConsumer); 21 | 22 | verify(node).visit(nodeConsumer); 23 | } 24 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/parser/parboiled/model/KeywordTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.model; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.junit.Test; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Collection; 8 | 9 | public class KeywordTest { 10 | @Test 11 | public void printKeywords() throws Exception { 12 | Collection list = new ArrayList<>(); 13 | for (Keyword keyword : Keyword.values()) { 14 | list.add(String.format("%s", keyword.toString())); 15 | } 16 | 17 | System.out.println(StringUtils.join(list, " ")); 18 | } 19 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/parser/parboiled/node/DoNodeParserTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.node; 2 | 3 | import org.jtwig.model.tree.SetNode; 4 | import org.jtwig.parser.parboiled.AbstractParserTest; 5 | import org.junit.Test; 6 | import org.parboiled.support.ParsingResult; 7 | 8 | import static org.hamcrest.MatcherAssert.assertThat; 9 | import static org.hamcrest.core.Is.is; 10 | 11 | public class DoNodeParserTest extends AbstractParserTest { 12 | private DoNodeParser underTest = context.parser(DoNodeParser.class); 13 | 14 | @Test 15 | public void set() throws Exception { 16 | ParsingResult result = parse(underTest.NodeRule(), "{% do 1 + 123 %}"); 17 | 18 | assertThat(result.matched, is(true)); 19 | assertThat(result.valueStack.isEmpty(), is(false)); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/parser/parboiled/node/SetNodeParserTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.node; 2 | 3 | import org.jtwig.model.tree.SetNode; 4 | import org.jtwig.parser.parboiled.AbstractParserTest; 5 | import org.junit.Test; 6 | import org.parboiled.support.ParsingResult; 7 | 8 | import static org.hamcrest.MatcherAssert.assertThat; 9 | import static org.hamcrest.core.Is.is; 10 | 11 | public class SetNodeParserTest extends AbstractParserTest { 12 | private SetNodeParser underTest = context.parser(SetNodeParser.class); 13 | 14 | @Test 15 | public void set() throws Exception { 16 | ParsingResult result = parse(underTest.NodeRule(), "{% set a = 123 %}"); 17 | 18 | assertThat(result.matched, is(true)); 19 | assertThat(result.valueStack.isEmpty(), is(false)); 20 | } 21 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/parser/parboiled/node/TextNodeParserTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.parser.parboiled.node; 2 | 3 | import org.jtwig.model.tree.TextNode; 4 | import org.jtwig.parser.parboiled.AbstractParserTest; 5 | import org.junit.Test; 6 | import org.parboiled.support.ParsingResult; 7 | 8 | import static org.hamcrest.MatcherAssert.assertThat; 9 | import static org.hamcrest.core.Is.is; 10 | 11 | public class TextNodeParserTest extends AbstractParserTest { 12 | private TextNodeParser underTest = context.parser(TextNodeParser.class); 13 | 14 | @Test 15 | public void testTextNode() throws Exception { 16 | ParsingResult result = parse(underTest.NodeRule(), "test {{"); 17 | 18 | assertThat(result.matched, is(true)); 19 | TextNode textNode = result.valueStack.pop(); 20 | assertThat(textNode.getText(), is("test ")); 21 | } 22 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/property/resolver/EmptyPropertyResolverTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.resolver; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.property.resolver.request.PropertyResolveRequest; 5 | import org.jtwig.reflection.model.Value; 6 | import org.junit.Test; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | import static org.mockito.Mockito.mock; 10 | 11 | public class EmptyPropertyResolverTest { 12 | private EmptyPropertyResolver underTest = EmptyPropertyResolver.instance(); 13 | 14 | @Test 15 | public void resolve() throws Exception { 16 | Optional result = underTest.resolve(mock(PropertyResolveRequest.class)); 17 | 18 | assertEquals(Optional.absent(), result); 19 | } 20 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/property/resolver/request/PropertyNameExtractorTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.resolver.request; 2 | 3 | import com.google.common.base.Optional; 4 | import org.jtwig.model.expression.ConstantExpression; 5 | import org.jtwig.model.position.Position; 6 | import org.junit.Test; 7 | 8 | import static org.hamcrest.CoreMatchers.is; 9 | import static org.junit.Assert.assertThat; 10 | import static org.mockito.Mockito.mock; 11 | 12 | public class PropertyNameExtractorTest { 13 | private PropertyNameExtractor underTest = new PropertyNameExtractor(); 14 | 15 | @Test 16 | public void noVariableNeitherFunction() throws Exception { 17 | Position position = mock(Position.class); 18 | ConstantExpression expression = new ConstantExpression(position, 1); 19 | 20 | Optional result = underTest.extract(expression); 21 | 22 | assertThat(result.isPresent(), is(false)); 23 | } 24 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/property/strategy/method/argument/AssignableTypesTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.property.strategy.method.argument; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertTrue; 6 | 7 | public class AssignableTypesTest { 8 | private AssignableTypes underTest = new AssignableTypes(IsNativeType.instance()); 9 | 10 | @Test 11 | public void isAssignable() throws Exception { 12 | assertTrue(underTest.isAssignable(Integer.TYPE, Integer.TYPE)); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/render/context/ContextTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.context; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.mockito.Mockito.mock; 6 | import static org.mockito.Mockito.verify; 7 | 8 | public class ContextTest { 9 | @Test 10 | public void content() throws Exception { 11 | Runnable runnable = mock(Runnable.class); 12 | Context context = Context.create(new Object()); 13 | context.onEnd(runnable); 14 | 15 | context.end(); 16 | 17 | verify(runnable).run(); 18 | } 19 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/render/expression/calculator/ConstantExpressionCalculatorTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator; 2 | 3 | import org.jtwig.model.expression.ConstantExpression; 4 | import org.jtwig.render.RenderRequest; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.assertSame; 8 | import static org.mockito.Mockito.mock; 9 | import static org.mockito.Mockito.when; 10 | 11 | public class ConstantExpressionCalculatorTest { 12 | private ConstantExpressionCalculator underTest = new ConstantExpressionCalculator(); 13 | 14 | @Test 15 | public void calculate() throws Exception { 16 | Object expected = new Object(); 17 | ConstantExpression expression = mock(ConstantExpression.class); 18 | 19 | when(expression.getConstantValue()).thenReturn(expected); 20 | 21 | Object result = underTest.calculate(mock(RenderRequest.class), expression); 22 | 23 | assertSame(expected, result); 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/render/expression/calculator/operation/binary/calculators/AndOperationCalculatorTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.hamcrest.core.Is.is; 6 | import static org.junit.Assert.assertThat; 7 | 8 | public class AndOperationCalculatorTest { 9 | private AndOperationCalculator underTest = new AndOperationCalculator(); 10 | 11 | @Test 12 | public void calculate() throws Exception { 13 | assertThat(underTest.calculate(true, true), is(true)); 14 | assertThat(underTest.calculate(false, true), is(false)); 15 | assertThat(underTest.calculate(true, false), is(false)); 16 | assertThat(underTest.calculate(false, false), is(false)); 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/render/expression/calculator/operation/binary/calculators/OrOperationCalculatorTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.expression.calculator.operation.binary.calculators; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.hamcrest.core.Is.is; 6 | import static org.junit.Assert.assertThat; 7 | 8 | public class OrOperationCalculatorTest { 9 | private OrOperationCalculator underTest = new OrOperationCalculator(); 10 | 11 | @Test 12 | public void calculate() throws Exception { 13 | assertThat(underTest.calculate(true, true), is(true)); 14 | assertThat(underTest.calculate(false, true), is(true)); 15 | assertThat(underTest.calculate(true, false), is(true)); 16 | assertThat(underTest.calculate(false, false), is(false)); 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/render/node/renderer/FlushNodeRenderTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.render.node.renderer; 2 | 3 | import org.jtwig.model.tree.FlushNode; 4 | import org.jtwig.render.RenderRequest; 5 | import org.jtwig.renderable.Renderable; 6 | import org.jtwig.renderable.impl.FlushRenderable; 7 | import org.junit.Test; 8 | 9 | import static org.junit.Assert.assertSame; 10 | import static org.mockito.Mockito.mock; 11 | 12 | public class FlushNodeRenderTest { 13 | private FlushNodeRender underTest = new FlushNodeRender(); 14 | 15 | @Test 16 | public void render() throws Exception { 17 | FlushNode flushNode = mock(FlushNode.class); 18 | RenderRequest request = mock(RenderRequest.class); 19 | 20 | Renderable result = underTest.render(request, flushNode); 21 | 22 | assertSame(FlushRenderable.instance(), result); 23 | } 24 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/renderable/StringBuilderRenderResultTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.renderable; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.hamcrest.core.Is.is; 6 | import static org.junit.Assert.assertThat; 7 | 8 | public class StringBuilderRenderResultTest { 9 | private StringBuilderRenderResult underTest = new StringBuilderRenderResult(); 10 | 11 | @Test 12 | public void appendAndContent() throws Exception { 13 | underTest.append("one"); 14 | 15 | String result = underTest.content(); 16 | 17 | assertThat(result, is("one")); 18 | } 19 | 20 | @Test 21 | public void flush() throws Exception { 22 | underTest.flush(); 23 | 24 | // no effect 25 | } 26 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/renderable/impl/StringRenderableTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.renderable.impl; 2 | 3 | import org.jtwig.escape.NoneEscapeEngine; 4 | import org.jtwig.renderable.RenderResult; 5 | import org.junit.Test; 6 | 7 | import static org.mockito.Mockito.mock; 8 | import static org.mockito.Mockito.verify; 9 | 10 | public class StringRenderableTest { 11 | public static final String CONTENT = "content"; 12 | private final RenderResult renderResult = mock(RenderResult.class); 13 | private StringRenderable underTest; 14 | 15 | @Test 16 | public void acceptWithNoneEscapeMode() throws Exception { 17 | underTest = new StringRenderable(CONTENT, NoneEscapeEngine.instance()); 18 | 19 | underTest.appendTo(renderResult); 20 | 21 | verify(renderResult).append(CONTENT); 22 | } 23 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/resource/exceptions/ResourceExceptionTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.exceptions; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.hamcrest.core.Is.is; 6 | import static org.junit.Assert.assertThat; 7 | import static org.mockito.Mockito.mock; 8 | 9 | public class ResourceExceptionTest { 10 | @Test 11 | public void apiNeededForClients() throws Exception { 12 | Exception exception = mock(Exception.class); 13 | 14 | ResourceException result = new ResourceException("message", exception); 15 | 16 | assertThat(result.getMessage(), is("message")); 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/resource/loader/ClasspathResourceLoaderIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.loader; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.hamcrest.Matchers.is; 6 | import static org.junit.Assert.assertThat; 7 | 8 | public class ClasspathResourceLoaderIntegrationTest { 9 | private ClasspathResourceLoader underTest = new ClasspathResourceLoader(getClass().getClassLoader()); 10 | 11 | @Test 12 | public void exists() throws Exception { 13 | boolean result = underTest.exists("/example/classpath-error.twig"); 14 | 15 | assertThat(result, is(true)); 16 | } 17 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/resource/reference/PosixResourceReferenceExtractorTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.reference; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.hamcrest.core.Is.is; 6 | import static org.junit.Assert.assertThat; 7 | 8 | public class PosixResourceReferenceExtractorTest { 9 | private PosixResourceReferenceExtractor underTest = new PosixResourceReferenceExtractor(); 10 | 11 | @Test 12 | public void extractUnix() throws Exception { 13 | String path = "/path/location"; 14 | 15 | ResourceReference result = underTest.extract(path); 16 | 17 | assertThat(result.getType(), is(ResourceReference.ANY_TYPE)); 18 | assertThat(result.getPath(), is(path)); 19 | 20 | } 21 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/resource/resolver/path/RelativeFilePathResolverTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.resource.resolver.path; 2 | 3 | import org.junit.Test; 4 | 5 | import java.io.File; 6 | 7 | import static org.hamcrest.core.Is.is; 8 | import static org.junit.Assert.*; 9 | 10 | public class RelativeFilePathResolverTest { 11 | private RelativeFilePathResolver underTest = RelativeFilePathResolver.instance(); 12 | 13 | @Test 14 | public void isRelative() throws Exception { 15 | assertFalse(underTest.isRelative(new File("test").getAbsolutePath())); 16 | assertTrue(underTest.isRelative(new File("test").getPath())); 17 | } 18 | 19 | @Test 20 | public void resolve() throws Exception { 21 | String result = underTest.resolve("test", "test2"); 22 | assertThat(result, is(new File("test2").getPath())); 23 | } 24 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/util/ClasspathFinderTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.util; 2 | 3 | import org.jtwig.reflection.model.java.JavaClassManager; 4 | import org.junit.Test; 5 | 6 | import static org.hamcrest.core.Is.is; 7 | import static org.junit.Assert.assertThat; 8 | 9 | public class ClasspathFinderTest { 10 | private ClasspathFinder underTest = new ClasspathFinder(getClass().getClassLoader(), JavaClassManager.classManager()); 11 | 12 | @Test 13 | public void existsWhenValid() throws Exception { 14 | boolean result = underTest.exists(getClass().getName()); 15 | 16 | assertThat(result, is(true)); 17 | } 18 | 19 | @Test 20 | public void existsWhenInvalid() throws Exception { 21 | boolean result = underTest.exists("blah"); 22 | 23 | assertThat(result, is(false)); 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/util/EscapeUtilsTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.util; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.hamcrest.core.Is.is; 6 | import static org.junit.Assert.assertThat; 7 | 8 | public class EscapeUtilsTest { 9 | 10 | @Test 11 | public void escapeJtwig() throws Exception { 12 | String result = EscapeUtils.escapeJtwig("c:\\"); 13 | 14 | assertThat(result, is("c:\\\\")); 15 | } 16 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/value/convert/NullConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.convert; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class NullConverterTest { 8 | private NullConverter underTest = new NullConverter(); 9 | 10 | @Test 11 | public void convertNull() throws Exception { 12 | Converter.Result result = underTest.convert(null); 13 | 14 | assertEquals(null, result.get()); 15 | assertEquals(true, result.isDefined()); 16 | } 17 | 18 | @Test 19 | public void convertNotNull() throws Exception { 20 | Converter.Result result = underTest.convert(new Object()); 21 | 22 | assertEquals(false, result.isDefined()); 23 | } 24 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/value/convert/character/CharConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.convert.character; 2 | 3 | import org.jtwig.value.convert.Converter; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | public class CharConverterTest { 9 | private CharConverter underTest = new CharConverter(); 10 | 11 | @Test 12 | public void convert() throws Exception { 13 | Object item = 'a'; 14 | 15 | Converter.Result result = underTest.convert('a'); 16 | 17 | assertEquals(item, result.get()); 18 | } 19 | 20 | @Test 21 | public void convertString() throws Exception { 22 | Object item = 'a'; 23 | 24 | Converter.Result result = underTest.convert("a"); 25 | 26 | assertEquals(item, result.get()); 27 | } 28 | } -------------------------------------------------------------------------------- /src/test/java/org/jtwig/value/convert/string/DefaultStringConverterTest.java: -------------------------------------------------------------------------------- 1 | package org.jtwig.value.convert.string; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class DefaultStringConverterTest { 8 | private DefaultStringConverter underTest = new DefaultStringConverter(); 9 | 10 | @Test 11 | public void convert() throws Exception { 12 | String result = underTest.convert(null); 13 | 14 | assertEquals("", result); 15 | } 16 | 17 | @Test 18 | public void convertString() throws Exception { 19 | Object input = new Object(); 20 | 21 | String result = underTest.convert(input); 22 | 23 | assertEquals(input.toString(), result); 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/resources/example/base/base.twig: -------------------------------------------------------------------------------- 1 | {% block body %}{% endblock %} World -------------------------------------------------------------------------------- /src/test/resources/example/base/nested/file.twig: -------------------------------------------------------------------------------- 1 | {% include '../../classpath-template.twig' %} -------------------------------------------------------------------------------- /src/test/resources/example/classpath-error.twig: -------------------------------------------------------------------------------- 1 | {{ undefined.test(value) -------------------------------------------------------------------------------- /src/test/resources/example/classpath-extends-include-in-block.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.twig' %} 2 | {%- block body %} 3 | {%- include 'classpath-template.twig' %} 4 | {%- endblock %} -------------------------------------------------------------------------------- /src/test/resources/example/classpath-include.twig: -------------------------------------------------------------------------------- 1 | {% include 'classpath-template.twig' %} World -------------------------------------------------------------------------------- /src/test/resources/example/classpath-template.twig: -------------------------------------------------------------------------------- 1 | Hello -------------------------------------------------------------------------------- /src/test/resources/example/extends/extendable-template.twig: -------------------------------------------------------------------------------- 1 | {% block one %}Two{% endblock one %} -------------------------------------------------------------------------------- /src/test/resources/example/extends/nested-extendable-template.twig: -------------------------------------------------------------------------------- 1 | {% extends 'extendable-template.twig' %} 2 | 3 | {% block one %}One{% endblock one %} -------------------------------------------------------------------------------- /src/test/resources/example/macros/macro-example.twig: -------------------------------------------------------------------------------- 1 | {% macro text (name) -%} 2 | {{ name }} 3 | {%- endmacro %} -------------------------------------------------------------------------------- /src/test/resources/example/macros/macro-self-example.twig: -------------------------------------------------------------------------------- 1 | {% import _self as this %} 2 | {% macro text (name) -%} 3 | {{ name }} 4 | {%- endmacro %} 5 | 6 | {% if (true) %}{{ this.text('one') }}{% endif %} 7 | {% for item in [1] %}{{ item }}{% endfor %} -------------------------------------------------------------------------------- /src/test/resources/example/macros/mixed-imports-example.twig: -------------------------------------------------------------------------------- 1 | {% import 'macro-example.twig' as another %} 2 | {% import _self as m %} 3 | {% macro test() %}Hello!{% endmacro %} 4 | {{ m.test() }} {{ another.text('oi') }} -------------------------------------------------------------------------------- /src/test/resources/example/macros/nested-macro-child-example.twig: -------------------------------------------------------------------------------- 1 | {% macro test() %} 2 | {% import 'macro-example.twig' as another %} 3 | {{ another.text('oi') }} 4 | {% endmacro %} -------------------------------------------------------------------------------- /src/test/resources/example/macros/nested-macro-example.twig: -------------------------------------------------------------------------------- 1 | {% import 'nested-macro-child-example.twig' as macros %} 2 | 3 | {{ macros.test() }} -------------------------------------------------------------------------------- /src/test/resources/example/structure/base-layout.twig: -------------------------------------------------------------------------------- 1 | {%- for presentation in presentations -%} 2 | {% block item %} 3 | {% endblock %} 4 | {%- endfor -%} -------------------------------------------------------------------------------- /src/test/resources/example/structure/index-jtwig.twig: -------------------------------------------------------------------------------- 1 | {% extends "base-layout.twig" %} 2 | 3 | {%- block item -%} 4 | {{ presentation.title }} - {{ presentation.speakerName }} 5 | {%- endblock -%} -------------------------------------------------------------------------------- /src/test/resources/issues/333.twig: -------------------------------------------------------------------------------- 1 | {% import _self as m %} 2 | {% macro test() %}Hello world!{% endmacro %} 3 | {{ m.test() }} --------------------------------------------------------------------------------