Return-Path: X-Original-To: apmail-cocoon-dev-archive@www.apache.org Delivered-To: apmail-cocoon-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 0AC1576FC for ; Fri, 28 Oct 2011 09:32:11 +0000 (UTC) Received: (qmail 67425 invoked by uid 500); 28 Oct 2011 09:32:10 -0000 Delivered-To: apmail-cocoon-dev-archive@cocoon.apache.org Received: (qmail 67369 invoked by uid 500); 28 Oct 2011 09:32:10 -0000 Mailing-List: contact dev-help@cocoon.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: dev@cocoon.apache.org List-Id: Delivered-To: mailing list dev@cocoon.apache.org Received: (qmail 67362 invoked by uid 99); 28 Oct 2011 09:32:10 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 28 Oct 2011 09:32:10 +0000 X-ASF-Spam-Status: No, hits=0.7 required=5.0 tests=SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (nike.apache.org: local policy) Received: from [78.134.5.44] (HELO rovere.tirasa.net) (78.134.5.44) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 28 Oct 2011 09:32:02 +0000 Received: from localhost (localhost [127.0.0.1]) by rovere.tirasa.net (Postfix) with ESMTP id 6737B182874 for ; Fri, 28 Oct 2011 11:31:41 +0200 (CEST) X-Virus-Scanned: amavisd-new at tirasa.net Received: from rovere.tirasa.net ([127.0.0.1]) by localhost (rovere.tirasa.net [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id IHzU8KjGOSIz for ; Fri, 28 Oct 2011 11:31:37 +0200 (CEST) Received: from [192.168.0.2] (mogano.tirasa.net [192.168.0.2]) by rovere.tirasa.net (Postfix) with ESMTPSA id 17C50181E4F for ; Fri, 28 Oct 2011 11:31:37 +0200 (CEST) Message-ID: <4EAA7679.6020403@apache.org> Date: Fri, 28 Oct 2011 11:31:37 +0200 From: =?UTF-8?B?RnJhbmNlc2NvIENoaWNjaGlyaWNjw7I=?= User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:7.0.1) Gecko/20110929 Thunderbird/7.0.1 MIME-Version: 1.0 To: dev@cocoon.apache.org Subject: Re: [c3] Implementing presentation logic in c3 References: <1319755181.4195.96.camel@mcKenny> <4EAA6253.5000700@apache.org> <1319793469.4071.26.camel@mcKenny> In-Reply-To: <1319793469.4071.26.camel@mcKenny> Content-Type: multipart/mixed; boundary="------------020006090302080703080207" X-Virus-Checked: Checked by ClamAV on apache.org This is a multi-part message in MIME format. --------------020006090302080703080207 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit On 28/10/2011 11:17, Thorsten Scherler wrote: >>> I tried to use the "string-template" component but I am running into a problem when using $if(boolean)$. >>> >>> I am ATM integrating Apache Shiro, a security framework that performs authentication, authorization, cryptography, and session management, into c3 and want to use something in the spirit of their taglibs >>> >>> Pleaselogin. >>> >>> >>> So what I did is I wrote a ShiroInterpreter implements LanguageInterpreter that can extract this info. >>> However the interface LanguageInterpreter defines the return type to String. >>> >>> >>> >>> >>> >>> will fail then interpreting >>> $if(!isUser)$ >>> /logout >>> $else$ >>> /login >>> $endif$ >>> >>> with >>> ... >>> Caused by: org.stringtemplate.v4.compiler.STException: null >>> at org.stringtemplate.v4.compiler.Compiler.reportMessageAndThrowSTException(Compiler.java:213) ~[ST4-4.0.4.jar:na] >>> >>> If I use only $isUser$ I get the correct value. Reading "Conditional subtemplates" [1] >>> "You may only test whether an attribute is present or absent, preserving separation of model >>> and view. The only exception is that if an attribute value is a Boolean object, it will test it for true/false." >> I think you've hit a bug of StringTemplate transformer: see the attached patch (for cocoon-sample in C3 sources) using conditional and boolean value from sitemap; ST generator works well and ST transformer raises an exception similar to the one reported above. > Ok I will have a look. Thorsten, see attached a patch for cocoon-stringtemplate and cocoon-sample that should fix your issue about $if$ with StringTemplateTransformer. In fact, I've checked that problems arise with transformer only, while generator is safe in this respect; this happens because generator let ST handle the whole file, while transformer doesn't. Transformer's approach makes it able, however, to parse ST expressions in XML attributes as well. If you want to try my patch, just apply it to fresh C3 sources, do an "mvn clean install" of cocoon-stringtemplate and afterwards launch "mvn jetty:run" under cocoon-sample: you will be able to watch results at http://localhost:8888/string-template/generator and http://localhost:8888/string-template/transformer. I did not commit this yet because, as you can see from StringTemplateTransformer's source, my patch is limited to "$if$" case, and only when the whole $if$ evaluates to CDATA from XML point of view: i.e. this work link while this does not: $if(!booleanParameter)$ expression evaluated to true $else$ expression evaluated to false $endif$ As an alternative to my patch's approach, StringTemplateTransformer could act in a way similar to StringTemplateGenerator's, i.e. buffering the whole input document and passing it as a whole to ST: what do you think? Cheers. -- Francesco Chicchiriccò Apache Cocoon Committer and PMC Member http://people.apache.org/~ilgrosso/ --------------020006090302080703080207 Content-Type: text/x-patch; name="stringtemplate-if.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="stringtemplate-if.patch" Index: cocoon-stringtemplate/src/test/java/org/apache/cocoon/stringtemplate/StringTemplateTransformerTest.java =================================================================== --- cocoon-stringtemplate/src/test/java/org/apache/cocoon/stringtemplate/StringTemplateTransformerTest.java (revisione 1190180) +++ cocoon-stringtemplate/src/test/java/org/apache/cocoon/stringtemplate/StringTemplateTransformerTest.java (copia locale) @@ -15,41 +15,43 @@ */ package org.apache.cocoon.stringtemplate; -import static junit.framework.Assert.*; +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.assertNotNull; import java.io.ByteArrayOutputStream; -import java.util.Collections; -import junit.framework.Assert; +import java.io.File; +import java.util.HashMap; +import java.util.Map; import org.apache.cocoon.pipeline.NonCachingPipeline; import org.apache.cocoon.pipeline.Pipeline; import org.apache.cocoon.sax.SAXPipelineComponent; import org.apache.cocoon.sax.component.XMLGenerator; import org.apache.cocoon.sax.component.XMLSerializer; +import org.apache.commons.io.FileUtils; import org.custommonkey.xmlunit.Diff; +import org.custommonkey.xmlunit.XMLUnit; import org.junit.Test; public class StringTemplateTransformerTest { - private static final String INPUT = - "" - + "" - + "This text content also contains $param$" - + "" - + "and also this contains $param$" - + "while this does not" - + ""; - @Test public void test() throws Exception { + final String inputString = FileUtils.readFileToString(new File( + getClass().getResource("/transformerTest.xml").toURI())); + + final StringTemplateTransformer transformer = new StringTemplateTransformer(); - transformer.setup(Collections.singletonMap("param", (Object) "value")); + final Map params = new HashMap(); + params.put("param", "value"); + params.put("booleanParam", Boolean.FALSE); + transformer.setup(params); final Pipeline pipeline = new NonCachingPipeline(); - pipeline.addComponent(new XMLGenerator(INPUT)); + pipeline.addComponent(new XMLGenerator(inputString)); pipeline.addComponent(transformer); pipeline.addComponent(new XMLSerializer()); @@ -58,10 +60,14 @@ pipeline.execute(); final String actualDocument = new String(baos.toByteArray(), "UTF-8"); - Assert.assertNotNull(actualDocument); + assertNotNull(actualDocument); - final String expectedDocument = INPUT.replaceAll("\\$param\\$", "value"); + final String expectedDocument = inputString.replaceAll("\\$param\\$", + "value").replaceAll("\\$.*\\$", ""). + replaceAll("expression evaluated to true", ""); + XMLUnit.setIgnoreWhitespace(true); + XMLUnit.setIgnoreComments(true); final Diff diff = new Diff(expectedDocument, actualDocument); assertTrue("StringTemplate transformer didn't work as expected " + diff, diff.identical()); Index: cocoon-stringtemplate/src/test/java/org/apache/cocoon/stringtemplate/StringTemplateGeneratorTest.java =================================================================== --- cocoon-stringtemplate/src/test/java/org/apache/cocoon/stringtemplate/StringTemplateGeneratorTest.java (revisione 1190180) +++ cocoon-stringtemplate/src/test/java/org/apache/cocoon/stringtemplate/StringTemplateGeneratorTest.java (copia locale) @@ -19,7 +19,8 @@ import java.io.ByteArrayOutputStream; import java.io.File; -import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import junit.framework.Assert; import org.apache.cocoon.pipeline.NonCachingPipeline; import org.apache.cocoon.pipeline.Pipeline; @@ -27,6 +28,7 @@ import org.apache.cocoon.sax.component.XMLSerializer; import org.apache.commons.io.FileUtils; import org.custommonkey.xmlunit.Diff; +import org.custommonkey.xmlunit.XMLUnit; import org.junit.Test; public class StringTemplateGeneratorTest { @@ -34,7 +36,10 @@ private boolean doTest(final StringTemplateGenerator generator) throws Exception { - generator.setup(Collections.singletonMap("param", (Object) "value")); + final Map params = new HashMap(); + params.put("param", "value"); + params.put("booleanParam", Boolean.FALSE); + generator.setup(params); final Pipeline pipeline = new NonCachingPipeline(); @@ -49,9 +54,11 @@ Assert.assertNotNull(actualDocument); final String expectedDocument = FileUtils.readFileToString( - new File(getClass().getResource("/test.xml").toURI())). - replaceAll("\\$param\\$", "value"); + new File(getClass().getResource("/generatorTest.xml").toURI())). + replaceAll("\\$param\\$", "value").replaceAll("\\$.*\\$", ""). + replaceAll("expression evaluated to true", ""); + XMLUnit.setIgnoreWhitespace(true); final Diff diff = new Diff(expectedDocument, actualDocument); assertTrue("StringTemplate generation didn't work as expected " + diff, diff.identical()); @@ -64,7 +71,7 @@ throws Exception { assertTrue(doTest(new StringTemplateGenerator( - getClass().getResource("/test.xml")))); + getClass().getResource("/generatorTest.xml")))); } @Test @@ -72,7 +79,8 @@ throws Exception { assertTrue(doTest(new StringTemplateGenerator( - new File(getClass().getResource("/test.xml").toURI())))); + new File(getClass().getResource("/generatorTest.xml"). + toURI())))); } @Test @@ -80,14 +88,16 @@ throws Exception { assertTrue(doTest(new StringTemplateGenerator( - getClass().getResourceAsStream("/test.xml")))); + getClass().getResourceAsStream("/generatorTest.xml")))); } @Test public final void testString() throws Exception { - assertTrue(doTest(new StringTemplateGenerator(FileUtils.readFileToString( - new File(getClass().getResource("/test.xml").toURI()))))); + assertTrue(doTest(new StringTemplateGenerator( + FileUtils.readFileToString( + new File(getClass().getResource("/generatorTest.xml"). + toURI()))))); } } Index: cocoon-stringtemplate/src/test/resources/transformerTest.xml =================================================================== --- cocoon-stringtemplate/src/test/resources/transformerTest.xml (revisione 0) +++ cocoon-stringtemplate/src/test/resources/transformerTest.xml (revisione 0) @@ -0,0 +1,31 @@ + + + + + This text content also contains $param$ + + and also this contains $param$ + while this does not +$if(!booleanParam)$ + expression evaluated to true +$else$ + expression evaluated to false +$endif$ + Index: cocoon-stringtemplate/src/test/resources/generatorTest.xml =================================================================== --- cocoon-stringtemplate/src/test/resources/generatorTest.xml (revisione 1190180) +++ cocoon-stringtemplate/src/test/resources/generatorTest.xml (copia locale) @@ -19,4 +19,9 @@ --> $param$ +$if(!booleanParam)$ + expression evaluated to true +$else$ + expression evaluated to false +$endif$ Index: cocoon-stringtemplate/src/test/resources/test.xml =================================================================== --- cocoon-stringtemplate/src/test/resources/test.xml (revisione 1190180) +++ cocoon-stringtemplate/src/test/resources/test.xml (copia locale) @@ -1,22 +0,0 @@ - - - - $param$ - Index: cocoon-stringtemplate/src/main/java/org/apache/cocoon/stringtemplate/StringTemplateTransformer.java =================================================================== --- cocoon-stringtemplate/src/main/java/org/apache/cocoon/stringtemplate/StringTemplateTransformer.java (revisione 1190180) +++ cocoon-stringtemplate/src/main/java/org/apache/cocoon/stringtemplate/StringTemplateTransformer.java (copia locale) @@ -18,7 +18,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; - import org.apache.cocoon.sax.AbstractSAXTransformer; import org.apache.commons.lang3.StringEscapeUtils; import org.slf4j.Logger; @@ -37,13 +36,17 @@ LoggerFactory.getLogger(StringTemplateTransformer.class); private final transient Map parameters; + private final transient StringBuilder accumulator; + private boolean flushSuspended; + public StringTemplateTransformer() { super(); this.parameters = new HashMap(); this.accumulator = new StringBuilder(); + this.flushSuspended = false; } @Override @@ -54,7 +57,8 @@ } @Override - public void setConfiguration(final Map configuration) { + public void setConfiguration( + final Map configuration) { this.setup((Map) configuration); } @@ -68,7 +72,8 @@ for (Entry eachEntry : this.parameters.entrySet()) { final String key = eachEntry.getKey().replace(".", "_"); - final String value = StringEscapeUtils.escapeXml(eachEntry.getValue().toString()); + final String value = StringEscapeUtils.escapeXml( + eachEntry.getValue().toString()); stringTemplate.add(key, value); if (LOG.isDebugEnabled()) { @@ -81,8 +86,10 @@ return stringTemplate.render(); } - private void flushAccumulator() throws SAXException { - if (this.accumulator.length() == 0) { + private void flushAccumulator() + throws SAXException { + + if (this.accumulator.length() == 0 || this.flushSuspended) { return; } @@ -93,31 +100,49 @@ } @Override - public void startElement(final String uri, final String localName, final String name, final Attributes attributes) + public void startElement(final String uri, final String localName, + final String name, final Attributes attrs) throws SAXException { - final AttributesImpl renderedAttributes = new AttributesImpl(); - for (int i = 0; i < attributes.getLength(); i++) { - final String attributeURI = attributes.getURI(i); - final String attributeLocalName = attributes.getLocalName(i); - final String attributeQName = attributes.getQName(i); - final String attributeType = attributes.getType(i); - final String attributeValue = this.renderTemplate(attributes.getValue(i)); - renderedAttributes.addAttribute(attributeURI, attributeLocalName, attributeQName, attributeType, attributeValue); + final AttributesImpl renderAttrs = new AttributesImpl(); + + for (int i = 0; i < attrs.getLength(); i++) { + renderAttrs.addAttribute(attrs.getURI(i), + attrs.getLocalName(i), + attrs.getQName(i), + attrs.getType(i), + this.renderTemplate(attrs.getValue(i))); } this.flushAccumulator(); - super.startElement(uri, localName, name, renderedAttributes); + if (!this.flushSuspended) { + super.startElement(uri, localName, name, renderAttrs); + } } @Override - public void characters(final char[] characters, final int start, final int length) throws SAXException { + public void characters(final char[] characters, final int start, + final int length) + throws SAXException { + + final String str = new String(characters, start, length); + if (str.contains("$if")) { + this.flushSuspended = true; + } else if (str.contains("$endif$")) { + this.flushSuspended = false; + } + this.accumulator.append(characters, start, length); } @Override - public void endElement(final String uri, final String localName, final String name) throws SAXException { + public void endElement(final String uri, final String localName, + final String name) + throws SAXException { + this.flushAccumulator(); - super.endElement(uri, localName, name); + if (!this.flushSuspended) { + super.endElement(uri, localName, name); + } } } Index: cocoon-sample/src/main/resources/COB-INF/string-template/generatorTemplate.xml =================================================================== --- cocoon-sample/src/main/resources/COB-INF/string-template/generatorTemplate.xml (revisione 1190180) +++ cocoon-sample/src/main/resources/COB-INF/string-template/generatorTemplate.xml (copia locale) @@ -24,5 +24,11 @@

StringTemplate demo

parameter=$parameter$

+

booleanParameter=$booleanParameter$

+$if(!booleanParameter)$ +expression evaluated to true +$else$ +expression evaluated to false +$endif$ Index: cocoon-sample/src/main/resources/COB-INF/string-template/template.xml =================================================================== --- cocoon-sample/src/main/resources/COB-INF/string-template/template.xml (revisione 1190180) +++ cocoon-sample/src/main/resources/COB-INF/string-template/template.xml (copia locale) @@ -1,28 +0,0 @@ - - - - - StringTemplate demo - - -

StringTemplate demo

-

parameter=$parameter$

- - Index: cocoon-sample/src/main/resources/COB-INF/string-template/transformerTemplate.xml =================================================================== --- cocoon-sample/src/main/resources/COB-INF/string-template/transformerTemplate.xml (revisione 0) +++ cocoon-sample/src/main/resources/COB-INF/string-template/transformerTemplate.xml (revisione 0) @@ -0,0 +1,34 @@ + + + + + StringTemplate demo + + +

StringTemplate demo

+

parameter=$parameter$

+

booleanParameter=$booleanParameter$

+link + + Index: cocoon-sample/src/main/resources/COB-INF/sitemap.xmap =================================================================== --- cocoon-sample/src/main/resources/COB-INF/sitemap.xmap (revisione 1190180) +++ cocoon-sample/src/main/resources/COB-INF/sitemap.xmap (copia locale) @@ -550,15 +550,17 @@ - + + - + + --------------020006090302080703080207--